答案
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的网络安全漏洞,它允许攻击者将恶意脚本注入到原本无害的网页中。当其他用户浏览这些已经被注入恶意脚本的网页时,嵌入其中的脚本会在用户的浏览器中被执行,攻击者可以利用这些脚本进行进一步的恶意操作,如窃取用户的会话令牌(cookies)、劫持用户会话、重定向到恶意网站或者在用户不知情的情况下进行其他攻击行为。
XSS 攻击的三种主要类型
-
存储型 XSS(Stored XSS)
- 恶意脚本被永久存储在目标服务器上(如数据库、消息论坛、评论区等)
- 当用户访问包含恶意脚本的页面时,脚本会被执行
- 危害最大,因为攻击者不需要诱骗用户访问特定 URL
- 示例:在评论区提交
<script>alert(document.cookie)</script>
-
反射型 XSS(Reflected XSS)
- 恶意脚本通过 URL 参数传递,服务器将其反射回响应中
- 需要用户点击恶意链接才会触发
- 常见于搜索功能、错误页面等
- 示例:
http://example.com/search?q=<script>alert(1)</script>
-
DOM 型 XSS(DOM-based XSS)
- 漏洞完全在客户端的 DOM 操作中产生
- 不经过服务器,恶意脚本直接在浏览器中执行
- 常见于使用
innerHTML、document.write等不安全的 DOM 操作 - 示例:
location.hash被直接插入到页面中
XSS 攻击的危害
- 窃取用户 Cookie 和会话信息
- 劫持用户会话,执行未授权操作
- 重定向用户到钓鱼网站
- 篡改网页内容
- 键盘记录
- 窃取敏感信息(如密码、信用卡号)
XSS 防护措施
-
输入验证
- 对所有用户输入进行严格的验证和过滤
- 使用白名单而非黑名单
- 验证数据类型、长度、格式等
-
输出编码
- HTML 编码:将
<、>、&、"、'等字符转义 - JavaScript 编码:对 JavaScript 上下文中的数据进行编码
- URL 编码:对 URL 参数进行编码
- CSS 编码:对 CSS 上下文中的数据进行编码
- HTML 编码:将
-
使用 Content Security Policy (CSP)
- 限制浏览器只能加载来自可信来源的资源
- 禁止内联脚本执行
- 示例:
Content-Security-Policy: default-src 'self'; script-src 'self'
-
HttpOnly Cookie
- 设置 Cookie 的 HttpOnly 标志,防止 JavaScript 访问
- 示例:
Set-Cookie: sessionid=xxx; HttpOnly
-
使用安全的 API
- 避免使用
innerHTML,改用textContent - 避免使用
eval()和new Function() - 使用框架提供的安全方法(如 React 的
dangerouslySetInnerHTML)
- 避免使用
-
框架防护
- 现代前端框架(如 React、Vue)默认提供 XSS 防护
- 合理使用框架提供的安全特性
XSS 检测方法
-
手动测试
- 在输入框中注入测试脚本:
<script>alert(1)</script> - 检查脚本是否被执行
- 在输入框中注入测试脚本:
-
自动化扫描工具
- OWASP ZAP
- Burp Suite
- XSStrike
- XSSer
-
代码审计
- 检查所有用户输入点
- 检查输出点是否进行了适当的编码
- 检查 DOM 操作是否安全
实际案例
案例 1:存储型 XSS
javascript// 不安全的代码 app.post('/comment', (req, res) => { const comment = req.body.comment; db.save(comment); // 直接保存用户输入 }); app.get('/comments', (req, res) => { const comments = db.getAll(); res.send(comments.join('')); // 直接输出,未编码 });
修复:
javascriptapp.get('/comments', (req, res) => { const comments = db.getAll(); const encodedComments = comments.map(c => escapeHtml(c)).join(''); res.send(encodedComments); });
案例 2:DOM 型 XSS
javascript// 不安全的代码 const userInput = location.hash.substring(1); document.getElementById('output').innerHTML = userInput;
修复:
javascriptconst userInput = location.hash.substring(1); document.getElementById('output').textContent = userInput;
总结
XSS 是一种严重的安全漏洞,需要开发者在开发过程中始终保持警惕。通过输入验证、输出编码、使用 CSP 等多种防护措施的结合,可以有效地防止 XSS 攻击。同时,定期进行安全测试和代码审计也是必要的。