目录

前端JS数据加密核心疑问操作

非加密流程修改位置

前端加密流程修改位置(关键)

核心结论

CryptoJS(MD5/AES/DES/HMAC)前端加密安全漏洞

漏洞 1:对称加密(AES/DES)密钥硬编码在 JS,攻击者直接提取密钥解密 / 伪造密文

攻击流程

漏洞 2:MD5/SHA1 仅做加密,无随机盐、无请求签名,可碰撞 / 批量伪造

风险

漏洞 3:HMAC 使用固定密钥,前端泄露密钥后可伪造任意签名

风险

漏洞 4:前端加密仅防窃听,后端缺失二次业务校验(最普遍高危漏洞)

漏洞 5:DES 弱加密算法安全性极低

jsencrypt RSA 非对称前端加密安全漏洞

漏洞 1:仅加密业务参数,未做请求签名,依然可篡改参数逻辑

攻击方式

漏洞 2:RSA 单次加密长度有限,分段加密易被篡改、拆分绕过

漏洞 3:依赖前端生成随机向量 / 随机数,随机因子可控可预测

漏洞 4:后端无会话绑定校验,加密数据可复用(重放攻击)

漏洞 5:公钥可替换中间人攻击(无证书校验)

JS 代码混淆的安全局限性与安全问题

1. 混淆只能提升逆向成本,无法防止逆向解密加密逻辑

漏洞

2. 混淆无法拦截抓包篡改请求

3. 混淆存在调试防护绕过

绕过手段

4. 压缩混淆会掩盖恶意后门 / 隐藏漏洞

5. 混淆不改变前端不可信核心问题

攻击手段

统一总结三大类技术核心安全缺陷

1. 前端对称加密(CryptoJS AES/DES/MD5/HMAC)致命短板

2. 前端 RSA 非对称加密(jsencrypt)短板

3. JS 代码混淆的本质局限

修复方案

前端JS数据加密核心疑问操作

安全测试修改数据包发生在哪一步?

非加密流程修改位置

流程:客户端明文 → 网络传输明文 → 服务端接收

修改点:网络传输阶段(抓包工具 Burp/Charles/Fiddler 拦截请求)

  • JS 只是把明文直接放进请求体 / 参数发送;
  • 中间人拦截 HTTP 请求,直接篡改明文参数再转发给后端。

示例:前端直接提交金额money=100,抓包改成money=0.01提交,后端无校验直接生效。

前端加密流程修改位置(关键)

流程:明文前端 JS 加密 → 传输密文 → 后端解密处理

两种修改场景

场景 1:篡改密文(无签名校验,后端仅解密不校验原始数据合法性)

修改阶段:网络传输阶段拦截,直接替换密文字符串发包。 后端解密后拿到篡改数据,业务沦陷。

场景 2:逆向前端加密逻辑,构造合法密文(最常用渗透手段)

修改阶段:客户端 JS 加密之前

  • 安全测试人员 F12 拿到 CryptoJS/jsencrypt 加密源码、密钥、盐值;
  • 本地逆向复现加密算法,手动构造恶意明文 → 加密生成合法密文,再发包; 后端无法区分是正常页面加密还是黑客手动构造的密文。
核心结论

前端加密不能防止抓包篡改,只能防止传输明文窃听,无法抵御中间人篡改攻击。

CryptoJS(MD5/AES/DES/HMAC)前端加密安全漏洞
漏洞 1:对称加密(AES/DES)密钥硬编码在 JS,攻击者直接提取密钥解密 / 伪造密文
// 前端危险代码(AES 加密,密钥写死在前端)
<script src="crypto-js.min.js"></script>
<script>
    // 密钥明文硬编码在JS,任何人F12可见
    const KEY = CryptoJS.enc.Utf8.parse("1234567890123456");
    const IV = CryptoJS.enc.Utf8.parse("1234567890123456");

    function encrypt(text){
        return CryptoJS.AES.encrypt(text, KEY, {iv:IV}).toString();
    }
    function decrypt(cipher){
        return CryptoJS.AES.decrypt(cipher, KEY, {iv:IV}).toString(CryptoJS.enc.Utf8);
    }

    // 提交订单金额加密
    let money = document.getElementById("money").value;
    let cipherText = encrypt(money);
    // AJAX发送密文给后端
    $.post("/pay", {data:cipherText})
