диплом Глазунов

advertisement
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ
РОССИЙСКОЙ ФЕДЕРАЦИИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ
ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ООБРАЗОВАНИЯ
«ТЮМЕНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ»
ИНСТИТУТ МАТЕМАТИКИ И КОМПЬЮТЕРНЫХ НАУК
КАФЕДРА ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ
Допустить к защите в ГАК
Заведующий кафедрой
информационной безопасности
д.т.н. профессор
А.А. Захаров
(подпись)
«___» ________20__ г.
Глазунов Сергей Павлович
РАЗРАБОТКА РАСПРЕДЕЛЕННОЙ СИСТЕМЫ
АВТОМАТИЗИРОВАННОГО ОБНАРУЖЕНИЯ УЯЗВИМОСТЕЙ В
ПРОГРАММНОМ ОБЕСПЕЧЕНИИ
(Выпускная квалификационная работа)
Научный руководитель:
д.т.н. профессор
__________________/А.А. Захаров/
(подпись)
Автор работы:
__________________ /С.П. Глазунов/
(подпись)
Тюмень – 2014
ОГЛАВЛЕНИЕ
ВВЕДЕНИЕ .............................................................................................................. 4
ГЛАВА 1. ОБЗОР СУЩЕСТВУЮИХ ТЕХНОЛОГИЙ ВЫЯВЛЕНИЯ
УЯЗВИМОСТЕЙ В ПРОГРАММНОМ ОБЕСПЕЧЕНИИ.................................. 8
1.1. Основные типы уязвимостей. .......................................................... 8
1.1.1. Ошибки повреждения памяти. .................................................. 8
1.1.2. Состояние гонки. ...................................................................... 12
1.1.3. Отказ в обслуживании.............................................................. 12
1.1.4. Уязвимости веб-приложений. ................................................. 13
1.2. Методы обнаружения уязвимостей............................................... 15
1.2.1. Принцип «белого ящика». ....................................................... 15
1.2.2. Принцип «черного ящика». ..................................................... 18
1.2.3. Принцип «серого ящика». ........................................................ 20
1.3. Фаззинг. ............................................................................................ 23
1.3.1. Определение. ............................................................................. 23
1.3.2. Этапы фаззинга. ........................................................................ 23
1.3.3. Методы фаззинга. ..................................................................... 25
1.3.4. Типы фаззеров. .......................................................................... 26
Глава 2.
РАЗРАБОТКА РАСПРЕДЕЛЕННОЙ СИСТЕМЫ ПОИСКА
УЯЗВИМОСТЕЙ. .................................................................................................. 28
2.1. Обоснование выбора технологии. ................................................. 28
2.2. Требования к системе. .................................................................... 28
2.3. Модель системы. ............................................................................. 29
2.4. Реализация сервера. ........................................................................ 29
2.4.1. Общие сведения. ....................................................................... 29
2.4.2. Структура базы данных............................................................ 30
2.4.3. Веб-интерфейс управления системой..................................... 31
2.4.4. API для взаимодействия с клиентами..................................... 33
2.5. Разработка клиента. ........................................................................ 33
2.6. Разработка фаззера.......................................................................... 34
2.6.1. Общие сведения. ....................................................................... 34
2.6.2. Основные структуры фаззера. ................................................. 34
2.6.3. Сценарий работы. ..................................................................... 35
2.7. Оценка эффективности системы. .................................................. 36
2.7.1. Методика испытаний................................................................ 36
2.7.2. Результаты. ................................................................................ 36
ЗАКЛЮЧЕНИЕ ..................................................................................................... 38
СПИСОК ЛИТЕРАТУРЫ..................................................................................... 39
4
ВВЕДЕНИЕ
Актуальность темы дипломной работы. Задача поиска уязвимостей в
программном обеспечении возникает в процессе разработки средств
получения несанкционированного доступа специалистами государственных
или частных разведывательных организаций, специальных служб либо
киберпреступниками. Об актуальности этой задачи можно судить благодаря
появляющимся в открытом доступе данным о вознаграждениях , которые
предлагаются на «черном» рынке в обмен на информацию об уязвимостях для наиболее популярных программных продуктов эта сумма может достигать
сотен тысяч долларов США.[1][2]
Проблема обнаружения уязвимостей также является острой и для самих
разработчиков ПО. Ведущие игроки на рынке информационных технологий
используют новейшие средства затруднения эксплуатации вредоносных
программ и методы проактивной защиты и, тем не менее, вынуждены каждый
год исправлять сотни ошибок, связанных с безопасностью. Разумеется, для
разработчиков предпочтительней находить подобные ошибки в процессе
аудита приложения, а не в результате расследования уже произошедшего
инцидента ИБ.
Стремление
обнаружить
уязвимость
раньше,
чем
это
удастся
злоумышленникам, побуждает такие компании, как PayPal, Facebook или
Google,
организовывать
собственные
программы
вознаграждения
исследователей ИБ в обмен на данные об ошибках , причем бюджет наиболее
крупных программ превышает миллион долларов.
Готовность сторон расходовать на информацию об уязвимостях
значительные финансовые ресурсы позволяет предположить высокую
заинтересованность
автоматизирующих
в
инструментах,
процесс
облегчающих
обнаружения
и
тем
более
ошибок,
5
связанных с безопасностью.
Степень разработанности проблемы. Вопросы контроля качества и
поиска уязвимостей в ПО становились предметом изучения многих
отечественных исследователей, таких как Благодаренко А.В., Угрюмов Д.В.,
Миноженко А.В., Несов В.С., Маликов О.Р., Козлов Д. Д., Петухов А. А.
Однако используемый в данной работе метод обнаружения ошибок
(фаззинг) достаточно подробно рассмотрен лишь иностранными авторами ,
среди которых Ари Таканен, Джаред ДеМотт, Чарльз Миллер и Скот Ламберт.
Целью дипломной работы является разработка распределенной
системы автоматизированного обнаружения уязвимостей.
Поставленная цель обусловила следующие задачи дипломной
работы:

разработать модель распределенной системы поиска уязвимостей;

имплементировать модель с помощью подходящих программных
средств;

разработать нетривиальный фаззер, функционирующий в рамках данной
распределенной системы;

