2017年英国航空公司数据泄露事件中,攻击者通过篡改网站JavaScript代码窃取38万笔支付信息——这就是典型的XSS攻击后果。
XSS攻击的三种形态与防御方案
1. 反射型XSS:钓鱼链接的陷阱
攻击者构造特殊URLhttp://example.com/search?q=<script>stealCookie()</script>
,当用户点击时恶意脚本在受害者浏览器执行。某社交平台曾因此导致百万用户会话劫持。
防御措施:
- 使用
encodeURIComponent()
对所有动态插入的内容编码 - 设置
Content-Security-Policy: script-src 'self'
- 启用
HttpOnly
属性保护cookie
2. 存储型XSS:论坛发帖的持久威胁
攻击者将恶意脚本存入数据库(如评论区),所有访问页面的用户都会中招。2015年某知名CMS漏洞导致5万个网站被植入挖矿脚本。
解决方案:
- 服务端使用DOMPurify库过滤HTML
- 前端采用
textContent
替代innerHTML
- 实现富文本编辑器时严格白名单控制
3. DOM型XSS:客户端渲染的暗礁
通过eval()
或location.hash
等操作DOM时产生的漏洞。某PWA应用曾因JSON.parse
解析恶意数据导致XSS。
最佳实践:
- 禁用
eval()
和new Function()
- 使用
document.createTextNode()
处理动态内容 - 对URL参数进行
decodeURIComponent
验证
CSRF攻击:冒充用户的隐形杀手
典型案例还原
某银行转账接口POST /transfer
未做防护,攻击者构造页面:
<form action="https://bank.com/transfer" method=POST>
<input type=hidden name=amount value=10000>
<input type=hidden name=to value=attacker>
</form>
<script>document.forms[0].submit()</script>
用户登录银行后访问该页面即自动转账。
多层防御体系
- Token验证:
// 服务端生成并埋入表单
const csrfToken = crypto.randomBytes(32).toString('hex');
res.cookie('XSRF-TOKEN', csrfToken);
// 前端拦截请求
axios.interceptors.request.use(config => {
config.headers['X-XSRF-TOKEN'] = getCookie('XSRF-TOKEN');
return config;
});
- SameSite Cookie:
Set-Cookie: session=abc123; SameSite=Strict; Secure
- 关键操作二次验证:
- 短信验证码
- 生物识别
- 密码确认
安全编码黄金法则
输入输出规范
- 数据验证三板斧:
// 类型检查
if (typeof input !== 'string') throw Error();
// 格式验证
const isEmail = /^[^@]+@\w+\.\w+$/.test(input);
// 长度限制
if (input.length > 100) return false;
- 上下文敏感编码:
场景 处理方法 HTML文本 textContent
HTML属性 setAttribute
+编码URL参数 encodeURIComponent
CSS值 CSS.escape()
JavaScript插值 JSON.stringify
现代前端框架防护
- React的自动转义:
// 安全
<div>{userInput}</div>
// 危险!需要显式使用dangerouslySetInnerHTML时:
<div dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(html)}} />
- Vue的v-html指令防护:
// 全局过滤器
Vue.filter('safeHtml', val => DOMPurify.sanitize(val));
// 模板中使用
<div v-html="userInput | safeHtml"></div>
安全工具链配置
开发阶段
- ESLint安全规则:
{
"rules": {
"no-eval": "error",
"no-implied-eval": "error",
"no-script-url": "error"
}
}
- 自动化扫描:
- OWASP ZAP动态扫描
- Snyk检测依赖漏洞
生产环境
- CSP策略配置示例:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' cdn.example.com;
style-src 'self' 'unsafe-inline';
img-src * data:;
connect-src https://api.example.com;
- 安全头设置:
add_header X-Frame-Options "DENY";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin";
真实漏洞复盘
案例1:SVG文件上传漏洞
某平台允许上传SVG头像,攻击者植入:
<svg xmlns="http://www.w3.org/2000/svg">
<script>alert(1)</script>
</svg>
修复方案:
- 服务端检测SVG文件内容
- 使用
<img>
标签渲染时添加sandbox
属性
案例2:JSONP回调注入
不安全的实现:
callback = req.query.callback;
res.send(`${callback}(${data})`);
攻击者构造:
/api?callback=alert(1);//
正确做法:
const cbName = /^[\w\$]+$/.test(callback) ? callback : 'defaultCallback';
res.send(`${cbName}(${JSON.stringify(data)})`);
持续安全实践
- 依赖更新策略:
- 每周执行
npm audit
- 使用
dependabot
自动更新
- 安全培训计划:
- 季度红队演练
- 漏洞赏金计划
- OWASP TOP10专题学习
- 监控响应机制:
- 部署WAF实时拦截
- 异常行为分析(如突然大量
eval()
调用) - 建立安全事件响应SOP
记住:安全不是功能,而是贯穿整个开发生命周期的基础属性。从今天开始,把你的console.log
语句换成安全审计代码吧!