在渗透测试中,前端加密是阻碍参数篡改、重放攻击和漏洞验证的常见障碍。无论是登录密码加密、API签名还是返回数据加密,只有破解或模拟其算法,才能构造有效请求、发现后端漏洞。本笔记从实战出发,系统梳理加密算法定位、解密模拟的方法论,以及Sign签名机制的绕过技术,涵盖“扣代码”与“替代库”两种核心策略。


1. 加密算法定位:找到加密入口

定位加密函数是解密的第一步,常用两种方法:

方法

操作

适用场景

调用堆栈回溯

在发起网络请求的XHR断点处,通过调用堆栈向上回溯,寻找加密函数。

加密逻辑与请求发送紧密耦合,易找到调用关系。

关键字全局搜索

在Sources面板中搜索请求参数名(如passwordsign)、加密方法名(如encryptmd5)或常量。

加密函数命名规范或参数名可见。

实战步骤

  1. 网络面板定位请求:找到包含加密参数(如paramsign)的请求。
  2. XHR断点拦截:在Sources面板设置XHR断点(URL包含关键字),刷新页面触发断点。
  3. 调用堆栈分析:断点处查看Call Stack,从栈顶向下查找,重点关注名称含encrypthashsubmit等函数。
  4. 进入加密函数:点击栈帧进入可疑函数,观察参数和作用域,找到加密逻辑。

2. 解密策略:扣代码 vs 替代库模拟

根据算法复杂度和依赖环境,可选择两种策略:

策略

原理

优点

缺点

适用场景

扣代码(JS模拟)

将加密函数及其依赖的完整代码从浏览器中复制,在Node.js中运行。

无需理解算法细节,100%还原。

代码可能庞大、依赖Web环境(需模拟DOM)、混淆度高时难以扣全。

加密函数独立,无复杂外部依赖(如WebAssembly、Canvas)。

替代库模拟

分析算法类型(AES、RSA、MD5),用Python/Node.js的标准库重新实现。

代码简洁、可控,适合自动化集成。

需要识别算法类型和参数(key、iv、mode)。

算法标准、密钥已知或可逆向提取。


3. 请求数据解密实战(扣代码模拟)

场景:登录请求参数password被加密,需模拟加密算法以爆破密码。

步骤

  1. 定位加密函数
    • 在登录请求处打断点,通过调用堆栈找到处理密码的函数,例如hidetxtPassword
    • 进入该函数,观察其调用了encrypt方法,可能位于某个外部JS文件。
  1. 提取加密代码
    • 在Sources面板找到包含加密算法的JS文件,可能是Webpack打包后的文件。
    • 将整个文件内容保存为本地.js文件。若文件过大,可只复制关键函数及其依赖。
  1. 搭建Node.js运行环境
    • 创建新目录,执行npm init -y初始化。
    • 安装必要依赖(如crypto-jsjsdom等,若需模拟浏览器环境)。
    • 将保存的JS文件放入目录,并创建测试脚本encrypt.js
  1. 编写调用脚本
// 假设加密函数为 window.encryptPassword
const fs = require('fs');
// 加载提取的JS代码(如果它依赖全局对象,可能需要模拟)
eval(fs.readFileSync('extracted.js', 'utf8'));

// 调用函数
let encrypted = window.encryptPassword('123456');
console.log(encrypted);
    • 根据浏览器中断点处的调用方式,在Node.js中调用该函数。
    • 如果遇到windowdocument未定义,可使用jsdom模拟或修改代码剥离依赖。
  1. 验证
    • 运行脚本,对比浏览器中生成的加密值是否一致。若一致,则扣代码成功。

渗透测试应用:在爆破脚本中调用此加密函数,生成有效加密密码。


4. 返回数据解密实战(替代库模拟)

场景:API返回的数据(如result)是密文,需解密后查看明文内容。

步骤

  1. 定位解密函数
    • 在返回数据的响应断点处(可在XHR断点命中后,在回调函数中下断),查看调用堆栈,找到处理返回数据的函数。
    • 例如,发现webInstace.shell函数调用了一个解密方法,参数为响应数据。
  1. 分析算法参数
    • 进入解密函数,观察其使用的算法和密钥来源。例如:
      • CryptoJS.AES.decrypt(encryptedData, key, { mode: CryptoJS.mode.ECB })
      • 密钥key可能是一个常量,或由其他函数生成(如SHA1(secret)取前32位)。
  1. 确定算法类型
    • 识别算法(AES、DES、RSA等)和模式(ECB、CBC等)、填充方式。
    • 从代码中提取密钥生成逻辑。
  1. 使用替代库实现

Python示例(AES-128-ECB)

from Crypto.Cipher import AES
import base64, hashlib

def decrypt(data_b64, key_secret):
    # 密钥生成:SHA1(key_secret)[:32]
    key = hashlib.sha1(key_secret.encode()).hexdigest()[:32]
    cipher = AES.new(key.encode(), AES.MODE_ECB)
    encrypted = base64.b64decode(data_b64)
    decrypted = cipher.decrypt(encrypted)
    # 去除填充(PKCS7)
    pad_len = decrypted[-1]
    return decrypted[:-pad_len].decode('utf-8')

decrypted = decrypt('encrypted_base64_string', 'secret_constant')
print(decrypted)
    • 在Python或Node.js中导入对应库,如pycryptodome(Python)或crypto-js(Node.js)。
    • 根据提取的密钥生成逻辑,编写解密函数。
  1. 验证
    • 用相同密钥和算法解密浏览器中获取的密文,与页面显示明文对比,一致则成功。

