В ядре Linux обнаружена опасная уязвимость, которая связана с обработкой подсистемой памяти ядра механизма copy-on-write (COW). Эксплуатируя баг можно спровоцировать так называемое состояние гонки (race condition). При эксплуатации уязвимости неавторизованный локальный пользователь сможет получить доступ к memory mappings с правом записи, хотя доступ должен быть ограничивать только чтением (read-only). Уязвимость относится к privilege escalation.

Уязвимость была обнаружена в самом ядре Linux и, что немаловажно, присутствует в составе любых дистрибутивов почти десять лет => 2.6.22.
«Как заметил Линус Торвальдс в своем коммите, этот древний баг живет в ядре уже много лет. Всем пользователям Linux стоит отнестись к проблеме серьезно и установить патч как можно быстрее»

Уязвимость присвоен CVE-2016-5195, ей подвержены большинство современных дистрибутивов Linux, более того, исследователь (Phil Oester), обнаруживший уязвимость, утверждает что эта уязвимость эксплуатируется злоумышленниками.

В четверг, 20 октября, один из ключевых разработчиков ядра Linux Грег Кроа-Хартман (Greg Kroah-Hartman) сообщил о выходе обновлений для версий Linux 4.8, 4.7 и 4.4 LTS, исправляющих уязвимость Dirty COW.

Уязвимость вызвана состоянием гонки при обработке copy-on-write (COW) операций в подсистеме управления памятью и позволяет нарушить работу маппинга памяти в режиме только для чтения. С практической стороны, проблема позволяет осуществить запись в области памяти, отражённые в режиме только для чтения. Например, в прототипе эксплоита показано как использовать данную проблему для изменения содержимого файла, принадлежащего пользователю root и доступного только на чтение. В том числе, при помощи предложенного метода атаки непривилегированный злоумышленник может изменить исполняемые системные файлы, обойдя штатные механизмы управления доступом.

 $ sudo -s
   # echo this is not a test > foo
   # chmod 0404 foo
   $ ls -lah foo
   -r-----r-- 1 root root 19 Oct 20 15:23 foo
   $ cat foo
   this is not a test

   $ gcc -lpthread dirtyc0w.c -o dirtyc0w
   $ ./dirtyc0w foo m00000000000000000
   mmap 56123000
   madvise 0
   procselfmem 1800000000

   $ cat foo
   m00000000000000000

Для проверки уязвимости доступен Proof-of-Concept эксплоит: клик.

UPD: по просьбе в комментариях — инструкция по обновлению.
Поделиться с друзьями
-->

