xss-labs(1~16)通关超详解

关于靶场的搭建:

关于工具:HackBar(目前只能在火狐浏览器的插件使用)、Burpsuite
概要:xss主要分为

反射型
·非持久性跨站点脚本攻击
·攻击是一次性的,仅对当次的页面访问产生影响
存储型
·持久型跨站点脚本
·攻击者的数据存储在服务器端,攻击行为将伴随着攻击数据-直存在
DOM型
·既可能是反射型的,也有可能是存储型的
·基于文档对象模型
(Document Objeet Model,DOM)的一种漏洞

xss-labs主要是针对GET方式进行注入,POST方法抓包就行了

第一关

在这里插入图片描述
打开第一关源码,发现参数是通过GET方法传递的,并且对传过去的参数没有作过滤

同时该变量的值是直接插入的,所以不需要闭合

payload:

name=<script>alert(1)</script>

第二关

在这里插入图片描述

分析代码,还是通过GET传参并将变量进行html实体化输出。

htmlspecialchars()是一个PHP函数,用于将特殊字符转换为HTML实体。它可以将一些特殊字符转换为HTML实体,以防止这些字符被解释为HTML标签或JavaScript代码,从而增强了网页的安全性。

htmlspecialchars()函数将以下字符转换为HTML实体:

    &(和号)转换为 &amp;
    "(双引号)转换为 &quot;
    '(单引号)转换为 &#039;
    <(小于号)转换为 &lt;
    >(大于号)转换为 &gt;

这样做可以确保用户输入的内容不会被误解释为HTML标签或JavaScript代码,从而防止跨站点脚本(XSS)攻击。通常在输出用户输入的内容到HTML页面时,应该使用htmlspecialchars()函数进行转义,以增强网页的安全性。

但是value的值是通过 表单提交,并没有对表单提交的值进行html实体化,因此只用针对value进行payload的构造
在这里插入图片描述

还输入上一关的payload,发现需要闭合

进行双引号闭合

"><script>alert(1)</script>

第三关

=

输入上一关的payload,发现输入输出的值都被实体化了,并且使用了单引号闭合。

但我们知道,htmlspecialchar()函数只会针对一些特定的字符转化为HTML实体,既然<>" ’ 被过滤了不妨用JavaScript中的事件进行绕过。

在这里插入图片描述

事件可以直接嵌入到标签当中,因此不需要进行标签的闭合,从而可以绕过标签被闭合的情况。

这里我们使用onclick构造payload,当点击输入框时就会触发onclick事件(因为onclick在input标签里,input自己会产生一个输入框)

在这里插入图片描述

直接输入οnclick=alert(1)发现前后单引号需要闭合

先闭合一个单引号发现不行

在这里插入图片描述

发现前一个已经闭合了,只需再闭合后面的就成功了

在这里插入图片描述

但是不能将第二个引号放在最后

‘οnclick=alert(1)’

因此payload

'onclick='alert(1) 

第二种方法是用onerror事件

onerror 事件是 JavaScript 中的一个事件,用于处理当文档、图像、脚本或其他资源加载过程中发生错误时的情况。当浏览器尝试加载一个资源时,如果该资源无法加载(如文件不存在、网络错误等),就会触发 onerror 事件。

在 HTML 中,onerror 事件通常用于图像 ()、脚本 () 和样式表 (``) 等元素上,以便在加载资源失败时执行一些特定的操作,例如显示备用图像、向用户报告错误等。

因此我们可以故意写一个让他报错的代码,从而触发onerror事件

第四关

直接输入

<script>alert(1)</script>

在这里插入图片描述

发现我们输入的<>都被去掉了

查看源码发现

$str = $_GET["keyword"];
$str2=str_replace(">","",$str);
$str3=str_replace("<","",$str2);

它使用了一个str_replace函数

str_replace()函数用于在字符串中替换指定的子字符串。它的基本用法是:

str_replace($search, $replace, $subject)

