什么是XSS 攻击
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的网络安全漏洞,攻击者通过在网页中注入恶意脚本代码,使其在用户的浏览器中执行。这种攻击利用了网页应用程序对用户输入的不充分验证和转义,使得攻击者能够在受害者的浏览器上执行恶意脚本。
XSS攻击通常分为以下三种类型:
- 存储型XSS:攻击者将恶意脚本代码存储在目标网站的数据库中,当用户访问包含该恶意代码的页面时,代码会从数据库中提取并在用户浏览器中执行。
- 反射型XSS:攻击者将恶意脚本代码作为参数附加到受害者的请求URL中,服务器将参数返回给用户的浏览器,并在浏览器中执行。这种类型的攻击通常通过诱使用户点击包含恶意链接的欺骗性电子邮件或社交媒体消息来实施。
- DOM型XSS:攻击者通过修改网页的DOM(文档对象模型)来执行恶意脚本代码。这种类型的攻击不依赖于服务器端的漏洞,而是利用了网页前端代码中的漏洞。
XSS攻击可能导致以下危害:
- 盗取用户的敏感信息,如登录凭据、会话令牌等。
- 欺骗用户进行某些操作,如转账、更改密码等。
- 修改网页内容,篡改页面显示,传播虚假信息。
- 在受害者的浏览器上执行任意恶意操作,如下载恶意软件或进行网络钓鱼攻击。
为了防止XSS攻击,我们需要对用户输入进行适当的验证、过滤和转义,以确保输入内容不会被解释为恶意脚本代码。
利用 Symbol 防止 XSS 攻击
我们都知道,React 元素是一个 plain object
:
let el = {
type: 'marquee',
props: {
bgcolor: '#ffa7c4',
children: 'hi',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element'),
}
如果你的服务器有允许用户存储任意 JSON 对象的漏洞,而前端需要一个字符串,这可能会发生一个问题:导致潜在的安全风险
// 服务端允许用户存储 JSON
let expectedTextButGotJSON = {
type: 'div',
props: {
dangerouslySetInnerHTML: {
__html: 'dangerous InnerHTML'
},
},
// ...
};
let message = { text: expectedTextButGotJSON };
然后在某段 JSX 中使用了它,攻击者就可以运行我们不期望的 html 代码:
// React 0.13 中有风险
<p>
{message.text}
</p>
但是 React 在之后的版本中使用了 Symbol 标记 React 元素:
let el = {
type: 'marquee',
props: {
bgcolor: '#ffa7c4',
children: 'hi',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element'),
}
因为 JSON 不支持 Symbol 类型。所以即使服务器存在用 JSON 作为文本返回安全漏洞,JSON 里也不包含 Symbol.for(‘react.element’)。React 会检测 element.$$typeof,如果元素丢失或者无效,会拒绝处理该元素。