组组组合拳艰难渗透
字数 2577 2025-10-18 11:17:50
渗透测试教学文档:通过源代码审计与JWT伪造攻破后台
文档核心: 本文档基于一次真实的渗透测试案例,详细讲解了在常规漏洞利用受阻时,如何通过信息收集、源代码审计、逻辑漏洞发现与利用,最终实现权限提升的完整流程与思维方法。
一、 前期信息收集与关键发现
- 目标探测:
- 动作: 访问目标系统界面,初步观察功能点。
- 结果: 未发现明显的可利用功能(如登录框、上传点等)。
- 目录/文件扫描:
- 工具: 使用目录扫描工具(如DirBuster, DirSearch等)。
- 关键发现: 扫描到存在
xxx.zip文件。 - 分析: 此类压缩文件通常是开发或运维人员遗留的备份文件,可能包含源代码、配置文件、数据库备份等敏感信息。这是本次渗透的第一个关键转折点。
二、 源代码获取与分析准备
- 下载源代码:
- 使用
wget或浏览器直接下载xxx.zip文件。 - 文件大小: 200+ MB,进一步增加了是完整源代码的可能性。
- 使用
- 技术栈识别:
- 判断: 通过分析文件内容,确定目标系统采用 .NET 框架开发。
- 审计工具: 准备使用 dnSpy(.NET程序集的反编译与调试工具)进行源代码审计。
三、 漏洞审计与利用尝试(受挫阶段)
在拿到源码后,按照常规思路寻找高危漏洞,但均告失败。
-
文件上传漏洞审计(尝试一):
- 发现: 在源码中找到
uploadimg接口,代码层面未对上传文件的格式、内容进行任何过滤,存在理论上的漏洞。 - 实际利用尝试:
- 尝试上传Webshell(如
.aspx文件)。 - 尝试变换文件格式、文件内容、
Content-Type请求头、使用各种绕过技术(如双后缀、大小写、空格、::$DATA等)。
- 尝试上传Webshell(如
- 结果: 服务器始终返回
{"Status":1,"Data":"null"},利用失败。 - 分析: 可能存在前端校验、WAF(Web应用防火墙)防护、运维层面的文件类型限制等,导致漏洞无法直接利用。
- 发现: 在源码中找到
-
SQL注入漏洞审计(尝试二):
- 发现: 代码中定义了一个名为
SqlChecker的全局类,对所有用户输入参数进行强制性的安全检查和过滤。 - 结果: 代码层面已有效防御了SQL注入,此路不通。
- 发现: 代码中定义了一个名为
四、 转变思路:发现信息泄露与认证逻辑漏洞(突破阶段)
当直接攻击路径被阻断时,需要寻找系统的“软肋”——逻辑缺陷和信息泄露。
-
发现敏感接口(信息泄露):
- 接口路径:
/api/user/getusers - 关键问题: 该接口未做任何权限验证(鉴权),任何用户均可访问。
- 利用: 直接构造HTTP请求包访问该接口。
- 返回数据: 系统返回所有用户的敏感信息,包括:
- 姓名、出生日期
- 微信账号、手机号码、邮箱
- 密码(可能是明文或加密存储的)
- 意义: 这是极其严重的信息泄露漏洞,为后续攻击提供了数据基础。
- 接口路径:
-
分析认证机制(JWT):
- 动作: 通过系统正常的注册和登录功能,分析其认证流程。
- 发现:
- 登录成功后,服务器会返回一个 JWT (JSON Web Token) 以及用户信息。
- 前端使用此JWT来维持登录状态,并在后续请求中携带它来访问需要权限的接口。
- 关键点: 系统的权限控制依赖于JWT的有效性。
-
寻找JWT密钥(Secret):
- 动作: 在源代码中搜索用于签发和验证JWT的密钥(Secret或Key)。
- 发现: 成功找到密钥。
- 坑点: 该密钥并非可读字符串,而是一个随机生成的字节序列(byte array)。这意味着不能直接使用常见的JWT在线工具(如jwt.io)或CyberChef来生成Token,因为它们通常需要字符串形式的密钥。
五、 伪造身份,拿下权限(最终攻击)
-
编写JWT伪造脚本:
- 语言: Python(因其对字节操作友好)。
- 核心步骤:
- 处理密钥: 将源代码中的字节序列密钥转换为16进制字符串,以便Python的
bytes.fromhex()函数能够读取。 - 选择算法: 使用JWT标准算法(如HS256)。
- 构造Payload:
- 利用从
/api/user/getusers接口获取的管理员信息(如用户名admin)。 - 设置一个较长的过期时间(
exp)。
- 利用从
- 生成Token: 使用Python库(如
PyJWT)用正确的密钥和算法生成新的JWT。
- 处理密钥: 将源代码中的字节序列密钥转换为16进制字符串,以便Python的
- 示例代码逻辑:
import jwt # 1. 将源代码中的字节数组转换为hex字符串,例如: secret_hex = "1a2b3c4d5e6f..." # 2. 将hex字符串转换回bytes secret_bytes = bytes.fromhex(secret_hex) # 3. 构造Payload payload = { "username": "admin", # 从信息泄露接口获取 "exp": 长期时间戳 # ... 其他必要字段 } # 4. 生成JWT Token forged_token = jwt.encode(payload, secret_bytes, algorithm="HS256") print(forged_token)
-
实施身份伪造:
- 工具: 使用Burp Suite等代理工具拦截流量。
- 场景: 使用一个普通注册的账号登录系统。
- 攻击: 在登录请求的返回包中,将服务器返回的普通用户的JWT和用户信息,替换成我们自己生成的
admin的JWT和管理员信息。 - 原理: 前端接收到伪造的返回包后,会认为当前登录的是管理员,从而跳转到管理员后台页面,并使用伪造的JWT去请求数据。
-
成功获取权限:
- 完成替换后,前端顺利通过验证,成功进入管理员后台,靶标系统被攻破。
六、 总结与教学要点
- 思维转变: 现代渗透测试不再是“单点突破”,而是“组合拳”。当直接攻击路径(如文件上传、SQL注入)被防御时,应立即转向信息泄露、逻辑漏洞、配置错误等方向。
- 信息收集的价值: 一次不经意的目录扫描发现的
zip文件,成为了整个攻击链的基石。永远不要忽视任何看似微小的信息。 - 代码审计的核心: 审计源码不仅要找漏洞代码,更要理解系统的整体架构和认证授权机制。本次成功的关键在于理解了JWT认证流程,并顺藤摸瓜找到了密钥。
- 技术细节的重要性: 遇到“密钥是字节序列”这种技术细节时,需要具备解决问题的能力(如编写Python脚本),而不是依赖现成工具。这体现了扎实的编程基础在渗透测试中的重要性。
- 漏洞链利用: 本次攻击形成了一个完美的漏洞链:
- 信息泄露漏洞(
getusers接口) → 获取管理员身份标识。 - 信息泄露漏洞(源代码备份) → 获取JWT密钥。
- 设计缺陷/逻辑漏洞(JWT密钥硬编码+可伪造) → 允许攻击者伪造身份。
- 最终通过中间人篡改完成攻击。
- 信息泄露漏洞(
通过本案例的学习,应重点掌握在渗透测试中灵活变通的思维、对认证机制的深入理解以及将多个低危问题串联成高危攻击链的能力。