很久之前的随笔讲过XSS的编码绕过的一些内容
本次侧重整理一下常见的防御思路,顺便补充一些针对性的绕过思路以及关于XSS个人想到的一些有趣的事情
开篇之前,先看一下XSS介绍(包括mXSS、uXSS、blind XSS):
https://blog.csdn.net/Perpetual_Blue/article/details/109643465
https://blog.51cto.com/14149641/2557871
0x01防御
首先需要明确的一点是,XSS的防御检测一定不能只在前端进行(但不能不做),风险很大,还需要在后端同时进行,这是根本。前端与后端防御缺一不可
想防御,就要先清楚一个XSS的攻击流程是怎样的?
整理一下这个问题的思路:
类型
恶意代码存放点
由谁取得恶意代码并插入
存储型 XSS
后端数据库
HTML
反射型 XSS
URL
HTML
DOM 型 XSS
后端数据库/前端存储/URL
前端 JavaScript
存储型 XSS(常见于发帖、评论、私信等功能点) 的攻击步骤:
反射型 XSS (常见于需要通过URL传递参数的功能点如搜索、跳转,需要被害者手动点击触发)的攻击步骤:
DOM 型 XSS 的攻击步骤:
根据整个流程来看,无论是什么类型的XSS都客观存在共通点:攻击者提交的恶意代码可以被识别、执行并造成危害
于是产生了几种思路:
1.从用户输入的角度过滤
2.从防止恶意代码执行的角度过滤
先来说第一种,从输入侧过滤
正如前文所说,对用户输入的检测,必须要有后端检测,因为只是前端检测很轻松就能绕过了,基本上形同虚设
黑名单,是过滤不干净的,靠封锁很难,因为师傅们总能整出点新花样
推荐使用白名单,来保留部分允许的标签和属性
然后,可以在后端写入数据库之前来一次过滤,把过滤后的内容返回给前端
但是这里有一个问题,返回的内容不方便判断要输出到哪里,可能输出到HTML标签,可能输出到HTML属性、可能输出到script标签、可能输出到事件、可能输出到CSS中、可能输出到地址URL。。。。。。
前端不同位置,不同功能处的编码要求不同,过滤方法也不尽相同(白名单也好,编码转义也可能有不同的好几种写法),而且可能会引起显示乱码等问题,非常复杂
除非是一些固定格式的,比如电话号之类的,其他都不推荐在输入侧防御
所以思路转为干脆防止HTML中出现注入
或者防止JS执行时,执行了恶意代码,这样可以把XSS的危害无效化
于是再来说第二种,从防止HTML中出现注入及防止恶意代码执行的过滤
(1)存储型与反射型XSS
这两者都与后台发生交互,即从服务端取出恶意代码后插入到响应的HTML中了,并且被执行
常见方式:要么使用纯前端渲染,把代码和数据分离
要么对HTML进行充分的转义
纯前端渲染的过程:
在纯前端渲染中,我们会明确的告诉浏览器:下面要设置的内容是文本(.innerText),还是属性(.setAttribute),还是样式(.style)等等。浏览器不会被轻易的被欺骗,执行预期外的代码了(但需要注意DOM型XSS,前端渲染防御对其无效,例如 onload
事件和 href
中的 javascript:xxx
等)
问题是,纯前端渲染对于系统性能要求很高,不是所有系统都适用的,大多数还是需要面临HTML拼接的问题,所以我们尝试第二种办法,转义HTML
常用的一些模板引擎会采取简单的转义规则,比如把& < > “ ` / 等字符转义,可以说是能起到一些作用,但是并不完善
XSS 安全漏洞
简单转义是否有防护作用
HTML 标签文字内容
有
HTML 属性值
有
CSS 内联样式
无
内联 JavaScript
无
内联 JSON
无
跳转链接
无
所以要使用更加完善仔细的转义策略,比如一些语言专有的转义库,如Java中的org.owasp.encoder
(2)DOM型XSS
DOM型XSS的出现,锅要由前端JS背了,代码本身不严谨,将不可信代码执行了
在使用 .innerHTML
、.outerHTML
、document.write()
时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent
、.setAttribute()
等
如果用 Vue/React 技术栈,并且不使用 v-html
/dangerouslySetInnerHTML
功能,就在前端 render 阶段避免 innerHTML
、outerHTML
的 XSS 隐患。
DOM 中的内联事件监听器,如 location
、onclick
、onerror
、onload
、onmouseover
等,<a>
标签的 href
属性,JavaScript 的 eval()
、setTimeout()
、setInterval()
等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免
例如:
如果完全依赖可爱的小开发,可能要累死
接下来谈谈一些补充的通用办法
1.CSP(Content Security Policy)
内容安全策略
这东西相当于一种白名单制度
两种设置方法:一种是通过 HTTP 头信息的Content-Security-Policy
的字段,另一种是通过网页的标签
严格的 CSP 在 XSS 的防范中可以起到以下的作用:
参考文章:http://www.ruanyifeng.com/blog/2016/09/csp.html
2. X-Xss-Protection
HTTP X-XSS-Protection 响应头是 Internet Explorer,Chrome 和 Safari 的一个功能,当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面。它有四种取值:
(1)X-XSS-Protection: 0:禁止浏览器启用 XSS 过滤
(2)X-XSS-Protection: 1:启用浏览器启用 XSS 过滤(通常浏览器默认的值)
(3)X-XSS-Protection: 1;mode=block:启用 XSS 过滤。如果检测到攻击,浏览器将不会清除页面,而是阻止页面加载
(4)X-XSS-Protection: 1; report=
默认设置为(3)
3.HTTP-only
cookie中设置此选项,禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie
4.上WAF
软WAF、硬WAF、云WAF,帮你拦一拦
总之,防御的思想为:
(1)利用好各个模板引擎的转义功能
(2)避免内联事件,例如onLoad="onload('{{data}}')"
、onClick="go('{{action}}')"
(3)避免拼接HTML,前端采用拼接 HTML 的方法比较危险,如果框架允许,使用 createElement
、setAttribute
之类的方法实现。或者采用比较成熟的渲染框架,如 Vue/React 等。
(4)增加攻击难度,使用上文的通用手段,降低被攻击的后果
0x02绕过
上一点中谈了防御,如果完全像我说的那样从代码层面严格审查,是很难利用XSS的,绕过也无从谈起
如果能绕过的,一定是防御不完全
部分思路可以参考下图:
关于编码原则的部分,我在前面的随笔写过,可以翻翻
一些payload。。。篇幅原因就不写了
可以参考这两篇文章,值得仔细阅读:
https://www.freebuf.com/articles/web/226719.html(转自外网)
https://www.freebuf.com/articles/web/262013.html
0x03利用与危害
最后说说XSS的利用和危害
有一位表哥,面试HW的时候,遇到一位小伙汁,问他XSS的危害是什么?
答:能弹窗
危害请见下图:
图片详解请参考:
https://zhuanlan.zhihu.com/p/299678160
https://zhuanlan.zhihu.com/p/61773197
举…个例子
1.CSRF+XSS
构造csrf的poc,同时构造XSS代码(例如这种)
对方一点击访问,通过存储型XSS,实现打开页面自动调用CSRF,实现对密码的篡改
或者通过CSRF ,用POST脚本提交请求,结合selfxss(自己输入payload,自己触发,只有自己能看到)触发漏洞
2.暂时没想好写点啥
先写到这,下一篇文章继续写
关于XSS的利用,可写的还有很多很多……
抽时间继续写
可能会单独开一篇
闪电五连鞭,缺一鞭都不行,没有劲儿
参考文章:
https://www.freebuf.com/vuls/225096.html
https://www.bilibili.com/read/cv5322293/
https://zhuanlan.zhihu.com/p/299678160
https://www.cnblogs.com/vege/p/12655830.html
https://segmentfault.com/a/1190000022678120
https://www.freebuf.com/articles/web/244524.html
https://cloud.tencent.com/developer/article/1621427
https://segmentfault.com/a/1190000016551188
未经允许,禁止转载
手机扫一扫
移动阅读更方便
你可能感兴趣的文章