Комментарии (51)


  1. nikitasius
    21.10.2016 13:17
    -7

    Был 11 лет и никому дела не было… как работало, так и будет работать. Да и область бага как бы ограниченная.


    1. Pinsky
      21.10.2016 13:48
      +1

      но вполне себе опасный момент


      1. nikitasius
        22.10.2016 20:47
        -3

        Таких опасных моментов вагон и маленькая тележка.
        Веб серверу — насрать.
        Файлопомойке — насрать.
        Игровым серверам/серверам стримминга — насрать.

        Вообще всему вебсегменту, где зверьки в клетках и не могут запускать программы вне белого списка — насрать.

        Проболема носит чисто ДОМАШНИЙ характер, то есть та система, где админ юзер сидит и все ставит и ставит и ставит в систему рандомное говно.

        Ей богу развели панику.


    1. AVX
      21.10.2016 13:51
      +4

      Ничего себе ограниченная область! Если можно изменить файл, доступный только root — это всё, компьютер уже не Ваш. Такую штуку обернуть в скрипт, обфусцировать, и впаривать в виде решения какой-то распространённой проблемы под линуксом — и спокойно можно поиметь кучу домашних компов под линуксом в своё распоряжение. Остаётся придумать, как заставить пользователя сделать файл исполняемым (без этого он не запустится).

      Интересно, поможет ли от этого флаг -i (immutable)? Ведь с этим флагом даже рут не может редактировать файл, пока не снимет атрибут. Правда, на raiserfs нет поддержки его (разок попалось).


      1. Saffron
        21.10.2016 15:20
        +8

        > Остаётся придумать, как заставить пользователя сделать файл исполняемым (без этого он не запустится).

        curl | sh

        Я серьёзно, многие сайты предлагают так устанавливать софт.


      1. SironyCh
        21.10.2016 15:22

        Атрибут immutable не канает:
        $ cat foo
        I do it every day!
        $ lsattr foo
        ----i----------- foo
        $ ./dirtyc0w foo «I do what I want!»
        mmap 14922000

        madvise 0

        procselfmem 1700000000
        $ cat foo
        I do what I want!!!


  1. mwizard
    21.10.2016 13:20
    +18

    С другой стороны, владельцы разнообразных залоченных устройств возрадовались возможности наконец-то их рутануть.


    1. xRay
      21.10.2016 14:42
      +5

      Тот случай, когда баг принесет пользу :)


      1. Hikko
        21.10.2016 17:47

        «Это не баг, это фича» (с)

        В таком случаи — да :)


    1. boris768
      21.10.2016 21:58

      На Xperia XA (Linux 3.18.22, 64 битный, SELinux включен) не сработало — телефон перезагрузился, результат выполнения отрицательный. Скомпилировал эксплоит C4Droid`ом, создал файл с правами 0404, натравил бинарник в терминале adb, но телефон ушел в ребут, а содержимое файла осталось прежним. Сразу скажу, что рут права есть на телефоне, но мне было интересно попробовать. Если кто знающий увидит в моих действиях ошибку — подскажите


  1. Tatikoma
    21.10.2016 14:00
    -1

    Linux Mint 17.3 — PoC сработал.

    При компиляции пришлось немного поколдовать (я ни разу не разбираюсь в C).

    dirtyc0w.c:96:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘void *’ [-Wformat=]
       printf("mmap %x\n\n",map);

    Тут я просто убрал printf под комментарий, как не самый важный функционал.

    $ gcc -lpthread dirtyc0w.c -o dirtyc0w
    /tmp/ccJWttLa.o: In function `main':
    dirtyc0w.c:(.text+0x1c3): undefined reference to `pthread_create'

    Скомпилировал вот так: gcc -pthread dirtyc0w.c -o dirtyc0w

    После запуска PoC завис, однако файл был успешно перезаписан.


    1. roman_kashitsyn
      21.10.2016 14:16
      +8

      Директива у printf должна быть p, а не x. Опять кто-то перепутал указатель и число.


      - printf("mmap %x\n\n",map);
      + printf("mmap %p\n\n",map);


    1. aragaer
      21.10.2016 15:31
      +1

      Про printf просто предупреждение, можно игнорировать. Ошибка в -lpthread — его надо либо убрать в конец, либо заменить на -pthread.

      Сработало в убунте 16.04


      1. SironyCh
        21.10.2016 16:41

        В debian 8.4 — без проблем: gcc -lpthread dirtyc0w.c -o dirtyc0w


        1. roman_kashitsyn
          21.10.2016 16:50
          +5

          Обычно флага линкера -lpthread недостаточно для корректной компиляции. -pthread не только линкует libpthread, он ещё и выставляет макрос _REENTRANT, который используется в заголовках libc и меняет поведение стандартной библиотеки (переменная errno становится thread_local переменной, к примеру).
          Т.е. программа скомпилируется, но может работать неправильно.


        1. Tatikoma
          21.10.2016 17:14

          В Debian 8.5 аналогично не вызвало проблем. И тоже сработало, так же зависло, но перезаписало.


  1. Konachan700
    21.10.2016 14:08
    +2

    Интересно, как такие неочевидные вещи вообще находят?


    1. roman_kashitsyn
      21.10.2016 14:11
      +17

      Методом пристального взгляда.


    1. solver
      21.10.2016 15:41
      +4

      Это со стороны они не очевидны.
      Но если знаешь как работают эти механизмы, то начинаешь анализировать и всячески ковырять опасные участки. Да, это не «раз два и готово», работа часто нудная. Для этого пишут различные тулзы автоматизирующие этот процес. Тут все зависит от того, на сколько ты хорошо знаешь как работает этот участок. Ну и еще немного везения)


    1. Am0ralist
      21.10.2016 16:23
      +10

      Когда я занимался постоянным тестированием одной проги для разработки мебели перед тем, как внедрять ее обновления на производство, то я места поиска ошибок в программе понимал еще только читая релиз разрабов: что они добавили и что исправили. Просто исходя из опыта того, как их программисты любят делать и понимания нюансов системы. Самое эпичное было, когда я однотипную ошибку в третий раз нашел именно по принципу, что новый функционал был основан на старом, а в старом они уже дважды так косячили и исправляли.

      Чем больше понимания работы того или иного механизма в системе и опыта по нахождению косяков программистов, тем больше «чуйка» срабатывает на слабые места. Опять же, уязвимость вроде как эксплуатировали и человек мог целенаправленно искать в нужном направлении.


  1. Pilat
    21.10.2016 15:39

    Интересно, в Windows 10 проблема присутствует?


    1. vaut
      21.10.2016 15:51
      +3

      А откуда?
      Там не ядро линуха, а wine наоборот. Прослойка которая системные вызовы приложений транслирует.


      1. icoz
        22.10.2016 12:18

        Серьёзно? А можно пруф-линк в студию?


        1. icoz
          22.10.2016 12:24

          1. Zverienish
            22.10.2016 12:49

            Не написано там, что ядро линукс внедряют. А всего лишь подсистему линукс в виндоус.


            1. icoz
              22.10.2016 14:55

              Там написано:

              На слайде указано, что речь идет именно о полноценной подсистеме Linux, а не о псевдо-эмуляции или виртуальных машинах. Да, Linux становится частью Windows 10 и так же как POSIX и OS/2 будет работать в пользовательском режиме с реализацией семантики системных вызовов на уровне ядра.

              Так что никакого «wine наоборот», как указали здесь выше. Поэтому и запросил пруф.


              1. Saffron
                22.10.2016 15:59

                А чем UML отличается от «wine наоборот»? Тем что линукс открыт и не приходится переписывать тонну кода и угадывать недокументированные API?


              1. vaut
                22.10.2016 22:20

                Я немного слукавил, wine работает в пространстве пользователя и работает поверх системных вызовов, а в десятке транслятор это модуль самого ядра.
                Так что формально я не прав.


                1. sumanai
                  22.10.2016 23:13

                  а в десятке транслятор это модуль самого ядра.

                  Вроде как подсистема над ядром, на одном уровне с Win32.


                1. icoz
                  23.10.2016 00:08

                  Спасибо.


        1. a5b
          24.10.2016 08:39
          +1

          Реализован собственный драйвер, реализующий часть системных вызовов, используемых приложениями. Также реализован ряд концепций, необходимых для совместимости с POSIX: VFS с инодами и правами, pipe, и т.п. А также ряд новых потенциальных уязвимостей. При желании можно поизучать содержимое lxss.sys / lxcore.sys и/или почитать подробные логи использования подсистемы (инструкции есть в https://github.com/Microsoft/BashOnWindows/blob/master/CONTRIBUTING.md)


          Пруф: BlackHat 2016, ALEX IONESCU (Co-author of Windows Internals 5th and 6th Editions), доклад "THE LINUX KERNEL HIDDEN INSIDE WINDOWS 10"
          https://github.com/ionescu007/lxss/blob/master/The%20Linux%20kernel%20hidden%20inside%20windows%2010.pdf


          WSL COMPONENT OVERVIEW: Pico Provider driver (LXSS.SYS / LXCORE.SYS) which provides the kernel-mode implementation of a Linux-compatible Kernel ABI and API… implements a virtual file system (VFS) interface, including a device inode
          LXCORE.SYS is the large (800KB) kernel-mode Ring 0 driver which implements all the functionality that a Linux application inside of a Pico process will see
          • In some cases, functionality is implemented from scratch (such as pipes)
          • In other cases, functionality is wrapped on top of an existing NT kernel mechanism or subsystem (scheduling)
          • In yet other cases, functionality is heavily built on top of an existing NT kernel primitive, with some from-scratch functionality
          SYSTEM CALLS… 216 implemented as of the release build…
          VFS / FILE SYSTEM Implements a “VolFs” system, which is the Linux-facing file system with support for UNIX rights, etc.
          Provides emulation/wrapping/actual implementation for various virtual file system concepts:
          • ProcFs mostly works (calls kernel query APIs as needed) or just already has the data
          • TmpFs also exists and implements various devices, including the Binder (key Android IPC from the BeOS days)
          • SysFs is there, etc…

          В https://github.com/ionescu007/lxss есть различные экспериментальные утилиты по работе с WSL.


          Еще линк от авторов WSL и сотрудников MS — https://github.com/benhillishttps://github.com/Microsoft/BashOnWindows/issues/178#issuecomment-249443216


          Lxcore.sys is a clean room implementation of the Linux kernel ABI. It contains no code from the Linux kernel and we have a policy that our developers cannot even look at any of the kernel source.

          https://github.com/bitcrazedhttp://bitcrazed.com/about/https://github.com/Microsoft/BashOnWindows/issues/107#issuecomment-209147763


          The Windows Subsystem for Linux (WSL) doesn't modify or derive any GPL code: It runs native, unmodified ELF binaries by loading them into a lightweight process created by the Windows Kernel, binding the ELF binary's imports to our syscall implementation and then executing as normal. Bash.exe is a simple Windows app that binds a console (i.e. terminal) window to a process that loads and runs the native /bin/bash from the Ubuntu… It was named Bash.exe as a convenience since, in end-user testing, most users expected bash to

          Посты от разработчиков WSL про системные вызовы и подсистемы и их трансляцию в запросы к NT ядру — https://blogs.msdn.microsoft.com/wsl/2016/04/22/windows-subsystem-for-linux-overview/ https://blogs.msdn.microsoft.com/wsl/2016/06/08/wsl-system-calls/


  1. nvv
    21.10.2016 16:25

    Статические анализаторы кода, видимо, не особо помогают в выявлении таких ошибок?


    1. khim
      21.10.2016 19:25

      Статические — нет. Вот динамические (типа ASAN/TSAN) — могут поймать… а могут и не поймать, там нет детерминизма, увы.


    1. bobafett1337
      22.10.2016 12:01

      На самом деле статический анализатор кода может указать на подобную уязвимость. Не понятно как давно эксплуатируется баг, думаю можно самостоятельно устроить проверку каким-нибудь Coverity


  1. u1d
    21.10.2016 17:28
    +3

    А из OpenVZ контейнера с помощью этой Dirty COW можно выскочить?


    1. kamtec1
      22.10.2016 12:01

      Хороший вопрос. Я лично думаю что нет… Жаль что сейчас протестировать не могу, но если да то OpenVZ/Virtuozzo скажут :)


  1. istui
    21.10.2016 17:29

    Несет ли опасность уязвимость для веб-серверов, или для этого необходимо иметь возможность запустить исполняемый файл на машине?


    1. SkidanovAlex
      21.10.2016 20:02
      +5

      На сервере может гоняться какое-то ПО, которое в свою очередь имеет уязвимости, позволяющие закинуть файл и запустить, так что лучше патч накатить все равно.


  1. rad1us
    21.10.2016 17:47
    +1

    Есть инструкция для непрограммистов, как пофиксить это уязвимость?


    1. istui
      21.10.2016 17:57
      +4

      yum update (RHEL/CentOS) или sudo apt-get upgrade (Debian/Ubuntu)


    1. LukaSafonov
      21.10.2016 18:14
      +7

      Сделал апдейт к посту.


  1. navion
    21.10.2016 18:03

    Прошли почти сутки, а патча для RHEL 6 всё ещё нет. Для RHEL 7 и Ubuntu 16.04 прилетели какие-то обновления ядра.


    1. knutov
      22.10.2016 02:32

      в интернетах пишут, что на RHEL 6 уязвимость не работает, хотя формально и есть.


    1. smb_z
      22.10.2016 12:01
      +1

      В коде эксплоита такой комментарий:
      > The in the wild exploit we are aware of doesn't work on Red Hat
      > Enterprise Linux 5 and 6 out of the box because on one side of
      > the race it writes to /proc/self/mem, but /proc/self/mem is not
      > writable on Red Hat Enterprise Linux 5 and 6.


      1. DarkByte
        22.10.2016 17:28

        Стоит отметить, что этот комментарий относится к конкретной реализации сплоита. Вот тут можно найти несколько вариантов, в том числе тот, который не используется /proc/self/mem.


  1. msatersam11
    21.10.2016 21:58
    +2

    «Исходники в свободном доступе же! Над ними долго и упорно работает столько народу, что там попросту не может быть сколь-нибудь серьёзных уязвимостей — это же не дырявая венда»

    Почему-то вспомнилось. К чему бы это…


    1. DenMMM
      22.10.2016 15:08
      +5

      В Windows уязвимости специально по заказу АНБ, а в Линухе «по-недосмотру». ;)


  1. semibiotic
    21.10.2016 21:58

    Судя по всему, вот патч:
    https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619


  1. Cheater
    21.10.2016 23:28

    Одно хорошо — на Linux машинах, на которые гарантированно логинятся только не-злоумышленники (например, на личных и домашних ПК), эту уязвимость можно эксплуатировать только если спровоцировать пользователя запустить левый бинарник/скрипт, от чего, надеюсь, большинство отучено.

    (Я, правда, не учитываю системные аккаунты вида apache, ftp и т.д.)


    1. technic93
      22.10.2016 12:02

      1. на личных машинах для злоумышлеников интересней папка /home
      2. ну а если каким то образом через уязвимсоть в других программах удается выполнять код из под юзера то повысить права до рута через эту уязвимость уже как бонус будет.


    1. Am0ralist
      22.10.2016 13:58
      +1

      под винду, знаете ли, то же большая часть локеров запускалась пользователем, которые еще и уак игнорировали.
      пользователи — это главная проблема безопасности…