什么是 XSS
概念
跨站脚本攻击(Cross-site scripting
,XSS
)是一种在 Web 应用中的安全漏洞,它允许恶意 Web 用户将代码植入到提供给其它用户使用的页面中。
一旦 Web 应用没有进行安全验证,这些攻击很容易成功。裸奔的恶意代码,可想而知是非常危险的。这些脚本可以任意读取 cookie,session tokens,或者其它敏感的网站信息,或者让恶意脚本重写 HTML 内容 。
分类
一般来说,XSS 攻击可以分为3类:存储型(持久型)、反射型(非持久型)、和 DOM 型。DOM 型 跟前两种 XSS 的区别的区别是:在 DOM 型 XSS 攻击中,取出和执行恶意代码都由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
存储型 XSS
存储型,意思就是恶意的代码片段被永久地存储在被攻击网站的服务器上。当用户进入网页,浏览器请求资源的同时,恶意脚本从服务器上传回并执行。
反射型 XSS
反射型 XSS 通常在用户被诱导点击点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站的时候发生的,响应的内容可能被插入到script
、a
、style
等标签中,由于浏览器认为这个响应来自"可信任"的服务器,所以会执行这段脚本。
DOM 型 XSS
DOM 型和反射型 XSS 的攻击原理相似,但是通常不需要浏览器响应来完成攻击,一般是用户执行了某个操作,导致客户端代码被包含进了页面并且意外执行,从而导致 DOM 环境被恶意修改。
常见危害
- 通过
document.cookie
窃取 cookie 信息 - 使用 js 或者 css 破坏页面的正常结构与样式,使得用户无法正常访问
- dos攻击:利用合理的客户端请求来占用过多的服务器资源,从而使合法用户无法得到服务器响应
常见场景
// This WILL run
div.innerHTML = '<script deferred>alert("XSS Attack");</script>';
// This will, too
div.innerHTML = '<img src=x onerror="alert(\'XSS Attack\')">';
<img src=javascript:alert("XSS") />
前端的 XSS 防御姿势
输入安全
前端可以对提交的内容进行过滤、转义处理,比如表示 html标记的 <>
等符号。但是前端并不能完全解决这个问题,因为前端校验可以被绕过,模拟直接请求,所以后台也要有相应的安全策略。
function encode(str) {
if (!str || str.length === 0) return '';
str = str.replace(/>/gm, '>');
str = str.replace(/</gm, '<');
str = str.replace(/"/gm, '"');
str = str.replace(/'/gm, ''');
return str;
}
插入安全
客户端 XSS,也就是 DOM 型 XSS 攻击,通常由 JavaScript 执行了不安全的操作导致的。比如 innerHTML
、document.write()
、location.href
等在页面中插入代码的操作产生的。在不能确保内容安全的情况下,我们要采用更加安全的替代方案。
textContent
替代 innerHtml
对于不包含标签的插入的内容,我们使用textContent
插入,这个时候内容会被转义,浏览器将内容识别为文本,因此插入的脚本不能执行
var sanitizeHTML = function (str) {
var temp = document.createElement('div');
temp.textContent = str;
return temp.innerHTML;
};
这个时候,插入操作变成:
div.innerHTML = '<h1>' + sanitizeHTML('<img src=x onerror="alert(\'XSS Attack\')">') + '</h1>';
DOMPurify
对于需要直接插入 HTML 的情况,我们可以使用第三方库 DOMPurify、jsxss等来处理。主要原理是,通过移除所有非安全的 HTML 内容(标签),从而得到一个“纯净”的 HTML。
const DOMPurify = require('dompurify')(window);
// Sanitize the review
return (<p dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(review)}}></p>);
资源安全
HttpOnly
对于不需要对 JavaScript 可用,只是用于持久化服务器端会话的 Cookie,我们通过设置 HttpOnly
标识,防止恶意脚本通过 document.cookie
访问到用户隐私数据。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; HttpOnly
CSP
内容安全策略(Content Security Policy
,CSP
),可以通过约定一系列的安全策略,指定可信的内容来源。一个兼容 CSP 的浏览器将只会执行加载与白名单域名的源文件的脚本,忽略那些其他的脚本(包括内联脚本和事件操控HTML属性)。
// 禁止价值外域脚本
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' ssl.google-analytics.com;">
SRI
子资源完整性(Subresource Integrity
,SRI
),是允许浏览器检查其获得的资源(例如从 CDN 获得的)是否被篡改的一项安全特性。SRI 是用来解决由于 CDN 资源被污染(恶意注入/替换)而导致的 XSS 漏洞的方案。
# 规定了所有脚本都要有 integrity 属性,且通过验证才能被加载
Content-Security-Policy: require-sri-for script;
# 规定了所有样式表都要有 integrity 属性,且通过验证才能被加载
Content-Security-Policy: require-sri-for style;
- integrity: 文件指纹。密码散列可以唯一标识一个数据块,任何两个文件的密码散列均不相同。浏览器在下载脚本后会计算它的散列,然后将得出的值与 integrity 提供的值进行比较。如果不匹配,则说明目标脚本被篡改,浏览器将不使用它。
React 中的 XSS 防御
默认转义
在 React 中,默认会对内容文本进入转义处理,减少我们自己处理的负担
<div>{ text }</div>
JSX
我们知道,JSX 在编译阶段实际是调用了 React.createElement()
函数来创建实际的标签,它会告诉 React 接下来要渲染的内容和一个唯一标识 $$typeof
,React 会检测 element.$$typeof
,如果标识缺失或者无效,会拒绝处理该元素。
{
type: 'div',
props: {
children: 'text',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element')
}
参考资料
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!