СОВРЕМЕННЫЕ ТЕХНОЛОГИИ СТАТИЧЕСКОГО И ДИНАМИЧЕСКОГО АНАЛИЗА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
Чукляев Евгений Игоревич,
научный сотрудник Смоленской общественной организации содействия науки и образованию «Региональный союз ученых» г. Смоленск, Россия, [email protected]
Аннотация
В статье представлены результаты анализа существующих подходов защиты и идентификации дефектов (уязвимостей и ошибок) в исходном и бинарном кодах программ, проводимых на различных этапах их разработки, проектирования и эксплуатации. Обобщены наиболее распространенные дефекты кода и объекты воздействия, функциональные и эргономические требования, предъявляемые к современным системам анализа.
Ключевые слова: статический и динамический анализ; исходный и бинарный код; дефекты (уязвимости и ошибки); требования, технологии защиты; объекты несанкционированных воздействий.
Поиск и устранение дефектов в программном обеспечении (ПО) требует больших трудозатрат, при этом многие из них могут остаться незамеченными. По данным исследования, проведенного по заказу Национального института стандартов и технологий США, убытки, возникающие из-за недостаточно развитой инфраструктуры устранения дефектов в ПО (уязвимостей и некритических ошибок), составляют от 22 до 60 миллиардов долларов в год [8], часто являются причиной переноса сроков выпуска программ. Стоимость устранения дефекта, пропущенного на этапах разработки и тестирования, может возрасти после поставки программы от 2до 100 раз [9].
Как следствие, наибольшее распространение получили методы статического анализа исходного кода ПО, рассматривающие все возможные пути выполнения программы без ее фактического выполнения. Дело в том, что такие методы реализуются в системах, полностью интегрируемые в цикл разработки ПО, применяемые как на этапе тестирования, так и на более ранних этапах — в ходе разработки, причем как во время, так называемых, «ночных сборок», так и непосредственно на аппаратуре разработчика.
Применение систем поиска дефектов (уязвимостей и некритических ошибок) ПО в промышленном масштабе обуславливает следующие функциональные и эргономические требования'.
минимальные действия пользователя для интеграции инструмента анализа в систему сборки ПО (отсутствие необходимости в изменении, аннотировании, интегрировании в процесс анализа исходного кода ПО);
автоматический поиск дефектов и уязвимостей (без участия пользователя непосредственно в процессе анализа); масштабируемость анализа (проведение анализа объемом нескольких миллионов строк кода и сотен тысяч функций); низкий процент ложных срабатываний (значительная часть выдаваемых предупреждений должна быть истинной; приемлемым считается уровень в 30-50% истинных срабатываний, а для важнейших — около 70%);
расширяемость инфраструктуры анализа (дополнение алгоритмами идентификации различными новыми классами уязвимостей (дефектов и критических ошибок);
удобный пользовательский интерфейс просмотра результатов и настройки инструмента анализа. В свою очередь, описанные требования влекут необходимость реализации следующих технологий системы анализа: анализ без доступа к полному исходному коду анализируемого ПО (наличие в инструменте анализа внутренних спецификаций, позволяющих описывать действия стандартных библиотечных функций объекта анализа);
выполнение глубокого межпроцедурного анализа (возможность учета влияния разных функций на поведение ПО при поиске заданных ситуаций);
инкрементальный анализ (т.е. анализ только измененной части проекта при наличии полных результатов анализа старой версии проекта);
проведение удаленного анализа, поддержка нескольких разработчиков, ведение истории результатов анализа. Необходимо отметить, что даже при выполнении всех упомянутых требований методы статического анализа имеют ряд ограничений, не позволяющих в ряде случаев достигнуть высокой точности анализа. Во-первых, при отсутствии полного исходного кода программы возникает неопределенность, не связанная непосредственно с качеством анализа: в зависимости от свойств недоступного при анализе кода, некоторая операция может как приводить, так и не приводить
к ошибке. Например, для библиотечного кода часто возможно построение некорректного вызова из пользовательского кода, приводящего к выполнению некорректной операции в коде библиотеки, но при отсутствии кода этого вызова ошибка в коде библиотеки, как правило, диагностироваться не должна.
Во-вторых, независимо точности статического анализа при обнаружении конструкций, которые могут потенциально указывать на уязвимость, во многих случаях не удается установить, возможен ли в действительности путь исполнения программы и входные данные, приводящие к ошибке. Выдача всех предупреждений в таких ситуациях приводит к тому, что большая их доля оказывается ложной, делая систему статического анализа малополезной для многих приложений.
Наконец, для больших программных систем (в миллионы строк кода) не удается за приемлемое время провести точный межпроцедурный анализ даже имеющегося кода, с учетом необходимости выполнять анализ указателей, интервальный анализ (анализ возможных значений переменных).
Как следствие упомянутых ограничений, промышленные коммерческие анализаторы вынуждены использовать эвристические алгоритмы анализа: при отборе важнейших (с точки зрения анализа) данных о программе среди полученных, при поиске конкретных ситуаций (шаблонов) в потоке данных и управления программы; и последующей выдаче лишь по этим отобранным данным или ситуациям предупреждений о возможных дефектах. Иначе проценты ложных срабатываний инструмента или потребляемые им ресурсы становятся неприемлемо большими. Улучшение алгоритмов анализа или использование других видов анализа, требующих больших вычислительных ресурсов (например, символьного исполнения в комбинации с решателями логических уравнений для отсеивания ложных путей выполнения), повышает точность анализа, но в силу затрачиваемых ресурсов может применяться только к самым важным предупреждениям и сравнительно небольшим частям программы (тысячи строк кода).
Поэтому, в промышленных инструментах анализа возникают ситуации пропуска истинных дефектов как следствие ошибок эвристик, то есть выполняется нестрогий анализ. Разные инструменты анализа всегда выдают частично пересекающиеся множества предупреждений для одной и той же программы: часть предупреждений общая, часть—уникальна для каждого инструмента, что обусловлено различием применяемых эвристик.
Всеми заявленными свойствами из коммерческих систем, по всей видимости, обладают системы Coverity Insight [10], KlocworkK9 [11], GrammaTech CodeSonar [12], Svace ИСПРАН [13-15]. Точное суждение об архитектуре и алгоритмах анализа, положенных в основу этих систем, затруднено из-за их закрытости, равно как и сравнение результатов их работы. Проводившиеся в ИСП РАН оценки инструмента Svace на доступном для анализа материале показали качество анализа, сравнимое с остальными коммерческими системами [15].
Существуют и другие классы систем обнаружения дефектов в исходном коде программ, однако точность и требуемые для использования ресурсы ограничивают их область применения (рисунок 1). Данные системы не получили такого распространения, как упомянутые системы автоматического поиска дефектов на основе статического анализа. Из этих классов систем можно упомянуть следующие системы: автоматизации экспертного аудита; верификации ограниченного исходного кода; проверки корректности пользовательских аннотаций. Необходимо отметить, что эффективность систем автоматического поиска дефектов ПО зависит от того, на каком наборе тестовых программ нарабатывались эвристики этих систем. По умолчанию эвристики поиска ситуаций в исходном коде, ранжирования собранных данных по важности, параметры точности применяемых алгоритмов настроены на некоторое «среднее» значение поведения анализируемых программ. Так, если программист перед использованием некоторого указателя проверяет его значение на корректность во всех точках программы, кроме одной-двух, то велика вероятность, что и в этих точках программы значение указателя может быть некорректным, и требуется выдать предупреждение о возможном разыменовании нулевого указателя. Конечно, такая эвристика применяется лишь в том случае, если основные алгоритмы статического анализа не смогли с достаточной точностью установить значение указателя.
Следовательно, для специальных классов программ является возможной такая доработка системы автоматического поиска, что точность выполняемого системой анализа для этих классов программ повысится. При этом основные виды анализов, выполняемые системой, останутся неизменными.
Перечислим основные способы такой доработки систем автома- Рис L Классы систем обнаружения дефектов тического поиска. в ИСХОдНОМ коде программ
СУЩЕСТВУЮЩИЕ ПОДХОДЫ ИДЕНТИФИКАЦИИ ДЕФЕКТОВ (УЯЗВИМОСТЕЙ И ОШИБОК) ПО
системы статического анализа исходного кода
системы динамическою анализа бинарного кода
автоматизации экспертного аудита
верификации ограниченного исходного кода
проверки коррсю ности пользовательских аннотаций
определение специфичных для данного класса программ ситуаций, сигнализирующих о дефектах в исходном коде, доработка эвристик системы для выдачи предупреждений о таких ситуациях;
настройка параметров анализа системы или применение дополнительных высокоточных методов анализа (например, чувствительных к путям выполнения) для ключевых, ограниченных по объему участков программы;
ранжирование вычисленной в ходе анализа информации по важности для конкретного класса программы (например, более точное вычисление информации о параметрах вызовов интерфейсов межпроцессного взаимодействия ОС для параллельных программ);
создание спецификаций для используемых программой библиотек, исходный код которых недоступен (как правило, система анализа знает о поведении лишь стандартных библиотек POSIX, С, С++).
Важным специальным классом программы являются системные программы, в частности, ядро и драйверы операционной системы. Как показано выше, объектами воздействия при эксплуатации уязвимостей являются чаще всего именно системные ресурсы, ошибки в привилегированных программах ОС сразу при эксплуатации позволяют добиться необходимой эскалации прав, а также дальнейшего нарушения защищенности информации. Например, при анализе ядра Linux можно создать спецификации для функций выделения и освобождения памяти, используемых в ядре, а также учесть соглашения ядра о возврате кодов ошибок из интерфейсных функций. Для встраиваемых систем, ОС реального времени можно воспользоваться относительно небольшим объемом анализируемого исходного кода и повысить точность алгоритмов анализа. Разработка и реализация таких методов специализации системы автоматического поиска дефектов в настоящий момент является предметом исследований авторов.
Системы динамического анализа бинарного кода программ выполняют поиск дефектов (уязвимостей и некритических ошибок) путем генерации различных наборов данных и последующей передачей их на вход исследуемой программе. Возникновение исключительной ситуации, означающей наличие дефекта, отслеживается системой анализа, и текущие входные данные сохраняются для последующего воспроизведения и отладки. Кроме того, собранная информация анализируется на предмет возможности эксплуатации найденной ошибки. Уязвимости, лишь позволяющие провести атаку типа «отказ в обслуживании», считаются менее критическими, чем эксплуатируемые уязвимости, так как существуют технологии, позволяющие найти возможность для эксплуатации уязвимости и автоматической генерации взламывающей программы (эксплоита) [16, 17].
Основными задачами, которые решаются при динамическом анализе, являются: задача генерации наборов входных данных, покрывающих интересующие пути выполнения программы; запуск и трансляция программы; отслеживание возникающих уязвимостей. Часто исследование программы затрудняется применением приемов антиотладки, упаковщиков кода и навесными системами защиты от обратной инженерии. Снятие подобных защит и обход приемов антиотладки является отдельной задачей, поэтому в дальнейшем изложении будем считать, что программа не пытается препятствовать анализу.
Процесс генерации различных наборов входных данных с последующей передачей их программе получил название «фаззинг» (fuzzing), его целью является получение набора данных, выявляющих дефекты работы целевой программы. При этом не все пути исполнения программы представляют интерес, и для более интеллектуальной генерации входных данных требуется учитывать трассу выполнения программы. Для решения этой задачи программа исполняется неким транслятором, который позволяет анализировать пути выполнения, инструментировать исполняемый код или снимать трассу исполнения для последующего анализа.
Попытка сгенерировать все возможные сочетания входных данных приводит к экспоненциальному росту их объема. А значит, от транслятора требуется возможность: производить анализ выбранных или интересующих для анализа путей (например, применяя технологию символьного исполнения для некоторых путей); генерации входных данных, обеспечивающих переход по интересующим путям для увеличения покрытия; возможность параллельного запуска системы с разными входными данными для ускорения анализа.
Примером систем осуществляющих динамическую бинарную трансляцию, являются QEMU и Valgrind. QEMU — эмулятор процессоров и вычислительных систем, способен эмулировать всю вычислительную систему, в этом случае динамической трансляции подвергается код программы, все библиотеки и операционная система. В режиме эмуляции приложения транслируется только код программы и необходимые библиотеки. В свою очередь, QEMU выполняет обработку системных вызовов [18]. Valgrind является инфраструктурой для отладки и профилирования программ, в которой транслируется лишь пользовательская программа в том же окружении, что и при обычном выполнении. Valgrind включает в себя ряд инструментов, реализованных поверх базовой инфраструктуры трансляции, самым популярным из которых является Memcheck, ориентированный для анализа утечек памяти и обращений к невыделенной памяти, позволяет транслировать программу в промежуточное представление, находящееся в SSA-форме, затем код инструментируется и транслируется в машинный код [19].
KLEE — инструмент для символьного исполнения [20], анализ производится над внутренним представлением компиляторной инфраструктуры LLVM [21]. Инструмент позволяет запускать «символьные» процессы, при этом в ходе интерпретации инструкции внутреннего представления LLVM отображаются в систему уравнений, которые затем решаются с использованием инструмента SLP [22] для получения новых путей выполнения, которые требуется обойти. Для ускорения анализа система позволяет выполнять несколько путей одновременно.
S2E — система выборочного символьного исполнения, построенная на базе QEMU и KLEE. S2E основывается на двух базовых идеях: выборочном символьном выполнении, позволяющем автоматически минимизировать количество кода, который будет исполнен символьно, и модели консистентности, обеспечивающей при анализе контроль баланса производительность/точность. Ключевые возможности системы заключаются в одновременном анализе нескольких путей, возможности анализа всей системы (программ пользователя, библиотек, ядра, драйверов), возможность анализа бинарного кода [23].
Avalanche—система динамического анализа, разрабатываемая в ИСП РАН [24]. Avalanche решает задачи отслеживания уязвимостей в ходе выполнения программы и интеллектуальной генерации входных данных для увеличения покрытия путей через собственные инструменты на основе инфраструктуры Valgrind и упомянутый решатель STP. Для поддержки языка Java используется статическая инструментация кода, но сохраняется общая схема итеративного динамического анализа.
Mayhem — система автоматического поиска эксплуатируемых уязвимостей в бинарном коде [25]. Каждая найденная уязвимость сопровождается рабочим эксплоитом. Ключевые особенности инструмента: гибридное онлайн-оффлайн исполнение кода, эмуляция на уровне приложения, а не всей системы, набор различных эвристик для работы с символьными указателями. Система основана на инфраструктуре двоичной трансляции PIN [26], обеспечивающей инструментирование бинарного кода, для перевода во внутреннее представление используется ВАР [27], в качестве решателя используется Z3 [28].
Таким образом, системы динамического анализа представляют совокупность нескольких модулей-инструментов (зачастую, с открытым исходным кодом), решающих основные сформулированные задачи анализа. Экспоненциальная сложность анализа и применения в случае нетривиальных алгоритмов обработки входных данных и/или модели исполнения (например, обратные вызовы процедур на мобильных платформах) преодолевается новыми эвристиками, позволяющими производить более глубокий анализ программы.
Список литературы
1. Аветисян А. И. Современные методы статического и динамического анализа программ для решения приоритетных проблем программной инженерии: автореф. дис. ... д-ра физ.-мат. наук: 05.13.11/Аветисян АрутюнИшханович. М., 2011. 36 с.
2. Марков А. С. Немонотонные модели оценки надежности и безопасности функционирования программных средств на ранних этапах испытаний. Научно-практический журнал «Вопросы кибербезопасности». М.: ОАО «НПО «Эшелон». ISNB2311-3456. 2014. №2(3). С. 10-17.
3. Макаренко С.П., ЧукляевИ.И. Терминологический базис в области информационного противоборства. Научно-практический журнал «Вопросы кибербезопасности». М.: ОАО «НПО «Эшелон». ISNB2311-3456. 2014. № 1 (2). С. 13-22.
4. ЧукляевИ.И., МорозовА.В., БолотинИ.Б. Теоретические основы построения адаптивных систем комплексной защиты информационных ресурсов распределенных информационно-вычислительных систем: монография. Смоленск: ВА ВПВО ВС РФ, 2011. 227 с.
5. Морозов А. В., Чукляев И. И. Информационная безопасность вычислительных систем боевого управления в аспекте информационного противоборства. Научно-практический журнал «Проблемы безопасности российского общества». М.: МГУПС. ISNB2307-4396. 2013. №2-3. С. 85-91.
6. База Common Weakness Enumeration. Режим доступа: http://cwe.mitre.org.
7. База Common Vulnerabilities and Exposures. Режим доступа: http://cve.mitre.org.
8. Gallaher M. P. and Kropp В. M. Economic impacts of inadequate infrastructure for software testing. Technical report, RTI International, National Institute of Standards and Technology, US Dept of Commerce, May 2002.
9. Forrest Shull, Vic Basili, Barry Boehm, Winsor A. Brown, Patricia Costa, Mikael Lindvall, Dan Port, Ioana Rus, Roseanne Tesonero, and Marvin Zelkowitz. What we have learned about fighting defects. In International Software Metrics Symposium. Ottawa, Canada, 2002.
10. Klocwork Insight. Системы анализа исходного кода [Электронный ресурс]. Режим доступа: http://www.klocwork. com/products.
11. Coverity. Static source code analysis solutions [Электронный ресурс]. Режим доступа: http://www.coverity.com.
12. GrammaTech, Inc. CodeSonar [Электронный ресурс]. Режим доступа: http://www.grammatech.com/products/ codesonar/overview. html.
13. Аветисян А. П., Белеванцев А. А., Бородин А. Е., Несов В. Использование статического анализа для поиска уязвимостей и критических ошибок в исходном коде программ. Труды ИСП РАН Т. 2011. 21. С. 23-38.
14. Аветисян А. И., Бородин А. Е. Механизмы расширения системы статического анализа Svace детекторами новых видов уязвимостей и критических ошибок. Труды ИСП РАН. 2011. Т. 21. С. 39-54.
15. Иванников В. П., Белеванцев A.A., Бородин А. Е., Игнатьев В.Н., Журихин ДМ., Аветисян А. П., Леонов М.И. Статический анализатор Svace для поиска дефектов в исходном коде программ. Труды ИСП РАН том 26. 2014. Вып. 1. С. 231-250.
THE MODERN TECHNOLOGIES OF STATIC AND DYNAMIC ANALYSIS OF SOFTWARE
Chuklyaev Eugenii Igorevich,
Smolensk, Russia, [email protected]
Abstraet
The article presents the results of an analysis of existing approaches protect and identify defects (vulnerabilities and errors) in the source and binary codes programs conducted at various stages of their development, design and operation. Summarizes the most common defects in the code and objects of influence, functional and ergonomic requirements for a modern system of analysis.
Keywords: static and dynamic analysis; source and binary code; defects (vulnerabilities and bugs); requirements; security technologies; facilities tampering.
References
1. Avetisyan AI Modern methods of static and dynamic analysis of programs to address priority issues of software engineering: Author. Dis... Dr. Sci. Sciences: 05.13.11 / Harutyun Avetisyan Ishhanovich. Moscow, 2011. 36 p.
2. A. Markov model Nonmonotone assess the reliability and safety of software in the early stages of testing. Scientific and practical journal "Issues of cybersecurity." Moscow, "NPO" Echelon ". ISNB2311-3456. 2014. No. 2 (3). Pp. 10-17.
3. Makarenko SI Chuklyaev II terminological basis in the field of information warfare. Scientific and practical journal "Issues of cybersecurity." Moscow, "NPO" Echelon ". ISNB2311-3456. 2014. No. 1 (2). Pp. 13-22.
4. Chuklyaev I. I., Morozov V., Bolotin I. B. Theoretical bases of construction of complex adaptive systems to protect information resources of distributed information systems: monograph. Smolensk: BA VPVO Armed Forces, 2011. 227 p.
5. Morozov A. V., Chuklyaev I. I. Information security of computer systems in the command and control aspect of information warfare. Scientific and practical journal "Problems of security of the Russian society." Moscow, MGUPS. 2013. No. 2-3. Pp. 85-91.
6. Base Common Weakness Enumeration. URL: http://cwe.mitre.org.
7. Base Common Vulnerabilities and Exposures. URL: http://cve.mitre.org.
8. Gallaher M. P., Kropp B. M. Economic impacts of inadequate infrastructure for software testing. Technical report, RTI International, National Institute of Standards and Technology, US Dept of Commerce, May 2002.
9. Forrest Shull, Vic Basili, Barry Boehm, Winsor A. Brown, Patricia Costa, Mikael Lindvall, Dan Port, Ioana Rus, Roseanne Tesoriero, and Marvin Zelkowitz. What we have learned about fighting defects. In International Software Metrics Symposium. Ottawa, Canada, 2002.
10. Klocwork Insight. System source code analysis. URL: http://www.klocwork.com/products.
11. Coverity.Static source code analysis solutions. URL: http://www.coverity.com.
12. GrammaTech, Inc. CodeSonar. URL: http://www.grammatech.com/products/codesonar/overview.html.
13. Avetisyan A. I., Belevantsev A., Borodin A. E., Nessov B. Using static analysis to find vulnerabilities and critical errors in the source code of programs.Proceedings of ISP RAS is 21. 2011. Pp. 23-38.
14. Avetisyan A. I., Borodin A. E. extension mechanism of static analysis Svace detectors of new types of vulnerabilities, and critical errors. ISPRAS Proceedings. 2011. Vol. 21. Pp. 39-54.
15. Ivannikov V. P., Belevantsev A. A., Borodin A. E., Ignatiev V. N., Zhurikhin D. M., Avetisyan A. I., Leonov M. I. A static analyzer Svace to find defects in the source code of programs.Proceedings ISPRAS that 26. 2014. Vol. 1. Pp. 231-250.
Information about author:
Chuklyaev E. I., Researcher Smolensk public organization to promote science and education "Regional Union of Scientists", Smolensk, Russia.