前端加密是纸老虎:一次「信封加密」的自解密实录"

admin 2026-11-06 02:53:21 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

前端加密是纸老虎:一次「信封加密」的自解密实录

原创

mao
mao

three安全之路

2026年11月5日 14:46
四川

去阅读

抓包全是密文就是安全?一个随机生成的 AES key,就能让整套前端加密形同虚设。


一、引子:抓包看到一串密文

做安全测试时,经常会遇到这种请求:

GET /api/xxx/distribution?key=RYExrzov6bs6...&data=721b0283bd2f...&expireTime=1793755364651

URL 里没有明文参数,data 是一串十六进制,key 是一串 Base64。很多人第一反应是:\"加密了,看不到,安全了。\"

但在\"信封加密\"体系下,这恰恰是一个容易被忽视的安全假象。


二、什么是\"信封加密\"

这类系统通常这样设计:

  1. 前端每次发请求前,随机生成一个 AES key(比如 16 位随机字符串);
  2. 用服务端下发的公开 RSA 公钥,把这个 AES key 加密,放进 key 字段;
  3. 用这个 AES key,把业务参数加密成 data(hex);
  4. 再带上 expireTime(公钥有效期)。

服务端收到后:用自己的 RSA 私钥解开 key 拿到 AES key,再解开 data,处理业务,最后用同一个 AES key 加密响应返回。

形象的比喻:

  • data 是信;
  • AES key 是拆信的钥匙;
  • 而这把钥匙被装进一个只有服务端能开的小盒子(RSA 加密),就是 key。

三、致命点:钥匙是客户端自己造的

听起来很安全对不对?但关键在第 1 步——

AES key 是前端自己生成的,服务端只是\"用你给的 key 加密响应\"。

也就是说,服务端从不关心你的 key 从哪来,只要它自己的私钥能解开 key 字段就行。而 key 字段是用公开公钥加密的——公钥本来就公开。

结论一目了然:

攻击者自己生成一把 AES key,自己用公开公钥包好,自己加密参数发过去,服务端就会用攻击者自己的 key 加密响应,攻击者再自己解开。

整个流程里,攻击者从头到尾都不需要破解 RSA。


四、三步自解密

以 Python 为例,核心就三步:

第 1 步:取公钥(这个接口通常无认证)

pk = requests.get(\"https://目标/getRsaPublicKeyInfo\").json()[\"data\"]
pub, expire = pk[\"publicKey\"], pk[\"expireTime\"]

第 2 步:自己造 key、组信封

key = \"\".join(random.choices(string.ascii_letters+string.digits, k=16))
env = {
    \"key\":  rsa_encrypt(key, pub),              # 用公开公钥加密
    \"data\": aes_encrypt('{\"page\":1,\"limit\":10}', key),  # 用自己的 key 加密参数
    \"expireTime\": expire,
}
r = requests.get(\"https://目标/接口\", params=env)

第 3 步:用同一把 key 解响应

data = r.json()[\"data\"]           # 服务端用「你的 key」加密的响应
plain = aes_decrypt(data, key)    # 你自然能解

算法通常是 AES-128-CBC + 固定 IV + PKCS7 填充,IV 就直接写死在前端 JS 里。

注意:IV 固定、AES key 随机——这两点让\"加密\"看起来很正规,但 key 自产,所以对脚本客户端完全透明。


五、加密挡不住的三类漏洞

加密只挡住了\"看不到明文\",但一旦能自解密,真正的问题才浮出水面:服务端有没有鉴权和归属校验。

常见的三类:

1. 内部接口越权

/internal/xxx、/console/xxx 这类内部管理接口,如果网关只校验\"有没有登录\"、不校验\"是不是管理员\",那么普通用户也能调。

自产 key 打过去,可能直接返回未脱敏的敏感数据,比如账号、手机号,甚至密码哈希。

2. 公开接口未授权

/open/xxx、/public/xxx 这类公开接口,如果\"本应公开的信息\"里混进了不该公开的字段(联系人手机号、财务数据、内部 ID),那任何人不用登录就能批量拉取。

3. 写接口越权

新增/修改接口,如果信任客户端传来的 orgId/tenantId,攻击者把它改成别人的机构,就能往别人名下写数据。

实战踩坑(这次真实遇到的)

  1. URL 编码二次坑:从 Burp 复制的 key 已经 URL 编码过(含 %2F 等),如果直接塞进脚本的 params 会被再编码一次,key 就废了。要么用原始 URL 拼接,要么先解码再组。
  2. IV 是写死的:在 JS 里搜 AES.encrypt 附近的 iv,通常是固定字符串(16 位)。IV 不变、key 随机,是这类系统的典型特征。
  3. AES key 长度不一定是 16:前端随机生成 16–32 位[0-9a-zA-Z],别写死 16 位,按 JS 里随机函数的范围来。

六、为什么\"前端加密\"不是安全边界

一句话:客户端加密只能防\"没有 key 的被动窃听者\",而 TLS 已经覆盖了这一点。

对\"会写脚本的客户端\"来说,对称加密的 key 是可获取的(自己造),所以加密不能阻止:

  • 阅读请求/响应;
  • 修改参数重放;
  • 批量枚举;
  • 越权访问。

真正能保护数据的,只有服务端的:

  • 身份认证;
  • 权限校验;
  • 数据归属;
  • 字段脱敏;

结语

\"信封加密\"是一个很典型的误区:看起来密不透风,实际上钥匙就攥在客户端手里。

评价一个系统的安全性,不要看\"抓包能不能看到明文\",要看——换一个身份、换一个 ID、去掉登录,服务端还认不认。


> 作者:three安全之路 · 欢迎关注

    评论:0   参与:  0