Fuzzing Irssi

Перевод статьи Fuzzing Irssi, автор Joseph Bisch

Привет, друзья пользователя Irssi и люди, заинтересованные в изучении fuzzing.

В сообществах Irssi и открытыъ сообществах были предприняты недавние усилия, чтобы сделать Irssi более безопасным с помощью размытия. Например, ошибки безопасности, выявленные в первом совете по безопасности Irssi 2017 года, были обнаружены путаницей. В этом сообщении в блоге мы рассмотрим введение в fuzzing, как fuzz Irssi и взглянем на пару фактических ошибок, обнаруженных в прошлых версиях Irssi.

Введение в Fuzzing

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

Fuzzing обычно выполняется с помощью некоторой программы, которая отвечает за генерацию ввода, а затем вызывает программу, которая тестируется с этим вводом. Это повторяется до тех пор, пока не произойдет авария, или некоторые фьюзеры будут продолжать работать и собирать несколько сбоев. Хотя эти fuzzers могут не знать о том, как вход влияет на выполнение программы, есть другие fuzzers, которые используют что-то, называемое инструментами, которое позволяет fuzzer определять, какие входные данные приводят к новому охвату программы. Идея состоит в том, что могут быть ошибки, которые присутствуют только в определенной части программы, и в противном случае их было бы трудно найти, если бы не fuzzer, пытающийся найти новый охват. Примерами fuzzers, которые используют покрытие, являются AFL и libfuzzer, Хотя AFL также имеет режим «тупой fuzzer», который ведет себя как традиционный fuzzer без инструментария. Libfuzzer на самом деле является fuzzing-библиотекой, поэтому она не запускает вашу программу несколько раз, а скорее фактически связывает ваш код с тем, чтобы сформировать «цель fuzz», которая будет повторно вызывать функции, которые вы хотите протестировать. Это называется «in-process fuzzing».

Fuzzing Irssi

В этом разделе мы рассмотрим патч, написанный dx, который позволяет развязать Irssi с использованием AFL. Он делает это, перемещая сетевое общение на stdin и stdout. Фюзер, по сути, действует как IRC-сервер, с которым Irssi подключается и принимает данные. Как только fuzzer завершает отправку данных, Irssi прекратит работу, чтобы позволить fuzzer снова начать работу с новыми данными.

Мы также рассмотрим конкретную CVE, найденную с помощью этой методологии, а именно CVE-2017-5193.

Вот патч, который можно применить к вашему исходному дереву Irssi, чтобы разрешить fuzzing Irssi с AFL: patch.

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

Следующие команды будут клонировать новую копию Irssi и применять вышеуказанный патч (с именем fuzz.diff) к вашей копии Irssi. Обратите внимание, что патч больше не применяется к git-хозяину, поэтому вам нужно будет либо исправить часть, src/fe-text/irssi.cкоторая не применяется, либо проверить фиксацию 70f9db3cbdc0a3c6b622e64edbd504592f921892до применения патча. Обратите внимание, что это включает любой релиз Irssi на момент написания этой статьи (1.0.2 или ранее).

git clone https://github.com/irssi/irssi.git irssi-fuzz
cd irssi-fuzz
patch -p1 < fuzz.diff

Следующие команды будут конфигурировать и создавать Irssi. Если вы уже использовали autogen.sh в своей копии источника Irssi, вы можете заменить ./autogen.sh на ./configure.

CC=/path/to/afl/afl-clang-fast CXX=/path/to/afl/afl-clang-fast++ ./autogen.sh --disable-shared
make

Теперь двоичный файл irssi находится в src/fe-text/irssi.

Запустите AFL, используя следующие команды:

mkdir afl
cd afl
mkdir in
echo 'initial testcase' > in/initial
cp ../src/fe-fuzz/tokens.dict .
/path/to/afl/afl-fuzz -i in -o out -x tokens.dict -- ../src/fe-text/irssi

in - каталог каталог исходных материалов каждый из которых содержит определенную последовательность байт, которые будут начальные входами , подаваемые программа тестируется (Irssi в нашем случае). Входы идеально подходят для тестируемой программы или, возможно, были собраны с предыдущей сессии fuzzing с использованием AFL или какого-либо другого fuzzer. В этой демонстрации у меня есть только один ввод с строкой 'initial testcase \ n'. В этом outкаталоге хранятся аварийные сообщения, зависания и другие интересные данные. tokens.dictФайл представляет собой набор значимых маркеров, которые будут использоваться в качестве составной части процесса Fuzzing найти новые пути коды быстрее. Тонеры словаря будут вставлены во вход и также будут использованы для перезаписи частей ввода. --Отделяет afl-fuzzкоманды от двоичного файла, мы путаем и флаги, которые мы будем давать. Обратите внимание, что AFL также поддерживает fuzzing программу, которая читает из файла, переданного в качестве аргумента. Поэтому, если мы вместо этого изменим Irssi для чтения из файла, мы могли бы вместо этого, -- ./src/fe-text/irssi @@ будет подавать Irssi файл как argv [1]. Но в этом случае нет какой-либо @@ части команды, поэтому AFL передает данные Irssi на stdin.

