什么是XSS?
wikipedia中是这样介绍的:
XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy.
简言之 通过注入客户端脚本(js)呈现给其他用户的攻击手段既XSS
尽管是最常见的安全漏洞,在漏洞统计中依旧占很大比重 (Cross-site scripting carried out on websites accounted for roughly 84% of all security vulnerabilities documented by Symantec up until 2007)
XSS有哪些类型?
- 反射型(非持久型)
将注入的脚本数据(未存储到数据库)通过服务端反射给其他用户,进行攻击的手段既反射型XSS
- 存储型(持久型)
存储型和反射型的漏洞数据均由服务端提供,相对于反射型,存储型将漏洞数据存储到了数据库,这就表明只要用户访问了此漏洞数据,便会遭到攻击,所以就危害程度而言: 存储型XSS > 反射型XSS
- DOM Based型
DOM Based 型,表现形式也是反射型,相对于前面两者的本质区别在于,有漏洞的数据并非通过服务端,而是直接由JS执行进行DOM节点的操作所造成的XSS漏洞,如下图案例所示:
案例是通过输入框输入,也可能通过url等其他形式注入操作DOM,造成XSS
- Self XSS
前面提及的XSS都可以通过各种手段影响到其他用户(窃取其他用户cookie、信息等造成危害),Self XSS相对于前文提到的区别在于,漏洞只有在本人当前上下文执行,并不会影响其余用户。 例如个人简介中的nickname存在xss漏洞,即使注入了漏洞脚本,影响范围也仅是本人.
- Mutated XSS (mXSS)
此类XSS通常是浏览器自行执行一些解析所引起的XSS,看以下例子:
function generateText (inputText) {
const domElem = document.createElement('div')
domElem.innerHTML = inputText
return domElem.innerText
}
看似没什么问题,inputText即使带有普通的html标签,也能正常返回文本,然而却隐藏了安全风险
当执行generateText('\<img onerror="alert(XSS)" src="xx"\>'),alert(XSS)被成功执行了
因为innerHTML自行去解析了HTML,所以导致的XSS漏洞
如何预防?
- 预防Cookie窃取,设置HttpOnly
- 对不可信数据进行编码 (涉及XSS注入的场景包括:HTML、Javascript、Base64、HTML Attribute、CSS) XSS攻防示例代码
router.get('/', (ctx, next) => {
// HTML注入XSS
const htmlXSS = '<script>alert("HTML XSS")</script>' // ESAPI.encoder().encodeForHTML('<script>alert("XSS")</script>');
// CSS注入XSS,IE 7 下复现
const cssXSS= `expression(alert('CSS XSS'),1)` // ESAPI.encoder().encodeForCSS(`expression(alert('CSS XSS'),1)`)
// HTML Attribute注入XSS, 漏洞复现访问 http://127.0.0.1:3000/?cb=javascript:alert(123)
const cbParam = ctx.request.url.slice(ctx.request.url.indexOf('cb') + 3)
const parsedCb = cbParam // handleHrefXss(cbParam)
console.log(cbParam)
// Javascript 注入XSS
const jsXSS = `";alert('JS XSS');"`; // ESAPI.encoder().encodeForJavaScript(`";alert('JS XSS');"`)
// base64 中注入XSS
const base64XSS = `data:text/html;base64,PHNjcmlwdD5hbGVydCgnYmFzZTY0IFhTUycpPC9zY3JpcHQ+` // ESAPI.encoder().encodeForBase64(`data:text/html;base64,PHNjcmlwdD5hbGVydCgnYmFzZTY0IFhTUycpPC9zY3JpcHQ+`)
ctx.body = `
<div>${htmlXSS}</div>
<a href=${parsedCb}>HTML Attribute XSS</a>
<div style="height:${cssXSS}"></div>
<h2>Base64 XSS: </h2>
<iframe src=${base64XSS}>Base64 XSS</iframe>
<script>
var a = "${jsXSS}"
</script>
`;
});
- 响应头添加CSP策略
- 未支持CSP旧版浏览器,添加X-XSS-Protection
参考文献
- wikipedia, zh.wikipedia.org/wiki/
- 《白帽子讲web安全》
- mozilla, developer.mozilla.org/