浅谈 React 中的 XSS 攻击( 三 )

所以平时开发时最好避免使用 dangerouslySetInnerHTML , 如果不得不使用的话 , 前端或服务端必须对输入进行相关验证 , 例如对特殊输入进行过滤、转义等处理 。前端这边处理的话 , 推荐使用白名单过滤 (https://jsxss.com/zh/index.html) , 通过白名单控制允许的 HTML 标签及各标签的属性 。
通过用户提供的对象来创建 React 组件举个例子:
// 用户的输入const userProvidePropsString = `{"dangerouslySetInnerHTML":{"__html":"<img onerror='alert("xss");' src=https://www.isolves.com/it/aq/sj/2020-09-24/'empty.png' />"}}"`;// 经过 JSON 转换const userProvideProps = JSON.parse(userProvidePropsString);// userProvideProps = {// dangerouslySetInnerHTML: {// "__html": `浅谈 React 中的 XSS 攻击`// }// };render() { // 出于某种原因解析用户提供的 JSON 并将对象作为 props 传递 return

}这段代码将用户提供的数据进行 JSON 转换后直接当做 div 的属性 , 当用户构造了类似例子中的特殊字符串时 , 页面就会被注入恶意代码 , 所以要注意平时在开发中不要直接使用用户的输入作为属性 。
使用用户输入的值来渲染 a 标签的 href 属性 , 或类似 img 标签的 src 属性等const userWebsite = "JAVAscript:alert('xss');";<a href=https://www.isolves.com/it/aq/sj/2020-09-24/{userWebsite}>如果没有对该 URL 进行过滤以防止通过 JavaScript: 或 data: 来执行 JavaScript , 则攻击者可以构造 XSS 攻击 , 此处会有潜在的安全问题 。用户提供的 URL 需要在前端或者服务端在入库之前进行验证并过滤 。
服务端如何防止 XSS 攻击服务端作为最后一道防线 , 也需要做一些措施以防止 XSS 攻击 , 一般涉及以下几方面:
  • 在接收到用户输入时 , 需要对输入进行尽可能严格的过滤 , 过滤或移除特殊的 HTML 标签、JS 事件的关键字等 。
  • 在输出时对数据进行转义 , 根据输出语境 (html/javascript/css/url) , 进行对应的转义
  • 对关键 Cookie 设置 http-only 属性 , JS脚本就不能访问到 http-only 的 Cookie 了
  • 利用 CSP (https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP) 来抵御或者削弱 XSS 攻击 , 一个 CSP 兼容的浏览器将会仅执行从白名单域获取到的脚本文件 , 忽略所有的其他脚本 (包括内联脚本和 HTML 的事件处理属性)
总结出现 XSS 漏洞本质上是输入输出验证不充分 , React 在设计上已经很安全了 , 但是一些反模式的写法还是会引起安全漏洞 。Vue 也是类似 , Vue 做的安全措施主要也是转义 , HTML 的内容和动态绑定的属性都会进行转义 。无论使用 React 或 Vue 等前端框架 , 都不能百分百的防止 XSS 攻击 , 所以服务端必须对前端参数做一些验证 , 包括但不限于特殊字符转义、标签、属性白名单过滤等 。一旦出现安全问题一般都是挺严重的 , 不管是敏感数据被窃取或者用户资金被盗 , 损失往往无法挽回 。我们平时开发中需要保持安全意识 , 保持代码的可靠性和安全性 。
作者:陈吉
转发链接:https://mp.weixin.qq.com/s/HweEFh78WXLawyQr_Vsl5g




推荐阅读