</script>
攻击流程

1、F12 查看源码拿到KEY=1234567890123456

2、本地调用同一套加密函数,构造恶意金额money=0.01

3、生成合法密文,Burp 拦截替换请求里的data参数提交;

4、后端用相同密钥解密,收到篡改金额,直接扣款。

漏洞 2:MD5/SHA1 仅做加密,无随机盐、无请求签名,可碰撞 / 批量伪造
// 错误用法:仅对参数 MD5 加密,后端只解密不校验完整性
// 前端对订单ID简单MD5
function getMd5(id){
    return CryptoJS.MD5(id).toString();
}
let orderId = 10001;
let sign = getMd5(orderId);
$.post("/api/order", {orderSign:sign})
风险

MD5 不可逆但可枚举彩虹表,攻击者遍历订单 ID 批量生成签名,遍历查询所有用户订单; 若后端仅校验 “字符串是合法 MD5”,不绑定会话 / 随机盐,完全失去防护意义。

漏洞 3:HMAC 使用固定密钥,前端泄露密钥后可伪造任意签名
// HMAC 设计本意是做数据完整性校验,但密钥放前端直接失效:
const hmacKey = "mysecret123";
function getHmac(data){
    return CryptoJS.HmacSHA256(data, hmacKey).toString();
}
// 请求参数 + hmac签名一起发送
let data = "money=100";
let sign = getHmac(data);
$.post("/pay", {data, sign})
风险

攻击者提取hmacKey,自行构造data="money=0.01"并生成合法 sign,后端无法分辨数据被篡改。

漏洞 4:前端加密仅防窃听,后端缺失二次业务校验(最普遍高危漏洞)

哪怕加密算法无漏洞,只要后端不校验业务逻辑,篡改密文后依然能越权:

前端加密用户 ID:userId=1001加密传输;

攻击者逆向加密逻辑生成userId=1002密文发包;

后端解密拿到 1002,直接返回他人订单数据 → 水平越权

漏洞 5:DES 弱加密算法安全性极低

DES 密钥短(56 位),可暴力破解,前端使用 DES 极易被快速破解密文。

jsencrypt RSA 非对称前端加密安全漏洞

RSA 逻辑:公钥放前端加密,私钥保存在后端解密。

漏洞 1:仅加密业务参数,未做请求签名,依然可篡改参数逻辑
// 错误示例:只加密金额,请求其他参数明文传输
<script src="jsencrypt.js"></script>
<script>
    // 公钥公开写在前端
    const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
