[护网杯 2018]easy_tornado

[护网杯 2018]easy_tornado

给了三个txt,flag.txt给出了flag文件,welcome.txt提示了render,hints.txt给出了摘要算法md5(cookie_secret+md5(filename))。并且观察url可以发现提交了两个参数分别为一个filename和一个filehash。既然这里给出了摘要算法,应该就是提交的filehash值算法。

这里要计算filehash值就要获取cookie_secret,根据welcome提示,应该是render模板注入(ssti),通过ssti获取cookie_secret再计算出filehash读取flag文件获取flag。注入点在一个错误提示中,当提交的filehash不正确时就会跳转到一个错误消息的url,其中有一个参数为msg,修改这个参数发现提交的值显示在页面中。提交msg={{1}}回显为1,尝试提交{{1+1}}发现被过滤了,但是{{2^2}}回显为0,说明确实存在ssti。但是如何获取cookie_secret还是不知道,看了一下wp发现时利用handler.settings进行读取,但是都没有说明为什么这样读取。我们利用这个变量可以获取到cookie_secret然后使用hints.txt中给出的算法即可计算出filehash读取flag文件。

Tornado templates support control statements and expressions. Control statements are surrounded by {% and %}, e.g. {% if len(items) > 2 %}. Expressions are surrounded by {{ and }}, e.g. {{ items[0] }}.

Python中从服务端模板注入到沙盒逃逸的源码探索 (一)一文对为什么利用handler.settings获取cookie_secret做出了部分解释,该文放出了部分tornado源码,我们可以在一下代码中看到有一个将self赋值给handler的操作

    def get_template_namespace(self):
        namespace = dict(
            handler=self,
            request=self.request,
            current_user=self.current_user,
            locale=self.locale,
            _=self.locale.translate,
            pgettext=self.locale.pgettext,
            static_url=self.static_url,
            xsrf_form_html=self.xsrf_form_html,
            reverse_url=self.reverse_url
        )
        namespace.update(self.ui)
        return namespace

这是RequestHandler类中的一个方法,也就是说这里将RequestHandler类本身赋值给了handler,因此handler.settings实际上就是RequestHandler.settings(self.settings),这一点在tornado文档中也有说明。

  • Expressions can be any Python expression, including function calls. Template code is executed in a namespace that includes the following objects and functions. (Note that this list applies to templates rendered using RequestHandler.render and render_string. If you’re using the tornado.template module directly outside of a RequestHandler many of these entries are not present).
  • escape: alias for tornado.escape.xhtml_escape
  • xhtml_escape: alias for tornado.escape.xhtml_escape
  • url_escape: alias for tornado.escape.url_escape
  • json_encode: alias for tornado.escape.json_encode
  • squeeze: alias for tornado.escape.squeeze
  • linkify: alias for tornado.escape.linkify
  • datetime: the Python datetime module
  • handler: the current RequestHandler object
  • request: alias for handler.request
  • current_user: alias for handler.current_user
  • locale: alias for handler.locale
  • _: alias for handler.locale.translate
  • static_url: alias for handler.static_url
  • xsrf_form_html: alias for handler.xsrf_form_html
  • reverse_url: alias for Application.reverse_url
  • All entries from the ui_methods and ui_modules Application settings
  • Any keyword arguments passed to render or render_string

tornado提供了一些变量可以在模板中访问,因此我们可以利用handler来访问settings。

Tornado小记 -- 模板中的Handler一文对RequestHandler.settings做出了解释,RequestHandler.settings实际上是指向了self.application.settings,在tornado文档中也能看到这个说明。

RequestHandler.settings

An alias for self.application.settings.

在[tornado文档](https://www.tornadoweb.org/en/stable/guide/security.html#User authentication)此处能够看到

class MainHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        name = tornado.escape.xhtml_escape(self.current_user)
        self.write("Hello, " + name)

settings = {
    "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
    "login_url": "/login",
}
application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/login", LoginHandler),
], **settings)

在这里我们可以看到在cookie_secret是存在settings中的,settings又作为参数传入了Application构造函数,因此可以通过self.application.settings获取到cookie_secret。

既然这里最终是访问到self.application.settings获取cookie_secret,并且需要利用tornado提供的handler来访问,那么我们不仅可以通过handler.settings来获取,也可以使用handler.application.settings,这样实际上也是访问到self.application.settings。

你可能感兴趣的:([护网杯 2018]easy_tornado)