Для приблизительной оценки степени защищенности того или иного веб-ресурса мы часто обращаемся за помощью к различным сканерам уязвимостей – монструозным продуктам, требующим обязательной установки на компьютер. В этой статье я рассмотрю процесс создания инструмента, который полностью изменит твое представление о проведении аудита веб-приложений.
Наиболее полную картину состояния защищенности той или иной инфраструктуры позволяют получить только комплексные методы анализа. Если говорить о веб-среде в общем и ее технологиях в частности, то подавляющее большинство распространенных уязвимостей представляют собой следствие некорректной работой того или иного алгоритма фильтрации входящих данных. И прошу не спешить бросать в автора камни, описывая причины появления и принципы обнаружения (эксплуатации) уязвимостей типа XSS/SQL-inj/PHP-including. Несомненно, техническая сторона атак подобного типа сильно отличается и направлена на разные объекты, но нас не интересует эксплуатация багов. Мы, как примерные аудиторы/пентестеры/администраторы, заинтересованы в их обнаружении, а методы обнаружения, в свою очередь, можно свести к принципу нахождения «нештатных» ситуаций в функционировании фильтров веб-приложения. Этого можно добиться только путем передачи фильтру различных входных данных. Кстати, именно так и поступают сканеры уязвимостей (да простят меня их разработчики), анализируя полученные результаты мощными эвристическими алгоритмами. Но имеется ряд ситуаций, когда использование этих инструментов не желательно для нас. Большинство серьезных коммерческих продуктов при сканировании целевого ресурса оставляют в логах веб-сервера записи, однозначно идентифицирующие факт сканирования, а иногда и узел, с которого оно проводилось. Вряд ли кто-то захочет лишней «популярности» в кругах администрации целевого сайта. К тому же процесс сканирования весьма ресурсоемок и требует временные затраты, которые, в некоторых случаях, эквивалентны денежным.
Думаю, самое время прекратить заниматься «болталогией» и приступить к созданию инструмента, который в силу своих особенностей, лишен вышеописанных недостатков и будет доступен для нас в виде веб-сервиса.
Глазами разработчика
С позиции разработчика, процесс сканирования – процедура весьма однотипная и представляет собой формирование запросов к целевому ресурсу и обработке полученных результатов. Договоримся сразу, что исследуемый сайт для нас – это некоторое подобие «черного ящика», то есть нам не известны детали функционирования скриптов. В общем, все как при настоящем тесте на проникновении, где все параметры, передаваемые исследуемому скрипту, приходится перебирать практически случайным образом, опираясь исключительно на свои опыт и интуицию.
Почему именно веб-сервис? Ну хотя бы потому, что аналогов его в русском сегменте интернета не имеется, а это значит, данная ниша будет интересна и разработчикам (деньги всегда были хорошим стимулом ;)) и пользователям, так как отсутствует необходимость устанавливать требовательные к ресурсам (и дорогие) продукты с целью просканировать свою домашнюю страничку для того, чтобы иметь приблизительное представление о ее состоянии защищенности. Другие причины можешь придумать сам, а я, с твоего позволения, перейду к теоретической части и непосредственно к кодингу.
И в первый день создал он…
Как я уже отмечал, наша разработка будет представлять собой веб-сервис. Попробуем дать более точное определение. Web-service – приложение, которое:
- исполняется на web-сервере;
- ожидает поступления HTTP-запросов и предоставляет web-методы для их обработки;
- непосредственно исполняет web-методы и возвращает результаты.
У истоков данной технологии стоит Microsoft, которая реализовала ее в рамках Microsoft .NET. Кстати, именно веб-сервисы являются основной причиной, по которой .NET Framework вообще существует: максимально упростить разработку веб-сервисов и веб-клиентов. За примерами далеко ходить не надо – в предыдущем номере журнала мы рассмотрели, как с помощью технологии .NET Remoting можно быстро создать сеть распределенных вычислений.
И все же web-сервисы – не собственность MS, а являются промышленным стандартом на основе открытых протоколов HTTP и SOAP (Simple Object Access Protocol). Именно поэтому сервисы можно писать в любом текстовом редакторе, однако .NET Framework – несомненно, лучший вариант, упрощающий процесс кодинга. Кстати, кодить мы будем на языке C#, но ничто не мешает тебе писать приложение на любом другом языке, поддерживаемым ASP.NET – технологией создания веб-приложений от Майкрософт в рамках платформы .NET. С инструментами разобрались, теперь перейдем к проектированию логики приложения.
Хочу сразу сказать, что процесс создания онлайн-сканера будет рассмотрен на примере уязвимостей класса “Cross-Site Scripting” (также известного как XSS), так как на основу их поиска опираются методы обнаружения других багов (с точки зрения сканера, как автоматизированного инструмента). Тебе лишь, как программисту, нужно будет научить приложение передавать специальные данные и требуемым тобой образом обрабатывать полученные результаты. Моя же задача – продемонстрировать тебе особенности программирования веб-сервисов на концептуальном уровне, ну и, конечно, задать направление дальнейшего развития приложения и поделиться своими идеями. Но обо всем по порядку ;).
Рассмотрим логику работы сканера:
- Переход по ссылке на целевой сайт.
- Сбор всех скриптов на целевом сайте.
- Определение всех параметров, принадлежащих конкретному скрипту.
- Передача собранным параметрам специальных значений, характерных для данного вида уязвимостей.
- Анализ полученного результата (произошло ли внедрение наших переданных значений в код страницы).
Как видишь, приблизительный алгоритм функционирования приложения довольно прост, но прошу не спешить с выводами: каждый из вышеперечисленных пунктов содержит подводные камни, часть из которых нам придется преодолевать вместе, а часть я оставлю тебе в качестве пищи для размышлений.
Напиши программу мышкой
Создается впечатление, что если Майкрософт продолжит развивать свои технологии, входящие в комплект .NET Framework, и среду программирования Visual Studio, то процесс создания программного обеспечения будет доступен для широких масс, исключительно владеющих мышкой и умеющих собирать конструкторы.
При создании проекта «ASP.NET Web Service Application» студия автоматически сформирует структуру каталогов, характерную для приложения данного типа и создаст все необходимые файлы для его корректного функционирования. Обычно структура проекта содержит в себе файлы одного или нескольких следующих типов:
- ASPX-файлы, содержащие web-формы;
- ASMX-файлы, которые, собственно, и реализуют web-сервисы;
- файлы Web.config, в которых описываются параметры конфигурации;
- файл Global.asax, который содержит глобальные элементы приложения;
- различные DLL, включающие в себя специфичные для приложения типы.
Файл ICholeScaner.asmx, находящийся в проекте (ищи его на нашем диске), демонстрирует несколько важных принципов программирования веб-сервисов с помощью .NET Framework. Вот содержание этого файла:
-
//Содержимое ASMX-файла
-
<%
-
@ WebService Language="C#"
-
CodeBehind="~/App_Code/ICholeScaner.cs"
-
Class="ICholeScaner"
-
%>
Директива @WebService содержит обязательный атрибут Class, задающий класс, из которого состоит веб-сервис, и атрибут CodeBehind, который содержит описание web-методов класса.
Web-методы объявляются в файле ICholeScaner.cs путем назначения открытым методам класса “ICholeScaner” атрибута [WebMethod]. Таким образом .NET Framework автоматически делает доступным этот метод для внешних вызовов.
-
[WebMethod]
-
public string StartScan(string domen)
-
{
-
// инструкции метода
-
…
-
}
В этом отражается вся суть веб-сервиса: предоставить функционал своих методов (то есть предоставить «сервис») для обработки данных, поступающих от клиента, который может являться как обычным пользователем, передающим информацию через какие-либо поля ввода, так и программой (сайтом), предоставляющим свои данные в автоматическом режиме средствами HTTP и SOAP. SOAP – это XML-язык для вызовов удаленных процедур по HTTP и другим протоколам.
Нашим веб-сервисом предоставляется метод StartScan, который принимает единственный строковой параметр – доменное имя целевого сайта и инициализирует процедуру сканирования. Если URL сервиса, например, www.site.com/icholescaner.asmx, то вот таким образом клиент может вызвать метод StartScan, переслав SOAP-конверт в HTTP-запросе.
Задача web-сервиса:
- разобрать SOAP-конверт, содержащий входные данные;
- выполнить сканирование;
- сгенерировать SOAP-конверт, содержащий результат;
- возвратить его клиенту в теле HTTP-отклика.
Также параметры сканирования можно задавать с помощью обычных HTTP-команд GET и POST, например:
GET /icholescaner.asmx/StartScan?domen=www.enemysite.com HTTP/1.1
Host: www.site.com
После того, как мы рассмотрели особенности создания и функционирования веб-сервисов и их принципиальное отличие от обычных веб-приложений (которые функционируют в закрытом режиме, не предоставляя никому свои методы), ты уже можешь начинать писать свой сервис, аналогов которого нет в онлайн-приложениях, но полным полно на пользовательских компьютерах. Но я настоятельно рекомендую не останавливаться на полученных знаниях, а перейти к следующему этапу, на котором мы реализуем процесс обнаружения XSS-уязвимостей.
Да у вас жуки, батенька
Уязвимости класса «межсайтовый скриптинг», как известно, являются следствием неправильной работы фильтра, принимающего входные данные от пользователя. Таким образом, хакер может вставить в исходный код страницы свой набор символов (коим в подавляющем большинстве случаев является JavaScript-код), который впоследствии может скомпрометировать легитимного пользователя, открывшего страницу.
Различают два «подтипа» XSS-уязвимостей: активные и пассивные (уязвимости, угу!). В двух словах: первые встраиваются непосредственно в код страницы и пользователю достаточно ее открыть, а вторые требуют активности со стороны компрометируемого (например, переход по специально сформированной ссылке). За подробностями атак этого типа я отправлю тебя (нет, не к гуглу) к сноскам в статье, где собран список полезных ресурсов, ждущих твоего внимания.
С точки зрения программиста сервиса, различия в уязвимостях не играют никакой роли, ведь так или иначе являются следствием некорректной фильтрации, поэтому не будем дальше заострять внимание на описании багов, а перейдем к их непосредственному обнаружению средствами онлайн-сканера.
Для начала нам нужно выявить список всевозможных скриптов на исследуемом ресурсе. Как это сделать – однозначного ответа дать, увы, не смогу, потому что подходы к этой задаче у каждого свои и скорость выполнения задачи может заметно отличаться. С другой стороны, зачем нам лишние заботы? Пусть пользователь сам укажет тот скрипт, который хочет проверить, а благотворительностью пусть гугл занимается ;).
После того как у нас появился URL адрес скрипта, нам необходимо получить генерируемый им исходный код страницы и записать его в какую-нибудь переменную с целью последующего анализа. Делается это просто:
-
//Получение HTML-кода страницы
-
//формирование запроса к скрипту
-
WebRequest request = WebRequest.Create(Url+"?"+Parametrs);
-
//получение ответа
-
WebResponse response = request.GetResponse();
-
//запись полученного ответа в строковую переменную
-
StreamReader reader = new StreamReader(response.GetResponseStream());
-
Content = reader.ReadToEnd();
-
reader.Close();
Имея на руках исходный код страницы, нужно определить количество параметров, принимаемых скриптом, чтобы проверить корректность их фильтрации. Сделать это можно двумя способами: определить на странице все формы для ввода каких-либо данных или же пропарсить полученный HTML-код на наличие строк вида «/script.php?a=abcd&b=1234», где script.php – имя исследуемого скрипта. Во втором случае у нас в распоряжении находится вся мощь регулярных выражений.
После того, как параметры скрипта собраны и аккуратно помещены в массив наступает самый интересный момент – подстановка «ядовитых» запросов и анализ полученных ответов. Под «ядовитыми» запросами понимается такое значение, передаваемое параметру, которое вызовет выполнение запланированного нами действия, например, внедрение в исходный код страницы нашего тега, JavaScript-кода и т.п. Коллекция таких «ядовитых» строк собрана в массиве XSSrequest. Вот несколько элементов этого массива:
-
string[] XSSrequest =
-
{ "<script>alert()</script>",
-
"<IMG SRC=\"javascript:alert();\">",
-
"<IMG SRC=javascript:alert("XSS")>",
-
…
-
}
Поочередно подставляя их в каждый из собранных параметров, необходимо анализировать ответ на наличие внедренного JavaScript-кода. Другими словами нужно каждый раз парсить исходный HTML-код, полученный после отправки запроса, на наличие искомой последовательности символов (и опять регулярные выражения).
О SQL-inj, PHP-inc и другой нечисти
Распространенные уязвимости других классов хоть и имеют другую природу и способы эксплуатации, но все же находятся одинаковым, с точки зрения автоматизированного поиска, способом.
Рассмотрим, например, SQL-инъекции – уязвимости, позволяющие нападающему изменить логику запроса скрипта к базе данных. Ошибки этого типа также, в подавляющем большинстве, являются следствием некорректной обработки поступающих от пользователя данных, а это значит, что нам не придется менять алгоритмы поиска в нашем сканере. Достаточно создать массив «ядовитых» запросов, характерных для уязвимостей подобного типа и проанализировать реакцию скрипта (полученный HTML-код + регулярные выражения). Вот небольшой список характерных ответов SQL-сервера, говорящих о возможости проведения атаки:
-
string[] SQLErrors = { "mysql_fetch",
-
"mysql_query", "\\[obdc", "mysql error",
-
"you have an error in your sqlsyntax",
-
"odbc drivers error", "\\[microsoft sql"
-
...
-
};
Существую еще SQL-инъекции, которые в силу своей природы, не вносят изменения в исходный код страницы, и как следствие, не подлежат обнаружению простым парсингом страницы. С другой стороны, тебе открывается широкий спектр атак, дающий повод для постоянного совершенствования своего продукта.
Пасмурно, но без осадков
Перспектива развития облачных технологий и веб-сервисов становится заметна не только крупным компаниям и конечным пользователям. С развитием технологий создания web-приложений, разработчики приобретают возможность воплотить самые яркие идеи, которые уже давно реализованы в качестве стандартных (оффлайновых) приложений и востребованы у пользователей персональных компьютеров. Кому-то важна финансовая сторона дела, кто-то гонится за оригинальностью, а кто-то просто «на волне» и за пару часов создает продукт, приносящий пользу и пользователю и создателю.
Если тема онлайн-сервисов вообще и онлайн-сканера уязвимостей в частности стала для тебя интересна и ты решил попробовать себя в этом направлении, то прошу не держать накопившиеся вопросы (и идеи ;)), а смело задавать их мне – разберемся вместе. Облачных тебе приложений и безоблачной погоды!
1 comment
Отредактированная версия статьи на официальном веб-ресурсе журнала “Хакер”: http://www.xakep.ru/post/53648/default.asp