6rPJj+CvfSC8+2qYuJH+j7khFcnX5QA+N4hK03sIfxBVDvQZvODA/vwf44r1BHfr
MzdrO7blaKEAAQekKsYzkElRWwH0vsyjEZqy9WRU+vVrZ5kSTnHx+Hvz3o/WGObAEV
5rypMxb9q4vM14qFevzhtXeoQIDAQAB
-----END PUBLIC KEY-----`;
    let encrypt = new JSEncrypt();
    encrypt.setPublicKey(publicKey);

    let money = $("#money").val();
    let cipherMoney = encrypt.encrypt(money);
    // userId明文传输,仅money加密
    $.post("/pay", {userId:1001, money:cipherMoney})
</script>
攻击方式

Burp 抓包修改明文userId:1002,加密金额不变;后端解密金额正常,同时读取篡改后的用户 ID,操作他人账户。

漏洞 2:RSA 单次加密长度有限,分段加密易被篡改、拆分绕过

jsencrypt RSA 加密有明文长度上限,开发会拆分长文本分段加密,攻击者可修改其中一段数据,后端拼接后逻辑错乱。

漏洞 3:依赖前端生成随机向量 / 随机数,随机因子可控可预测

若前端自行生成加密随机因子用于签名,攻击者复现随机规则,批量伪造合法请求。

漏洞 4:后端无会话绑定校验,加密数据可复用(重放攻击)

攻击者抓一次合法加密请求,反复重复发包(重复扣款、重复提交表单);

仅靠 RSA 加密无法防御重放,必须增加时间戳、一次性 nonce 随机数做签名校验。

漏洞 5:公钥可替换中间人攻击(无证书校验)

如果网站没有 HTTPS,中间人劫持页面替换前端公钥为黑客私钥对应的公钥;

前端加密的数据黑客可解密窃取,再用真实公钥加密转发给服务器,全程窃听篡改。

JS 代码混淆的安全局限性与安全问题

JS代码混淆为保护前端JS代码不被轻易逆向,但是也会产生安全问题

1. 混淆只能提升逆向成本,无法防止逆向解密加密逻辑

混淆本质只是修改变量名、压缩代码、增加无效僵尸代码,算法逻辑完全保留。

原始清晰代码:

function getAesCipher(text){
    let key = "admin123456";
    return CryptoJS.AES.encrypt(text, key).toString();
}

混淆后代码示例:

var _0x123a=["admin123456","encrypt","toString"];function _0x45b(_0xc1){let _0x22=_0x123a[0];return CryptoJS.AES[_0x123a[1]](_0xc1,_0x22)[_0x123a[2]]()}
漏洞

1、使用反混淆工具(js-beautify、在线解混淆网站)一键格式化还原代码;

2、正则匹配CryptoJS.AES.encryptJSEncrypt关键字,快速定位加密密钥与算法;

3、密钥、加密逻辑依然完整暴露,混淆不能保护前端密钥。

2. 混淆无法拦截抓包篡改请求

混淆只是修改 JS 代码可读性,网络传输的密文 / 请求参数完全不受影响

Burp 依然可以拦截、替换请求数据,混淆对中间人攻击完全无效。

3. 混淆存在调试防护绕过

市面上混淆工具常用 debugger 无限循环阻止开发者调试控制台:

setInterval(function(){debugger;},100);
绕过手段

浏览器控制台勾选「禁用调试器」,直接跳过防护,正常断点分析加密逻辑。

4. 压缩混淆会掩盖恶意后门 / 隐藏漏洞

业务 JS 混淆后,隐藏高危逻辑(硬编码密钥、后门接口)难以快速审计;

恶意攻击者可植入僵尸函数、隐藏窃取 Cookie 代码,审计人员难以快速识别风险。

5. 混淆不改变前端不可信核心问题
攻击手段

无论混淆多复杂,JS 运行在用户浏览器,攻击者拥有完整控制权:

1、控制台覆盖加密函数,直接输出明文;

// 控制台执行覆盖原有加密函数,直接拿到原始明文
function _0x45b(text){
    console.log("原始明文:",text); // 打印要加密的原始数据
    return 原来的加密结果;
}

2、删除、重写加密逻辑,自定义恶意密文提交。

统一总结三大类技术核心安全缺陷
1. 前端对称加密(CryptoJS AES/DES/MD5/HMAC)致命短板

1、密钥必须存放前端,攻击者 100% 可提取;

2、仅加密传输内容,无数据完整性校验,中间人可篡改;

3、无法防御重放、越权、业务逻辑绕过;

4、仅能解决 HTTP 明文窃听,不能做权限 / 数据防篡改防护。

2. 前端 RSA 非对称加密(jsencrypt)短板

1、仅加密参数无法保护整个请求,明文参数易被篡改;

2、无时间戳 / 随机数防护,存在重放攻击;

3、HTTP 环境下存在公钥劫持中间人风险;

4、长文本分段加密存在篡改漏洞。

3. JS 代码混淆的本质局限

1、仅增加逆向时间成本,不能阻止逆向;

2、无法保护密钥、加密算法;

3、无法防御抓包篡改请求;

4、调试防护可一键绕过。

修复方案

1、区分加密作用:前端加密仅用于防止传输窃听,防篡改、权限校验必须放在后端

2、数据完整性防护:后端使用后端私钥生成全局签名(包含全部参数 + 时间戳 + 会话 ID + 随机 nonce),前端仅传参,签名由后端计算校验;

3、密钥管理:对称密钥、RSA 私钥绝不前端存放;敏感参数加密、签名计算全部后端完成;

4、业务双重校验:解密后后端二次校验用户身份、金额、权限,不能只依赖前端传入数据;

5、防重放:请求携带时间戳 + 一次性随机数,后端校验有效期,拒绝重复请求;

6、HTTPS 强制部署,杜绝中间人劫持替换公钥;

7、混淆仅作辅助,不能作为安全防护手段,核心加密逻辑移至后端接口处理。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