其中:

  • $search:要查找并替换的字符串或字符串数组。
  • $replace:替换成的字符串或字符串数组。如果search和search和search和replace是数组,那么search中的每个元素都会被search中的每个元素都会被search中的每个元素都会被replace中相应位置的元素替换。
  • $subject:要在其中进行查找和替换的字符串或字符串数组。

这个函数返回一个新的字符串,其中search中的每个元素都被相应位置的search中的每个元素都被相应位置的search中的每个元素都被相应位置的replace元素替换了。如果search和search和search和replace都是数组,并且search的长度不等于search的长度不等于search的长度不等于replace的长度,那么search中多余的元素将被忽略,而search中多余的元素将被忽略,而search中多余的元素将被忽略,而subject中的多余元素将保持不变。

示例:

// 替换单个字符串
$str = "Hello world!";
$new_str = str_replace("world", "PHP", $str);
echo $new_str;  // 输出:Hello PHP!

// 替换多个字符串
$str = "Apples and oranges";
$find = array("apples", "oranges");
$replace = array("bananas", "pears");
$new_str = str_replace($find, $replace, $str);
echo $new_str;  // 输出:Bananas and pears

// 替换数组中的元素
$search = array("black", "brown", "beige");
$replace = "green";
$subject = array("black shoes", "brown belt", "beige jacket");
$new_subject = str_replace($search, $replace, $subject);
print_r($new_subject);  // 输出:Array ( [0] => green shoes [1] => green belt [2] => green jacket )

这里既然将<>给替换为空,那么就可以延用上一关的思路,当<>被过滤时使用事件进行绕过

payload

"onclick="alert(1)

第五关

直接输入

<script>alert(1)</script>

试试水,发现

在这里插入图片描述

在我们的第一个<script标签中多了一个_ ,查看代码看看他到底做了什么手脚

$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);

通过代码分析发现:首先对传过来的参数进行了strtolower()处理

strtolower()函数是PHP中的一个字符串函数,用于将字符串中的所有字母转换为小写字母。

例如:

$str = "Hello World!";
$new_str = strtolower($str);
echo $new_str;  // 输出:hello world!

然后还是用str_replace函数进行替换

发现不仅<script被替换了,on也被替换了

这意味着我们我们不能使用Script标签和on事件了

但是他并没有对<>进行过滤,因此我们使用a标签来构造payload

在这里插入图片描述

在这里插入图片描述

当进行点击时,会跳转到herf的值对应的链接。

但是herf后面跟链接对我们解出payload并没有什么帮助,此时就要用到JavaScript伪协议

JavaScript 伪协议(JavaScript pseudo-protocol)是一种特殊的 URL 格式,用于在网页中执行 JavaScript 代码。它通常以 “javascript:” 开头,后面跟随着 JavaScript 代码。

JavaScript 伪协议最常见的用途是在 HTML 的链接 (`` 标签) 的 href 属性中,或者在 HTML 的事件处理器中,如 onclick 事件。

例如,以下是一个在链接中使用 JavaScript 伪协议的例子:

<a href="javascript:alert('Hello, world!');">Click me</a>

点击这个链接会弹出一个包含 “Hello, world!” 的警告框

因此我们用这个来构造payload

在这里插入图片描述

"><a href=javascript:alert(1)>1</a>

在这里插入图片描述

点击1后触发了payload,成功绕过!

第六关

在这里插入图片描述

输入上一关的payload等,发现<script , on事件,和href都被过滤了

查看源码

$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);

发现过滤了好多标签啊,汗流浃背了?

但是前一关不是使用了strtolower函数吗?这关咋没了?

很明显就是想让你用这个来绕过啊

在 HTML 中,对于标签名和属性名,是不区分大小写的。这意味着

,
,
都表示同一个标签。同样地,属性名也是不区分大小写的,例如 hrefHREFHRef 都表示同一个属性。

但是,对于标签和属性的值,HTML 是区分大小写的。例如,在 [Link](https://example.com) 中,https://example.comHTTPS://example.com 被认为是不同的链接地址。

在 JavaScript 和 CSS 中,通常也是对于标签名和属性名不区分大小写的,但是对于属性值是区分大小写的。

因此

"><Script>alert(1)</script>

第七关

一点儿一点儿探测太累了怎么办?

xss万能语句来进行探测

<SCRscriptIPT>'"()Oonnjavascript

输入后查看网页源码

在这里插入图片描述

与原来的对比发现他过滤了script,on,同时大写也变成了小写。

查看源码

$str =strtolower( $_GET["keyword"]);
$str2=str_replace("script","",$str);
$str3=str_replace("on","",$str2);
$str4=str_replace("src","",$str3);
$str5=str_replace("data","",$str4);
$str6=str_replace("href","",$str5);

与上一关比,他多了个strtolower()函数来使所有的字母都变成小写,那么说明我们无法用大小写进行绕过了,但是通过万能语句发现,进行拼接而成的最后变成了

"><sscriptcript>alert(1)</sscriptcript>

第八关

添加友情链接?什么鬼

先用万能语句试试

在这里插入图片描述

发现双写不管用了,同时双引号也被实体化了,但是单引号没有,说明对过滤没有使用实体化函数,而是将双引号替换为了&quot

查看源码

$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','&quot',$str6);

果然如我们所推理的一样

但是双引号被实体编码了,我们已经没法闭合href标签了,同时双写,大小写都失效了,该怎么办呢?

我们观察href可以知道,如果我们插入的是javascript:alert(1)就可以直接执行payload,可惜的是被过滤了,但是倘若在传参给$str的时候就是编码格式是不是就能绕过呢?

这里我们可以对payload进行Unicode编码或者十六进制编码

Unicode:

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

Hex:

&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;

在线编码网站:CTF在线工具-CTF工具|CTF编码|CTF密码学|CTF加解密|程序员工具|在线编解码 (hiencode.com)

或者使用HackBar在这里插入图片描述

HTML Characters也可完成编码

第九关

还是让我们添加一个链接,试试上一关的payload

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

在这里插入图片描述

提示不合法?正常的链接是不是应该有http://

加个http://试试

http://&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

在这里插入图片描述

发现再次点击友情链接并不会报错了,说明后台代码有检测链接合法不合法的机制,让我们查看源码

<?php
if(false===strpos($str7,'http://'))
{
  echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';
        }
else
{
  echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>

这关与上一关相比,多了一个检测机制

这里还用到了strpos()函数

strpos() 函数用于在字符串中查找第一次出现子字符串的位置,并返回其位置的索引。如果找到子字符串,则返回第一次出现的位置(索引值),如果没有找到,则返回 false

语法如下:

strpos(string $haystack, string $needle, int $offset = 0): int|false

参数说明:

  • $haystack:要搜索的字符串。
  • $needle:要查找的子字符串。
  • $offset(可选):指定搜索的起始位置,默认为 0。

示例用法:

$string = 'Hello, world!';
$substring = 'world';

$pos = strpos($string, $substring);

if ($pos !== false) {
    echo "子字符串 '$substring' 在字符串中的位置为: $pos";
} else {
    echo "未找到子字符串 '$substring'";
}

意思是他将经过检测后的字符串 s t r 7 传入 s t r p o s ()函数中,检索字符串中是否含有 h t t p : / / ,如果没有返回 f a l s e ;否则就将 str7传入strpos()函数中,检索字符串中是否含有http://,如果没有返回false;否则就将 str7传入strpos()函数中,检索字符串中是否含有http://,如果没有返回false;否则就将str7直接传入href中

但是http://存在时,代码也没法正常执行,想办法不让http:// 出现

可以使用注释

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;/* http:// */

(注释不能放在前面,否则无法正常执行)

第十关

在这里插入图片描述

这一关看了一圈都没有输入框

但是看见在这里插入图片描述

URL栏好像可以传参,他用的还是GET方法

先输入万能语句看看过滤了什么

在这里插入图片描述

发现应该是只用了htmlspecialchars()函数

查看源码

$str = $_GET["keyword"];
$str11 = $_GET["t_sort"];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link"  value="'.'" type="hidden">
<input name="t_history"  value="'.'" type="hidden">
<input name="t_sort"  value="'.$str33.'" type="hidden">
</form>

但是实际值应该传给t_sort而不是传给keyword

发现他对t_sort传来的值过滤了<>

还记不记之前提的,过滤了<>就用on事件,但是这次并没有输入框啊

那就加个属性吧

"onclick=javascript:alert(1) type="text

点击出现的输入框即可完成本关

这里还有一种更简单的办法

在这里插入图片描述

F12打开开发者模式,直接修改前端的内容进行绕过

在这里插入图片描述

双击就可以修改了,这样绕过嘎嘎快

在这里插入图片描述

然后点击框框就可以绕过了

第十一关

还使用刚刚的方法试试

在这里插入图片描述

但是这样算是走捷径了

在这里插入图片描述

因为这个函数,只要弹出框就算通过了,所以我们还是用正常的方法过吧

在这里插入图片描述

F12发现有四个值可以传,且最后一个t_ref的值是上一关的地址,我们不难猜出,这个t_ref是http-referer的意思

那我们对前面三个参数传值

t_sort=<SCRscriptIPT>'"()Oonnjavascript &t_link=<SCRscriptIPT>'"()Oonnjavascript &t_history=<SCRscriptIPT>'"()Oonnjavascript

发现没啥用,唯一可以显示出来的值t_sort还被实体化了,用不了事件也闭合不了,那就只能从referer下手了

通过观察我们不难发现t_ref的值是上一关的referer,并且没有对refer进行过滤

那我们就可以构造恶意的referer从而进行绕过
在这里插入图片描述

打开HackBar

勾选Referer,然后在下面直接修改为我们的payload

"onclick=javascript:alert(1) type="text

点击Execute(执行)
在这里插入图片描述

点击文本框,成功!

另一种方法是通过BurpSuite进行抓包,我们先返回第十关
在这里插入图片描述

这时候抓包在这里插入图片描述

把referer改成11关的payload就可以了

不过这种方法没有使用HackBar好用

第十二关

在这里插入图片描述

打开12关,也是没有什么头绪,那就看看页面源码吧

在这里插入图片描述

上一关是referer那这一关很明显就是关于UA的了

在这里插入图片描述

和上一关一样轻轻松松

第十三关

前两关是referer和UA我猜这次是cookie

在这里插入图片描述

。。。猜对了

在这里插入图片描述

记得不要删去cookie中的user,否则会传参失败

第十四关

在这里插入图片描述

这关挂了,不用做了。。。

第十五关

在这里插入图片描述

点击上一关的进入下一关会跳转到错误的url,改一下你原本的url就好在这里插入图片描述

没啥思路就看看网页源码吧,发现之前的表单提交都没了,多了一个ng-include:,且url传的值放在了ng-include后面

在这里插入图片描述

ng-include 是 AngularJS 框架中的一个指令,用于将外部 HTML 文件或 AngularJS 模板包含到当前页面中。

具体来说,ng-include 指令可以在页面中指定一个 HTML 文件或者 AngularJS 模板的 URL,并将其包含到当前页面中的指定位置。这样可以实现页面模块化和重用性,使得页面结构更加清晰和易于维护。

简单来说在这里插入图片描述

他的作用就是这样,可以引用其他的文件也就是能够包含其他的文件

前面测了一下绕过什么了,就不展示了也就是给实体化

payload

src='./level1.php?name=<img src=1 onerror=alert(1)>'

第十六关

输入我们的万能语句

在这里插入图片描述

发现大写变成了小写,但是<>没有说明没有实体化,同时可以发现script被替换为了&nbsp ;也就是空格,从而避免我们拼接script

那我们试试这个payload

</center><img src=1 onerror=alert(1)><center>

使用img src=1进行错误的语法从而触发onerror事件

在这里插入图片描述

但是发现/,空格,也被&nbsp ; 替换掉了

空格被替换了问题也不大,我们用换行符url编码就好了

<img%0Asrc=1%0Aonerror=alert(1)>

(换行不影响代码的执行,只要他在标签里面就好了)

第十七关

这关使用到了embed标签

`` 标签是 HTML 中用来嵌入外部内容的标签,通常用于嵌入多媒体文件(如音频、视频、Flash 等)或其他插件(如 PDF、SVG 等)到网页中。

具体来说,`` 标签可以通过指定 src 属性来指定要嵌入的外部资源的 URL,以及通过其他属性来设置嵌入内容的属性,如宽度、高度、类型等。

示例用法:

<embed src="video.mp4" width="400" height="300">

但是这关需要flash插件的支持,由于flash插件漏洞太多了

使用img src=1进行错误的语法从而触发onerror事件

但是发现/,空格,也被&nbsp ; 替换掉了

空格被替换了问题也不大,我们用换行符用url编码就好了

<img%0Asrc=1%0Aonerror=alert(1)>

(换行不影响代码的执行,只要他在标签里面就好了)

这关需要flash插件的支持,由于flash插件漏洞太多了

并且性能与技术早已落后,所以17-20关就不做了…

总结

XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。

XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。

形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。

因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:

输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;

输出转义:根据输出点的位置对输出到前端的内容进行适当转义
以下是一些防范存储型XSS攻击的建议:

  1. 输入过滤和验证:对用户输入的数据进行严格的过滤和验证,确保只允许合法的数据格式输入。
  2. 转义输出:在显示用户输入的内容时,确保对特殊字符进行转义,以防止恶意脚本的执行。比如,在Web页面中显示用户输入的内容时,可以使用HTML编码来转义特殊字符。
  3. 内容安全策略(CSP):实施内容安全策略,限制页面可以加载的资源,包括脚本文件、样式表等,从而减少XSS攻击的风险。
  4. HTTPOnly标记:对于Cookie,使用HTTPOnly标记可以防止JavaScript访问敏感的Cookie信息,减少会话劫持的风险。
  5. 定期安全审计:定期对网站进行安全审计和漏洞扫描,及时发现并修复潜在的安全问题。
  6. 敏感操作的二次验证:对于涉及敏感操作的页面,如修改密码、支付等,应该实施二次验证机制,增加安全性。

下面是一些防范DOM型XSS攻击的建议:

  1. 输入验证和过滤:与其他类型的XSS攻击一样,对用户输入的数据进行严格的验证和过滤,确保不会执行恶意脚本。
  2. 不要信任客户端数据:不要直接信任客户端提供的数据,始终在服务器端对数据进行验证和处理。
  3. 避免使用eval():避免使用eval()函数执行动态生成的JavaScript代码,因为这可能会导致DOM型XSS漏洞。
  4. 安全的编码:在操作DOM时,确保对用户输入的内容进行适当的编码,以防止恶意脚本的执行。
  5. 使用安全的JavaScript框架:使用经过安全审计的JavaScript框架,这些框架通常会提供一些内置的安全机制来防范XSS攻击。
  6. 定期更新和监控:及时更新浏览器和相关的安全补丁,监控网站的安全情况,发现潜在的漏洞并及时修复。

xss基础测试语句:

'';!--"<XSS>=&{()}

<script>alert(/1/)</script>

<img scr=1 onerror="alert(/1/)">

<img src="javascript:alert('1');">

<a href="javascript:alert(1)">

同时关于xss还有许多使用的工具:
https://blog.csdn.net/p36273/article/details/131263927
https://blog.csdn.net/weixin_54977781/article/details/123555545

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aaa彤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值