2. Заголовок
Владимир Кочетков – руководитель отдела исследований
по анализу защищённости приложений Positive Technologies
https://about.me/vladimir.kochetkov
vkochetkov@ptsecurity.com
:~$ whoweare
3. Заголовок
Денис Колегов – руководитель группы исследований технологий
защиты Positive Technologies
Доцент, к. т. н., доцент кафедры защиты информации
и криптографии ТГУ
https://twitter.com/dnkolegov
dkolegov@ptsecurity.com
:~$ whoweare
4. Заголовок
Евгений Рыжов – руководитель отдела разработки веб-сканера
eryzhov@ptsecurity.com
:~$ whoweare
5. Заголовок
• Теоретические основы Application Security
• Эвристические методы защиты приложений
• Формальные методы защиты на основе исходного кода
• Объединяя подходы
• Немного о чёрных ящиках
Agenda
7. Заголовок
Предметная область, рассматривающая в качестве
объекта защиты гипотетическую информационную
систему (ИС):
• включающую в себя конкретное приложение
• объединяющую объекты окружения в единую
сущность
• замкнутую относительно информационных
потоков приложения
AppSec (Application Security) 1/2
12. Заголовок
Абстракция объекта в некотором контексте, обладающая
следующими характеристиками:
• Свойство – значимый атрибут абстрагируемого сущностью объекта
• Состояние – множество текущих значений всех свойств сущности
• Инвариант – множество допустимых состояний сущности
Отношение – утверждение, определяющее взаимосвязь
изменения состояний сущностей
Сущность
16. Заголовок
Сущность: точки на карте города
• Свойство: координаты – пара значений «широта-долгота»
• Инвариант: координаты принадлежат перекресткам города или
строениям
Сущность: маршрут
• Свойство: путь - упорядоченное множество точек на карте города
• Инвариант: путь непрерывен, проходит по улицам города в соответствии
с ПДД
• Отношение: оптимальность – длина пути минимальна для заданных
начальной и конечной точек
Сущности: точка загрузки, точка доставки
• Свойство: точка на карте города
• Инвариант: координаты принадлежат строениям
Пример: логистика
17. Заголовок
В терминах предметной области логистики:
построить оптимальный маршрут
из точки загрузки, проходящий через все
точки доставки по одному разу
и возвращающийся в точку загрузки.
Пример: логистика
18. Заголовок
В терминах предметной области теории
графов:
найти гамильтонов цикл минимального
веса в полном (дополненном ребрами
бесконечной длины) взвешенном графе.
Пример: логистика
20. ЗаголовокПредметные области приложений
Вторичные:
• защищенность
• отказоустойчивость
• опыт взаимодействия
• производительность
Первичные (основные):
• интернет-торговля
• онлайн-банкинг
• бухучет
• … (тысячи их)
Каждое приложение реализует как модели основной предметной области,
так и множество моделей вторичных предметных областей
40. ЗаголовокПотоки данных (пример 1/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
41. ЗаголовокПотоки данных (пример 2/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
42. ЗаголовокПотоки данных (пример 3/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
43. ЗаголовокПотоки данных (пример 4/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
44. ЗаголовокПотоки данных (пример 5/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
45. ЗаголовокПотоки данных (пример 6/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
46. ЗаголовокПотоки данных (пример 7/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
47. ЗаголовокПотоки данных (пример 8/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
48. ЗаголовокПотоки данных (пример 9/9)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
49. Заголовок
Множество всех возможных значений потока данных в конкретной
точке потока выполнения определяет его состояние
Состояние потока данных
50. ЗаголовокСостояние потока данных (пример)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
str1 ∈ {
Encoding.UTF8.GetString(data),
"Wrong Key!"
}
51. Заголовок
Множество состояний всех потоков данных в конкретной точке
потока выполнения определяет состояние приложения
Состояние приложения
52. ЗаголовокСостояние приложения (пример)
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
str1 ∈ {
Encoding.UTF8.GetString(data),
"Wrong Key!"
}
name ∈ { Request.Params["name"] }
key1 ∈ { Request.Params["key1"] }
parm ∈ { Request.Params["parm"] }
data ∈ {
new char[0],
Convert.FromBse64String(parm)
}
53. Заголовок
Граф переходов между состояниями приложения определяет все
возможные потоки вычисления и является искомой моделью
процесса его выполнения
Граф потоков вычисления
62. Заголовок
Приводимые далее термины и определения локальны
и не претендуют на признание в качестве общеупотребительных.
Тем не менее, они устраняют существующие разночтения
и противоречия в традиционной терминологии, позволяя перейти
от интуитивных формулировок к формальным
Disclaimer
70. Заголовок
То, что может сделать атакующий с потоками информации,
называется угрозой (threat)
То, когда и благодаря чему он может это сделать, называется
уязвимостью (vulnerability), обусловленной недостатком
(weakness)
Иными словами
71. Заголовок
То, как он может это сделать, называется атакой (attack)
То, с какой вероятностью у него это удастся и какие
последствия может повлечь, называется риском (risk)
Иными словами
72. Заголовок
То, что не позволяет атакующему провести атаку, обеспечивает
защищенность (security)
То, что минимизирует риск, обеспечивает безопасность (safety)
Иными словами
76. Заголовок
• Потоки операций являются и информационными потоками,
и сущностями модели основной предметной области
приложения
• Потоки вычисления являются и информационными потоками,
и сущностями предметной области защищённости приложения
• Потоки данных окружения являются и информационными
потоками, и сущностями модели окружения
А теперь – всё вместе
77. Заголовок
• Недостаток – неэффективная реализация моделей предметных
областей приложения или окружения (контролей инвариантов
их сущностей)
Примеры контролей:
• предварительная обработка потоков данных
• подтверждение аутентичности потоков операций
• проверка прав доступа к потокам данных
• обеспечение целостности потока операций
• …
А теперь – всё вместе
78. Заголовок
• Уязвимость приложения – состояние возможности нарушения
конфиденциальности, целостности, доступности, аутентичности
или авторизованности любого из потоков операций или
вычисления приложения, а также потоков данных окружения
• Состояние защищённости приложения возникает при
невозможности эксплуатации в нём любой уязвимости
А теперь – всё вместе
79. Заголовок
• Вычислительный – уязвимости, описываемые в терминах
модели процесса выполнения приложения
• Логический – уязвимости, описываемые в терминах модели
предметной области приложения
• Экзогенный – уязвимости, описываемые в терминах модели
окружения
Суперклассы уязвимостей приложения
81. Заголовок
Атаки на нарушение целостности потоков данных в результате их
преобразования принято называть инъекциями
Тип инъекции определяется грамматикой атакуемого потока
данных (HTML, XML, SQL, XPath, XQuery, LDAP, LINQ, Path, …)
Вычислительный класс: инъекции
82. Заголовок
«Пусть C – граф потоков вычисления приложения.
Пусть pvf(t) – достижимая вершина потока управления на C,
являющаяся вызовом функции прямой или косвенной
интерпретации текста t, соответствующего известной
формальной грамматике G.
Пусть e – поток аргумента входных данных на С.
Пусть De – множество потоков данных на C, порождаемых от e
и достижимых в точке вызова pvf(t), где t принадлежит De»
Моделирование инъекций (1/3)
83. Заголовок
«Тогда приложение уязвимо к угрозе нарушения целостности
потоков данных De в точке выполнения pvf(t), если среди них
найдётся хотя бы одна пара таких значений, при которых,
в результате их синтаксического разбора в соответствии с
грамматикой G, получаются не изоморфные друг другу деревья
разбора»
Моделирование инъекций (2/3)
85. Заголовок
Несогласованная работа с разделяемым ресурсом
в многопоточном окружении приводит к гонкам за ресурс
Окружение любого веб-приложения является многопоточным
Вычислительный класс: гонка за ресурс
86. Заголовок
Пусть P – сеть Петри, построенная по C, где переходами сети
являются все промежуточные вершины C, позициями – его
вершины, соответствующие операциям чтения или записи
каждого ресурса окружения, а условиями перехода – условия
достижимости соответствующих вершин C
Тогда, возможность появления более одной метки в любом
состоянии графа маркировок P укажет на возможность
реализации угрозы нарушения целостности или аутентичности
потока вычисления
Вычислительный класс: гонка за ресурс
87. Заголовок
• Направлены на реализацию угрозы (нарушение одного
из свойств защищённости какого-либо потока вычисления,
операций или данных окружения)
• Могут являться как производными от предыдущих атак, так и
первообразными для последующих. Например:
• HTTP Response Splitting →
Header Spoofing →
Session Fixation
Unvalidated Redirection
Body spoofing →
Content Spoofing
Session Fixation
Unvalidated Redirection
Cross-Site Scripting
…
Свойства атак
90. ЗаголовокКлассификация: спуфинг потока операций
Признак Значение
Предметная область Защищённость приложения
Недостаток Неэффективное подтверждение
аутентичности идентификатора
потока операций
Информационный поток Поток операций
Угроза Нарушение аутентичности
91. ЗаголовокКлассификация: переполнение буфера
Признак Значение
Предметная область Защищённость приложения
Недостаток Неэффективный контроль записи
производных потоков окружения
в память
Информационный поток Метаданные на стеке или в куче
Угроза Нарушение целостности
92. ЗаголовокКлассификация: обход бизнес-логики (частный случай)
Признак Значение
Предметная область Онлайн-торговля
Недостаток Неэффективный контроль
использования купонов на скидку
Информационный поток Поток операций транзакции оплаты
заказа
Угроза Нарушение авторизованности
97. Заголовок
Веб-приложение – клиент-серверное приложение, в котором
клиентом является веб-браузер, сервером – веб-сервер,
а протоколом взаимодействия между ними – веб-протокол
Базовый состав
• Веб-браузер
• Веб-сервер / Сервер приложений
• СУБД
Определение
98. Заголовок
Огромное количество технологий и их реализаций
Простота использования
Доступность и распространенность
Низкий порог входа
• Для разработчиков
• Для пентестеров / баг-хантеров
• Для злоумышленников
Особенности
99. Заголовок
Необходимо построить многоуровневую защиту
В принципе невозможно устранить уязвимость в самом приложении
• Legacy
• Third-party
Необходимый механизм защиты отсутствует или сложно реализуем
• Защита от подбора паролей
• Управление доступом
• Защита от нежелательной автоматизации
Необходимо немедленно устранить обнаруженную уязвимость до ее
реального устранения в исходном коде
А что если …?
100. Заголовок
В 1990-х годах активно используется принцип внешнего
монитора безопасности
Текущий подход: разрабатывать приложения защищенными,
а не полагаться на внешние механизмы защиты
Владимир Кочетков. Как разработать защищенное
веб-приложение и не сойти при этом с ума
Как правильно защищать приложения?
102. Заголовок
• An appliance, server plugin, or filter that applies a set of rules to an HTTP
conversation
• A security solution on the web application level which does not depend
on the application itself
• A security policy enforcement point positioned between a web application
and the client end point. This functionality can be implemented in software
or hardware, running in an appliance device, or in a typical server running
a common operating system. It may be a stand-alone device or integrated into
other network components
Что такое WAF?
Web Application Firewall Evaluation Criteria
105. Заголовок
Detective
• Первичная валидация данных (методы, длина запроса, длина и число заголовков, …)
• Обнаружение инъекций
Mitigative – ослабление атак, от которых трудно защититься
• Проверка на соответствие RFC
• Аутентификация сообщений
• Шифрование URL или скрытых полей
• Маскирование данных
• Блокирование IP-адреса или завершение сессии
Предотвращение (prevention) – предотвращение использования
обнаруженных уязвимостей
• Виртуальный патчинг
Механизмы защиты
107. Заголовок
• Валидация HTTP-запроса (метод, длина запросов, количество
заголовков и т. д.)
• Нормализация HTTP-запроса (HTTP Parameter Pollution &
Contamination)
• Обнаружение инъекций (SQLi, LDAP, XPath и т. д.)
• Парсинг данных (XML, JSON, AMF и т. д.)
• Проверка репутации IP
Обработка запросов
108. Заголовок
Обнаружение утечек данных:
• stack traces
• debug information
• application errors
Обнаружение недостатков конфигураций:
• отсутствие заголовков безопасности
• небезопасная политика CSP
• небезопасная конфигурация SSL/TLS
Обработка ответов
109. Заголовок
Корреляция запросов и ответов HTTP:
• обнаружение отражения параметров запроса в ответе (Reflected
XSS, Open Redirect, HTTP Response Splitting)
• обнаружение успешной эксплуатации уязвимости (например,
наличие вектора Path Traversal в запросе и содержимого файла
/etc/passwd в ответе)
• User tracking – ассоциирование запросов и ответов с учетными
записями пользователей защищаемого веб-приложения
Обработка транзакций
110. Заголовок
• Credentials bruteforcing
• Site scraping
• Common vulnerability scanning
• Account takeover
• HTTP slow DoS attacks
• L7 DDoS
• Fraud
Механизмы защиты реализуются на основе машинного обучения
или счетчиков (например, max requests per second, max 404 errors
per minute и т. д.)
Поведенческий анализ
111. Заголовок
Теория
• Теория формальных языков
• LangSec
Практика
• Модель черного ящика
• Множество технологий
• Отсутствие стандартов
• Развитие клиентских частей веб-приложений
Источники ограничений
112. Заголовок
Входные данные – формальный язык
WAF – универсальный распознаватель (recognizer) языков атак
на веб-приложения
Можно распознать эквивалентный или менее мощный язык
Теория формальных языков
Грамматика Распознаватель
Типа 0 Машина Тьюринга
Контекстно-зависимая Линейно-ограниченный
автомат
Недетерминированная
контекстно-свободная
Недетерминированный
автомат с магазинной памятью
Детерминированная
контекстно-свободная
Недетерминированный
автомат с магазинной памятью
Регулярная Конечный автомат LangSec: Language-theoretic security
113. Заголовок
Недостаточное (неэффективное) распознавание (insufficient
recognition)
• Распознавание КС-языка с помощью регулярного выражения
Различимость парсеров (parser differentials)
• Одни и те же входные данные распознаются парсерами по-разному
Входные данные сложнее, чем детерминированный контекстно-
свободный язык
Проблемы
M. Patterson, S. Bratus, etc. The Seven Turrets of Babel: A
Taxonomy of LangSec Errors and How to Expunge Them
114. Заголовок
Предположение. Язык инъекций КС-языка является как минимум
КЗ-языком
• ' or '1 ' = '1
Язык инъекций как минимум содержит цепочки (вектора) целевого
языка, а значит, является КС-языком
• select * from foo where id = <injection>
• (select ((1)))
При этом префикс и постфикс являются контекстно-зависимыми
Проблемы
115. Заголовок
Веб-приложение для WAF – это просто последовательность
запросов и / или ответов
Непонимание контекста
Непонимание логики взаимодействия
• Боты
• Взлом аккаунта
• Злоупотребления (abuse / misuse)
Модель черного ящика
118. ЗаголовокМинута из жизни WAF
CATS /app?pageId=1 HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 403 Forbidden
Server: WAF
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: close
Forbidden
119. ЗаголовокМинута из жизни WAF
CATS /app?pageId=1 HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 403 Forbidden
Server: WAF
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: close
Forbidden
120. ЗаголовокМинута из жизни WAF
GET /app?pageId=<svg/onload=alert(1)> HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Acunetix-Product: WVS/7 (Acunetix Web Vulnerability Scanner – NORMAL)
Acunetix-Scanning-agreement: Third Party Scanning PROHIBITED
Acunetix-User-agreement: http://www.acunetix.com/wvs/disc.htm
HTTP/1.1 403 Forbidden
Server: WAF
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: close
Forbidden
121. ЗаголовокМинута из жизни WAF
GET /app?pageId=<svg/onload=alert(1)> HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Acunetix-Product: WVS/7 (Acunetix Web Vulnerability Scanner – NORMAL)
Acunetix-Scanning-agreement: Third Party Scanning PROHIBITED
Acunetix-User-agreement: http://www.acunetix.com/wvs/disc.htm
HTTP/1.1 403 Forbidden
Server: WAF
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: close
Forbidden
122. ЗаголовокМинута из жизни WAF
GET /app?pageId=<script>alert(1)</script> HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 403 Forbidden
Server: WAF
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: close
Forbidden
123. ЗаголовокМинута из жизни WAF
GET /app?pageId=<script>alert(1)</script> HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 403 Forbidden
Server: WAF
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: close
Forbidden
124. ЗаголовокМинута из жизни WAF
GET /app/?id=50484e6a636d6c776444356862475679644367784b54777663324e796158423050673d3d HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
125. ЗаголовокМинута из жизни WAF
GET /app/?id=50484e6a636d6c776444356862475679644367784b54777663324e796158423050673d3d HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
function getID(request) {
var rawID = request.getValue('id');
var id = hexdecode(base64decode(rawID));
return id;
}
// rawID = 50484e6a636d6c776444356862475679644367784b54777663324e796158423050673d3d
// id = <script>alert(1)</script>
Исходный код
126. ЗаголовокМинута из жизни WAF
GET /app/?id=50484e6a636d6c776444356862475679644367784b54777663324e796158423050673d3d HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 200 OK
X-XSS-Protection: 0
Content-Type: text/html; charset=utf-8
Date: Wed, 15 Jun 2016 12:34:25 GMT
Content-Length: 26
Connection: close
<script>alert(1)</script>
127. ЗаголовокМинута из жизни WAF
GET /app?callback=delete_user_data HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 200 OK
X-XSS-Protection: 1
Content-Type: text/html; charset=utf-8
Date: Wed, 15 Jun 2016 12:34:25 GMT
Content-Length: 26
Connection: close
<html><body><script type="text/javascript">
window.opener.delete_user_data({"status":0,"token":"ItHumYWI[...snip..]","oauthstate":"1234","tokenid":"ToKeN1234
","tokenexp":"0","gid":"401223423..","url":"http://example.com"}); </script></body></html>
128. ЗаголовокМинута из жизни WAF
GET /app?callback=delete_user_data HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 200 OK
X-XSS-Protection: 1
Content-Type: text/html; charset=utf-8
Date: Wed, 15 Jun 2016 12:34:25 GMT
Content-Length: 26
Connection: close
<html><body><script type="text/javascript">
window.opener.delete_user_data({"status":0,"token":"ItHumYWI[...snip..]","oauthstate":"1234","tokenid":"ToKeN1234
","tokenexp":"0","gid":"401223423..","url":"http://example.com"}); </script></body></html>
129. ЗаголовокМинута из жизни WAF
GET /app?page=1&page=<script>alert(1)</script> HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
130. ЗаголовокМинута из жизни WAF
GET /app?page=1&page=<script>alert(1)</script> HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
131. ЗаголовокМинута из жизни WAF
POST /download?document_id=1123123&user_id=234123423&action_id=100 HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
132. ЗаголовокМинута из жизни WAF
POST /download?document_id=1123123&user_id=234123423&action_id=100 HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
133. ЗаголовокМинута из жизни WAF
GET /delete_account HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 200 OK
X-XSS-Protection: 1
Content-Type: text/html; charset=utf-8
Date: Wed, 15 Jun 2016 12:34:25 GMT
Content-Length: 26
Connection: close
134. ЗаголовокМинута из жизни WAF
GET /delete_account HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=EAEC35B5E8741B4BA1524F25301A5E10
HTTP/1.1 200 OK
X-XSS-Protection: 1
Content-Type: text/html; charset=utf-8
Date: Wed, 15 Jun 2016 12:34:25 GMT
Content-Length: 26
Connection: close
141. Заголовок
«Подписи запросов» API
• Yahoo, Amazon S3, Facebook
ASP.NET Framework
• Event Validation
• View State MAC
WAF
• ModSecurity: HMAC Token Protection
• F5 Networks ASM: Dynamic Content Value
• Citrix NetScaler: Form Signature
• PT AF: Form Signing
Механизм защиты
142. Заголовок
Client ← Server: p, h(k, p)
Client → Server: p', h(k, p)
Server: h(k, p) = h(k, p')
Параметры:
• h – функция HMAC
• p – значение параметра
• k – секретный ключ сервера
Элементарный протокол
144. Заголовок
Содержание в формах большого количества полей
Различное представление форм для различных клиентов
Наличие в формах опциональных элементов
• Checkbox
• Option
• Radio
Идентификация защищаемых форм в HTTP-ответах
Идентификация скрытых элементов форм в HTTP-запросах
Ввод данных на стороне клиента
Сложности на практике
145. Заголовок
Client ← Server: p, h(k, p)
Client → Server: p', h(k, p)
Server: h(k, p) = h(k, p')
Как использовать этот протокол, если значение p формируется
в браузере на основе ввода пользователя?
Ввод данных на стороне клиента
146. Заголовок
Client ← Server: p, h(k, Tr(p, regex))
Client → Server: p', h(k, Tr(p, regex))
Server: h(k, Tr(p, regex)) = h(k, Tr(p', regex))
Параметры:
• regex – валидирующее регулярное выражение для значения параметра
• Tr(s, regex) – операция удаления из строки s подстрок, соответствующих
regex
• Tr("abc123", "[a-z]+" ) = "123"
Валидирующее хэширование
key
string
regex R
HMAC of L(R)
147. Заголовок
1. Построение Authentication Base String (ABS)
• Method
• URL
• Идентификатор сессии
• Параметры
• Имя
• [Значение]
• [Тип]
Метод вычисления токена
150. Заголовок
1. Парсинг входящего HTTP-запроса
2. Проверка метода запроса
3. Проверка наличия токена
4. Для POST-запроса по полученному URL выполняется поиск политики
5. Если политика найдена, то распаковываются данные из токена
6. Проверка опциональных и скрытых полей, если они есть
7. Формирование ABS и его проверка
Метод проверки токена
151. Заголовок
• Нельзя защитить формы, динамически сгенерированные
на стороне клиента средствами JavaScript
• Нельзя защитить формы, отправленные средствами JavaScript
• Необходимо различать запросы, отправленные средствами
веб-форм от запросов AJAX
• Сложно защитить формы, отправляемые на сервер
методом GET
Ограничения метода
152. Заголовок
• Защита приложения от анализа
• Уменьшение поверхности атак на приложение
• Противодействие средствам автоматизации
• Предотвращение использования известных эксплойтов
Результаты
167. Заголовок
Алгоритм формирования выходных данных DOUTPUT на основе
входных данных DINPUT уязвим к атаке инъекции, если
дерево разбора (parse tree) для DOUTPUT зависит от DINPUT
Признак уязвимости к инъекции
178. Заголовок
Основные принципы нормализации
• Приведение обрабатываемых данных к такому же формату и виду,
к каким приведет его защищаемое веб-приложение
• Эквивалентный парсинг
T. Ptacek, T.Newsham. Insertaion, Evasion, and Denial of Service: Eluding
Network Intrusion Detection. Secure Networks, Inc. 1998
Ivan Ristic. Protocol-Level Evasion of Web Application Firewalls
Нормализация
182. Заголовок
Использование регулярных выражений (конечных автоматов)
для распознавания регулярного языка атак
Имеется L – регулярный язык атак, заданный регулярными
выражениями R
Если входное слово принадлежит языку L, т. е. допускается
регулярным выражением из R, то входное слово – атака
Лексический подход
187. Заголовок
Регулярные выражения – определение языка атак
Правила – определение контекста и логики
Правила
• Условия
• Ограничения
• Контекст
• Источники
• Корреляции
• Реакции
Правила
188. ЗаголовокПример правил CloudFlare WAF
Anonymous Attack
rule 1234567A Simple POST botnet
REQUEST_METHOD is POST and
REQUEST_URI is /q
deny
rule 12345679 Anonymous attack
REQUEST_METHOD is GET and
REQUEST_URI begins /?msg=Nous%20sommes%20Anonymous
deny
Simple POST Botnet
194. Заголовок
Предложил Nick Galbreath в 2012 для обнаружения SQL-инъекций
Позднее данный подход был адаптирован для обнаружения XSS
Реализован в библиотеке libinjection
Основные идеи
• Токенизация в соответствии с универсальной грамматикой лексера
в 3-х контекстах
• Строится свертка токенов
• Строка из первых пяти токенов ищется в базе сигнатур
• База сигнатур строится по популярным векторам атак
Лексико-сигнатурный подход
213. Заголовок
Ложные срабатывания
• if all else fails call grandma
• "Dr. Who" and coffee
• "SWEATER DRESS" AND "CHRISTMAS”
Пропуски
• Неизвестные токены
• Неизвестные контексты
Недостатки
Ivan Novikov. How to bypass libinjection in many WAF/NGWAF
Reto Ischi. An Alternative Approach for Real-life SQLi Detecion
216. Заголовок
Впервые применение парсеров для обнаружения инъекций было описано
в работе Роберта Хансена и Мередит Паттерсон Guns and Butter: Towards
Formal Axioms of Input Validation для Black Hat 2005
Сontext-free parse tree validation
• По известным запросам приложения грамматика для SQL преобразуется
в грамматику для subSQL
• По построенной грамматике генерируется парсер
• Парсер subSQL распознает только цепочки подъязыка SQL этого приложения
Robert J. Hansen, Meredith L. Patterson. Guns and Butter: Towards Formal
Axioms of Input Validation
Синтаксический подход
217. Заголовок
Ленивые – эвристическое использование готовых парсеров
• DOMPurify
• DOMSanitizer
Грамматические
• libdetection (Wallarm)
• libdejection (PT AF, DBFW)
• libprotection (PT AI)
В идеале необходимо использовать парсеры целевых
компьютерных систем, для предотвращения уязвимостей типа
parser differentials
Новые методы
218. Заголовок
Строка s – инъекция для языка L(G), если в построенном дереве разбора s по грамматике G
содержится хотя бы одна опасная инструкция
• 11111
• alert(1)
Базовая идея – с использованием готового парсера построить дерево разбора; если дерево
разбора содержит запрещенные узлы-нетерминалы, то исходная строка является инъекцией
Характеристики подхода
• Возможность использования готовых парсеров
• Универсальность
• Эвристичность
• Различимость парсеров
Ленивый метод
220. ЗаголовокПример: DOM-based XSS
http://ex.com/foo.html#1;alert(1)
var input = location.hash.slice(1);
document.write("<scr"+"ipt>var foo = "+ input +";</scr"+"ipt>");
<script> var foo = 1;alert(1); <script>
Program
ExpressionStatement
Literal
ExpressionStatement
CallExpression
Identifier
Literal
221. Заголовок
Запрещенные нетерминалы (опасные конструкции) в простейшем
случае задаются перечнем типов узлов
Для уменьшения числа ложных срабатываний могут быть
использованы дополнительные проверки на основе родительских
или дочерних узлов
Что делать, когда дерево разбора не может быть построено?
""};alert(1);var f={t:"
Поиск вредоносного кода
222. Заголовок
Вход: строка S, контекст CTX
Выход: является ли S инъекцией в контексте CTX?
1. Построить tokens – список токенов s в CTX
2. Построить дерево разбора для S в CTX
3. Если в дереве есть запрещенные узлы, то S – инъекция
4. Иначе удалить из S следующий токен
5. Если S – непустая строка, то перейти на шаг 2
Метод поиска с левым приведением
223. ЗаголовокAcorn Plugins
function sanitize(dirty) {
var acorn = require('acorn'), detected = false, tree ;
acorn.plugins.detectCallExpression = function(parser) {
parser.extend('finishNode', function(nextMethod) {
return function(code, node) {
if(node === 'CallExpression') {
detected = true;
}
return nextMethod.call(this, code, node);
}
})
};
tree = acorn.parse(dirty, {plugins: {detectCallExpression: true}});
if (detected) {
return 'xss';
}
return dirty;
}
Acorn is designed support allow plugins which, within reasonable bounds, redefine the
way the parser works. Plugins can add new token types and new tokenizer contexts (if
necessary), and extend methods in the parser object
224. ЗаголовокEsprima Syntax Delegate
function sanitize(dirty) {
var esprima = require('esprima'), detected = false, tree;
tree = esprima.parse(dirty, {}, function(node, meta) {
if(node.type === 'CallExpression') {
detected = true;
}
});
if (detected) {
return 'xss';
}
return dirty;
}
sanitize(';alert(1);var f={t:')
// 'xss'
A powerful feature available in Esprima since version 3.0 is the ability to invoke a callback
function after every syntax node in the abstract syntax tree is created, often referred as
the syntax delegate
Ariya Hidayat. On-the-fly JavaScript Syntax Node Inspection.
232. ЗаголовокПримеры обнаруживаемых векторов
http://friendfeed.com/api/feed/public?callback=var WshShell=new
ActiveXObject("WScript.Shell");WshShell.Exec("calc");//
Internet Explorer Reflected File Download
Reflected XSS on developer.uber.com via Angular template injection
ES6
alert`1`
https://developer.uber.com/docs/deep-
linking?q=wrtz{{(_="".sub).call.call({}[$="constructor"].getOwnPropertyDescript
or(_.__proto__,$).value,0,"alert(1)")()}}zzzz
233. ЗаголовокТолерантность к ошибкам
)},{0:prompt(1
Prompt.ml Challenge Hidden Level 4
function escape(input) {
// You know the rules and so do I
input = input.replace(/"/g, '');
return '<body onload="think.out.of.the.box(' + input + ')">';
}
return '<body onload="think.out.of.the.box()},{0:prompt(1)">';
"… the solution might work for some older versions of Chrome, while for others, a
different vector would be needed…"
234. ЗаголовокТолерантность к ошибкам
nodes = {CallExpression}
input = )},{0:prompt(1
Program
ExpressionStatement
SequenceExpression
…
ObjectExpressionIdentifier
CallExpression
name: x