最近做了一道题,是buu上的easy-tornado。可把我为难坏了。因为之前并没听说过SSTI模板注入。经过了几天,查阅了大量资料,明白了一丢丢。
先说一下漏洞是怎么产生的。因为现在的服务器端框架,如python的flask,php的tp,java的spring等一般都采用成熟的的MVC的模式。而在这个MVC模式下,我们用户输入的请求会先进入Controller控制器。然后跟据根据请求的类型,发送给相应模块进行逻辑判断和数据库的存取。最后把结果返回到视图层。
洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web
应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell
等问题。其影响范围主要取决于模版引擎的复杂性。
那么什么叫渲染呢?先说说模板,模板是一种提供给程序员解析的语法。当服务器难道数据以后,放到模板中。让后模板中的渲染引擎会将这些数据转化为html文本返回给浏览器。这个就叫渲染。[个人理解]
模板注入,大概意思就是我们将一些有害代码通过有害请求提交给服务器,服务器把它编码为html文本返回给浏览器执行并返回值。这样我们就达到了注入的目的。
语法:
{% … %} 用来声明变量
{{ … }} 用来将表达式打印到模板输出
{# … #} 表示未包含在模板输出中的注释
在模板注入中,主要使用的是{{}} 和 {%%}
注入思路:
利用命令进行查询(类似于sql注入)如:
获取内置类型所对应的类:
> (''__class__.mor__)(注意此处是双'_')
> {}__class__.bases__
> 等等
查看子类
__subclasses__()
初始化返回值
__init__
对包含函数全局变量的字典的引用
globals__
之后还可以跟.open('我们输入的命令').read
来执行我们的命令结果并输出。
返回描述对象的字符串(可以理解为打印出来)
__str__
好,下面我们来看一道题。
攻防世界:Web_python_template_injection:
打开靶机
我们也看不出有什么玄机。我们稍微尝试一下。访问一下flag.php
现在就可以猜个差不多了。像这种返回值很多都是SSTI模板注入。我们再实验一下,试一下flag={{3*2}}看看什么结果。
看,他说’6not find ‘说明3*2被执行了。那就证明了存在模板注入。
那我们就开始查询payload:/flag={{’‘.class}}
所以说这个变量的类是str。然后从这个类中找他的基类,payload:/flag={{’‘.class.mro}}
然后我们就可以从其中任意一个基类查找他的引用表列,payload:/flag={{’'.class.mro[2].subclasses()}}
再来介绍一下os模块:
os模块是Python中整理文件和目录最为常用的模块,该模块提供了非常丰富的方法用来处理文件和目录。
也就是所我们找到了引用os模块的基类就可以找到存放fllag的文件。os模块
从其中可以找到我们想要 所在的 site._Printer
类,它在列表的第七十二位所以我们构造__subclasses__()[71]
(我也不知道为什么是71,搞了半天没弄懂,呜呜呜)。payload:/flag={{‘’.class.mro[2].sub
classes()[71].init.globals[‘os’].popen(‘ls’).read()}}。
可以看到flag是在一个名为fl4g的无后缀文件中。我们cat flag。payload:/flag={{‘’.class.mro[2].sub
classes()[71].init.globals[‘os’].popen(‘cat fl4g’).read()}}。
出来了。
再看看buu的题:[护网杯 2018]easy_tornado:
打开靶机
我们挨个看:
可以看到flag.txt中说flag在/fllllllllllllag中,welcome.txt中只有一个render。查了一下才知道:
r ender是使用js的完全编程能力来渲染页面,即用js来构建DOM.
那么就想到了ssti模板注入。hint.txt中说md5(cookie_secret+md5(filename))是获得flag的方法。
仔细观察会发现url的形式都是:/file?filename=/hints.txt&filehash=31c37b7829da13445b849896c8a10517
filename我们知道是/fllllllllllllag问题是怎么找cookie_secret。查阅资料后,我知道了cookie_secret可以在浏览器中设置cookie。但是Cookie并不安全,客户端可以轻松修改。如果你需要设置Cookie,例如,识别当前登录的用户,则需要对cookie签名以防止伪造。Tornado支持使用set_secure_cookie和get_secure_cookie方法签名的cookie。 要使用这些方法,您需要在创建应用程序时指定名为cookie_secret的密钥。
在tornado模板中,存在一些可以访问的快速对象,这里用到的是handler.settings,handler指向RequestHandler,而RequestHandler.settings又指向self.application.settings,所以handler.settings就指向RequestHandler.application.settings了,这里面就是我们的一些环境变量
所以我们尝试注入。先试验一下:我们改变filehash的值,然后报错了。
再实验一下是否可以注入payload:error?msg={{datetime}}
(在Tornado的前端页面模板中,datetime是指向python中datetime这个模块)
好的存在注入点,我们再次注入,payload:error?msg={{handler.settings}}
好的出来了我们再去哈希一下然后payload:/file?filename=/fllllllllllllag&filehash=1626467bafc734338e47716cdc66f70f
好的出来了。
怎么说呢,感觉好难的。这一个知识点搞了3天,感觉还是不太明白。谁理解的透彻啊,教教我啊。
最后养养眼。
参考链接:
https://www.cnblogs.com/bmjoker/p/13508538.html
http://t.csdn.cn/NW1Ur
http://t.csdn.cn/ZQtFs
等等