Разработка правил для Approof

Approof - инструмент статического анализа веб сайтов на предмет уязвимостей. Разрабатывается Positive Technologies. Содержит в себе, по-видимому, несколько движков для разных анализов. В рамках PDUG 10 августа Алексей Гончаров как раз делал доклад о движке Fingerprint. Предложил всем поучаствовать в написании правил. Не долго думая, было решено поковыряться в инструменте, посмотреть что он умеет, и как им пользоваться. За загруженностью обычными делами, удалось к нему притронуться лишь недели через три.

Движок Fingerprint выполняет следующий вид анализа. Запускаясь на наборе исходных кодов сайта (бэкенда, фронтенда), он, согласно имеющимся правилам, ищет известные версии компонентов(например, библиотеку bla-bla версии 3). Правила составляются так, что содержат сигнатуры уязвимых версии библиотек с текстовым описанием проблемы.

Что собой представляет правило для движка? Это набор нескольких условий для проверки файла. Например, условий на наличие в файле определённых строк. Если файл им удовлетворяет, то Approof в итоговом отчёте выдает информацию о том, что в таком-то компоненте с версией N были обнаружены следующие уязвимости, выдаёт описания CVE.

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

Собственно говоря, на текущий момент мне представляется, что в основе движка Fingerprint лежит идея поиска по регуляркам в исходном коде нужных сигнатур. Именно такое сопоставление мне пришло в голову во время доклада, и как всегда в таких случаях вызвало неизменный вопрос "Как об этом раньше-то никто не додумался!?". Идея - красивая и простая, а при должной степени развития инструмента способная успешно выстрелить и принести большую пользу.

Вот пример правила:

private rule php_file
{
meta:
	custom_description = "Private rule for identifying
	   php files"
strings:
	$start = /^<\?php/ nocase
condition:
	$start
}

private rule RoundCubeWebmail
{
meta:
	custom_description = "Private rule for identifying 
	   RoundCube Webmail"
strings:
	$string = "Roundcube Webmail IMAP Client"
condition:
	$string
}

rule CVE_2016_4069
{
meta:
	component_name = "Roundcube Webmail"
	component_version = "1.1.4 and bellow"
	custom_title = "Cross-site request forgery (CSRF)
	   vulnerability in Roundcube Webmail before 1.1.5"
	custom_level = "Medium"
	custom_description = "<p>Cross-site request forgery (CSRF) vulnerability
	   in Roundcube Webmail before 1.1.5 allows remote attackers to hijack
	   the authentication of users for requests that download attachments
	   and cause a denial of service (disk consumption) via unspecified
	   vectors.</p>"
strings:
	$v1_1_4 = /Version\s+1.1.4\W/
	$v1_1_3 = /Version\s+1.1.3\W/
	$v1_1_2 = /Version\s+1.1.2\W/
	$v1_1_1 = /Version\s+1.1.1\W/
	$v1_1_0 = /Version\s+1.1.0\W/
condition:
	php_file and RoundCubeWebmail and any of ($v*)
}

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

Так, например, правило php_file ищет по регулярному выражению строку <?php в начале файла. Если она есть, то правило срабатывает. Правило RoundCubeWebmail ищет простую строку "Roundcube Webmail IMAP Client" в файле. В правиле CVE_2016_4069 составное условие. Для того, чтобы оно сработало файл должен сначала сопоставиться с правилом php_file, затем RoundCubeWebmail и удовлетворять одному из регулярных выражений, описанных в секции strings. Достаточно легко понять, что последние описывают версии уязвимого компонента. Можно было бы записать это одним регулярным выражением, но, судя по существующим правилам, хорошим тоном считается явное выписывание всех версий.

Сначала я решил особо не замахиваться на какие-то сложные, значимые проекты и попробовать найти такие уязвимые компоненты, создание правил для которых хорошо автоматизировалось бы. После пробных пяти правил, стало понятно что модули языка perl отлично подходят.

И написал программу yargen с целью создания подобных правил. Она работает следующим образом:

  1. Берет описание указанного CVE с http://cve.mitre.org/ и http://vuldb.com;
  2. С http://metacpan.org берёт информацию об уязвимом модуле;
  3. На основании информации с metacpan составляется список всех релизов модуля. Исходники разных версий модуля загружаются с того же metacpan и в каждом ищется идентификатор версии. В perl существует несколько довольно стандартных способов задать версию модуля и в большинстве случаев удаётся найти идентификатор без особых проблем;
  4. На выходе генерируется yara правило с перечислением всех версий модуля с metacpan. Лишние (не уязвимые) нужно убирать в ручную.

Что по итогам? 5 правил составил вручную. Остальные ~20 с помощью программы. Последние потребовали минимальной правки, в основном, в части выкидывания лишних версий.

P.S. Футболку, кстати говоря, так и не заслали. Заслали шикарную футболку. За что, огромное спасибо!

Comments

comments powered by Disqus