Пожалуйста, обратите внимание, что пользователь заблокирован
В последних трех статьях я сосредоточился на том, как обойти WAF, чтобы удаленно выполнять команды. В этой статье я покажу вам, какие возможности предоставляет нам PHP для выполнения удаленного выполнения кода, обхода фильтров, очистки входных данных и правил WAF. Обычно, когда я пишу подобные статьи, люди всегда спрашивают: «Неужели люди пишут такой код?», И обычно они не пентестеры. Позвольте мне ответить, прежде чем вы спросите меня снова - Дааааааа.
Это первый из двух уязвимых PHP-скриптов, которые я собираюсь использовать для всех тестов. Этот сценарий, безусловно, слишком прост и глуп, но он просто воспроизводит сценарий уязвимости удаленного выполнения кода (вероятно, в реальном сценарии вам придется проделать немного больше работы, чтобы достичь подобной ситуации):
Первый скрипт PHP
Очевидно, шестая строка - чистое зло. Третья строка пытается перехватить такие функции, как system, exec или passthru (в PHP есть много других функций, которые могут выполнять системные команды, но давайте сосредоточимся на этих трех). Этот сценарий выполняется на веб-сервере за CloudFlare WAF (как всегда, я использую CloudFlare, потому что он прост и широко известен людям, это не означает, что CloudFlare WAF небезопасен. Все другие WAF имеют те же проблемы...). Второй скрипт будет за ModSecurity + OWASP CRS3.
Попытка прочитать /etc/passwd
В первом тесте я пытаюсь прочитать /etc/passwd с помощью функции system() по запросу /cfwaf.php?code=system(“cat /etc/passwd”);
CloudFlare WAF блокирует мою первую попытку
Как вы можете видеть, CloudFlare блокирует мой запрос (может быть, потому что «/etc/passwd»), но, если вы прочитали мою последнюю статью о неинициализированной переменной, я могу легко это обойти такой строкой: cat /etc$u/passwd.
CloudFlare WAF обойден, но входные фильтры блокируют мой запрос
Мы обошли CloudFlare WAF, но проверка ввода пользователя заблокировала мой запрос, потому что я пытаюсь использовать «системную» функцию. Есть ли синтаксис, который позволяет мне использовать системную функцию без использования строки «system»? Давайте посмотрим на PHP документацию!
PHP String escape-последовательности
\ [ 0–7] {1,3} последовательность символов в восьмеричной записи, которая молча переполняется, чтобы уместиться в байте (например, «\ 400» === «\ 000»)
\ x [ 0–9A-Fa- f] { 1,2} последовательность символов в шестнадцатеричной записи (например, «\ x41»)
\ и {[0-9A-fa- F] +} последовательность Unicode кода, который будет выводиться в как UTF-8.
Не все знают, что в PHP есть множество синтаксисов для представления строки , и с помощью « функций PHP Variable » он становится нашим швейцарским армейским ножом для обхода фильтров и правил.
Переменные функции PHP
это означает, что такие синтаксисы, как $var(args); и “string”(args); равны function(args);. Если я могу вызвать функцию, используя переменную или строку, это означает, что я могу использовать escape- последовательность вместо имени функции. Вот пример :
Третий синтаксис - это escape-последовательность символов в шестнадцатеричном формате, которую PHP преобразует в строку «system», а затем преобразует в функцию system с аргументом «ls». Давайте попробуем с нашим уязвимым скриптом:
Обход пользовательской очистки
Этот метод не работает для всех функций PHP, различные функции не будут работать с такими языковыми конструкциями, как echo , print , unset () , isset () , empty () , include , require и т.п. Используйте функции-оболочки, чтобы использовать любую из этих конструкций в качестве переменных функций.
Улучшить очистку пользовательского ввода
Что произойдет, если я исключу символы, такие как двойные и одинарные кавычки, из пользовательского ввода в уязвимом сценарии? Можно ли обойти это, даже не используя двойные кавычки? Давай попробуем:
Не используйте " и ' на $ _GET [код]
Как вы можете видеть в третьей строке, теперь скрипт запрещает использование “ и ' внутри $ _GET [код]. Моя предыдущая полезная нагрузка должна быть заблокирована:
Теперь мой уязвимый скрипт не позволяет использовать "
К счастью, в PHP нам не всегда нужны кавычки для представления строки. PHP позволяет вам объявлять тип элемента, например, $ a = (string) foo; в этом случае $ a содержит строку «foo». Более того, все, что находится внутри круглых скобок без специального определения типа и рассматривается как строка:
В этом случае у нас есть два способа обойти новый фильтр: первый - использовать что-то вроде (system) (ls); но мы не можем использовать «system» внутри параметра кода, поэтому мы можем объединять строки вроде ( sy . ( st ). em ) (ls); , Второй заключается в использовани ипеременных $ _ GET. Если я отправлю запрос как ? A = system & b = ls & code = $ _ GET [a] ($ _ GET ); результат: $ _GET [a] будет заменен строкой «system», а $ _GET будет заменен строкой «ls», и я смогу обойти все фильтры!
Давайте попробуем: ( sy . ( St ). Em ) ( whoami );
Мы обошли WAF и фильтр
И вторая команда: ? a = system & b = cat + / etc & c = / passwd & code = $ _ GET [a] ($ _ GET . $ _ GET [c]);
Мы обошли WAF и фильтр
В этом случае это бесполезно, но вы можете даже вставить комментарии внутри имени функции и внутри аргументов (это может быть полезно для обхода набора правил WAF, который блокирует определенные имена функций PHP). Все следующий синтаксисы являются действительными:
get_defined_functions
Эта функция PHP возвращает многомерный массив, содержащий список всех определенных функций , как встроенных (внутренних), так и пользовательских. Внутренние функции будут доступны через $ arr [«internal»] , а пользовательские - через $ arr [«user»] . Пример :
Это может быть еще один способ получить доступ к системной функции без использования ее имени. Если я наберу слово system, то я смогу найти его индекс и использовать его в качестве строки для выполнения моего кода:
1077 = system
Очевидно, это будет работать против нашего CloudFlare WAF и фильтров сценариев:
обход с помощью get_defined_functions
Массив персонажей
Каждая строка в PHP может использоваться как массив символов (почти как в Python), и вы можете ссылаться на один символ строки с синтаксисом $ string [ 2] или $ string [-3] . Это может быть еще один способ избежать правил, которые блокируют имена функций PHP. Например, с эта строка $a=”elmsty/ “; будет сопоставима с system(«ls /tmp»);
Если вам повезет, вы можете найти все необходимые символы в имени файла скрипта. Используя ту же технику, вы можете найти все нужные вам символы с помощью чего-то вроде (__FILE_ _) [ 2] :
OWASP CRS3
Позвольте мне сказать, что с OWASP CRS3 все становится сложнее. Во-первых, с помощью техник, которые я видел раньше, я могу обойти только первый уровень paranoia, и это удивительно! Поскольку Уровень paranoia 1 является лишь небольшим подмножеством правил того, что мы можем найти в CRS3, и этот уровень предназначен для предотвращения любого ложного срабатывания. С уровнем paranoia 2 все становится сложнее из-за правила 942430 «Обнаружение аномалий в символах с ограниченным доступом ( аргументы ): превышено количество специальных символов»). Что я могу сделать, так это просто выполнить одну единственную команду без аргументов, таких как «ls», « whoami » и т. Д., Но я не могу выполнить что-то вроде system ( «cat /etc/passwd »), как это было сделано с CloudFlare WAF:
Переведено специально для https://xss.pro
Переводчик статьи - https://xss.pro/members/177895/
Оригинал - https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/
Это первый из двух уязвимых PHP-скриптов, которые я собираюсь использовать для всех тестов. Этот сценарий, безусловно, слишком прост и глуп, но он просто воспроизводит сценарий уязвимости удаленного выполнения кода (вероятно, в реальном сценарии вам придется проделать немного больше работы, чтобы достичь подобной ситуации):
Первый скрипт PHP
Очевидно, шестая строка - чистое зло. Третья строка пытается перехватить такие функции, как system, exec или passthru (в PHP есть много других функций, которые могут выполнять системные команды, но давайте сосредоточимся на этих трех). Этот сценарий выполняется на веб-сервере за CloudFlare WAF (как всегда, я использую CloudFlare, потому что он прост и широко известен людям, это не означает, что CloudFlare WAF небезопасен. Все другие WAF имеют те же проблемы...). Второй скрипт будет за ModSecurity + OWASP CRS3.
Попытка прочитать /etc/passwd
В первом тесте я пытаюсь прочитать /etc/passwd с помощью функции system() по запросу /cfwaf.php?code=system(“cat /etc/passwd”);
CloudFlare WAF блокирует мою первую попытку
Как вы можете видеть, CloudFlare блокирует мой запрос (может быть, потому что «/etc/passwd»), но, если вы прочитали мою последнюю статью о неинициализированной переменной, я могу легко это обойти такой строкой: cat /etc$u/passwd.
CloudFlare WAF обойден, но входные фильтры блокируют мой запрос
Мы обошли CloudFlare WAF, но проверка ввода пользователя заблокировала мой запрос, потому что я пытаюсь использовать «системную» функцию. Есть ли синтаксис, который позволяет мне использовать системную функцию без использования строки «system»? Давайте посмотрим на PHP документацию!
PHP String escape-последовательности
\ [ 0–7] {1,3} последовательность символов в восьмеричной записи, которая молча переполняется, чтобы уместиться в байте (например, «\ 400» === «\ 000»)
\ x [ 0–9A-Fa- f] { 1,2} последовательность символов в шестнадцатеричной записи (например, «\ x41»)
\ и {[0-9A-fa- F] +} последовательность Unicode кода, который будет выводиться в как UTF-8.
Не все знают, что в PHP есть множество синтаксисов для представления строки , и с помощью « функций PHP Variable » он становится нашим швейцарским армейским ножом для обхода фильтров и правил.
Переменные функции PHP
PHP поддерживает концепцию переменных функций. Это означает, что если к имени переменной добавлены круглые скобки, PHP будет искать функцию с тем же именем, что и для переменной, и попытается ее выполнить. Среди прочего, это может быть использовано для реализации обратных вызовов, таблиц функций и так далее.
это означает, что такие синтаксисы, как $var(args); и “string”(args); равны function(args);. Если я могу вызвать функцию, используя переменную или строку, это означает, что я могу использовать escape- последовательность вместо имени функции. Вот пример :
Третий синтаксис - это escape-последовательность символов в шестнадцатеричном формате, которую PHP преобразует в строку «system», а затем преобразует в функцию system с аргументом «ls». Давайте попробуем с нашим уязвимым скриптом:
Обход пользовательской очистки
Этот метод не работает для всех функций PHP, различные функции не будут работать с такими языковыми конструкциями, как echo , print , unset () , isset () , empty () , include , require и т.п. Используйте функции-оболочки, чтобы использовать любую из этих конструкций в качестве переменных функций.
Улучшить очистку пользовательского ввода
Что произойдет, если я исключу символы, такие как двойные и одинарные кавычки, из пользовательского ввода в уязвимом сценарии? Можно ли обойти это, даже не используя двойные кавычки? Давай попробуем:
Не используйте " и ' на $ _GET [код]
Как вы можете видеть в третьей строке, теперь скрипт запрещает использование “ и ' внутри $ _GET [код]. Моя предыдущая полезная нагрузка должна быть заблокирована:
Теперь мой уязвимый скрипт не позволяет использовать "
К счастью, в PHP нам не всегда нужны кавычки для представления строки. PHP позволяет вам объявлять тип элемента, например, $ a = (string) foo; в этом случае $ a содержит строку «foo». Более того, все, что находится внутри круглых скобок без специального определения типа и рассматривается как строка:
В этом случае у нас есть два способа обойти новый фильтр: первый - использовать что-то вроде (system) (ls); но мы не можем использовать «system» внутри параметра кода, поэтому мы можем объединять строки вроде ( sy . ( st ). em ) (ls); , Второй заключается в использовани ипеременных $ _ GET. Если я отправлю запрос как ? A = system & b = ls & code = $ _ GET [a] ($ _ GET ); результат: $ _GET [a] будет заменен строкой «system», а $ _GET будет заменен строкой «ls», и я смогу обойти все фильтры!
Давайте попробуем: ( sy . ( St ). Em ) ( whoami );
Мы обошли WAF и фильтр
И вторая команда: ? a = system & b = cat + / etc & c = / passwd & code = $ _ GET [a] ($ _ GET . $ _ GET [c]);
Мы обошли WAF и фильтр
В этом случае это бесполезно, но вы можете даже вставить комментарии внутри имени функции и внутри аргументов (это может быть полезно для обхода набора правил WAF, который блокирует определенные имена функций PHP). Все следующий синтаксисы являются действительными:
get_defined_functions
Эта функция PHP возвращает многомерный массив, содержащий список всех определенных функций , как встроенных (внутренних), так и пользовательских. Внутренние функции будут доступны через $ arr [«internal»] , а пользовательские - через $ arr [«user»] . Пример :
Это может быть еще один способ получить доступ к системной функции без использования ее имени. Если я наберу слово system, то я смогу найти его индекс и использовать его в качестве строки для выполнения моего кода:
1077 = system
Очевидно, это будет работать против нашего CloudFlare WAF и фильтров сценариев:
обход с помощью get_defined_functions
Массив персонажей
Каждая строка в PHP может использоваться как массив символов (почти как в Python), и вы можете ссылаться на один символ строки с синтаксисом $ string [ 2] или $ string [-3] . Это может быть еще один способ избежать правил, которые блокируют имена функций PHP. Например, с эта строка $a=”elmsty/ “; будет сопоставима с system(«ls /tmp»);
Если вам повезет, вы можете найти все необходимые символы в имени файла скрипта. Используя ту же технику, вы можете найти все нужные вам символы с помощью чего-то вроде (__FILE_ _) [ 2] :
OWASP CRS3
Позвольте мне сказать, что с OWASP CRS3 все становится сложнее. Во-первых, с помощью техник, которые я видел раньше, я могу обойти только первый уровень paranoia, и это удивительно! Поскольку Уровень paranoia 1 является лишь небольшим подмножеством правил того, что мы можем найти в CRS3, и этот уровень предназначен для предотвращения любого ложного срабатывания. С уровнем paranoia 2 все становится сложнее из-за правила 942430 «Обнаружение аномалий в символах с ограниченным доступом ( аргументы ): превышено количество специальных символов»). Что я могу сделать, так это просто выполнить одну единственную команду без аргументов, таких как «ls», « whoami » и т. Д., Но я не могу выполнить что-то вроде system ( «cat /etc/passwd »), как это было сделано с CloudFlare WAF:
Переведено специально для https://xss.pro
Переводчик статьи - https://xss.pro/members/177895/
Оригинал - https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/
Вложения
Последнее редактирование: