看到题目,查一下tornado是什么,发现是python的web框架,因此猜测存在模板注入。
首先进入环境,有三个文件,一个文件告诉我们flag在哪,一个文件提示我们请求的url中的filehash如何构造,另外的welcome.txt里是render。经过谷歌后知道,render是python中的一个渲染函数,因此这题考察的应该是python的模板注入了。
因此我们接下来解题有2个点,一个就是要想办法得到cookie_secret,另外一个是要想办法利用模板注入。
这里原理直接引用一下别人的:
tornado render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页,如果用户对render内容可控,不仅可以注入XSS代码,而且还可以通过{ {}}进行传递变量和执行简单的表达式。
例子:#!/usr/bin/env python # -*- coding:utf-8 -*- from tornado.web import UIModule from tornado import escape class custom(UIModule): def render(self, *args, **kwargs): return escape.xhtml_escape('<h1>wupeiqi</h1>') #return escape.xhtml_escape('<h1>wupeiqi</h1>') ``` 和 #!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') class LoginHandler(BaseHandler): def get(self): ''' 当用户访登录的时候我们就得给他写cookie了,但是这里没有写在哪里写了呢? 在哪里呢?之前写的Handler都是继承的RequestHandler,这次继承的是BaseHandler是自己写的Handler 继承自己的类,在类了加扩展initialize! 在这里我们可以在这里做获取用户cookie或者写cookie都可以在这里做 ''' ''' 我们知道LoginHandler对象就是self,我们可不可以self.set_cookie()可不可以self.get_cookie() ''' # self.set_cookie() # self.get_cookie() self.render('login.html', **{ 'status': ''}) def login(request): #获取用户输入 login_form = AccountForm.LoginForm(request.POST) if request.method == 'POST': #判断用户输入是否合法 if login_form.is_valid():#如果用户输入是合法的 username = request.POST.get('username') password = request.POST.get('password') if models.UserInfo.objects.get(username=username) and models.UserInfo.objects.get(username=username).password == password: request.session['auth_user'] = username return redirect('/index/') else: return render(request,'account/login.html',{ 'model': login_form,'backend_autherror':'用户名或密码错误'}) else: error_msg = login_form.errors.as_data() return render(request,'account/login.html',{ 'model': login_form,'errors':error_msg}) # 如果登录成功,写入session,跳转index return render(request, 'account/login.html', { 'model': login_form})
在tornado模板中,存在一些可以访问的快速对象,例如:
<title>
{
{
escape(handler.settings["cookie"]) }}
</title>
handler.settings指向RequestHandler.settings,而RequestHandler.settings又指向self.application.settings 。
所有handler.settings就指向RequestHandler.application.settings了。而这里面正是我们的环境变量。。
怎么利用到模板注入呢?只要你访问的不正确,就会跳转到这个页面:
get传入的msg参数里的内容似乎出现到了网页里,似乎这里就是模板注入的点。尝试输入{
{1+2}},发现500。。输入{
{1*2}},输出ORZ。。。。
经过一些尝试,发现这里应该是存在了过滤,但是并没有对我们要进行注入的内容进行过滤,因此直接获取环境变量:
成功得到了cookie_secret。然后写个python脚本,得到md5后的结果,就可以成功得到flag:
import hashlib
filename='/fllllllllllllag'
cookie_secret='3edd4d3c-190e-415f-9a7b-c6e4520f8249'
m=hashlib.md5()
m.update(filename.encode("utf-8"))
n=m.hexdigest()
v=cookie_secret+n
m=hashlib.md5()
m.update(v.encode("utf-8"))
n=m.hexdigest()
print(n)