Stack Clash – серьёзная уязвимость с 12ти летним опытом

Уязвимость The Stack Clash - разбираем и изучаем

19 июня опубликована информация по группе уязвимостей Stack Clash – основной уязвимости на “столкновение сегмента стека с другим сегментом” CVE-2017-1000364 и нескольким дополнительным – CVE-2017-1000365 kernel: RLIMIT_STACK/RLIMIT_INFINITY string size limitation bypass, и прочими “дырками” в kernel, glibc и даже sudo.

В чём дело

В 2005 году Gaël Delalleau показывает наличие уязвимости в управлении памятью в linux 2.6 и ряде других unix-based ОС (FreeBSD, OpenBSD – не удаётся эксплуатировать разве что в Solaris 9/10). Дело в отсутствии защиты от stack gap – которая [защита] присутствует в Windows NT уже давно, поэтому такой трюк не проходит даже на Windows XP SP1, вызывая 0xC0000005.

В качестве временного костыля предлагается всё, собранное с gcc, пересобирать с -fstack-check, что с возмущением воспринимается “опенсорсной общественностью”, ведь “всё ж тормозить будет, и целый нулевой байт на каждую страницу в 4К тратится”.

Несмотря на работоспособные PoC, все забивают и проблема тянется до августа 2010 года, когда Rafal Wojtczuk обнаруживает очередной способ эксплуатации данной уязвимости.

У Microsoft в это время уже есть не только защита от таких атак, но целая гибкая система управления для предотвращения подобных классов атак – доступный бесплатно EMET, про которого есть целый цикл статей на нашей Knowledge Base.

Становится понятно, что с уязвимостью надо что-то делать, потому что уязвимы все системы на базе linux и атакующий может не вызывая segmentation fault записывать в чужие регионы памяти произвольные данные.

Выпускается заплатка и ситуация на время затихает. Ну, что такого – 6 лет можно было ломать линукс-системы – это ещё не рекорд по забиванию на исправление дырок в ядре, в линуксе и подольше бывало. Ответственных же нет, есть же “полупрозрачное огромное коммьюнити супер-экспертов, которые постоянно идеально пишут код, а любую ошибку молниеносно видят миллионы глаз и сразу исправляют, ведь если у миллионов глаз есть теоретическая возможность что-то увидеть, то они это обязательно увидят, обязательно изучат, обязательно разберутся и обязательно исправят”, а значит делать ничего не надо, надо просто подождать да скачать готовенькое. Что ж, подождали и скачали – 6 лет прошло, экая ерунда.

Новая серия начинается 19 июня 2017 года. Выясняется, что патч-то уязвимость недозакрывал и эксплуатировать её всё это время было возможно – просто чуть иначе, “перепрыгнув” stack guard page и получив доступ к чужой памяти (обычно это “куча”), не вызвав при этом ошибки. Добавление -fstack-check, таким образом, решало проблему только частично. Исправления на данный момент нет.

Что делать?

Ждать патчей, которые опять “в принципе поправят”, но т.к. это будет уже третий раз, то относиться к этому можно изначально с некоторым подозрением.

Снизить вероятность атаки можно, увеличив размер stack guard от одной страницы (4 КБ, например) до 1 МБ, что сделает использование уязвимости более сложным (но не уберёт возможность целиком).

Также возможны манипуляции с ограничением выделения памяти при обработке LD_AUDIT, LD_HWCAP_MASK и LD_PRELOAD, но они будут привязаны к используемому ПО и конкретной системе, поэтому какие-либо числа назвать затруднительно.

Какие масштабы?

Судя по краткому списку PoC, всё очень весело:

To illustrate our findings, we developed the following exploits and proofs-of-concepts:

– a local-root exploit against Exim (CVE-2017-1000369, CVE-2017-1000376) on i386 Debian;

– a local-root exploit against Sudo (CVE-2017-1000367, CVE-2017-1000366) on i386 Debian, Ubuntu, CentOS;

– an independent Sudoer-to-root exploit against CVE-2017-1000367 on any SELinux-enabled distribution;

