脚本如何检测页面篡改

wen 实用脚本 36

本文目录导读:

脚本如何检测页面篡改

  1. 内容完整性校验(Subresource Integrity, SRI)
  2. DOM 元素内容/属性对比校验
  3. 元素存在性与异常注入检测
  4. 完整性监控(MutationObserver)
  5. 后端签名与前端验证
  6. 防篡改容器与“看门狗”脚本
  7. 总结与建议

检测页面篡改(即检测网页是否被恶意修改或注入恶意代码)通常涉及前端后端的结合,由于脚本(通常指 JavaScript)在用户浏览器中运行,它本身也可能被篡改,因此需要配合服务端校验或使用浏览器安全特性。

以下是几种常见的脚本检测页面篡改方法,从简单到复杂:

内容完整性校验(Subresource Integrity, SRI)

这是最推荐的防御方式之一,由浏览器原生支持,它用于检测引用的外部脚本或样式文件是否被篡改。

  • 原理:在 <script><link> 标签中添加 integrity 属性,浏览器会计算加载文件的哈希值,并与提供的哈希值比对,若不匹配,则阻止执行。
  • 适用场景:防止 CDN 上的文件被篡改。

示例:

<script src="https://example.com/analytics.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQGTkchBcPkYdA=="
        crossorigin="anonymous"></script>

analytics.js 被修改,浏览器会拒绝加载并在控制台报错。

DOM 元素内容/属性对比校验

通过 JavaScript 定期检查页面关键节点的内容是否与预期一致。

  • 步骤
    1. 选择一个或多个关键且稳定的 DOM 节点(如 document.title<head> 中的某个 meta 标签,或 <body> 中的固定文本)。
    2. 在页面加载时,将该节点的内容(innerHTMLtextContentinnerText 或特定属性)加密(如使用 SHA-256)并记录或发送到服务器作为基准。
    3. 定期(如每隔 5 秒)重新获取该节点内容并重新哈希,与基准值比对。
  • 缺点
    • 容易被 JS 禁用或 Hook。
    • 动态页面内容频繁变化会导致大量误报。
    • 检测代码本身可能被篡改。

元素存在性与异常注入检测

检测页面中是否出现了预期之外的元素。

  • 检测点
    • 检查 document.body.appendChild 是否被重写或监控(检测动态注入)。
    • 检测是否包含不熟悉的 <script> 标签(通常恶意代码会注入新的 <script>)。
    • 检查 innerHTML 操作是否出现异常关键字。
  • 简单检测示例
    (function detectInjection() {
    // 检查页面中的 <script> 标签数量(如果原本只有 2 个,现在出现 5 个)
    const scripts = document.getElementsByTagName('script');
    if (scripts.length > EXPECTED_SCRIPT_COUNT) {
        console.warn('检测到异常脚本注入!');
        // 可以记录异常,但不要在这里弹窗,因为弹窗也可能被劫持
    }
    })();
  • 缺点:容易误报,且可以被针对。

完整性监控(MutationObserver)

利用浏览器的 MutationObserver API 监控 DOM 变化,检测是否有非预期的修改。

  • 原理:监听 childListattributessubtree 等变化。
  • 操作
    • 当 DOM 发生变化时,检查变化的节点是否在白名单中(某个动态广告位)。
    • 如果不是,且来源不是已知的扩展或受信任脚本,则视为可疑篡改。

示例(监控 body 新增节点):

const targetNode = document.body;
const config = { childList: true, subtree: true };
const observer = new MutationObserver((mutationsList) => {
    for (const mutation of mutationsList) {
        if (mutation.type === 'childList') {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === 1 && node.tagName === 'SCRIPT') {
                    // 检测到非授权的脚本节点被添加到 body
                    console.warn('可能被注入了脚本:', node.src || node.textContent);
                }
            });
        }
    }
});
observer.observe(targetNode, config);

后端签名与前端验证

这是一种较强的防御方式,服务端对页面关键部分(如 HTML 主体或关键数据)生成一个带密钥的 HMAC 签名,并将其嵌入页面(通常放在一个不可见的 <script><meta> 中),前端 JS 在页面加载后用预置的公钥或相同密钥验证签名。

  • 优点:攻击者若不知道密钥,无法伪造签名。
  • 缺点
    • 前端密钥会暴露,容易被逆向,若使用对称密钥,密钥泄露则失效。
    • 需要服务端支持。

防篡改容器与“看门狗”脚本

  • 原理
    • 将核心业务逻辑放在一个闭包或沙箱环境中。
    • 建立一个独立的“看门狗”脚本,该脚本定期向服务端发送心跳,并请求服务端返回当前页面关键哈希值,然后在本地比对。
    • “看门狗”脚本是动态生成的,每次请求的算法或密钥可能不同。

总结与建议

方法 强度 实现难度 误报率 推荐指数
SRI 高(外部资源) ⭐⭐⭐⭐⭐
对比 ⭐⭐
元素存在性检测
MutationObserver ⭐⭐⭐
后端签名验证 ⭐⭐⭐⭐
看门狗脚本 很高 ⭐⭐⭐⭐

实际落地建议:

  1. 首选 SRI:为所有外部 CDN 资源启用,这是防篡改的第一道防线,且无需改动业务逻辑。
  2. 结合 CSP:使用 Content Security Policy (CSP) 限制允许执行的脚本源(script-src)和允许内联代码的哈希/Nonce,这能有效阻止绝大多数 XSS 和脚本注入导致的页面篡改。
  3. 关键页面增加服务端校验:对于登录、支付等高风险页面,可实施后端签名验证。
  4. 内联脚本使用 Nonce:对页面内的 <script> 标签使用 Nonce 属性,配合 CSP 防止非授权脚本执行。
  5. 定期扫描与监控:在浏览器端(通过自己的脚本)或服务器端(通过爬虫)定期抓取并比对页面快照,这是发现长期篡改的有效手段。

最后需要明白:没有任何前端脚本能100%防止页面篡改,因为攻击者如果控制了整个页面,同样可以篡改你的检测脚本,前端检测更多是作为一种监控和告警手段,而不是彻底防御,真正的安全需要服务端、网络传输、前端策略(CSP, SRI)等多层协同。

抱歉,评论功能暂时关闭!