打开题目,发现有三个链接,分别是

    • /flag.txt
    • /welcome.txt
    • /hints.txt

    内容分别为

    1. /flag.txt
    2. flag in /fllllllllllllag
    1. /welcome.txt
    2. render
    1. /hints.txt
    2. md5(cookie_secret+md5(filename))

    从第二个welcome.txt可以猜到,这题应该是考SSTI注入,而flag就在fllllllllllllag文件里面。
    但是观察url发现,后面还需要一个filehash参数,如果不正确就会报错

    1. http://220.249.52.134:39518/file?filename=/hints.txt&filehash=7ead89c8b1dd04017dcc2d72dbce2be2

    而这个filehash的计算方式在hints.txt中也给了

    1. md5(cookie_secret+md5(filename))

    filename是fllllllllllllag,就剩下cookie_secret需要找出来了。
    经过查阅tornado文档,找到cookie_secret的定义:

    1. application = tornado.web.Application([
    2. (r"/", MainHandler),
    3. ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")

    并且尝试在源码中搜索,还可以看到cookie_secret可以通过self.application.settings["cookie_secret"]的形式取得。
    这段代码在RequestHandler类中,那么只要能得到这个对象,就可以得到cookie_secret

    因为前面welcome.txt已经提示是SSTI注入,那么肯定是有一处地方是可以注入的,经过一番测试,最后发现Error页面可以注入。

    1. http://220.249.52.134:39518/error?msg=Error
    2. //return Error
    3. http://220.249.52.134:39518/error?msg=12345
    4. //return 12345

    但是测试后发现[]()_/*"'都被过滤了,所以魔术方法是用不了了。
    查阅文档,发现这么一段:

    表达式可以是任意的Python表达式, 包括函数调用. 模板代码会在包含以下对象 和函数的命名空间中执行 (注意这个列表适用于使用 RequestHandler.renderrender_string 渲染模板的情况. 如果你直接在 RequestHandler 之外使用 tornado.template 模块, 下面这些很多都不存 在).

    也就是说,在模板中可以直接使用列表中的这些别名,来使用原本的模块或者对象。
    可以看到,handler代表的就是当前的RequestHandler对象,那么通过handler.application.settings就可以得到cookie_secret了。

    加密部分就很简单了,写个python脚本就可以:

    1. #!/usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3. import hashlib
    4. filename="/fllllllllllllag"
    5. cookie_secret="******************"
    6. enc=""
    7. enc=hashlib.md5(cookie_secret+hashlib.md5(filename.encode(encoding='utf-8')).hexdigest()).hexdigest()
    8. print(enc)

    将filename和filehash分别替换后访问,得到flag。