文章目录
- 前言
- Level-1
- Level-2 标签中插入xss
- Level-3 单引号事件触发xss
- Level-4 双引号事件触发xss
- Level-5 a标签伪协议触发xss
- Level-6 大小写绕过
- Level-7 双写绕过
- Level-8 Html编码绕过
- Level-9 Html编码+strpos函数绕过
- Level-10 事件+标签隐藏
- Level-11 Referer注入+标签隐藏
- Level-12 User-Agent注入+标签隐藏
- Level-13 Cookie注入+标签隐藏
- Level-14 exif-xss漏洞
- Level-15 结合ng-include函数的文件包含注入xss
- Level-16 绕过php空格过滤
前言
为了记录学习过程的想法,写下这篇文章。关于xss-labs的文章有很多,有一些很优秀的讲的比较清楚,也有一些直接粘贴答案什么知识点也不提的,更有甚者复制他人文章作为自己的付费。这篇文章主要是更详细的去说明知识点,以及一些思路的来源,记录我的所思所想,希望能够帮到大家。
在刚开始写文章的时候,我只会<script>alert(1)</script>
,然后通过去了解才明白其他payload的原理。我在分析的时候会着重记录分析源代码的过程,即白盒来做,但实战肯定是黑盒偏多,只是我觉得白盒会让我对整个内部的架构有更深入的理解。
Level-1
第一关很简单,直接把test这个参数改为<script>alert(1)</script>
即可通关
这一关没什么知识点,但是有一个比较关键的点希望大家注意。
xss的最重要的一点是我们要首先能够找到我们能够注入的点,即可控的参数,找可控的参数是很关键的,不仅仅局限于登录框和留言板,任何可控的地方的可能存在xss
Level-2 标签中插入xss
我们打开页面源代码,观察js代码是如何处理的
发现我们的<>
会被转义导致无法被解析,我们查看后端源代码得知这一切都是可恶的htmlspecialchars()函数
导致的
这个函数就是用来防止xss的,你只要记住出现这个函数的时候,我们的xss代码中凡是带有<>
的均无法使用。
但是!!
这一关虽然这里会被过滤,但仔细看下面的input标签中的语句并没有被过滤
我们可以通过这里的value,构造一个特殊的script
这里先将前面的input标签闭合,然后我们再加入js代码,就成功过关了。
payload:"><scirpt>alert(1)</script>
常见问题:
这里的闭合符号是 " 是怎么知道的
源码中看出来的, 如上图源码画框中 value=" '.$str.' ">
其中 '.$str.' 和 ".$str." 不论哪种效果是一样的,这里的这对引号只是php写字符串的特性
真正传进去的参数会代替 '.$str.' 这个整体。所以闭合符号就是剩下的这对" "
实战不知道源码,单双引号都试试不就行了
Level-3 单引号事件触发xss
经过Level2的讲解,我们了解到了htmlspecialchars()函数
的特性,有他就没有<>
,我们进入关卡写入经典的<script>alert(1)<\script>
代码
查看页面的源代码发现这次两个参数点都被过滤了
我们不能再通过带有<>
的xss代码来进行攻击了,即我们不再能够通过直接写入js代码来造成xss。
但是如果我们想执行js代码可不止直接插入js语句这一个方法,我们还可以通过事件来执行js代码,我们以onclick事件为例,
如下图向搜索框写入 'onclick = 'alert(1)
payload:'onclick = 'alert(1)
提交后,由于我们写的是onclick事件,因此需要点击搜索框来触发。有不懂的可以看我给你接下来的解释
问题:
①为什么要用onclick事件
事件分为很多不同的,方便触发接下来写的js代码就行。
事件种类很多可以自行了解,不同的事件触发发生不同
②什么情况下用事件
这里因为<>被过滤,而onclick事件触发xss 的代码中不包含<>,所以这里能用。
事件的过滤方式一般会将on过滤掉,这种情况下带on的事件我们也不能再用,不过可以再用其他的方法绕过过滤
③这里事件怎么用的,没看懂。
这里前面有个input标签,我们可以向html元素写入事件,即事件可用于html的元素中,你随便找个能写进去事件的html元素中就行。
用法就如下,拼接出来的结果是
<input name=keyword value=' 'onclick = ' alert(1)'>
就像这样标签属性的写法给元素添加上事件就行。
Level-4 双引号事件触发xss
第四关和第三关差不多不详细讲
这里开始就将<>
过滤掉了,虽然下面的input标签这次没用htmlspecialchars()函数
,但是区别不大,和第三题的区别在于闭合符号换了,我们改第三题的单引号为双引号即可。
最终payload为"onclick = "alert(1)
Level-5 a标签伪协议触发xss
测试过程不再详细写,主要带大家具体分析源码
只有input标签中的<>
没被过滤,因为on被过滤了,好用的事件触发xss也不行了。
但是,除了直接写入js代码、写入事件能够执行js代码之外,有一些标签通过伪协议也可执行js代码,比如a
标签中的href
可用javascript
伪协议
payload为"><a href="javascript:alert(1)">xss</a>
,成功插入xss代码。
这里没见过没关系,主要的是要记住触发js代码有很多不同的方式。
Level-6 大小写绕过
源码分析:
没过滤大小写直接随便造
payload:" Onclick = "alert(1)
,随后点击搜索框触发事件
Level-7 双写绕过
源代码分析:
将敏感字符串都转化为空白字符串了,那直接双写绕过
payload:" oonnclick = "alert(1)
Level-8 Html编码绕过
如图我们分析源码
发现上面有许许多多的过滤,只有绿色框的地方是一个关键的突破点,这里会将这个a标签
输出,我们看到这个标签首先想到的是Level-5
的a标签伪协议
,所以应该向其中写入javascript:alert(1)
,但是这里的javascript
会被变为javascr_ipt
,因此我们要学习一种新方法来解决这个问题。引入html编码
。
Html编码:
已知我们的正常参数传入到后端会被过滤,同时这里的参数会被输出到a标签
中,那如何使得参数不被后端过滤,而且能够在html
的a标签
中被解析呢,答案是Html编码。(不懂的可以记住)
我们将原payloadjavascript:alert(1)
前面的javascript
进行html编码
这里随便找个html编码网站,编码替代后payload为javascript:alert(1)
提交payload,并点击友情链接
,成功通关,上面的payload其实只需要将javascript
中的script
中任意一个字符进行编码就能绕过,这里编多少都行。
这里之所以能用html编码
是因为传进去的变量会被作为字符串处理,如果不是作为字符串,php中出现&
、#
、;
这些特殊字符是会影响php语句执行的,具体的意思没理解没关系,我会在Level-16
中仔细对比让你看出来差异。
Level-9 Html编码+strpos函数绕过
我们分析源代码
和上一关很像,区别在于这里出现了strpos
函数,先学习下这个函数
strpos(A,B)
函数会从A字符串中找B字符串第一次出现的位置,如果没有返回false
,这里的过滤本意是不想让我们用javasript
伪协议,但是这个函数的过滤很容易绕过,因为这个函数只要字符串A
中任意位置含字符串B
即可。因此我们可以将字符串B
插入上一题的payload中即可
payload:javascript:alert('http://')
成功后点击链接即可通关
Level-10 事件+标签隐藏
分析源代码:
如图我们发现t_sort
参数是突破点,这里的参数只是对<>
过滤,我们可以用事件。
但是标签被隐藏掉了,我们打开F12
中找到指定元素并更改hidden
为text
。
然后向框中写入payload:"onclick="alert(1)
,然后提交并继续修改hidden
为text
,随后点击框触发事件。或者payload中也可以直接改标签的属性为text
。
我们这里传参是可以通过url来进行get传参的,但是由于我们使用的事件,让框显示出来才能更好地触发事件。
Level-11 Referer注入+标签隐藏
分析源代码:
如图我们发现一共有三个参数可控,但是只有第三个参数$str11
可以考虑。
&_SERVER['HTTP_REFERER']
会获取请求信息中Referer
字段的值。
因此$str11
参数来自于Referer
字段,我们抓包直接加上Referer
字段为恶意参数即可。
我们以burpsuite
抓包为例子(也可以用Hackbar等等插件提交参数)。
如图抓包并加上Referer
字段。
payload:Referer:" onclick="alert(1)" type="text
将包Forward
放回,回到网页中点击框触发事件,即可成功通关。
Level-12 User-Agent注入+标签隐藏
首先,分析源代码。
和Level-11关很相似,这里的区别在于参数3是获取的包中的User-Agent
头,我们只需要抓包在请求头中加入payload
就行。上一关我们使用的burpsuite
,这一关用最新版本的Hackbar
演示,我这里以Google
的插件Hackbar
演示,没有的谷歌直接搜索名字下载插件。
如图抓包,修改User-Agent
信息,通过回显确定我们的payload。
payload:User-Agent:" onclick="alert(1)" type="text
如下,触发事件成功通关。
Level-13 Cookie注入+标签隐藏
分析源代码
这里的第三个参数和前面两关思路一样,这里的参数设置在cookie
上面,我们同样用Hackbar
来向cookie
中写入恶意参数。
首先我们hackbar
先load
下来请求信息,然后execute
提交包,并查看返回包,发现了cookie
中的参数名称是user
,随后我们在请求信息中加入cookie
头,注意cookie中参数的书写形式是Cookie:参数=xxx
,随后点击事件触发。
Payload:Cookie:user="onclick=alert(1) type="text
Level-14 exif-xss漏洞
分析源代码
这一关是引入了外部url,这个网站只有翻墙才能进,而且网站的功能已经和当时靶场设计的时候的功能已经不一样了。
无法成功复现,但说一下漏洞原理。
这一关本意是有关exif-xss
漏洞的,exif
是一些图片中的信息,而有些网站会解析图片的exif
信息,如果其中存在恶意xss
攻击,而网站有没有过滤,会导致攻击者通过这个图片去用xss
进行攻击。下面解释相关概念,并给出例子。
1. Exif是什么
我们在用手机相机拍照的时候,图片中会记录我们当时拍照时的设备信息、地理位置、时间等信息。百度图片exif
信息查看,有许多在线看参数的网站,比如下面这张图。
2. Exif漏洞具体原理
像上面的这些参数信息,都是可以修改的,比如常见的修改Make
和Model
等这些字符串格式的参数,比如下面这张参数表是我修改过的。
一些网站处理参数不合理,可能会将这种参数中的js代码解析执行,即可触发exif-xss
,这就是exif-xss
漏洞的原理。
3. 一些在线网站和注意事项
上面所说的查看和修改exif
的网站我下面贴两个,但网站不知道会不会哪天消失,还是鼓励自己找。
Exif参数查看网站
Exif参数修改网站
注意事项:
照片要拍照的才有exif
,同时如果你尝试的时候发现手机拍出来的照片传到电脑上网站中打开却没有exif
信息,这是因为某些软件在传输图片的过程中为了保护用户信息,会将这些信息删掉。比如微信(因为很久之前有微信朋友圈图片泄露个人信息的例子),后来用wps传输原图才能查看,或直接使用手机打开网址上传图片。
Level-15 结合ng-include函数的文件包含注入xss
分析源代码,这题是有关angularjs
框架的ng-include
函数的使用。
这里有个参数src
,传入的参数会接在ng-include
后面,我们去学习下ng-include
函数。
通过菜鸟教程我们了解到,ng-include
是一个文件包含函数,能够通过包含其他文件来利用这个文件中的相关功能。我们尝试下包含同目录下的其他文件,利用其他文件的xss
漏洞来通关。这里以level4.php
为例,因为这里有htmlspecialchars
函数,我们后续需要使用事件来绕过这个函数的过滤。
我们先试着包含文件,再去考虑传参数。
包含文件payload:?src='level4.php'
带上引号之后,成功包含文件,现在我们向其中加入参数,其中经过回忆,Level-4
的参数是keyword
。
于是,构成payload:?src='level4.php?keyword="onclick="alert(1)'
,提交点击触发事件。
有人看到这里的"
会以为"
被函数过滤了,但是参数会正确的传输到Level-4
的php文件中,我们回忆下Level-4
的情形,参数传到Level-4
中的源代码应该是下图,但这里页面源代码中没有显示Level-4
的代码,但效果是一样的。
这题重点在于了解ng-include
函数是怎么包含文件的,了解清楚这个之后,利用包含前面通关过的文件,复现当时通关的过程即可。而angularjs
就算不知道是什么,也不影响我们通关。
Level-16 绕过php空格过滤
分析源代码:
由图可知,这题会过滤掉空格
字符串,因此我们的参数中不能含有空格
,这里补充一个知识点,在php
语法中,像Tab制表符
、回车
等字符均能代替 空格
。
通过突破点可知,参数在center
闭合标签之间,因此我们没办法去给这个标签加上事件
和属性
(之前写的事件和属性都是在<>
内部写的,而这里<>
都闭合了,无法向内部写),只能自己重新构建标签,想到a
标签。把空格
的地方我们都写成%0a
,这个字符就是回车,如下构成payload。注意script
不能连续,要用回车隔开。
如下成功通关。
Payload:
?keyword=<a%0ahref="javas%0acript:alert(1)">This
但是下面的才是这题的重点!!!
还记得Level-8
中的script->scr_ipt
我们是怎么绕过的吗,用的是html编码
,那这一题能用html编码
来绕过吗,答案是不行,至于为什么不行,下面带你仔细去对比下两关的差异。
首先Level-8
如下,这里的$str7
两端有两对引号,首先php变量两端至少是一对引号,告诉系统这里是个变量(严谨的说还有两个点".变量."
),多出来的一对引号将传进来的变量当成字符串处理。
假如没有多这一对引号,我们用html编码
会发生什么事情,肯定会报错,试想一下,html编码
中存在的特殊字符#
、&
、;
直接放入php代码中能执行吗?答案是不能,因此这里由于传进去的变量被作为字符串处理才能用html编码
。
而本关,由下图可知,传进去的变量没有作为字符串处理,因此如果用html编码
的话,其中的特殊字符&
、#
、;
会使php
在执行语句的时候发生错误。
那如果Level-8
中用%0a
符号能绕过对script
的过滤吗,答案是可以,虽然php中将其作为字符串%0a
处理绕过了限制,但是传到前端时html
也不会解析。但html编码
传进字符串中不仅绕过了php的限制,而且传到前端时html
会将这个编码作为正常字符处理。
比如Level-8
我传javasc%0aript
进去,输出前端时还是字符串javasc%0aript
,html可不会对这个%0a
进行解析,但能够对html编码
进行解析。
总结:
之所以能绕过script
的过滤,是因为向其中加入了%0a
等特殊字符,而php由于匹配不到连续的script
字符,因此就不会将其替换。上面啰嗦的这一堆引号细节,希望能够让你发现两关的差异。