оценить эффективность полученной системы в реальных условиях
(обнаруженные в популярных приложениях ошибки должны подтвердить
практическую значимость);
Объектом
исследования
выступает
процесс
обнаружения
уязвимостей в ПО.
Предметом исследования в дипломной работе являются технологии
фаззинга, применяемые в задаче поиска уязвимостей в ПО.
В качестве методологической и теоретической основой дипломной
работы выступили работы отечественных и иностранных исследователей ,
посвященные динамическому анализу ПО и фаззингу в частности.
6
Теоретическая значимость дипломного исследования состоит в
анализе
существующих
методов
автоматизированного
обнаружения
уязвимостей и выявления наиболее оптимального из методов по соотношению
сложности разработки и эффективности.
Практическая значимость работы определяется возможностью
полноценного использования построенной системы в качестве одного из
важных инструментов исследователя ИБ. Прозрачная масштабируемость и
модульная структура
системы
при
этом
дает
возможность
использовать ее в течение неограниченного времени.
Новизна дипломной работы состоит в создании легко развертываемой
и расширяемой системы обнаружения ошибок, связанных с безопасностью, с
акцентом на веб-браузер в качестве цели (отражая тот факт, что браузер
является наиболее привлекательной мишенью и в реальных условиях).
Программного продукта со сходными характеристиками в процессе
исследования не удалось обнаружить в открытом доступе.
Кроме того, суть фаззинга как метода такова, что каждый новый
нетривиальный фаззер является в некотором роде уникальным и со
значительной долей вероятности в течение определенного времени будет
способен обнаруживать новые уязвимости.
Наиболее существенные результаты, полученные в процессе
исследования, состоят в следующем:
- разработана и имплементирована модель распределенной системы
поиска уязвимостей, в основе которой лежит технология фаззинга;
- разработан фаззер, позволяющий оценить безопасность таких
компонентов веб-браузера, как объектная модель, визуализация и прикладной
интерфейс;
7
- эффективность системы доказана фактом обнаружения с ее помощью
уязвимостей в популярном ПО.
8
ГЛАВА 1.
ОБЗОР СУЩЕСТВУЮИХ ТЕХНОЛОГИЙ
ВЫЯВЛЕНИЯ УЯЗВИМОСТЕЙ В ПРОГРАММНОМ
ОБЕСПЕЧЕНИИ.
1.1. Основные типы уязвимостей.
1.1.1. Ошибки повреждения памяти.
Использование уязвимостей, связанных с повреждением памяти, является
наиболее распространенным и эффективным методом проведения атак на
локальную или удаленную систему. Если содержимое оперативной памяти
может быть повреждено (например, адрес возврата, указатель на функцию и
т.д.), часто поток выполнения может быть перенаправлен на код,
предоставленный злоумышленником.[3]
Термин переполнение буфера хорошо известен специалистам в области
компьютерной безопасности, однако является несколько общим. Например,
переполнение может произойти в статическом массиве в стеке либо в области,
выделенной в куче. Обе уязвимости представляют собой переполнение
буфера, однако детали их эксплуатации существенно отличаются. Рассмотрим
этот класс уязвимостей подробнее.
1.1.1.1. Переполнение стека.
Переполнение стека представляет собой повреждение памяти в стеке в
результате некорректно реализованной проверки выхода за границы области .
Уязвимость демонстрирует следующий код на языке Си:
void func(char* str)
{
char buffer[10];
strcpy(buffer, str);
9
}
Если длина строки в параметре str превысит 9 символов, возможна
подмена адреса возврата на значение, контролируемое атакующим.
Благодаря использованию технологий противодействия атакам для
современных операционных систем подобный код не представляет угрозы.
Однако все еще опасны менее тривиальные варианты данной уязвимости.
1.1.1.2. Ошибки форматной строки.
Данный вид ошибок получил наибольшее распространение в 1990-е годы.
Уязвимость связана с некорректным использованием функций семейства
printf, когда контролируемый пользователем параметр передается в
функцию в качестве строки формата. Пример:
int main(int argc, char* argv[])
{
printf(argv[1]);
}
Запуск такой программы с параметром %s%s%s%s%s может привести к
ее сбою.
В настоящее время данный вид практически не встречается в популярных
программных продуктах, поскольку он легко обнаруживается средствами
статического анализа.
1.1.1.3. Целочисленное переполнение.
Для
представления
целочисленных
переменных
используется
фиксированный объем памяти (для современных систем обычно это 32 или 64
бита). Соответственно диапазон значений, которые может принимать
целочисленная переменная, ограничен. При попытке инкрементировать
переменную, достигшую своего максимального значения, она будет сброшена
10
т.е. приравнена к нулю.
Уязвимость может возникнуть в том случае, когда значения, полученные
в результате целочисленных операций, ошибочно используются в качестве
аргументов в функциях выделения памяти. Кроме того, целочисленные
операции применяются в процессе проверки выхода за границы области во
время копирования из одного буфера в другой.
1.1.1.4. Ошибки с целочисленными знаковыми.
Существуют беззнаковые и знаковые целочисленные типы, отличие
между которыми заключается в возможности использовать отрицательные
значения.
Обычно
для
представления
таких
значений
применяется
дополнительный код, особенность которого состоит в том, что отрицательные
числа хранятся в памяти как большие беззнаковые. Таким образом, в
результате
умножения
положительных
значений
может
получиться
отрицательное.
Уязвимость также, как и в случае с целочисленными переполнениями,
может проявиться, когда результат подобных некорректных арифметических
операций используется для проверки выхода за границы выделенной области.
1.1.1.5. Ошибки завышения или занижения на единицу.
Подобная ошибка обычно возникает, когда размер записанных в буфер
данных на единицу превышает его емкость. Для некоторых архитектур (в их
числе наиболее распространенная Intel x86) это может привести к выполнению
произвольного
кода в случае, когда буфер расположен
в памяти
непосредственно перед указателем кадра или указателем на функцию.
Уязвимый код:
void func(char* s)
{
11
char buffer[100];
memset(buffer, 0, sizeof(buffer));
strncat(buffer, s, sizeof(buffer));
}
В данном случае не учитывается тот факт, что фактический размер строки
в Си превышает количество символов (каждая строка содержит нулевой байт
в конце).
1.1.1.6. Переполнение кучи.
Работа с динамически выделяемой памятью реализуется посредством
структуры данных, названной «куча». В отличие от стека, время жизни
объектов, выделенных в куче, не ограничено выполнением определенной
функции. После того как использование объекта завершится, необходимо
самостоятельно освободить занимаемую им память.
Так же как в случае с переполнением стека, переполнение буфера в куче
приводит к повреждению смежных участков памяти. Главное отличие
заключается в том, что в выделенные в стеке структуры имеют
фиксированный размер, тогда как размеры объектов, выделенных в куче могут
быть динамически изменены. Как правило, уязвимость возникает вследствие
некорректной реализации этого процесса.
1.1.1.7. Использование после освобождения.
Рассмотрим следующий код:
void func()
{
int* n = new int;
delete n;
*n = 123;
12
}
Очевидно, динамически выделенный объект в примере продолжает
использоваться после того, как область памяти, которую он занимает, была
освобождена. В этот момент данная область может быть заново выделена для
хранения другого объекта, в результате происходит повреждение памяти и
появляется возможность выполнения произвольного кода.
1.1.2. Состояние гонки.
Состояние гонки – это ошибка проектирования приложения в
многозадачной среде, при которой работа программы зависит от порядка и
времени выполнения частей кода. Пример:
if (!access(tempfile, W_OK)) {
fp = fopen(tempfile, “a+”);
…
Предположим, что приложение содержащее данный код, имеет более
высокий уровень привилегий, чем атакующий. Проблема заключается в том,
что
существует
задержка
между
проверкой
доступа
к
указанному
пользователем пути в системе и открытием файлового дескриптора. За это
время злоумышленник может подменить файл на символьную ссылку,
указывающую, например, на таблицу пользователей.
1.1.3. Отказ в обслуживании.
Отказ в обслуживании (denial of service, DoS), так же как и
распределенный отказ в обслуживании (DDoS), это действие, направленное на
перегрузку системы или службы до такой степени, когда она будет не в
состоянии обрабатывать поступающие запросы. Наиболее известным
примером такой атаки является SYN flood – отправка большого количества
пакетов на установление TCP соединения, что вызывает потребление всех
13
доступных ресурсов системы.
Отказ в обслуживании возможен также и на прикладном уровне .
Злоумышленник, обнаруживший в коде веб-сервера переполнение буфера,
которое невозможно эксплуатировать для выполнения произвольного кода,
может использовать его для аварийного завершения процесса. Однако, такой
подход будет несколько нерациональным.
1.1.4. Уязвимости веб-приложений.
В связи с непрерывным развитием сети Интернет все большую
значимость приобретает вопрос безопасности веб-приложений. Атаки
происходят повсеместно, им подвергаются и системы интернет-банкинга, и
корпоративные ресурсы, и просто популярные сайты с целью распространения
с их помощью вредоносного ПО. Поэтому специалисты в данной области
широко востребованы.[4]
Рассмотрим
наиболее
известные
классы
уязвимостей,
которым
подвержены веб-приложения.
1.1.4.1. PHP-инъекция.
PHP - один из наиболее популярных языков программирования ,
используемых для создания динамических веб-страниц. РНР-инъекции
позволяют атакующему выполнить произвольный код на уязвимом вебсервере. Пример:
include($page . ‘somefile.php’);
Если злоумышленник выполнит запрос вида:
http://victim.com/index.php?page=http://evil.com/
То произойдет загрузка и исполнение веб-сервером файла, содержание
которого контролируется атакующим.
14
1.1.4.2. SQL-инъекция.
Большинство приложений для получения информации из базы данных
использует запросы на языке SQL. В случае, когда проверка корректности
входных данных реализована неверно либо отсутствует, и эти данные
используются в качестве параметра в SQL-запросе, атакующий может
получить несанкционированный доступ к информации либо нарушить
процесс аутентификации. В определенных конфигурациях SQL-инъекция
может привести к выполнению произвольного кода на удаленной системе .
Рассмотрим код:
$query = “SELECT * FROM users WHERE name = ‘” + $user + “’”;
Если злоумышленник в качестве параметра $user передаст следующую
строку:
‘ or ‘a’=’a
В результате запрос, обработанный СУБД, будет выглядеть как
SELECT * FROM users WHERE name = ‘’ or ‘a’=’a’
что позволит обойти аутентификацию так как второе условие всегда
истинно.
1.1.4.3. Межсайтовое выполнение скриптов.
Самый распространенный метод, который применяют злоумышленники
для получения прав другого пользователя на определенном веб-ресурсе, - это
использование межсайтового выполнения скриптов (cross site scripting , XSS).
Данный вид уязвимостей так же, как и предыдущие, связан с недостаточной
фильтрацией входных данных, в данном случае элементов языка HTML и кода
JavaScript.
Существует два основных класса подобных уязвимостей: отраженные и
хранимые. Отраженные представляют собой выполнение в контексте
15
атакованного приложения кода, включенного в текст запроса (например, в
одном из параметров URL-адреса). Для успешного выполнения атаки жертва
должна перейти по специально сформированной ссылке. В случае, если
ошибка относится ко второму, наиболее опасному классу, внедряемый
злоумышленником код хранится на сервере и исполняется браузером каждого
пользователя, который зашел на уязвимую страницу.
1.2. Методы обнаружения уязвимостей.
После того, как основные классы уязвимостей определены, необходимо
составить представление о методах, которые применяются для обнаружения
таких ошибок. В данном случае признаком, по которому производится
группировка методов, является доступная исследователю информация о
программном продукте. Первый тип, тестирование по принципу «белого
ящика», предполагает наличие доступа к любым ресурсам, в первую очередь
к исходным кодам, а также техническому заданию и всевозможной
документации.
Второй тип, тестирование по принципу «черного ящика», наоборот не
требует никаких знаний о внутреннем устройстве программы, необходима
лишь возможность взаимодействия с ней. Примером такого тестирования
является внешний аудит веб-приложения с закрытым исходным кодом.
Наконец, третий тип, тестирование по принципу «серого ящика»,
подразумевает, что в распоряжении у специалиста находится исполняемый
файл приложения и, возможно, некая базовая документация.[6]
Далее каждый тип будет рассмотрен более подробно.
1.2.1. Принцип «белого ящика».
1.2.1.1. Аудит исходного кода.
Аудит исходного кода может быть выполнен либо вручную, либо с
16
использованием средств автоматизации. С учетом того, что современные
программы могут достигать объема в сотни тысяч строк программного кода ,
полностью ручной анализ представляется недостаточно эффективным.
Средства автоматизации способны избавить аналитика от необходимости
тщательно
изучать
каждую
строку
кода
программы,
однако
они
обнаруживают лишь потенциально уязвимые либо подозрительные участки.
Каждый такой участок должен быть впоследствии рассмотрен вручную.
Распространено мнение, что тестирование методом «белого ящика»
значительно эффективней чем методом «черного ящика», ведь исходный код
дает наиболее полное представление об устройстве программы. Однако не
стоит забывать, что во время трансляции исходного кода в процессорные
инструкции, компилятор может вносить в структуру программы значительные
изменения. Поэтому то что видит исследователь часто не совпадает с тем, что
выполняется на самом деле.
Данный факт свидетельствует о том, что не существует метода
обнаружения уязвимостей, который был однозначно лучше остальных. Для
получения наилучших результатов необходимо использовать все возможные
подходы.
1.2.1.2. Инструменты автоматизации.
Средства анализа исходного кода обычно относятся к одной из трех
категорий. Такими категориями являются средства проверки кода в процессе
компиляции, средства ускоренного просмотра исходных кодов и инструменты
автоматизированного аудита.
Утилиты первой категории предоставляют возможность обнаружить
ошибки, связанные с безопасностью, во время компиляции приложения.
Обычно такие утилиты встраиваются в сам компилятор. Примером может
17
служить опция /analyze для Microsoft Visual C++ Compiler, кроме того
Microsoft распространяет ПО PREfast for Drivers, которое позволяет находить
характерные для разработки драйверов уязвимости, которые не способен
обнаружить компилятор.[7]
Средства ускоренного просмотра исходного кода - это инструменты,
предоставляющие помощь при аудите кода вручную. Данный класс позволяет
применять продвинутые правила поиска, а также определять и перемещаться
между перекрестными ссылками в рамках исходных кодов программы .
Примерами популярных продуктов, относящихся к данной категории,
являются Cscope и LXR.
Инструменты автоматизированного аудита исходного кода, как очевидно
из названия, сканируют код приложения и выявляют потенциально опасные
места без участия человека. В настоящее время на рынке присутствует
большое количество программных решений данного класса. Из наиболее
популярных можно отметить Coverity[8] (см. рисунок 1) и HP Fortify среди
коммерческих, а также RATS и CodeSpy среди бесплатных.
Рисунок 1. Работа программы Coverity Security Library.
1.2.1.3. Оценка метода.
Тестирование
методом
«белого
ящика»
обладает
существенным
преимуществом – это покрытие кода. Так как исходные коды доступны,
18
каждый путь в программе может быть проанализирован на предмет наличия
потенциальных
уязвимостей.
Это,
однако,
может
приводить
к
ложноположительным срабатываниям, так как определенный путь может
быть недоступен во время выполнения.
К недостаткам данного метода можно отнести сложность, ведь
существующие инструменты неидеальны и производят большое количество
ложных срабатываний. Поэтому отчет, сформированный в результате работы
программы, должен быть тщательно изучен компетентным специалистом .
Учитывая объем кода, который содержат современные приложения, такие
отчеты могут достигать огромной длины.
Еще одним минусом такого подхода является доступность. В то время,
как в среде UNIX приложения часто поставляются вместе с исходными
кодами, в окружении Windows, а тем более в коммерческих продуктах, такой
подход практически не встречается. Очевидно, что в этом случае тестирование
по методу «белого ящика» не может быть использовано.
1.2.2. Принцип «черного ящика».
Принцип «черного ящика» подразумевает, что аналитик может лишь
наблюдать за поведением приложения, т.е. контролировать входные данные,
поступающие в программу, и анализировать выходные данные, но не имеет
представления о ее внутренней структуре. Обычно такая ситуация возникает
в процессе аудита удаленных веб-приложений. Кроме того, если в процессе
исследования программы, распространяемой в виде бинарных кодов, не
применяются приемы обратной разработки, метод «черного ящика» является
единственного возможным.
1.2.2.1. Ручное тестирование.
Рассмотрим пример веб-приложений. В этом случае при ручном
19
тестировании исследователь с помощью обычного интернет-браузера
перемещается по страницам приложения, подставляя в поля ввода и
параметры запросов специальные символы, например, символ одинарной
кавычки для выявления потенциально уязвимых к SQL-инъекциям сценариев.
В настоящее время, однако, ручное тестирование без использования
средств автоматизации считается неэффективным.
1.2.2.2. Автоматизированное тестирование (фаззинг).
Несмотря на то, что в основе фаззинга лежит метод грубой силы,
недостаток изящности при таком подходе компенсируется его простотой и
эффективностью. По сути фаззинг – это передача для обработки исследуемым
приложением большого количества случайных входных данных и анализ
результатов его работы. В дальнейшем этот метод будет рассмотрен
подробнее.
Стоит
отметить,
что
существуют
более
продвинутые
фаззеры,
генерирующие не полностью случайные входные данные, а опирающиеся на
спецификации
исследуемых
протоколов
и
форматов
файлов.
Такие
инструменты можно также отнести также категории методов «серого ящика».
1.2.2.3. Оценка метода.
К преимуществам тестирования по принципу «черного ящика» относят:
 Доступность. Данный метод применим в любых ситуациях и
может быть полезен даже в том случае, если доступны исходные
коды приложения.
 Универсальность. Так как подход не опирается на какие-либо
сведения о конкретном программном продукте, инструмент,
созданный, например, для оценки безопасности одного веб-сервера,
может использоваться и для любого другого.
20
 Простота. На самом элементарном уровне фаззинг не требует
никаких знаний о внутренней структуре программы . Разумеется,
однако, что наиболее сложные ошибки таким способом обнаружить
практически невозможно.
Данный метод тестирования имеет и ряд недостатков:
 Покрытие. Один из наиболее сложных вопросов, который
необходимо решить в процессе фаззинга, – когда необходимо
прекратить тестирование и насколько оно было эффективно.
 Примитивность. Фаззинг плохо справляется с обнаружением
сложных уязвимостей, таких, которые занимают несколько этапов
чтобы поместить программу в определенное состояние и из него
вызвать ошибку. Такие уязвимости как правило выявляют
посредством анализа исходного кода.
1.2.3. Принцип «серого ящика».
Тестирование по принципу «серого ящика» представляет собой
комбинацию методов, использующихся при тестировании по принципу
«черного ящика», а также технологий и приемов обратной разработки.
Ценность исходного кода в процессе поиска уязвимостей заключается в том,
что он представляет логику работы программы в понятном для исследователя
представлении.
Технология,
направленная
на
извлечение
подобной
информации напрямую из бинарного файла, имеет название двоичный анализ
(т.е. анализ двоичного кода).
1.2.3.1. Двоичный анализ.
Основная цель двоичного анализа – определение внутренней логики
работы уже скомпилированного приложения. Не существует инструмента,
который позволил бы получить оригинальный исходный код из бинарного
21
файла. Однако, с помощью средств обратной разработки возможно
представить программу в виде, который хоть и сложнее для восприятия чем
исходный код, но значительно легче, чем машинный. Пример такого
представления – графически связанные блоки ассемблерных инструкций,
отображающие поток выполнения (см. рисунок 2).
Рисунок 2. Скриншот из программы IDA Pro.
После этого, как и в случае с анализом исходного кода, программу
исследуют на предмет потенциально опасных участков. Кроме того,
необходимо определить, возможен ли такой набор входных данных, при
котором поток выполнения достигнет уязвимого участка.
К инструментам, использующимся в процессе двоичного анализа,
относятся дизассемблеры, декомпиляторы и отладчики. Дизассемблеры
переводят машинный код в список инструкций на языке ассемблера. Наиболее
известным продуктом и безусловным лидером в данной категории является
разработка наших соотечественников IDA Pro[9].
Декомпиляторы выполняют схожую задачу, однако выделяют в коде
22
более высокоуровневые конструкции, например, ветвления и циклы.
Восстановить изначальный код невозможно, ведь в процессе компиляции
программы теряется значительная часть информации: названия переменных и
функций, комментарии, и даже некоторые методы и структуры, поэтому
декомпиляторы чаще используют для языков, которые транслируются в
промежуточный байт-код, например, C# или Java. Тем не менее, в последнее
время появились подходящие для практического применения декомпиляторы
для C и C++,. Примером может служить еще одна отечественная разработка,
Hex-Rays Decompiler.
Отладчик – это инструмент динамического анализа. Такая программа
позволяет управлять состоянием процесса, создавать точки останова,
производить пошаговое выполнение, а также в реальном времени наблюдать
содержимое регистров процессора и оперативной памяти . К инструментам
данного класса относятся бесплатно распространяемые WinDBG и GDB.
1.2.3.2. Автоматизированный двоичный анализ.
Данная категория приложений – это попытка автоматизировать процесс
двоичного анализа с целью поиска потенциальных уязвимостей в двоичных
файлах. Стоит отметить невероятную сложность реализации подобного
продукта, имеющего реальную практическую ценность, так как даже ручной
аудит представляет собой нетривиальную задачу. Определенных успехов в
этой области добилась компания Veracode, предоставляющая услуги
автоматизированного анализа в виде SaaS.
1.2.3.3. Оценка метода.
Данный метод наследует одно из преимуществ тестирования по принципу
«черного ящика» – доступность. Для исследования подходят любые
приложения, за исключением удаленных сервисов.
23
Еще одним существенным достоинством является покрытие кода.
Информация, полученная в результате двоичного анализа, способна
существенно улучшить качество генерируемых фаззером входных данных .
Большим недостатком данного метода является его сложность. Среди
рассмотренных
технологий
поиска
уязвимостей
данная
предъявляет
наивысшие требования к квалификации аналитика.
1.3. Фаззинг.
1.3.1. Определение.
Фаззинг
–
это
технология
автоматизированного
тестирования
программного обеспечения с целью выявления потенциальных уязвимостей,
которая
охватывает
большое
количество
граничных
случаев
путем
порождения некорректных входных данных. В качестве входных данных при
этом могут выступать обрабатываемые приложением файлы, информация,
передающаяся по сетевым протоколам, функции прикладного интерфейса и
т.д. Термин возник в эпоху аналоговых телефонных сетей, когда
обнаружилось, что случайный шум (fuzz) на линии может вызвать сбой в
управляющим модемом программном обеспечении.
Впервые работа на данную тему была опубликована в 1988 году
профессором Университета штата Висконсин Бартоном Миллером. Он создал
простейший фаззер параметров командной строки для программ ОС UNIX.
Тем не менее, долгое время технология была неизвестной для большинства
специалистов
и
лишь
в
последние
годы
получила
значительное
распространение. В настоящий момент, фаззинг внедряется в качестве
обязательного этапа в процесс разработки программного обеспечения.
1.3.2. Этапы фаззинга.
Существует большое количество различных приемов и методов фаззинга,
24
выбор которых зависит от целей и квалификации аналитика. Однако,
последовательность основных этапов данного процесса остается неизменной:
Определение объекта. В случае, когда фаззинг является этапом процесса
разработки, объект исследования, очевидно, определен заранее. Если же
тестирование выполняется в рамках теста на проникновение, важно
определить, какой из сервисов в системе является потенциально наиболее
уязвимым.
Определение входных данных. В широком смысле, причина любой
уязвимости заключается в недостаточной фильтрации входных данных.
Вероятность обнаружить ошибку растет напрямую с количеством доступных
способов ввода. Причем, некоторые их таких способов могут быть достаточно
неочевидны.
Формирование входных данных. После того как все возможные виды
входных данных определены, наступает процесс генерации тестовых наборов.
В зависимости от формата данных этот процесс представляет собой изменение
существующих наборов, генерацию новых с нуля или использование
предопределенных значений.
Обработка входных данных. Полученные в предыдущем шаге тестовые
наборы передаются в исследуемое приложение. Эта задача может быть
реализована посредством отправки сетевого пакета, запуска файла и т.д.
Мониторинг исключений. Необходимо постоянно отслеживать состояние
приложения чтобы иметь возможность определить тестовый набор , который
вызвал сбой.
Определение возможности использовать уязвимость. Цель последнего
этапа фаззинга – определить, действительно ли ошибка, повлекшая сбой
программы, является уязвимостью, а также при каких условиях возможна ее
25
эксплуатация.
1.3.3. Методы фаззинга.
1.3.3.1. Полностью случайное тестирование.
Данный метод тестирования является наименее эффективным, обладая
ничтожным покрытием. В настоящий момент его использование практически
лишено смысла. При таком подходе фаззер, не имея никакой информации о
синтаксической
структуре
входных
данных,
формирует
массив
псевдослучайных данных, который передает исследуемой программе.
Несмотря на свою примитивность, подобный метод в прошлом позволял
выявлять уязвимости в популярных приложениях.
1.3.3.2. Мутирующее тестирование.
Мутирующий фаззер содержит коллекцию корректно сформированных
входных данных. Искажая в таких данных случайный байт или строку, он
получает
очередной
тестовый
набор.
Данный
подход
значительно
эффективней предыдущего. Кроме того, создание мутирующего фаззера не
требует значительных временных затрат и высокой квалификации .
Тем не менее, вероятнее всего, что тестируемая программа будет
отвергать большую часть поступающих данных как не соответствующую
спецификации. Также, покрытие кода в данном случае напрямую зависит от
того, насколько хорошо сформирована база корректных данных.
1.3.3.3. Порождающее тестирование.
Порождающее тестирование – наиболее продвинутый метод фаззинга. В
данном случае исследователь должен предварительно изучить спецификацию
протокола или формата файла и на основе такой спецификации создать
грамматику, указав в ней переменные, статические данные, а также
динамически вычисляемые величины (например, контрольные суммы). Затем
26
фаззер на ее основе формирует тестовые наборы.
Эффективность данного метода тем выше, чем точнее описана
грамматика, кроме того, она обычно выше в сравнении с эффективностью
мутирующего тестирования. К минусам подхода можно отнести повышенную
сложность разработки.
1.3.4. Типы фаззеров.
После того, как было дано описание этапов и методов фаззинга, перейдем
к рассмотрению популярных типов фаззеров. Тип определяется приложением,
для тестирования которого предназначен фаззер, а точнее форматом входных
данных, которые оно обрабатывает.
1.3.4.1. Локальные фаззеры.
Первые два типа обязаны своему появлению среде UNIX и механизму
setuid.
Благодаря этому механизму пользователь может выполнять
некоторые приложения с повышенными привилегиями, следовательно,
уязвимость в таком приложении позволит выполнить произвольный код от
имени суперпользователя. Поэтому, setuid-программы часто становятся
объектом фаззинга.
Фаззеры командной строки. Практически любое приложение во время
запуска считывает параметры командной строки, переданные пользователем,
в том числе и setuid-программы. Формат данных в данном случае
тривиальный, как и сам фаззер. Пример такого инструмента – утилита clfuzz.
Фаззеры переменных окружения. Аналогичный тип, за исключением
того, что вместо параметров командной строки используются переменные
окружения. Процесс фаззинга предельно прост, примером служит программа
Sharefuzz.
Фаззеры файловых форматов. Большинство приложений в процессе
27
работы взаимодействуют с различными файлами. С точки зрения фаззинга
файл – это один из видов входных данных. Сложность формата файла может
быть очень высокой, если это, например, формат документа современного
офисного редактора или видеозаписи, соответственно возрастает сложность
самих фаззеров. В качестве примера можно рассмотреть программу FileFuzz.
1.3.4.2. Удаленные фаззеры.
Фаззеры сетевых протоколов. Учитывая степень распространения сети
Интернет в настоящий момент, естественно, что сетевые приложения
являются наиболее вероятными объектами тестирования. Технология
фаззинга при этом значительно отличается в зависимости от сложности
исследуемого протокола. Простейшие случаи – это текстовые протоколы без
какой-либо проверки целостности. Наиболее сложные – бинарные протоколы
с использованием аутентификации, шифрования и контрольных сумм.
Мощный инструмент данного типа – фреймворк Peach.[10]
Фаззеры веб-приложений. Инструменты данного типа заточены на
выявление узявимостей, специфичных для веб приложений, таких как SQLинъекции или межсайтовый скриптинг. Фаззеры веб-приложений используют
протокол передачи гипертекста (HTTP) в качестве канала связи с исследуемым
веб-сервером. Один из примеров – Powerfuzzer.
Фаззеры
интернет-браузеров.
Современный
интернет-браузер
реализует огромное количество технологий: это сетевые протоколы, языки
разметки HTML и XML, CSS, объектная модель документа (DOM),
графические, аудио- и видео-форматы т.д. Кроме того, браузер – самая
популярная прикладная программа. Эти факторы послужили причиной
появления целого класса фаззеров, заточенных для тестирования интернетбраузеров. К данному типу относятся инструменты mangleme и ref_fuzz.[11]
28
ГЛАВА 2.
РАЗРАБОТКА РАСПРЕДЕЛЕННОЙ
СИСТЕМЫ ПОИСКА УЯЗВИМОСТЕЙ.
2.1. Обоснование выбора технологии.
В предыдущей главе был дан анализ существующих методов
обнаружения уязвимостей. Для реализации в рамках аттестационной работы
был выбран фаззинг. Основным аргументом в пользу этого выбора послужило
высокое соотношение эффективности и времени разработки инструмента.
Система подтвердила свою практическую ценность при поиске уязвимостей в
реальных приложениях еще на этапе.
Дополнительным аргументом стал существенный интерес к методу со
стороны корпораций - крупнейших разработчиков программного обеспечения,
инвестирующих
значительные
ресурсы
в
технологии
фаззинга.
Предположительно, подобна реакция указывает на перспективность метода.
2.2. Требования к системе.
Выбор технологии тестирования определил следующие основные
требования к системе:
 Автоматизация работы. Практически каждое исследование на
тему фаззинга содержит указание о необходимости максимально
автоматизировать процесс.[12] В данном случае это означает
контроль за состоянием исследуемого процесса (с его перезапуском
в случае сбоя) и автоматическая регистрация результатов работы
фаззера (включая отладочную информацию).
 Горизонтальное
масштабирование.
Фаззинг
является
ресурсоемкой задачей. Необходимо реализовать возможность
масштабирования системы хотя бы в рамках аппаратной базы
29
аналитика.
 Централизованное управление.
 Централизованное хранение результатов работы. Два этих
требования необходимы, чтобы обеспечить эффективную работу в
рамках масштабируемой системы.
2.3. Модель системы.
Набор ключевых компонентов и их функций был определен исходя из
предъявленных
к
системе
требований.
Ознакомиться
с
иехрархией
получившейся модели можно на рисунке 3.
Сервер
управление
отладка
запуск
Клиент
обработка
Тестируемое
приложение
…
Фаззер
Рисунок 3. Модель системы.
Рассмотрим каждый компонент индивидуально.
2.4. Реализация сервера.
2.4.1. Общие сведения.
Серверная
составляющая
элементами:
 база данных
системы
представлена
следующими
30
 веб-интерфейс управления
 прикладной интерфейс (API) для взаимодействия с клиентами
Веб-интерфейс и API реализованы на платформе Node.js[13]. Данная
платформа предоставляет возможность использовать язык JavaScript для
разработки серверных приложений. В качестве СУБД была выбрана
SQLite[14]
–
компактная
встраиваемая
реляционная
база
данных.
Преимущество такой конфигурации заключается в кроссплатформенности и
удобстве развертывания системы.
2.4.2. Структура базы данных.
На данный момент база данных содержит 7 таблиц.
Описание таблиц:
Fuzzers
Содержит информацию о доступных системе фаззерах.
Clients
Содержит информацию о клиентах, выполняющих тестирование.
Targets
Cодержит информацию о приложениях, проходящих тестирование.
Tasks
Содержит информацию заданиях, сформированных системой.
Results
Содержит информацию об успешных результатах (т.е. сбоях исследуемой
программы).
TaskClients
Содержит информацию о связанных заданиях и клиентах.
ClientTargets
Содержит информацию о связанных клиентах и доступных им
приложениях.
31
2.4.3. Веб-интерфейс управления системой.
Все функции веб-интерфейса сгруппированы по разделам.
Фаззеры.
Данный раздел позволяет загрузить в систему новый фаззер, а также
просмотреть или изменить информацию о уже существующем, например, его
имя или параметры запуска.
Клиенты.
Раздел служит для управления клиентами системы, также здесь можно
увидеть, какие из клиентов активны в данный момент.
Цели.
Примитивный раздел, который служит для управления списком программ
– объектов фаззинга.
Задания.
Основной раздел системы.
 фаззер
 тестируемое приложение
 список клиентов, используемых в данном задании
 начальный и конечный номер теста
32
Рисунок 4. Раздел "Задания".
Результаты.
Данный раздел содержит информацию о случаях, когда в процессе
фаззинга произошел сбой тестируемой программы, т.е. информацию о
потенциальных уязвимостях (см. рисунок 5).
Аналитику
предоставляется
возможность
информацию и сведения о тесте, вызвавшем сбой.
загрузить
отладочную
33
Рисунок 5. Раздел "Результаты".
2.4.4. API для взаимодействия с клиентами.
Интерфейс взаимодействия с клиентами реализован с использованием
REST-подобной архитектуры. Все передаваемые данные, кроме файлов,
сериализуются в формат JSON. Обмен ведется по протоколу HTTP.
Рассмотрим несколько типов сообщений, которые может отправлять сервер:
requestTest – предложение клиенту выполнить определенный тест из
задания, клиент вправе отказаться;
responseFuzzer – ответ клиенту на запрос фаззера. В ответе содержится
URL для загрузки;
pong – ответ на сообщение проверки соединения.
2.5. Разработка клиента.
Одной из основных задач клиента является контроль за состоянием
тестируемого процесса и регистрация отладочной информации в случае его
34
сбоя. Этого можно добиться, используя такие WinAPI функции, как
WaitForDebugEvent
и
MiniDumpWriteDump[15].
Применение
WinAPI
повлияло на выбор языка разработки – это С++.
Вторая важная задача – обеспечения взаимодействия с сервером. Для этих
целей используется библиотека JsonCpp.
Описание API было дано в предыдущем разделе.
2.6. Разработка фаззера.
2.6.1. Общие сведения.
Разработанный фаззер предназначен для оценки безопасности интернетбраузеров. Наиболее вероятными областями выявления уязвимостей в данном
случае являются объектная модель документа (DOM), визуализация и
прикладной интерфейс браузера (browser API). Фаззер ориентирован на
обнаружение
таких
типов
уязвимостей,
как
использование
после
освобождения, целочисленное переполнение, переполнение буфера и, в
меньшей степени, состояние гонки.
Инструмент разработан на языке JavaScript и не требует дополнительного
ПО для запуска. Используется собственная имплементация генератора
случайных чисел (ГПСЧ), так как встроенные средства JavaScript не
позволяют задавать инициализирующее значение для ГПСЧ. Это необходимо,
чтобы однозначно связать каждый тест с его порядковым номером, обеспечив
повторяемость результатов.
Данное средство совмещает мутирующий и порождающий методы
фаззинга.
2.6.2. Основные структуры фаззера.
Объект «окно» в прикладном интерфейсе браузера является корневым.
Логичным является решение начать обход дерева объектов с него. Чтобы
35
случайным образом не нарушить логику работы фаззера, все манипуляции
выполняются не над основным окном, а над специально созданными
вспомогательными.
В процессе обхода дерева объектов инструмент часто использует
информацию о типах параметров и свойств. База с такой информацией была
предварительно сгенерирована в процессе разработки фаззера из набора
файлов спецификации DOM.
Кроме того, для распространенных типов в JavaScript, например,
числовых, или функциональных, были составлены наборы граничных
значений, ориентируясь на соответствующую литературу в данной области.
Практически все действия, которые совершает фаззер, обозначаются как
«псевдослучайные», так как факт их выполнения определяется состоянием
ГПСЧ. Инструмент содержит таблицу эмпирически полученных наиболее
оптимальных величин вероятностей для каждого действия.
2.6.3. Сценарий работы.
Каждый тест делится на определенное количество раундов. Опишем
порядок действий, который выполняется во время каждого раунда:
1. Происходит загрузка файлов из предварительно сформированного
набора во вспомогательные окна.
2. Выполняется обход дерева объектов.
3. Содержимое окон случайным образом изменяется так, чтобы
спровоцировать
уязвимость
типа
использование
освобождения.
4. Инициируется вызов сборщика мусора.
5. Выполняется повторный обход дерева.
6. Исследуются объекты из промежуточного пула.
после
36
7. Происходит удаление и повторное создание вспомогательных окон.
8. Размер промежуточного пула корректируется для нового раунда.
9. Повторный вызов сборщика мусора.
Основная логика работы программы заложена в функции обхода . В
случайном порядке исследуются доступные свойства очередного объекта . В
зависимости от типа значения этого свойства принимаются разные решения:
 если значение – объект, он может быть добавлен в промежуточный
пул, также обход может продолжиться с этого объекта;
 если значение – функция, будет предпринята попытка составить
корректный вызов, используя информацию о типах аргументов из
предварительно
сформированной
базы,
а
также
объектов
промежуточного пула и эвристик;
 кроме того, программа может попытаться изменить свойство
объекта, используя набор граничных значений соответствующего
типа.
2.7. Оценка эффективности системы.
На данный момент система до сих пор находится в стадии разработки,
поэтому были проведены лишь испытания с целью подтвердить практическую
значимость.
2.7.1. Методика испытаний.
 Продолжительность испытаний – 16 часов.
 Приложение для тестирования – браузер Google Chrome версии 32.
 Использовался 1 компьютер.
 Тестирование велось без вмешательств извне.
2.7.2. Результаты.
За время тестирования была обнаружена одна уязвимость высокой
37
степени опасности – использование после освобождения в компоненте V8 (см.
рисунок 4).
Рисунок 6. Анализ обнаруженной уязвимости с помощью WinDBG.
Также было выявлено целочисленное переполнение в коде обработки
аудиофайлов, однако процесс браузера аварийно завершается прежде чем
появляется возможность эксплуатировать уязвимость.
Кроме того, система обнаружила не менее 9 (без учета повторений)
различных ошибок разыменования нулевого указателя. Такие ошибки не несут
вреда безопасности приложения и могут представлять лишь проблему
стабильности.
Обнаружение даже одной уязвимости в популярном приложении за такой
срок в автоматическом режиме можно считать свидетельством достаточной
эффективности.
38
ЗАКЛЮЧЕНИЕ
В
рамках
данной
аттестационной
работы
была
разработана
распределенная система автоматизированного обнаружения уязвимостей. На
первом этапе была дана классификация уязвимостей и выполнен анализ
методов и технологий их выявления. На основе данного анализа была выбрана
технология поиска уязвимостей, сформулированы требования и определена
модель системы.
На
этапе
программирования
разработанная
модель
была
имплементирована. Кроме того, был разработан фаззер, функционирующий в
рамках
созданной
системы.
Впоследствии
была
проведена
оценка
эффективности. Можно сделать вывод о том, что поставленные задачи
выполнены, соответственно достигнута цель работы.
39
СПИСОК ЛИТЕРАТУРЫ
1. Forbes [Электронный ресурс] //URL:
http://www.forbes.com/sites/andygreenberg/2012/03/23/shopping-forzero-days-an-price-list-for-hackers-secret-software-exploits/ (Дата
обращения: 20.12.13)
2. New York Times [Электронный ресурс] //URL:
http://www.nytimes.com/2013/07/14/world/europe/nations-buyin?g-ashackers-sell-computer-flaws.html (Дата обращения: 20.12.13)
3. Michael Sutton, Adam Greene, and Pedram Amini. Fuzzing : brute force
vulnerabilty discovery. Upper Saddle River, NJ: Addison-Wesley, 2007.
Print.
4. Takanen, Ari, Jared D. Demott, and Charles Miller. Fuzzing for software
security testing and quality assurance. Boston: Artech House, 2008. Print.
5. Code Injection [Электронный ресурс] //URL:
https://www.owasp.org/index.php/Code_Injection (Дата обращения:
23.01.14)
6. Fuzzing : the Past, the Present and the Future [Электронный ресурс]
//URL: http://actes.sstic.org/SSTIC09/Fuzzing-the_Pastthe_Present_and_the_Future/SSTIC09-article-A-Takanen-Fuzzingthe_Past-the_Present_and_the_Future.pdf (Дата обращения: 23.01.14)
7. Mark Dowd, John McDonald, and Justin Schuh. The art of software
security assessment : identifying and preventing software vulnerabilities .
Indianapolis, Ind: Addison-Wesley, 2007. Print.
8. Coverity [Электронный ресурс] //URL:
http://www.idapro.ru/description/ (Дата обращения: 23.01.14)
9. IDA Pro [Электронный ресурс] //URL: http://www.idapro.ru/description/
40
(Дата обращения: 27.01.14)
10.Peach Fuzzer [Электронный ресурс] //URL: http://peachfuzzer.com/
(Дата обращения: 27.01.14)
11.Lcamtuf’s blog [Электронный ресурс] //URL: http://lcamtuf.blogspot.ru/
(Дата обращения: 27.01.14)
12.Fuzzing [Электронный ресурс] //URL:
https://www.owasp.org/index.php/Fuzzing (Дата обращения: 28.01.14)
13.About Node.js [Электронный ресурс] //URL: http://nodejs.org/about/
(Дата обращения: 01.02.14)
14.About SQLite [Электронный ресурс] //URL:
http://www.sqlite.org/about.html (Дата обращения: 01.02.14)
15.WaitForDebugEvent [Электронный ресурс] //URL:
http://msdn.microsoft.com/enus/library/windows/desktop/ms681423(v=vs.85).aspx (Дата обращения:
01.02.14)
Download