输入过滤如何拦截XSS

wen 开源项目 27

本文目录导读:

输入过滤如何拦截XSS

  1. 核心原则:过滤+编码双保险
  2. 输入过滤的主要方法
  3. 关键过滤规则(针对常见XSS向量)
  4. 过滤的局限性(为什么不能只靠过滤)
  5. 实践建议
  6. 总结:过滤永远不是唯一防线

输入过滤是防御XSS(跨站脚本攻击)的重要环节,但仅靠输入过滤是不够的,需要与输出编码结合,以下是针对XSS的输入过滤策略及实现方法:


核心原则:过滤+编码双保险

  • 输入过滤:拦截明显恶意字符(如<script>onerror等)。
  • 输出编码:对输出到HTML、JavaScript、CSS等不同上下文的数据进行编码(更关键)。

输入过滤的主要方法

(1) 黑名单过滤(不推荐)

  • 原理:拦截已知的恶意关键字或模式。
  • 示例(PHP简单实现):
    $input = str_replace(['<script>', 'onerror=', 'javascript:'], '', $_POST['input']);
  • 缺陷:攻击者可绕过(如<ScRiPt><img src=x onerror=alert(1)>等变体)。

(2) 白名单过滤(推荐)

  • 原理:只允许特定类型的数据(如字母、数字、安全符号)。
  • 示例(仅允许数字和逗号):
    import re
    input_data = re.sub(r'[^0-9,]', '', user_input)
  • 适用场景:严格格式的输入(如年龄、邮编、选择框值)。

(3) 输入验证(语义层过滤)

  • 原理:按业务逻辑验证数据格式(如邮箱、URL)。
  • 示例(验证邮箱格式):
    import re
    if not re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', user_input):
        return "Invalid email"

(4) HTML标签剥离(保留安全标签)

  • 使用安全库(如HTMLPurifierBleach)白名单保留标签。
  • 示例(Python bleach库):
    import bleach
    allowed_tags = ['b', 'i', 'a', 'p']
    allowed_attrs = {'a': ['href', 'title']}
    clean_html = bleach.clean(user_input, tags=allowed_tags, attributes=allowed_attrs)

关键过滤规则(针对常见XSS向量)

拦截目标 过滤模式(正则或替换) 说明
<script>及变体 /<[^>]*script/gi 但可能误伤正常<script>标签(应使用白名单)
on事件处理器 /(\s|"|'|>)on\w+\s*=/gi onclickonerroronload
javascript:伪协议 /javascript:/gi URL中的<a href="javascript:alert(1)">
data:协议 /data:/gi <img src="data:image/svg+xml;...">
十六进制/Unicode编码绕过 /(\\x[0-9a-f]{2})/gi <a href="\x6aavascript:...">
特殊HTML实体(双重编码) 过滤&lt;&gt;等(但应输出编码) 不是输入过滤强项

过滤的局限性(为什么不能只靠过滤)

XSS绕过方式 示例 过滤失效原因
大小写变体 <ScRiPt> vs <script> 黑名单需处理多种大小写组合
嵌套或拆分 <scr<script>ipt> 过滤后剩余<script>
URL编码 %3Cscript%3E(即<script> 输入解码前未检查
使用转义序列 \x3cscript\x3e 过滤模式未匹配
利用CSS表达式(旧IE) <style>expression(...) 纯HTML过滤无法拦截
SVG/XML命名空间 <svg><script>alert(1)</script> 需额外处理非HTML上下文

实践建议

  1. 分层防御

    • 输入层:严格白名单过滤(如数字、枚举值)+ 格式验证。
    • 存储层:对特殊字符进行转义(可选,如<&lt;)。
    • 输出层必须根据上下文编码(HTML实体、JS字符串、CSS、URL)。
  2. 使用成熟库

    • JavaOWASP Java EncoderJSOUP(剥HTML)。
    • PythonbleachMarkupSafe
    • PHPHTMLPurifierstrip_tags()(谨慎使用)。
    • JavaScriptDOMPurify(前端清理)。
  3. 测试绕过

    • 使用工具如OWASP ZAPBurp Suite生成XSS payload列表。
    • 手动测试:<img src=x onerror=alert(1)><svg/onload=alert(1)>

过滤永远不是唯一防线

  • 输入过滤:适合严格格式(数字、选项),或作为“缩减攻击面”的手段。
  • 输出编码:才是防御XSS的核心(对HTML实体、JS字符串、CSS、URL分别编码)。
  • 黄金法则永不信任用户输入,对不同输出上下文分别编码。

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