В данной статье описывается суть динамического анализа ПО на основе инструментов фаззинга, обзор и сценарии применения различных инструментов, реализующих данный подход. Все инструменты, представленные в статье, используются в цикле проверки ПО обеспечения, разрабатываемого компанией Google.
Ключевые слова: фаззинг, fuzzing, динамический анализ, уязвимость, ошибка, AFL, LibFuzzer, Syzkaller, информационная безопасность, информатика, эксплойты, автоматический анализ, тестирование, fuzz, LLVM.
Современное программное обеспечение используется в различных областях человеческой жизни. Информатизация сфер, связанных с риском для жизни, предъявляет особые требования к качеству выпускаемых программных продуктов. Современные программы обладают сложной структурой и большим размером, в связи с чем ручная проверка ПО на наличие ошибок не представляется возможной, поэтому целесообразно использовать средства автоматического анализа. В настоящее время активно используются два основных метода полностью автоматического анализа программ — статический и динамический.
К преимуществам динамического анализа можно отнести отсутствие строгих шаблонов и критериев, что позволяет выполнять его непрерывно. Не стоит забывать о том, что компилятор может применять различные оптимизации к исходному коду, в результате чего возникают ошибки, которые невозможно обнаружить статическими методами анализа.
Динамический анализ программ производится в процессе или по результатам исполнения программы. Основное требование, предъявляемое к динамическому анализу ПО — это малый процент замедления выполнения программы. Поскольку за один запуск программы производится анализ на одном пути исполнения программы, то для анализа всей программы требуется многократный запуск анализируемого ПО. В основном ход исполнения программы зависит от входных данных. Если в программе имеются дефекты, то при специфических входных данных эти дефекты будут воспроизведены при исполнении ПО. Автоматические методы анализа, как правило, позволяют обнаруживать ограниченный класс ошибок в программах. Среди известных методов обнаружения ошибок в ПО можно выделить: тестирование, отладку, фаззинг и динамическое символьное исполнение.
Фаззинг (Fuzzing) — это технология тестирования программного обеспечения, когда вместо ожидаемых входных данных программе передаются случайные или специально сформированные данные [2]. В большинстве своем это некорректно составленные данные.
Цель такого анализа — это найти непредусмотренные программистом входные данные, которые приводят к аварийному завершению программы или к её некорректному поведению. Входные данные могут передаваться через файлы, сетевые сокеты, API, стандартного входа, переменные окружения и т. д.
В случае если программа входит в бесконечный цикл или аварийно завершает работу, это считается нахождением дефекта в программе, который может привести к обнаружению определенной уязвимости.
Основные фазы фаззинга:
– Определение цели.
– Определение протокола и типа входных данных. Для старта анализа требуются начальные входные данные.
– Изменение данных с учетом особенностей протокола передачи и типа данных. Изменение входных данных производится двумя методами — мутацией и генерацией.
– Исполнение программы с подачей ей на вход некорректных данных.
– Обнаружение ошибок, с целью определения на каких данных или цепочке данных обнаружилась уязвимость, а также подсчет покрытия по базовым блокам.
– Исследование уязвимости на возможность её эксплуатации.
Рис. 1. Принципиальная схема фаззинга
На рисунке 1 представлена схема фаззинга. Фаззер принимает на вход исходные входные данные для анализируемого ПО, запускает программу с этим входом, если имеется возможность, собирает информацию об исполнении. Используя собранные данные, фаззер генерирует алгоритмами мутации и генерации новые наборы входных данных для анализируемого ПО, которые должны заставить программу исполниться по новому пути исполнения или выявить дефект кода, если он есть. Далее алгоритм повторяется для каждого из этих сгенерированных входных данных. Входные данные, на которых программа вошла в бесконечный цикл или аварийно завершилась сохраняются для последующего изучения аналитиком и выявления дефекта.
Обзор применяемых в разработке ПО технологий фаззинга
AFL (American fuzzy lop) — это ориентированный на поиск ошибок инструмент анализа ПО, который использует обширный список типов инструментации кода для получения информации о покрытии и множество генетических алгоритмов мутации для автоматического обнаружения различных тестовых примеров, которые вызывают новые внутренние состояния в бинарном коде ПО. Фаззер AFL поддерживает инструментацию, реализующуюся на этапе компиляции из исходного кода с помощью оберток afl-gcc/afl-g++. afl-gcc/afl-g++ подменяет вызываемую команду на обертку, переписывающую ассемблерный код, сгенерированный компилятором. Для фаззинга уже скомпилированных бинарных файлов используется qemu mode — это патч к QEMU, эмулирующий запуск одного процесса и реализующий требуемую для анализа инструментацию кода. Изначально QEMU предназначалась для того, чтобы запускать отдельные процессы, собранные для другой архитектуры, используя ядро целевой операционной системы. На официальном сайте фаззера размещены различные «трофеи» данного инструмента. С его помощью были обнаружены уязвимости в следующем ПО: LibreOffice, GnuPG, OpenSSH, nginx, Internet Explorer, sqlite и др.
LibFuzzer — это инструмент анализа ПО, являющийся частью проекта LLVM, позволяющий производить анализ ПО без его перезапуска, осуществляя мутацию напрямую в памяти. Данный инструмент собирает информацию о покрытии (пройденных базовых блоках) и накапливает тестовые примеры, приводящие к его увеличению. В этом фаззере используется технология белого ящика, поэтому инструментация осуществляется средствами LLVM после компиляции исходного кода. LibFuzzer позволяет осуществлять фаззинг различных компонентов браузера Google Chrome, что освобождает от необходимости генерировать HTML страницу или полезную нагрузку, а также перезапускать браузер целиком. Это позволяет существенно сократить накладные расходы. LibFuzzer имеет возможность осуществлять анализ функций API напрямую. Благодаря перечисленным особенностям данный инструмент позволяет проводить анализ в несколько раз быстрее чем традиционные инструменты фаззинга. Данный инструмент используется в открытой разработке браузера Chromium, каждое изменение кода которого, вносимое разработчиками, проверяется на кластере с использованием LibFuzzer.
Syzkaller — это инструмент, предназначенный для поиска ошибок в ядрах ОС. Данный инструмент в различной степени поддерживает множество различных ОС, таких как akaros, freebsd, fuchsia, netbsd, windows и linux. Изначально syzkaller разрабатывался для анализа ядра ОС Linux, но со временем он стал поддерживать большее количество операционных систем.
Рис. 2. Схема работы инструмента syzkaller
На рисунке 2 представлена схема работы инструмента syzkaller. Процесс syz-manager запускает, осуществляет мониторинг и перезапускает различные экземпляры виртуальных машин, в которых порождает процесс syz-fuzzer. Syz-manager хранит различные корпуса входных данных и информацию об аварийных завершениях, которые были обнаружены в результате анализа ядер внутри виртуальных машин. Данный процесс работает на стабильном ядре, которое не подвержено влиянию процессов syz-fuzzer. Процесс Syz-fuzzer запускается внутри предположительно нестабильной виртуальной машины и осуществляет процесс фаззинга (генерацию и мутацию входов, минимизацию входных данных и т. д.), при этом отправляя входы, вызывающие прирост покрытия по базовым блокам, в процесс Syz-manager через механизм удаленного вызова процедур RPC. Syz-fuzzer запускает временный процесс syz-executor. Каждый процесс syz-executor исполняет единственный вход, являющийся последовательностью системных вызовов, после чего отправляет результат исполнения обратно в syz-fuzzer. Syz-executor осуществляет взаимодействие с syz-fuzzer через разделяемую память. Исследователь компании Google Андрей Коновалов, используя данный инструмент обнаружил множество различных уязвимостей в подсистеме Linux USB. В ходе исследования он обнаружил десятки ошибок, а при дальнейшем исследовании найденных ошибок выявил 22 уязвимости, различных типов, таких как: использование указателя после его освобождения, выход за границы чтения, разыменование указателя с значением NULL и др.
В данной статье были рассмотрены и кратко описаны основные возможности и сценарии применения различных инструментов фаззинга ПО. Опираясь на вышеизложенный материал можно сказать, что в современном мире одним из самых перспективных методов анализа ПО на предмет поиска в нем ошибок и уязвимостей является динамический анализ ПО. Крупные компании, такие как Google, Яндекс, Microsoft и т. д. уже активно применяют в цикле разработки ПО такие методы анализа как фаззинг.
Литература:
- И. Исаев, Д. Сидоров. Применение динамического анализа для генерации входных данных, демонстрирующих критические ошибки и уязвимости в программах. Программирование, № 4 2010.
- Fuzzing. Технология охоты за багами // VR-Online. URL: http://www.vr-online.ru/?q=content/fuzzing-tehnologija-ohoty-za-bagami-752 (дата обращения: 28.12.2017).
- Майкл Дж.Д. Саттон, Адам Грин, Педрам Амини. Fuzzing. Исследование уязвимостей методом грубой силы. ISBN 978–5-93286–147–9. 2009.
- P. Godefroid, M. Levin, D. Molnar. SAGE: Whitebox Fuzzing for Security Testing. 2012.
- american fuzzy lop (2.52b) // american fuzzy lop. URL: http://lcamtuf.coredump.cx/afl/ (дата обращения: 28.12.2017).
- Guided in-process fuzzing of Chrome components // Google Security Blog. URL: https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html (дата обращения: 28.12.2017).
- syzkaller — kernel fuzzer // GitHub. URL: https://github.com/google/syzkaller (дата обращения: 28.12.2017).