[护网杯 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.renderandrender_string. If you’re using thetornado.templatemodule directly outside of aRequestHandlermany of these entries are not present).escape: alias fortornado.escape.xhtml_escapexhtml_escape: alias fortornado.escape.xhtml_escapeurl_escape: alias fortornado.escape.url_escapejson_encode: alias fortornado.escape.json_encodesqueeze: alias fortornado.escape.squeezelinkify: alias fortornado.escape.linkifydatetime: the Pythondatetimemodulehandler: the currentRequestHandlerobjectrequest: alias forhandler.requestcurrent_user: alias forhandler.current_userlocale: alias forhandler.locale_: alias forhandler.locale.translatestatic_url: alias forhandler.static_urlxsrf_form_html: alias forhandler.xsrf_form_htmlreverse_url: alias forApplication.reverse_url- All entries from the
ui_methodsandui_modulesApplicationsettings- Any keyword arguments passed to
renderorrender_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。









网友评论