网页恶意代码如何过滤

wen 网络安全 31

本文目录导读:

网页恶意代码如何过滤

  1. 第一阶段:核心防御(必须做)
  2. 第二阶段:特定场景防御
  3. 第三阶段:检测与监控(主动防御)
  4. 第四阶段:具体代码示例(Java + Python)
  5. 过滤的黄金法则

过滤网页恶意代码(如XSS跨站脚本、SQL注入、恶意脚本等)是Web安全的核心,你需要从防御端(服务端/浏览器)检测端(安全工具)两个维度入手。

以下是一套系统性的过滤方案,按策略优先级排序:

第一阶段:核心防御(必须做)

这是最有效的防线,避免恶意代码“进入”系统。

输入验证与过滤(服务端)

原则:所有用户输入都是不可信的。

  • 白名单策略(推荐): 只允许特定格式。
    • 用户名:只允许字母、数字、、(如 /^[a-zA-Z0-9_-]{4,16}$/)。
    • 年龄:只允许数字(1-120)。
    • 邮箱:严格按RFC正则校验。
  • 黑名单策略(不推荐): 过滤关键字如 <script>alertonerrorjavascript:缺点: 很容易被绕过(编码、大小写、事件触发组合等)。
  • 编码与过滤库(必须使用): 不要自己写正则,使用成熟的库。
    • Java: OWASP Java EncoderESAPI
    • Python: bleach(用于清理HTML)、markupsafe(用于转义)。
    • PHP: htmlspecialchars()strip_tags()(谨慎使用)。
    • Node.js: DOMPurifyhelmet(中间件)。

输出转义(渲染端)

原则:在将数据显示到浏览器或数据库中时,清理掉可执行代码。

  • HTML实体编码:< 换成 &lt;> 换成 &gt;, 换成 &quot;, 换成 &#x27;& 换成 &amp;
    • 场景: 用户发表的评论、用户名、文章标题。
  • JavaScript 上下文转义: 如果数据插入到 <script> 标签内或事件属性(如 onclick="..."),需要进行JS字符串转义(反斜杠转义)。
  • URL 编码: 如果数据拼接到 URL 参数或 href 属性中,使用 encodeURIComponent()

CSP(内容安全策略)—— 浏览器端最强防线

原理: 通过 HTTP 响应头告诉浏览器“哪些来源的内容是安全的”,直接阻止内联脚本执行。

  • 配置示例(响应头):
    Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com; object-src 'none'; style-src 'self' 'unsafe-inline';
    • script-src 'self':只允许同源脚本。
    • 'unsafe-inline':如果不允许内联脚本,则 <script>alert(1)</script> 会直接被浏览器阻止。
    • report-uri /csp-report:将违规行为报告给服务器。
  • 效果: 就算攻击者成功注入了 <script> 标签,浏览器也不会执行它。

HTTP Only + Secure Cookie

原理: 防止恶意代码通过 document.cookie 窃取会话。

  • HttpOnly:禁止浏览器 JS 访问 cookie(只能通过 HTTP 请求自动携带)。
  • Secure:仅允许 HTTPS 传输 cookie。

第二阶段:特定场景防御

富文本编辑器(如 TinyMCE、Quill)

场景: 用户需要插入图片、链接、加粗等(需要部分CSS/HTML)。 策略: 绝对不能直接信任编辑器返回的HTML。

  • 服务器端过滤: 使用 DOMPurify(Node.js/Python/Java 版本可用)对返回的 HTML 进行清理。
    • 允许的标签:<b>, <i>, <u>, <a>, <img>
    • 允许的属性:href, src, alt绝不允许 onerror, onload, onclick, style)。
    • 过滤 javascript: 伪协议:<a href="javascript:alert(1)"> 会被移除。

SQL 注入防御

原则: 永远不要拼SQL字符串。

  • 使用参数化查询(Prepared Statement): 这是唯一有效的方式。
    # 错误:cursor.execute("SELECT * FROM users WHERE name='" + username + "'")
    # 正确:
    cursor.execute("SELECT * FROM users WHERE name=?", (username,))
  • ORM 框架: SQLAlchemy(Python)、Hibernate(Java)、Eloquent(PHP)等默认使用了参数化查询。

文件上传防御

场景: 用户上传头像或附件。 策略:

  • 白名单扩展名: .jpg, .png, .gif(不允许 .exe, .php, .html)。
  • MIME类型检查: 不信任 Content-Type,要检查文件真实魔数(Magic Number/Magic bytes)。
  • 保存时重命名: 不要使用用户提供的文件名(防止 路径穿越),生成唯一文件名。
  • 存储到对象存储: 存放于非 Web 目录(如只读存储桶),通过 CDN 或签名 URL 访问。

第三阶段:检测与监控(主动防御)

WAF(Web应用防火墙)

  • 商用: Cloudflare WAF、AWS WAF、阿里云WAF。
  • 开源: ModSecurity(可配合 Nginx/Apache)。
  • 作用: 在流量进入应用前,通过规则库匹配并拦截恶意Payload(如 UNION SELECT<img src=x onerror=...>)。

安全头与扫描

  • X-Content-Type-Options: nosniff:禁止浏览器嗅探响应内容类型。
  • X-Frame-Options: SAMEORIGIN:防止点击劫持(Clickjacking)。
  • 定期扫描: 使用 OWASP ZAP 或 Burp Suite 对站点进行自动化扫描。

第四阶段:具体代码示例(Java + Python)

示例1:Java 过滤 XSS(使用 OWASP 库)

import org.owasp.encoder.Encode;
String userInput = "<script>alert('xss')</script>";
// 输出到HTML body时使用:
String safeOutput = Encode.forHtml(userInput);
// 输出结果: &lt;script&gt;alert('xss')&lt;/script&gt;
// 输出到URL参数时使用:
String safeUrlParam = Encode.forUriComponent(userInput);

示例2:Python Flask + bleach 过滤富文本

import bleach
from flask import request, jsonify
def sanitize_article(request):
    raw_html = request.form['content']
    # 只允许特定标签和属性
    allowed_tags = ['p', 'b', 'i', 'u', 'a', 'img']
    allowed_attrs = {
        'a': ['href', 'title', 'rel'],
        'img': ['src', 'alt', 'width', 'height']
    }
    # 清理:移除onclick、javascript:等
    clean_html = bleach.clean(raw_html, tags=allowed_tags, attributes=allowed_attrs, strip=True)
    return clean_html

过滤的黄金法则

  1. 先校验后存储: 在入库前,做好输入验证(白名单优先)。
  2. 在输出时转义: 无论数据是否被存储,显示给用户前进行上下文转义(HTML/JS/URL)。
  3. 开启 CSP 头: 这是少数可以完全阻止0day XSS的工具。
  4. 永远不用黑名单: 攻击者总能想出绕过方法(<scr\0ipt>\u003c&#x3c; 等)。

最危险的误区: 在前端(JS)过滤,后端不检查,前端过滤只为了用户体验,后端必须重新检查,因为攻击者可以直接构造 HTTP 请求。

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