HOOOS

前端安全实战:如何防范XSS与CSRF攻击及安全编码实践

0 11 安全老司机 前端安全XSS防护CSRF防御
Apple

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>

用户登录银行后访问该页面即自动转账。

多层防御体系

  1. 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;
});
  1. SameSite Cookie
Set-Cookie: session=abc123; SameSite=Strict; Secure
  1. 关键操作二次验证
  • 短信验证码
  • 生物识别
  • 密码确认

安全编码黄金法则

输入输出规范

  1. 数据验证三板斧
// 类型检查
if (typeof input !== 'string') throw Error();

// 格式验证
const isEmail = /^[^@]+@\w+\.\w+$/.test(input);

// 长度限制
if (input.length > 100) return false;
  1. 上下文敏感编码
    场景 处理方法
    HTML文本 textContent
    HTML属性 setAttribute+编码
    URL参数 encodeURIComponent
    CSS值 CSS.escape()
    JavaScript插值 JSON.stringify

现代前端框架防护

  1. React的自动转义
// 安全
<div>{userInput}</div> 

// 危险!需要显式使用dangerouslySetInnerHTML时:
<div dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(html)}} />
  1. Vue的v-html指令防护
// 全局过滤器
Vue.filter('safeHtml', val => DOMPurify.sanitize(val));

// 模板中使用
<div v-html="userInput | safeHtml"></div>

安全工具链配置

开发阶段

  1. ESLint安全规则
{
  "rules": {
    "no-eval": "error",
    "no-implied-eval": "error",
    "no-script-url": "error"
  }
}
  1. 自动化扫描
  • OWASP ZAP动态扫描
  • Snyk检测依赖漏洞

生产环境

  1. 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;
  1. 安全头设置
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)})`);

持续安全实践

  1. 依赖更新策略
  • 每周执行npm audit
  • 使用dependabot自动更新
  1. 安全培训计划
  • 季度红队演练
  • 漏洞赏金计划
  • OWASP TOP10专题学习
  1. 监控响应机制
  • 部署WAF实时拦截
  • 异常行为分析(如突然大量eval()调用)
  • 建立安全事件响应SOP

记住:安全不是功能,而是贯穿整个开发生命周期的基础属性。从今天开始,把你的console.log语句换成安全审计代码吧!

点评评价

captcha
健康