В beep — стороннем модуле Linux — обнаружена уязвимость, позволяющая запускать побочные эффекты файлов и просматривать их типы, не имея на то соответствующих прав. Расскажем, в чем суть проблемы и как варианты её решения предложило ИТ-сообщество.
/ Flickr / Chris / CC
Модуль beep формирует звуковые оповещения об ошибках, возникающих при работе в командной строке и в целом позволяет управлять «бипером» ПК. Утилиту создал разработчик Джонатан Найтингейл (Johnathan Nightingale), который хотел получить больше возможностей при работе с консолью, чем позволяла обычная команда printf("\a").
Первые новости появились на сайте holeybeep.ninja, который описывает уязвимость в сатирической манере. В The Register полагают, что эта веб-страница — попытка высмеять тех, кто популяризирует баги и создает для них отдельные сайты. Уже позже начали появляться официальные отчеты об ошибках.
В отчете, опубликованном Debian, отмечено, что Beep выдает сведения о наличии любого файла, даже если он должен быть скрыт от пользователя, который сделал запрос.
При этом система выдает информацию о типе файла, даже если у запрашивающего пользователя нет на это прав (например, сокет может выдать сообщение: «No such device or address»). Этого не должно происходить, если файл лежит в директории, недоступной вызывающему пользователю. Кроме того, с помощью уязвимости злоумышленники могут запускать побочные эффекты и блокировать запуск произвольных программ. Например, запуск beep -s -e /bin/sh приведет к ошибке ETXTBSY («Текстовый файл занят»), что можно назвать DoS-атакой.
Как отмечают пользователи GitHub, причина уязвимости связана с возникновением гонок при использовании обработчиками сигнала функции free(). Эта функция не входит в список async-signal-safe, то есть не может быть безопасно вызвана внутри обработчика. Работа free() может прерваться другим сигналом, что вызывает нарушение структур данных и глобальных переменных управления кучей.
Резидент GitHub отмечает, что в последней версии beep.c один обработчик работает сразу с двумя сигналами (SIGINT и SIGTERM). Это позволяет повторно запускать handle_signal () несколько раз подряд, что приводит к двойному высвобождению памяти.
/ Flickr / Tomas Fano / CC
Чтобы устранить уязвимость, разработчики некоторых операционных систем (например, Ubuntu) выпустили фикс. Однако, по мнению сообщества, он адресует не все трудности, связанные с Beep. Как отмечают в обсуждении на GitHub, он решает ситуацию с гонками, но проблемы с раскрытием данных остаются.
По этим причинам, в качестве кардинального решения проблемы, исследователь Ханно Бок (Hanno Bock) предлагает перестать устанавливать Beep как suid. Он также отметил, что модуль Beep в принципе не нужен современным устройствам, так как биперы стоят не во всех компьютерах. В качестве замены Ханно Бок предлагает вернутся к простой и безопасной команде printf("\a"), как это сделали разработчики дистрибутива SUSE.
/ Flickr / Chris / CC
Что делает Beep
Модуль beep формирует звуковые оповещения об ошибках, возникающих при работе в командной строке и в целом позволяет управлять «бипером» ПК. Утилиту создал разработчик Джонатан Найтингейл (Johnathan Nightingale), который хотел получить больше возможностей при работе с консолью, чем позволяла обычная команда printf("\a").
Суть уязвимости
Первые новости появились на сайте holeybeep.ninja, который описывает уязвимость в сатирической манере. В The Register полагают, что эта веб-страница — попытка высмеять тех, кто популяризирует баги и создает для них отдельные сайты. Уже позже начали появляться официальные отчеты об ошибках.
В отчете, опубликованном Debian, отмечено, что Beep выдает сведения о наличии любого файла, даже если он должен быть скрыт от пользователя, который сделал запрос.
$ ls -ld /etc/hidden/
drwx------ 2 root root 4096 Apr 7 08:18 /etc/hidden/
$ ls -l /etc/hidden/secret
ls: cannot access '/etc/hidden/secret': Permission denied
$ ls -l /etc/hidden/nonexistent
ls: cannot access '/etc/hidden/nonexistent': Permission denied
$ beep -e /etc/hidden/secret
ioctl: Inappropriate ioctl for device
ioctl: Inappropriate ioctl for device
$ beep -e /etc/hidden/nonexistent
Could not open /etc/hidden/nonexistent for writing
open: No such file or directory
При этом система выдает информацию о типе файла, даже если у запрашивающего пользователя нет на это прав (например, сокет может выдать сообщение: «No such device or address»). Этого не должно происходить, если файл лежит в директории, недоступной вызывающему пользователю. Кроме того, с помощью уязвимости злоумышленники могут запускать побочные эффекты и блокировать запуск произвольных программ. Например, запуск beep -s -e /bin/sh приведет к ошибке ETXTBSY («Текстовый файл занят»), что можно назвать DoS-атакой.
Как отмечают пользователи GitHub, причина уязвимости связана с возникновением гонок при использовании обработчиками сигнала функции free(). Эта функция не входит в список async-signal-safe, то есть не может быть безопасно вызвана внутри обработчика. Работа free() может прерваться другим сигналом, что вызывает нарушение структур данных и глобальных переменных управления кучей.
Резидент GitHub отмечает, что в последней версии beep.c один обработчик работает сразу с двумя сигналами (SIGINT и SIGTERM). Это позволяет повторно запускать handle_signal () несколько раз подряд, что приводит к двойному высвобождению памяти.
/ Flickr / Tomas Fano / CC
Патчи и решение проблемы
Чтобы устранить уязвимость, разработчики некоторых операционных систем (например, Ubuntu) выпустили фикс. Однако, по мнению сообщества, он адресует не все трудности, связанные с Beep. Как отмечают в обсуждении на GitHub, он решает ситуацию с гонками, но проблемы с раскрытием данных остаются.
По этим причинам, в качестве кардинального решения проблемы, исследователь Ханно Бок (Hanno Bock) предлагает перестать устанавливать Beep как suid. Он также отметил, что модуль Beep в принципе не нужен современным устройствам, так как биперы стоят не во всех компьютерах. В качестве замены Ханно Бок предлагает вернутся к простой и безопасной команде printf("\a"), как это сделали разработчики дистрибутива SUSE.
Материалы по теме из корпоративного блога 1cloud:
Комментарии (16)
KennyGin
12.04.2018 21:15+2Еще раз повторю свой комментарий:
И ещё раз словите минусы, потому что слишком топорно набрасываете
Давно очевидно что на c/c++ невозможно написать софт без уязвимость
Программа beep написана на чистом C, зачем вы притягиваете C++, причём тут он вообще?
Но раз уж притянули: на современном C++ в прикладном коде использование сырых new и delete можно свести к минимуму. Побибикать динамиком — это как раз прикладуха, здесь жонглирование указателями и голой памятью в стиле C неоправдано. Так что переписывание на C++ даст точно такой же эффект, как и переписывание на Rust.
Жду комментариев, что просто программисты google, Microsoft, apple и другие не захотели написать хороший софт.
Программа beep написана сторонним разработчиком (Johnathan Nightingale), и даже не устанавливается по умолчанию (по-крайней мере, на Ubuntu). В репозиториях вы и не такое найдете. При чём тут «программисты google, Microsoft, apple» — совершенно неясно.interprise
12.04.2018 21:31Программа beep написана на чистом C, зачем вы притягиваете C++, причём тут он вообще?
Но раз уж притянули: на современном C++ в прикладном коде использование сырых new и delete можно свести к минимуму. Побибикать динамиком — это как раз прикладуха, здесь жонглирование указателями и голой памятью в стиле C неоправдано. Так что переписывание на C++ даст точно такой же эффект, как и переписывание на Rust.
С каких пор в с++ встроена защита от использования после освобождения и гонки? Вы просто нагло врете и передергиваете факты. На Rust не используя unsave невозможно написать так, чтобы появились эти типы уязвимость. На с++ или даже с можно свести к минимуму, а можно еще было не допускать уязвимости описанной в статье, только вывод, что все зависит от программиста.
Программа beep написана сторонним разработчиком (Johnathan Nightingale), и даже не устанавливается по умолчанию (по-крайней мере, на Ubuntu). В репозиториях вы и не такое найдете. При чём тут «программисты google, Microsoft, apple» — совершенно неясно.
В google chrome были найдены уязвимости? да
в windows? да
и так далее, приходим к выводу, что у крупных компаний не получалось это сделать. Видимо нужно нанять вас, вы то им покажете как нужно. Сейчас еще раз вспомним про openbsd, только вопрос кол-во пользователей и интерес хакеров. Вот как будет популярность на уровне хрома, тогда и поговорим. С вашей логикой мое приложение которое я в школе написал лет 12 назад самое безопасное в мире, ни одной уязвимости, а вот если посмотреть на популярный софт, то там сразу программисты какие-то не те.KennyGin
12.04.2018 21:48С каких пор в с++ встроена защита от использования после освобождения и гонки? Вы просто нагло врете и передергиваете факты.
Разговаривать на таких тонах с вами совершенно не имею желания. Если хотите содержательного диалога — потрудитесь указать конкретное место, где я «нагло соврал и передергивал факты». Про «встроенную защиту от use after free» в моём сообщении ничего не было.
На Rust не используя unsave невозможно написать так, чтобы появились эти типы уязвимость.
А вы сами-то много приложений на Rust написали? Или так, просто потролллить? Не представляю, как практикующий Rust-программист может сделать ошибку в кейворде 'unsafe' :)Nikita001
13.04.2018 16:56Вы нагло врете передергивая факты говоря практикующий программист не путает save и safe. Нет бога кроме Rust и interprise пророк его, а c++ это язычничество.
grossws
13.04.2018 01:26В модуле beep операционной системы Linux
Это сторонняя утилита для GNU/Linux, коих десятки тысяч, как минимум. Вы б хоть какого-нибудь технического специалиста подпускали к статьям перед публикацией, то такие ошибки глаз режут.
interprise
Еще раз повторю свой комментарий:
Раст кстати защищает и от гонок и от использования после освобождения. Жду комментариев, что просто программисты google, Microsoft, apple и другие не захотели написать хороший софт. Только мне кажется, что эти комментаторы даже не представляют как сложно отследить эти уязвимости, это вам не банальное переполнение буфера.
khim
Нет, всё гораздно проще: перепишите beep на rust и покажите как вы избежали гонок и прочего. Утилита-то небольшая.
Если «магический» rust спасёт вас от раскрытия информации без явных проверок — можно будет о чём-то говорить. Если потребуются явные if'ы — то говорить не о чем.
За выходные справитесь, я надеюсь?
Barafu
Я вообще не представляю, как можно было такую важную утилиту делать на таком неизкоуровневом языке. И веб-интерфейс ещё прикрутить.
interprise
Раст на уровне языка защищает от этих уязвимостей — это его основная фишка. Так, что задача для вас, напишите так, не используя unsafe, чтобы БЫЛИ уязвимости.
mayorovp
Он защищает только от гонок при доступе к памяти. Гонки при доступе к файлам никуда не делись.
Да, вот вам пример с гонкой:
Jef239
Дело не в гонках. Ключ -e указывает устройство, куда выводится сигнал. Чтобы сделать ioctl на этом устройстве, нужны привилегии. Но с привилегиями — мы видим скрытые файлы. А без привилегий — не сможем выполнить основную функцию.
Таких программ много. Условий для ошибки два:
velovich
Зависит от человека, котрый писать софт.
F0iL
Rust, может быть, и неплохой язык (хотя вырвиглазый синтаксис сразу бросается в глаза), но больше всего от него отталкивают его упоротые фанаты, которые прибегают в каждый пост, где упоминаются C, C++ или уязвимости в ПО, и начинают сразу твердить всем что нужно срочно перейти на раст и начать писать на нём и только на нём. Вам самим-то не тошно еще?
grossws
Судить о сообществе раста по данному экземпляру — то же, что судить о Си по воплям царя. Мне от таких товарищей, которые стараются агрессивно пропагандировать что угодно тошно вне зависимости от того как я отношусь к конкретной технологии.
Загляните в релевантные посты, особенно в англоязычном сегменте: у раста очень приветливое и приятное сообщество. И много выходцев из си и плюсов, что неудивительно.
Что же до синтаксиса — это штука вторичная. Если вам не нравится синтез MLного и плюсового синтаксиса — дело ваше. Мне, например, местами не нравится си-подобный синтаксис после языков с выводом типов, где декларация параметров и их типов выполняется в обратном порядке (scala, rust). Но это не повод на них не писать.