怎么防止跨站脚本攻击?

wen 网络安全 14

如何有效防止跨站脚本攻击(XSS)

目录导读

  1. XSS攻击的本质与危害 – 为什么你必须重视它?
  2. 三大XSS类型解析 – 反射型、存储型、DOM型有何区别?
  3. 输入验证与输出编码 – 第一道防线怎么建?安全策略(CSP)** – 浏览器的终极防火墙
  4. HttpOnly与Secure Cookie – 保护会话的杀手锏
  5. 常见误区与问答 – 开发者最容易犯的错
  6. 实战检查清单 – 一篇文章教你自查代码

XSS攻击的本质与危害

跨站脚本攻击(Cross-Site Scripting,简称XSS)是OWASP Top 10中常年名列前茅的Web安全漏洞,攻击者通过向Web页面注入恶意脚本,当其他用户访问该页面时,脚本会在用户浏览器中执行,从而窃取Cookie、会话令牌、敏感数据,甚至篡改页面内容。

怎么防止跨站脚本攻击?

一个真实案例: 2018年某社交平台因未对用户个人简介做转义处理,攻击者只需在简介中写入<script>alert(document.cookie)</script>,所有查看其主页的用户会话即被劫持。据统计,超过65%的大型网站曾存在XSS漏洞。


三大XSS类型解析

类型 触发方式 典型场景 危害等级
反射型 恶意脚本附加在URL参数中,服务器未过滤直接返回 搜索框、错误页面
存储型 脚本永久存储在服务器数据库,每次访问均执行 评论区、用户资料、博客文章
DOM型 客户端JavaScript动态操作DOM时执行恶意代码 URL哈希、innerHTML赋值

关键区别: 反射型需要用户点击恶意链接;存储型一次注入,持续攻击所有访问者;DOM型纯前端执行,服务器日志无法检测。


输入验证与输出编码:第一道防线

这是最基础也是最有效的防御手段,核心原则是:永远不要信任用户输入

1 输入过滤策略

  • 白名单优于黑名单:只允许特定字符(如只允许字母数字、中文),拒绝所有特殊符号。
  • 上下文感知验证:邮箱字段只接受标准邮箱格式,URL字段只允许http/https协议。
  • 长度与类型限制:防止超长输入绕过过滤。

2 输出编码黄金法则

根据输出位置选择不同编码方式:

输出上下文 编码方法 示例(PHP)
HTML标签内容 HTML实体编码 htmlspecialchars($input, ENT_QUOTES, 'UTF-8')
HTML属性值 属性值编码 转义, , <, >
JavaScript字符串 JavaScript编码 json_encode($input) + 反斜杠转义
URL参数 URL编码 urlencode($input)

错误示例: document.getElementById('msg').innerHTML = userInput; —— 直接修改innerHTML会执行任何HTML标签,应改为textContent或使用createTextNode


内容安全策略(CSP):浏览器的终极防火墙

CSP通过HTTP响应头告诉浏览器哪些资源可以加载执行,即使页面被注入了恶意脚本,浏览器也会拦截。

Content-Security-Policy: default-src 'self'; script-src 'self' .trusted-cdn.com; object-src 'none'

核心指令:

  • script-src:控制JavaScript来源,禁掉'unsafe-inline''unsafe-eval'
  • object-src 'none':防止Flash等插件执行
  • base-uri 'self':防止base标签劫持
  • report-uri /csp-violations:收集违规报告

实战建议: 先从Content-Security-Policy-Report-Only模式开始,收集误报后再严格实施,例如某电商平台启用CSP后,XSS攻击尝试减少了90%以上。


HttpOnly与Secure Cookie保护会话

即使脚本成功注入,如果Cookie设置了HttpOnly标志,那么JavaScript就无法读取document.cookie,直接从源头掐断会话劫持。

设置方式:

Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Strict
  • HttpOnly:禁止JavaScript访问
  • Secure:仅通过HTTPS传输
  • SameSite=Strict:防止跨站请求伪造(CSRF)和部分XSS利用

误区澄清: HttpOnly无法防御所有XSS(如执行表单提交、修改DOM),但它是防御会话劫持的必要条件。


常见误区与问答

Q1:前端做了过滤,后端还需要做吗?
A:必须双重防护,前端过滤仅提升用户体验,攻击者可以绕过浏览器直接发送恶意请求到服务器。

Q2:使用富文本编辑器(如TinyMCE、CKEditor)是否安全?
A:不安全,这些编辑器允许用户插入HTML,需要结合服务端HTML白名单过滤器(如PHP的HTMLPurifier),只允许安全标签如<b><i><a>

Q3:我的网站使用Vue/React,还需要担心XSS吗?
A:需要,虽然框架默认对插值做了转义,但以下场景仍存在风险:

  • 使用v-htmldangerouslySetInnerHTML
  • 通过location.hashhistory.pushState操作URL
  • 动态执行evalnew Function()

Q4:为什么我用了CSP还是被攻击?
A:检查是否开启了'unsafe-inline''unsafe-eval',以及是否遗漏了base-uriform-action等关键指令。


实战检查清单

  • [ ] 所有用户输入点(表单、URL参数、HTTP头部、文件上传)均进行白名单验证
  • [ ] 输出到HTML、JS、URL、CSS时使用对应的编码函数
  • [ ] 禁止使用innerHTML,改用textContentcreateElement
  • [ ] 实现CSP头部,禁用'unsafe-inline',使用nonce或hash认证内联脚本
  • [ ] 所有Cookie设置HttpOnlySecure标志
  • [ ] 使用自动安全扫描工具(如OWASP ZAP、Acunetix)定期检测
  • [ ] 在代码仓库集成XSS检查钩子(如ESLint的eslint-plugin-no-unsanitized
  • [ ] 对第三方库(如jQuery的.html()、MathJax、Markdown解析器)进行安全审计

防止XSS不是单一技术,而是防御纵深体系的建立,从输入验证到输出编码,从CSP策略到Cookie安全,每一层都在降低风险,记住三个核心原则:永远不信任用户输入、上下文敏感编码、最小权限原则,定期进行安全培训与代码审计,才能让XSS攻击无从下手。

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