前端加密是纸老虎:一次「信封加密」的自解密实录
原创
mao
mao
three安全之路
2026年11月5日 14:46
四川
去阅读
抓包全是密文就是安全?一个随机生成的 AES key,就能让整套前端加密形同虚设。
一、引子:抓包看到一串密文
做安全测试时,经常会遇到这种请求:
GET /api/xxx/distribution?key=RYExrzov6bs6...&data=721b0283bd2f...&expireTime=1793755364651
URL 里没有明文参数,data 是一串十六进制,key 是一串 Base64。很多人第一反应是:\"加密了,看不到,安全了。\"
但在\"信封加密\"体系下,这恰恰是一个容易被忽视的安全假象。
二、什么是\"信封加密\"
这类系统通常这样设计:
- 前端每次发请求前,随机生成一个 AES key(比如 16 位随机字符串);
- 用服务端下发的公开 RSA 公钥,把这个 AES key 加密,放进
key字段; - 用这个 AES key,把业务参数加密成
data(hex); - 再带上
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,攻击者把它改成别人的机构,就能往别人名下写数据。
实战踩坑(这次真实遇到的)
- URL 编码二次坑:从 Burp 复制的
key已经 URL 编码过(含%2F等),如果直接塞进脚本的params会被再编码一次,key 就废了。要么用原始 URL 拼接,要么先解码再组。 - IV 是写死的:在 JS 里搜
AES.encrypt附近的iv,通常是固定字符串(16 位)。IV 不变、key 随机,是这类系统的典型特征。 - AES key 长度不一定是 16:前端随机生成 16–32 位
[0-9a-zA-Z],别写死 16 位,按 JS 里随机函数的范围来。
六、为什么\"前端加密\"不是安全边界
一句话:客户端加密只能防\"没有 key 的被动窃听者\",而 TLS 已经覆盖了这一点。
对\"会写脚本的客户端\"来说,对称加密的 key 是可获取的(自己造),所以加密不能阻止:
- 阅读请求/响应;
- 修改参数重放;
- 批量枚举;
- 越权访问。
真正能保护数据的,只有服务端的:
- 身份认证;
- 权限校验;
- 数据归属;
- 字段脱敏;
结语
\"信封加密\"是一个很典型的误区:看起来密不透风,实际上钥匙就攥在客户端手里。
评价一个系统的安全性,不要看\"抓包能不能看到明文\",要看——换一个身份、换一个 ID、去掉登录,服务端还认不认。
> 作者:three安全之路 · 欢迎关注
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。




![buuctf WEB[强网杯2019]随便注writeup"](/images/random/titlepic/13.jpg)



评论