В ядре 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)
mwizard
21.10.2016 13:20+18С другой стороны, владельцы разнообразных залоченных устройств возрадовались возможности наконец-то их рутануть.
boris768
21.10.2016 21:58На Xperia XA (Linux 3.18.22, 64 битный, SELinux включен) не сработало — телефон перезагрузился, результат выполнения отрицательный. Скомпилировал эксплоит C4Droid`ом, создал файл с правами 0404, натравил бинарник в терминале adb, но телефон ушел в ребут, а содержимое файла осталось прежним. Сразу скажу, что рут права есть на телефоне, но мне было интересно попробовать. Если кто знающий увидит в моих действиях ошибку — подскажите
Tatikoma
21.10.2016 14:00-1Linux 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 завис, однако файл был успешно перезаписан.roman_kashitsyn
21.10.2016 14:16+8Директива у printf должна быть p, а не x. Опять кто-то перепутал указатель и число.
- printf("mmap %x\n\n",map); + printf("mmap %p\n\n",map);
aragaer
21.10.2016 15:31+1Про printf просто предупреждение, можно игнорировать. Ошибка в -lpthread — его надо либо убрать в конец, либо заменить на -pthread.
Сработало в убунте 16.04SironyCh
21.10.2016 16:41В debian 8.4 — без проблем: gcc -lpthread dirtyc0w.c -o dirtyc0w
roman_kashitsyn
21.10.2016 16:50+5Обычно флага линкера
-lpthread
недостаточно для корректной компиляции.-pthread
не только линкуетlibpthread
, он ещё и выставляет макрос_REENTRANT
, который используется в заголовках libc и меняет поведение стандартной библиотеки (переменнаяerrno
становится thread_local переменной, к примеру).
Т.е. программа скомпилируется, но может работать неправильно.
Tatikoma
21.10.2016 17:14В Debian 8.5 аналогично не вызвало проблем. И тоже сработало, так же зависло, но перезаписало.
Konachan700
21.10.2016 14:08+2Интересно, как такие неочевидные вещи вообще находят?
solver
21.10.2016 15:41+4Это со стороны они не очевидны.
Но если знаешь как работают эти механизмы, то начинаешь анализировать и всячески ковырять опасные участки. Да, это не «раз два и готово», работа часто нудная. Для этого пишут различные тулзы автоматизирующие этот процес. Тут все зависит от того, на сколько ты хорошо знаешь как работает этот участок. Ну и еще немного везения)
Am0ralist
21.10.2016 16:23+10Когда я занимался постоянным тестированием одной проги для разработки мебели перед тем, как внедрять ее обновления на производство, то я места поиска ошибок в программе понимал еще только читая релиз разрабов: что они добавили и что исправили. Просто исходя из опыта того, как их программисты любят делать и понимания нюансов системы. Самое эпичное было, когда я однотипную ошибку в третий раз нашел именно по принципу, что новый функционал был основан на старом, а в старом они уже дважды так косячили и исправляли.
Чем больше понимания работы того или иного механизма в системе и опыта по нахождению косяков программистов, тем больше «чуйка» срабатывает на слабые места. Опять же, уязвимость вроде как эксплуатировали и человек мог целенаправленно искать в нужном направлении.
Pilat
21.10.2016 15:39Интересно, в Windows 10 проблема присутствует?
vaut
21.10.2016 15:51+3А откуда?
Там не ядро линуха, а wine наоборот. Прослойка которая системные вызовы приложений транслирует.icoz
22.10.2016 12:18Серьёзно? А можно пруф-линк в студию?
icoz
22.10.2016 12:24Zverienish
22.10.2016 12:49Не написано там, что ядро линукс внедряют. А всего лишь подсистему линукс в виндоус.
icoz
22.10.2016 14:55Там написано:
На слайде указано, что речь идет именно о полноценной подсистеме Linux, а не о псевдо-эмуляции или виртуальных машинах. Да, Linux становится частью Windows 10 и так же как POSIX и OS/2 будет работать в пользовательском режиме с реализацией семантики системных вызовов на уровне ядра.
Так что никакого «wine наоборот», как указали здесь выше. Поэтому и запросил пруф.Saffron
22.10.2016 15:59А чем UML отличается от «wine наоборот»? Тем что линукс открыт и не приходится переписывать тонну кода и угадывать недокументированные API?
vaut
22.10.2016 22:20Я немного слукавил, wine работает в пространстве пользователя и работает поверх системных вызовов, а в десятке транслятор это модуль самого ядра.
Так что формально я не прав.sumanai
22.10.2016 23:13а в десятке транслятор это модуль самого ядра.
Вроде как подсистема над ядром, на одном уровне с Win32.
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/benhillis — https://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/bitcrazed — http://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/
nvv
21.10.2016 16:25Статические анализаторы кода, видимо, не особо помогают в выявлении таких ошибок?
bobafett1337
22.10.2016 12:01На самом деле статический анализатор кода может указать на подобную уязвимость. Не понятно как давно эксплуатируется баг, думаю можно самостоятельно устроить проверку каким-нибудь Coverity
istui
21.10.2016 17:29Несет ли опасность уязвимость для веб-серверов, или для этого необходимо иметь возможность запустить исполняемый файл на машине?
SkidanovAlex
21.10.2016 20:02+5На сервере может гоняться какое-то ПО, которое в свою очередь имеет уязвимости, позволяющие закинуть файл и запустить, так что лучше патч накатить все равно.
navion
21.10.2016 18:03Прошли почти сутки, а патча для RHEL 6 всё ещё нет. Для RHEL 7 и Ubuntu 16.04 прилетели какие-то обновления ядра.
knutov
22.10.2016 02:32в интернетах пишут, что на RHEL 6 уязвимость не работает, хотя формально и есть.
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.
msatersam11
21.10.2016 21:58+2«Исходники в свободном доступе же! Над ними долго и упорно работает столько народу, что там попросту не может быть сколь-нибудь серьёзных уязвимостей — это же не дырявая венда»
Почему-то вспомнилось. К чему бы это…DenMMM
22.10.2016 15:08+5В Windows уязвимости специально по заказу АНБ, а в Линухе «по-недосмотру». ;)
semibiotic
21.10.2016 21:58Судя по всему, вот патч:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619
Cheater
21.10.2016 23:28Одно хорошо — на Linux машинах, на которые гарантированно логинятся только не-злоумышленники (например, на личных и домашних ПК), эту уязвимость можно эксплуатировать только если спровоцировать пользователя запустить левый бинарник/скрипт, от чего, надеюсь, большинство отучено.
(Я, правда, не учитываю системные аккаунты вида apache, ftp и т.д.)technic93
22.10.2016 12:021. на личных машинах для злоумышлеников интересней папка /home
2. ну а если каким то образом через уязвимсоть в других программах удается выполнять код из под юзера то повысить права до рута через эту уязвимость уже как бонус будет.
Am0ralist
22.10.2016 13:58+1под винду, знаете ли, то же большая часть локеров запускалась пользователем, которые еще и уак игнорировали.
пользователи — это главная проблема безопасности…
nikitasius
Был 11 лет и никому дела не было… как работало, так и будет работать. Да и область бага как бы ограниченная.
Pinsky
но вполне себе опасный момент
nikitasius
Таких опасных моментов вагон и маленькая тележка.
Веб серверу — насрать.
Файлопомойке — насрать.
Игровым серверам/серверам стримминга — насрать.
Вообще всему вебсегменту, где зверьки в клетках и не могут запускать программы вне белого списка — насрать.
Проболема носит чисто ДОМАШНИЙ характер, то есть та система, где админ юзер сидит и все ставит и ставит и ставит в систему рандомное говно.
Ей богу развели панику.
AVX
Ничего себе ограниченная область! Если можно изменить файл, доступный только root — это всё, компьютер уже не Ваш. Такую штуку обернуть в скрипт, обфусцировать, и впаривать в виде решения какой-то распространённой проблемы под линуксом — и спокойно можно поиметь кучу домашних компов под линуксом в своё распоряжение. Остаётся придумать, как заставить пользователя сделать файл исполняемым (без этого он не запустится).
Интересно, поможет ли от этого флаг -i (immutable)? Ведь с этим флагом даже рут не может редактировать файл, пока не снимет атрибут. Правда, на raiserfs нет поддержки его (разок попалось).
Saffron
> Остаётся придумать, как заставить пользователя сделать файл исполняемым (без этого он не запустится).
curl | sh
Я серьёзно, многие сайты предлагают так устанавливать софт.
SironyCh
Атрибут 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!!!