– a local-root exploit against ld.so and most SUID-root binaries (CVE-2017-1000366, CVE-2017-1000370) on i386 Debian, Fedora, CentOS;

– a local-root exploit against ld.so and most SUID-root PIEs (CVE-2017-1000366, CVE-2017-1000371) on i386 Debian, Ubuntu, Fedora;

– a local-root exploit against /bin/su (CVE-2017-1000366, CVE-2017-1000365) on i386 Debian;

– a proof-of-concept that gains eip control against Sudo on i386 grsecurity/PaX (CVE-2017-1000367, CVE-2017-1000366, CVE-2017-1000377);

– a local proof-of-concept that gains rip control against Exim (CVE-2017-1000369) on amd64 Debian;

– a local-root exploit against ld.so and most SUID-root binaries (CVE-2017-1000366, CVE-2017-1000379) on amd64 Debian, Ubuntu, Fedora, CentOS;

– a proof-of-concept against /usr/bin/at on i386 OpenBSD, for CVE-2017-1000372 in OpenBSD’s stack guard-page implementation and CVE-2017-1000373 in OpenBSD’s qsort() function;

– a proof-of-concept for CVE-2017-1000374 and CVE-2017-1000375 in NetBSD’s stack guard-page implementation;

– a proof-of-concept for CVE-2017-1085 in FreeBSD’s setrlimit() RLIMIT_STACK implementation;

– two proofs-of-concept for CVE-2017-1083 and CVE-2017-1084 in FreeBSD’s stack guard-page implementation;

– a local-root exploit against /usr/bin/rsh (CVE-2017-3630, CVE-2017-3629, CVE-2017-3631) on Solaris 11.

Говоря проще, любое приложение на уязвимой системе может получить локального рута.

Размышления

Плохо, когда в середине 2017го года, в позиционируемой как “безопасная серверная ОС” живут ошибки 12ти летней давности, делающие возможными такие уязвимости, которые невозможны (в силу дизайна ОС) в настольной Windows XP с первым сервис-паком.

Ещё хуже, когда эту ошибку “абы как” исправляли дважды, но не исправили.

Показательна и история с “родословной” данной уязвимости. По всей видимости ошибка, допущенная изначально в SUN’овской операционке, была слепо скопирована вместе с кодом управления памятью везде, где только можно – и в BSD системы, и в linux. Несмотря на сказки о “экспертном сообществе, которое, благодаря открытости, постоянно вычитывает код, и ни одна ошибка не проскользнёт”, несмотря на двукратное напоминание о данной проблеме – в 2005 и в 2010 году – всё обходилось подходом “да вроде и так сойдёт”, либо созданием откровенных костылей типа “надо на уровне системы ограничить ресурсы жёстко” или “надо пересобрать со специальными ключами”.

Так как первый вариант с ограничением требовал интеллектуальных усилий по точному подбору значений RLIMIT_STACK / RLIMIT_AS, а второй требовал пересборки и мог приводить к потенциальному падению производительности (крохотному, но всё же), то экспертное сообщество решило просто забить на это. Сколько систем было взломано за эти 12 лет – неизвестно.

Полупрозрачные СПО-эксперты, имеющие теоретический доступ к исходным кодам, и теоретическую возможность всё исправить и написать в сто раз лучше самостоятельно, в очередной раз наглядно показывают унылый результат одного из самых громких провалов в IT-отрасли – концепции

Открытость и свободность* автоматически приводят к улучшению качества кода и появлению более безопасного, более технологичного и более надёжного ПО.

Результат этот состоит в том, что появление возможности “дайте списать” приводит лишь к снижению активности по разработке чего-то своего, а аудит чужого кода – не то чтобы до уровня “могу доработать”, а хотя бы до “понятно, что оно и зачем делает” становится возможностью всё меньшего процента участников – ведь остальные только и умеют, что копипастить чужое с аргументом “оно же открытое, а значит внутри там всё уже проверено и надёжно”.

12 лет – это очень и очень много. Ну, иногда- вполне норм:

но для уязвимости – всё ж перебор.

Возможно, вам будет также интересно почитать эти статьи с нашей Knowledge Base

Ruslan V. Karmanov