Теперь, когда вы запустили afl-fuzz, вы увидите, что в вашем терминале появится пользовательский интерфейс AFL, который позволит вам отслеживать прорыв. Вы должны начать видеть, что количество обнаруженных путей (второе число сверху вверху справа от интерфейса на момент написания сообщения) увеличивается. AFL должен быстро отобразить сообщение о том, что он нечетный, если пути не найдены. В этом случае вы должны проверить, действительно ли программа, которую вы путаете, на самом деле читает данные из stdin.

Вот изображение, показывающее интерфейс AFL, который отображает:

Как вы можете видеть, никаких сбоев не было найдено до сих пор во время этой пушистой сессии. AFL обнаружил в общей сложности 3090 входов, которые вызывают новые пути, и в настоящее время AFL находится в процессе путаницы 2520-го из этих входов, что составляет 81,55% от пути, найденного до сих пор. Конечно, этот процент может снизиться по мере обнаружения новых путей.

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

Теперь мы можем зайти afl/out/crashes в исходное дерево нашей программы и найти сбои с именами файлов, например out/crashes/id:000000,sig:06,src:000000,op:havoc,rep:32, с указанием уникального идентификатора для сбоя, сигнала, с которым была разбита программа, предыдущего ввода, на котором основана эта, и операции, выполняемой в предыдущем вход. Затем вы можете сделать следующее для воспроизведения краха и, надеюсь, получить некоторую информацию о сбое:, cat file | program, где файл - это файл, out/crashes/ - это программа, которую вы тестировали.

CVE-2017-5193

CVE-2017-5193 был выражением NULL-указателя в функции nickcmp, которую я нашел с использованием AFL и вышеупомянутого патча. Как вы можете видеть в заплатке, которая исправила проблему, исправление - это всего лишь вопрос обеспечения того, что nick не является NULL. Эксплуатация позволила серверу сбой Irssi. Поскольку разыменование указателя NULL приводит к segfault, этот вид проблемы можно обнаружить только с помощью Irssi, вышеприведенного патча и AFL.

Если вы хотите воспроизвести CVE-2017-5193, вам необходимо следовать приведенным выше инструкциям и быть готовым ждать много часов. Кроме того, вы должны убедиться, что вы создали Irssi <= 0.8.20, поскольку 0.8.21 исправляет CVE-2017-5193. Есть несколько вещей, которые вы можете сделать, чтобы ускорить fuzzing в случае этой конкретной демонстрации, например, установив исходный тестовый файл как нечто близкое к воспроизводителю и используя ограниченный словарь, который имеет только токены, которые являются частью репродуктора. Вот как вы можете это сделать:

echo $'001\nprivmsg\nprivmsg 0 ' > in/initial
echo '"\x01ACTION"' > tokens.dict

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

Для тех из вас, кто не хочет ждать или хочет убедиться, что на самом деле вы нашли CVE-2017-5193, вот минимальный триггер:

echo $'001\nprivmsg\nprivmsg 0 :\x01ACTION ' | nc -l -p 6667

Поскольку эта команда приводит к тому, что сервер, прослушивающий на порту 6667 локально, вы можете просто запустить уязвимый экземпляр Irssi, а затем ввести: /connect localhost для запуска сбоя.

Что я могу сделать, чтобы помочь с fuzzing Irssi?...

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

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

Существуют также другие подходы к fuzzing, помимо использования этого патча с AFL. Хотя это не было предметом этого сообщения в блоге, у нас есть fuzzing frontend, основанный на libfuzzer. Так что это еще что-то, что вы можете взглянуть на улучшение. Возможно, в ближайшее время появится еще одно сообщение в блоге, в котором будет рассмотрен фальшивый интерфейс.

Как всегда, #irssi на Freenode - отличное место для обсуждения Irssi.И мы хотели бы услышать о любых найденных ошибках, будь то путаница или другие методы. Вы можете сообщить об ошибках без защиты через репозиторий Irssi GitHub. Сообщайте об ошибках безопасности сотрудникам Irssi. Персонал можно добраться по адресу: staff@irssi.org.