如何防止生产环境JS代码被篡改导致中间人攻击?
最近在做项目安全加固时发现,线上环境的JavaScript文件可能被中间人篡改。我们用Webpack打包部署到Nginx服务器,但测试时发现有人能修改返回的JS代码添加恶意脚本。之前尝试过设置CSP头和代码签名,但具体该怎么实现有效防护呢?
比如这个签名验证函数,虽然在服务端生成了HMAC-SHA256签名:
const crypto = require('crypto');
function generateSignature(data) {
const secret = process.env.SECRET_KEY;
return crypto.createHmac('sha256', secret)
.update(data)
.digest('hex');
}
但前端如何验证响应中的代码是否被篡改?直接验证响应体签名的话,如果攻击者同时篡改验证逻辑怎么办?有没有更稳妥的防护方案?
打包时生成 JS 文件的哈希:
引入脚本时加上 integrity 属性:
浏览器会自动校验资源完整性,被篡改就直接拒绝执行。再配合 CSP 限制内联脚本和外部域名,基本就稳了。
最靠谱的方案是上 HTTPS + Subresource Integrity(SRI)。你用 Webpack 打包之后,每个 JS 文件都生成一个哈希值,然后在 HTML 引入脚本的时候加上 integrity 属性。比如你打包出 main.js,构建时算个 SRI 哈希:
然后你的 HTML 里这么写:
只要文件内容有任何改动,哪怕一个字节,浏览器加载时就会校验失败,直接拒绝执行。这个是浏览器原生支持的,比你自己写验证函数靠谱多了。
当然前提是必须走 HTTPS,不然中间人还能改 HTML 文件本身,把 integrity 也去掉了。所以第一步先确保全站上了 HTTPS,证书用 Let's Encrypt 这类免费的就行,不难搞。
另外配合 CSP 头,限制 script-src 'self',再加上 nonce 或 hash 策略,双重保险。Webpack 可以用 csp-html-webpack-plugin 自动把内联脚本的 hash 加到 CSP 里。
至于你写的 HMAC 签名那个,其实更适合做 API 接口防篡改,比如请求参数签名。静态资源这块还是交给 SRI 和 HTTPS 更省心也更安全。我们上线后跑了几个月,再没收到异常脚本上报了。