渗透测试应用:自动化获取解密后的数据,用于后续攻击(如提取敏感信息、越权测试)。


5. Sign签名机制与绕过实战

Sign机制是保护API接口完整性的常见手段,也是渗透测试中绕不开的“拦路虎”。

5.1 Sign机制概述

Sign是一种基于密钥和算法对请求参数进行哈希或加密生成的校验值,通常附加在请求头或参数中,用于:

  • 防篡改:确保请求数据在传输中未被修改。
  • 防重放:结合时间戳(timestamp)和随机数(nonce),使同一请求仅一次有效。
  • 身份认证:验证请求来源的合法性。

常见算法:MD5、SHA系列、HMAC、AES等。

5.2 Sign对渗透测试的影响

影响类型

具体表现

渗透测试应对策略

正面影响

1. 提高安全性,减少低风险漏洞(如简单重放)。
2. 迫使测试人员深入分析业务逻辑,而非依赖自动化扫描。

- 需结合逆向工程和动态调试。
- 关注签名生成逻辑本身是否安全。

负面影响

1. 增加复杂度:逆向混淆代码耗时,动态调试受限。
2. 自动化工具失效:Burp、AWVS等无法直接修改带签名的请求。
3. 可能掩盖漏洞:开发者过度依赖签名,忽视输入过滤、权限控制等基础安全。

- 掌握JS逆向、HOOK技术。
- 编写脚本自动生成签名。
- 重点测试签名校验逻辑缺陷(如客户端计算签名、密钥硬编码)。

5.3 案例:算法逆向绕过(调用堆栈定位)

目标:某API接口/api/questions/lists,请求头需携带Sign参数。

逆向步骤

  1. XHR断点定位:在Sources面板设置XHR断点,关键字/api/questions/lists,触发请求后断下。
  2. 调用堆栈回溯:在Call Stack中找到生成Sign的调用点,发现:
t.headers.Sign = h
h = bs()(o + c + r + n + o)
  1. 分析bs()和参数值
    • bs()处下断点,发现其为MD5算法
    • 各参数值:
      • o:硬编码常量 "12b6bb84e093532fb72b4d65fec3f00b"
      • c:从Cookie中提取的值 "dbbc7981-906b-45c5-8102-edf02376f9c4"
      • r:当前URL去掉/api后的路径 "/questions/lists"
      • n:当前时间戳 (new Date).getTime()
  1. 验证签名生成:在控制台手动计算:
crypto.MD5(o + c + r + n + o).toString()

与请求头中的Sign对比,一致。

  1. 编写Python脚本自动化:用hashlib.md5复现,在Burp Intruder中调用外部脚本生成签名,实现爆破。

绕过思路

  • 若签名仅依赖客户端可控参数(如时间戳、固定密钥),则可在本地完全模拟。
  • 若密钥硬编码在JS中,可直接提取。

6. 工具与辅助技巧

工具/技术

用途

说明

AI助手(如ChatGPT)

辅助分析混淆代码、生成解密脚本

将加密函数或算法描述提供给AI,可快速生成对应语言实现。

JsRPC

远程调用浏览器中的加密函数

在浏览器中注入RPC服务,Python脚本通过WebSocket实时调用加密函数,无需扣代码。

Yakit热加载

在Burp中动态执行JS解密

编写Yakit插件,将解密函数加载到Burp中,自动解密请求/响应数据。

AutoDecode

Burp插件,自动调用JS解密

配置解密函数后,自动对匹配的请求/响应进行解码。

浏览器本地替换

修改JS代码并保存,测试效果

在Sources面板修改加密函数,右键选择“Save for overrides”,可永久替换本地代码。


7. 总结:Sign绕过方法论

步骤

关键操作

技巧

1. 定位签名生成点

XHR断点、全局搜索关键字(signmd5encrypt)。

优先使用XHR断点,快速定位到请求发起位置。

2. 分析签名参数

查看作用域中的变量值,确定哪些参数参与签名。

关注时间戳、随机数、路径、Cookie、固定密钥等。

3. 提取算法和密钥

单步调试进入加密函数,识别算法类型;若密钥硬编码,直接复制。

若算法被混淆,可借助AI还原逻辑。

4. 本地复现签名

用Python/Node.js实现相同算法,并测试与浏览器生成的签名是否一致。

若依赖浏览器环境(如window对象),可使用JsRPC动态调用。

5. 集成到测试工具

在Burp中调用外部脚本(如Python脚本)生成签名,或使用Yakit热加载。

确保每次请求都附带有效签名,从而进行后续测试(如注入、越权)。


8. 学习建议

阶段

核心技能

目标

定位

熟练使用F12断点、调用堆栈、搜索

快速找到加密/解密函数入口。

提取

扣代码技巧(复制依赖、模拟环境)

获取完整的可执行加密逻辑。

模拟

算法识别、标准库使用

用Python/Node.js实现相同功能,便于自动化。

集成

JsRPC、Burp插件、Yakit

将解密能力无缝融入渗透测试流程。

核心思想:签名机制虽增加了测试门槛,但一旦破解,即可完全模拟客户端行为,进而深入测试服务端漏洞。始终记住:签名保护的只是传输完整性,而非业务安全本身。掌握这些技巧,你将能突破前端加密屏障,更深入地测试后端安全,发现更多逻辑漏洞。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