转载 大前端技术之路 欢迎关注
10个react安全最佳实践
在找保护React应用程序的最佳方法?那你找对地方了!
我创建了这个React安全最佳实践清单,用以帮助你和你的团队发现并解决React应用中的安全问题。我展示如何自动测试你的React代码中安全相关问题并修复它们。
让我们开始吧。
- 数据绑定( Data Binding)默认的xss保护
- 危险的URL
- 渲染html
- 直接访问dom
- 服务端渲染
- 检测依赖项中的漏洞
- JSON State
- 检测React易受攻击版本
- linter工具
- 危险的库代码
数据绑定( Data Binding)默认的xss保护
使用默认的{}
进行数据绑定,React会自动对值进行转义以防止XSS攻击。但注意这种保护只在渲染textContent
时候有用,渲染
HTML attributes的时候是没用的。
使用数据绑定语法{}
将数据在组件中。
这样做:
<div>{data}</div>
避免没有经过自定义验证的动态HTML attributes值。
别这样做:
<form action={data}>...
危险的URL
URL是可以通过javascript:
协议来引入动态脚本的。所以需要验证你的连接是否是http:
或者https:
以防止javascript:
url的脚本注入。使用原生的URL parsing方法进行URL验证,判断其协议是否在你的白名单中。
这样做:
function validateURL(url) {
const parsed = new URL(url)
return ['https:', 'http:'].includes(parsed.protocol)
}
<a href={validateURL(url) ? url : ''}>Click here!</a>
别这样做:
<a href={attackerControlled}>Click here!</a>
渲染html
React是可以通过dangerouslySetInnerHTML
将html代码直接渲染到dom节点中的。但以这种方式插入的任何内容都必须事先消毒。
在将任何值放入dangerouslySetInnerHTML
属性之前,需要用dompurify对其消毒。
在插入html时用dompurify进行处理
import purify from "dompurify";
<div dangerouslySetInnerHTML={{ __html:purify.sanitize(data) }} />
直接访问dom
应该避免访问DOM然后直接将内容注入DOM节点。如果你一定要插入HTML,那就先用dompurify
消毒,然后再用dangerouslySetInnerHTML
属性。
这样做:
import purify from "dompurify";
<div dangerouslySetInnerHTML={{__html:purify.sanitize(data) }} />
不要使用refs 和 findDomNode()
去访问渲染出来的DOM元素,然后用类似innerHTML
的方法或者属性去注入内容。
别这样做:
this.myRef.current.innerHTML = attackerControlledValue;
服务端渲染
在使用像ReactDOMServer.renderToString()
和ReactDOMServer.renderToStaticMarkup()
这类方法的时候,数据绑定会自动提供内容转义的功能。
避免在将字符串发送到客户端浏览器进行注水(hydration)之前,把其他的一些(未经检验的)字符串连接到renderToStaticMarkup()
的输出上。
不要把未经消毒的数据连接到renderToStaticMarkup()
的输出上,以防止XSS
app.get("/", function (req, res) {
return res.send(
ReactDOMServer.renderToStaticMarkup(
React.createElement("h1", null, "Hello World!")
) + otherData
);
});
检测依赖项中的漏洞
一些第三方组件的某些版本可能包含安全问题。检查您的依赖关系,并及时更新到更好的版本。
使用类似snyk CLI的工具进行漏洞检查。
snyk CLI还可以与代码管理系统集成,然后自动修复漏洞:
$ npx snyk test
JSON state
将JSON数据与SSR后的React页面一起发送是常见做法。一定要用无害的等价字符转移<
字符。
使用良性等效字符转义JSON中的HTML有效值:
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace( /</g, '\\u003c')}
易受攻击的React版本
React库在过去有一些严重性很高的漏洞,因此最好保持最新版本。
使用npm outdated查看是否处于最新版本,从而避免使用react和react dom的易受攻击版本。
linter工具
安装能自动检测代码中的安全问题并提供修正建议的Linter配置和插件。
使用 ESLint React security config 来检查安全漏洞。
配置能在使用husky这样的库检测到安全相关的问题时,会失败的pre-commit钩子。
使用Snyk自动更新版本 当其检查到你当前的版本有安全问题。
危险的库代码
库代码通常会进行危险的操作,如直接将HTML插入DOM。人工或使用linter工具来检查库代码,以检测是否有对React机制的不安全使用。
避免那些使用dangerouslySetInnerHTML
、innerHTML
、未验证的URL或其他不安全模式的库。使用linter工具对node_modules
目录进行检查。