XSS成因
通过在用户端注入恶意的可执行脚本,若服务器对用户的输入不进行处理或处理不严,则浏览器会直接执行用户注入的脚本。
XSS危害
攻击者通过Web应用程序发送恶意代码,一般以浏览器脚本的形式发送给不同的终端用户。当一个Web程序的用户输入点没有进行校验和编码,将很容易的导致 XSS 。
- 网络钓鱼,包括获取各类用户账号;
- 窃取用户 cookies 资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作;
- 劫持用户(浏览器)会话,从而执行任意操作,例如非法转账、强制发表日志、电子邮件等;
- 强制弹出广告页面、刷流量等;
- 网页挂马;
- 进行恶意操作,如任意篡改页面信息、删除文章等;
- 进行大量的客户端攻击,如ddos等;
- 获取客户端信息,如用户的浏览历史、真实ip、开放端口等;
- 控制受害者机器向其他网站发起攻击;
- 结合其他漏洞,如csrf,实施进一步危害;
- 提升用户权限,包括进一步渗透网站;
- 传播跨站脚本蠕虫等
容易产生XSS的地方
1、与数据交互的地方
- get、post、cookies、headers
- 反馈与浏览
- 富文本编辑器
- 各类标签插入和自定义
2、数据输出的地方
- 用户资料
- 关键词、标签、说明
- 文件上传
关于DOM
什么是DOM?
DOM全称是Document Object Model(文档对象模型),是为HTML和XML提供的API。那么为什么DOM可以同时提供给HTML和XML编程接口。虽然他们用来标记的标签不同,但是他们本质的结构是相同的。换句话说,按照DOM的标准,HTML和XML都是以标签为结点构造的树结构,DOM将HTML和XML的相同的结构本质抽象出来,然后通过脚本语言,如Javascript,按照DOM里的模型标准访问和操作文档内容。
在Chrome浏览器端,单击右键打开View Page Source展示文档结构。通过这种方式可以直观的看到文档当前的内容和结构。DOM则不同,它是提供一个API给编程语言,比如Javascript,通过一系列抽象的方法操作文档的内容,结构和样式。这有点想SQL和Excel,Excel可以直观的展示数据的结构,而SQL是一个负责操作数据的工具,帮助组织,更新,添加和删除数据内容。
DOM 和 HTML是一回事吗?
就像很多人把JQuery和Javascript的本质搞混一样,DOM和HTML也完全不是一回事,DOM是一个API,HTML(Hyper Text Markup Language)则是一种标记语言,HTML在DOM的模型标准中被视为对象,DOM只提供编程接口,却无法实际操作HTML里面的内容。
但是前端工程师,一般在浏览器端操作HTML。每个Web浏览器都会使用DOM,所以页面可以被脚本语言访问。而所有的浏览器都是以Javascript作为默认的脚本语言。所以HTML在浏览器端基本上可以直接通过DOM模型来操作,通过<srcipt>
标签载入或者直接插入Javascript脚本,通过DOM直接操作浏览器端的HTML文件。正是这种无缝融合,导致DOM和HTML的概念很容易混淆。
DOM 和 JavaScript什么关系?
Javascript可以通过DOM直接访问和操作网页文档的内容,一开始,DOM是为方便Javascript操作设计的API。但其实发展到后来,他们是两个独立的个体。而且Javascript不是唯一可以使用DOM的编程语言,比如python也可以访问DOM。所以DOM不是提供给Javascript的API,也不是Javascript里的API。但JavaScript可以通过DOM访问和操作HTML和XML文档内容。
Kinds Of Xss
0x01 Reflected XSS Attacks
介绍
反射型XSS,攻击具有一次性,只在用户单击时出发,因为payload在触发时,是客户端渲染了服务器的响应体,payload经过了服务器,是与服务器产生了交互了的。
常见注入点
网站的搜索框、用户登录入口、输入表单的地方,常用来切去客户端cookies火钓鱼欺骗
0x02 Dom Based XSS Attacts
介绍
DOM(Document Object Model),使用dom能够使程序和脚本动态访问和更新文档的内容、结构和样式。
DOM型XSS是一种特殊的反射型XSS。
特殊在于:DOM型XSS是基于js上的,不需要与服务器交互。
注入点
通过js脚本对文档对象进行编辑,从而修改页面的元素。
也就是说,客户端的脚本程序可以DOM动态修改页面的内容,从客户端获取DOM中的数据并在本地执行。
由于DOM是在客户端修改节点的,所以基于DOM型的XSS漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。
攻击方式
用户请求一个经过专门设计的URL,它由攻击者提供,而且其中包含XSS代码。服务器的响应不会以任何形式包含攻击者的脚本,当用户的浏览器处理这个响应时,DOM对象就会处理XSS代码,导致存在XSS漏洞。
0x03 Stored XSS Atacks
介绍
存储型XSS,最具有威胁性,甚至可能影响到web服务器自身的安全。攻击脚本将被永久的存放在目标服务器的数据库或文件中。
常见注入点
论坛、博客、留言板、评论、日志等需要存到服务器的地方。
攻击方式
攻击者在发帖或留言的过程中,将恶意脚本连同正常信息一起注入到发布内容中。随着发布内容被服务器存储下来,恶意脚本也将永久的存放到服务器的后端存储器中。当其他用户浏览这个被注入了恶意脚本的帖子时,恶意脚本就会在用户的浏览器中得到执行。
0x04 MXSS Atacks
介绍
突变型XSS(Mutation-Based Cross-Site-Scripting)
Mutation 突变
不论是服务器端或客户端的XSS过滤器,都认定过滤后的HTML源代码应该与浏览器所渲染后的HTML代码保持一致,至少不会出现很大的出入。然而,如果用户所提供的富文本内容通过JavaScript代码进属性后,一些意外的变化会使这个认定变得不再成立。
一串看似没有任何危害的HTML代码,将逃过XSS过滤器的检测,最终进入某个DOM节点中,浏览器的渲染引擎会将本来没有任何危害的HTMl代码渲染成具有危险的XSS攻击代码。随后,该段攻击代码,可能会被JS代码中的其它一些流程输出到DOM中或是以其他方式再次被渲染,从而导致XSS的执行。
一句话概括
用于绕过渲染器和waf以及其他检测而构造的XSS-Payload 叫做 突变型XSS
常见的MXSS注入
Input:
1 |
<img src="test.jpg" alt ="``onload=xss()" /> |
Output:
1 |
<IMG alt =``onload=xss() src ="test.jpg"> |
一些浏览器不支持HTML5的标记,例如IE8,会将article,aside,menu等当作是未知的HTML标签。可以通过设置这些标签的xmlns 属性,让浏览器知道这些未知的标签是的XML命名空间是什么。但解释后却产生了突变:
Input:
1 |
<pkav xmlns="><iframe onload=alert(1)">123</pkav> |
Output:
1 |
<?XML:NAMESPACE PREFIX = [default] ><iframe onload=alert(1) NS = "><iframe onload=alert(1)" /><pkav xmlns="><iframe onload=alert(1)">123</pkav> |
css中允许使用\来进行转义,但在在一起的时候,悲剧就产生了。
Input:
1 |
<p style="font-family:'ar\27 \3bx\3a expression\28xss\28\29\29\3bial';"></p> |
Output:
1 |
<P style="FONT-FAMILY: 'ar';x:xss());ial'"></P> |
\22转义后产生的悲剧。
Input
1 |
<img src=1 style="font-fam\22onerror\3d alert\28 1\29\20 ily:'aaa';"> |
Output
1 |
<IMG style="font-fam"alert(1) ily: ''" src="1"> |
Listing标签里面的东东会发生些奇葩事情:
Input
1 |
<listing><img src=1 onerror=alert(1) &</listing> |
Output
1 |
<LISTING><img src=1 onerror=alert(1) ></LISTING> |
0x05 UXSS
介绍
UXSS(Universal Cross-Site Scripting )通用型XSS
UXSS保留了基本XSS的特点,利用漏洞,执行恶意代码,但是有个重要的区别:
不同于常见的XSS,UXSS是一种利用浏览器或者浏览器扩展来制造产生XSS的条件并执行代码的一种攻击类型。
所以挖到这种洞,都能拿CVE了。
详情
Payload
以img、a、input、form、编码、iframe举例
1 |
<img src=javascript:alert("xss")> |
1 |
<a href="https://www.baidu.com">baidu</a> |
1 |
<input name="name" value=""> |
1 |
<form action=javascript:alert('xss') method="get"> |
1 |
<!--原code--> |
1 |
<iframe src=javascript:alert('xss');height=5width=1000 /><iframe> |
1 |
<svg onload=alert(1)> |
关于加密
0x01 五类HTMl元素
-
空元素(Void elements),如
1
<area> <br> <base> 等
-
原始文本元素(Raw text elements),有
-
<script> <style>
1
2
3
4
5
- RCDATA元素(RCDATA elements),有<textarea> <title>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
- 外部元素(Foreign elements),例如 MathML 命名空间或者 SVG 命名空间的元素
- 基本元素(Normal elements),即除了以上4种元素以外的元素
### 五类元素的区别
1. 空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签之间)。
2. 原始文本元素,可以容纳文本。
3. RCDATA元素,可以容纳文本和字符引用。
4. 外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释。
5. 基本元素,可以容纳文本、字符引用、其他元素和注释。
## 0x02 URL Ecode
一个百分号和该字符的ASCII编码所对应的2位16进制数字,例如 / 的URL编码为 %2F(大小写均可以)
## 0x03 Character Entity(字符实体)
在呈现HTML页面时,针对某些特殊字符如`<`或`>`直接使用,浏览器会误以为它们的标签的开始或结束,若想正确的在HTML页面呈现特殊字符就需要用到其对应的字符实体。
字符实体时一个预先定义好的转义序列,它定义了一些无法在文本内容中输出的字符或符号。
### 可容纳字符实体的三种特殊情况:
- 数据状态中的字符引用
- RCDATA状态中的字符引用
- 属性值状态中的字符引用
在这些状态中HTML字符实体将会从“&#...”形势解码,对应的解码字符会被放入数据缓冲区中。
### 字符实体和字符编号
#### 字符实体
字符实体以`&`开头+与定义的实体名称,以分号结尾,如`<`的编码为`<`
实体名称(Entity)是区分大小写的
#### 实体编号
以`&`开头+`#`符号以及字符的十进制数字,如<的实体编号为`<`
字符都是有实体编号的但有些字符没有实体名称。

#### **备注**
同一个符号,可以用“实体名称”和“实体编号”两种方式引用,“实体名称”的优势在于便于记忆,但不能保证所有的浏览器都能顺利识别它,而“实体编号”则没有这种担忧,但它实在不方便记忆。
## 0x04 Javascript Encode
1. 三个八进制数字,如果不够个数,前面补0,例如“e”编码为“\145”
2. 两个十六进制数字,如果不够个数,前面补0,例如“e”编码为“\x65”
3. 四个十六进制数字,如果不够个数,前面补0,例如“e”编码为“\u0065”
4. 对于一些控制字符,使用特殊的C类型的转义风格(例如\n和\r)
5. jsfuck编码
## 0x05 Javascript 内置的编码函数
\####String.fromCharCodeString.fromCharCode(97,108,101,114,116)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
这里是`alert`的编码
# Render(渲染)
这部分强烈推荐仔细阅读[Deep dive into browser parsing and XSS payload encoding](https://www.attacker-domain.com/2013/04/deep-dive-into-browser-parsing-and-xss.html),文章讲的很详细了,我这里浓缩一下。
## 原理
1、浏览器在解析HTML文档时无论按照什么顺序,主要有三个过程:HTML解析、JS解析和URL解析,每个解析器负责HTML文档中各自对应部分的解析工作。
2、首先浏览器接收到一个HTML文档时,会触发HTML文档进行词法解析,这一过程完成HTML解码并创建DOM树,接下来javaScript解析起会介入对内敛脚本进行解析,这一过程完成JS的解码工作,如果浏览器遇到需要URL的上下文环境,这时URL解析起也会介入完成URL的解码工作,URL解析起的解码顺序会根据URL所在的位置不同,可能在Javascript解析器之前或者之后解析。
## 浏览器的解析规则(顺序):
1. 浏览器收到HTML内容后,从头开始HTML解析。
2. 使用JS解析起解析。
3. 使用URL解析器解析。
4. 使用CSS解析器解析。
## 三种状态
### 数据状态中的字符引用<div><img src=x onerror=alert(4)></div>
1
2
3
4
5
6
7
8
9
10
11
例如,在这个例子中,`<`和`>`字符被编码为`<`和`>`。
当解析器解析完`<div>`并处于“数据状态”时,这两个字符将会被解析。当解析器遇到`&`字符,它会知道这是”数据状态的字符引用”,因此会消耗一个字符引用(例如`<`)并释放出对应字符的 token 。在这个例子中,对应字符指的是`<`和`>`。
你可能会想:这是不是意味着`<`和`>`的token将会被理解为标签的开始和结束,然后其中的脚本会被执行?答案是脚本并不会被执行。原因是解析器在解析这个字符引用后不会转换到”标签开始状态”。正因为如此,就不会建立新标签。因此,我们能够利用字符实体编码这个行为来转义用户输入的数据从而确保用户输入的数据只能被解析成”数据”。
### RCDATA状态中的字符引用<textarea><script>alert(5)</script></textarea>
1
2
3
4
5
6
7
8
9
10
11
这意味着在``和``标签中的字符引用会被 HTML 解析器解码。这里要再提醒一次,在解析这些字符引用的过程中不会进入“标签开始状态”。这样就可以解释这段代码了。
另外,对 RCDATA 有个特殊的情况。在浏览器解析 RCDATA 元素的过程中,解析器会进入”RCDATA状态”。在这个状态中,如果遇到`<`字符,它会转换到”RCDATA小于号状态”。如果`<`字符后没有紧跟着`/`和对应的标签名,解析器会转换回”RCDATA状态”。这意味着在 RCDATA 元素标签的内容中(例如``或``的内容中),唯一能够被解析器认做是标签的就是``或者``。当然,这要看开始标签是哪一个。因此,在``和``的内容中不会创建标签,就不会有脚本能够执行。这也就解释了为什么问题中的脚本不会被执行。
我们来迅速看一下 CDATA 元素。任何在 CDATA 元素中的内容将不会触发解析器创建开始标签。闭合 CDATA 元素的标志是`]]>`序列。因此如果用户想逃出 CDATA 元素,就要用未经任何编码的`]]>`序列,不然是不会逃出 CDATA 元素的。
### 属性值状态中的字符引用<a
href="javascript:%61
%6c%65%72%74%28%32%29">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
在这个情况中字符引用会被解码。在这里,HTML 解析器解析了文档,创建了标签 token,并且对 href 属性里的字符实体进行了解码。然后,当 HTML 解析器工作完成后,URL 解析器开始解析 href 属性值里的链接。在这时, javascript 协议已经被解码,它能够被 URL 解析器正确识别。然后 URL 解析器继续解析链接剩下的部分。由于是 javascript 协议,JavaScript 解析器开始工作并执行这段代码,这就是为什么问题中的代码能够被执行。
### JavaScript解析
JavaScript解析过程与HTML解析过程有点不一样。
script 块有个有趣的属性:在块中的字符引用并不会被解析和解码。如果你去看“脚本数据状态”的状态转换规则,就会发现没有任何规则能转移到字符引用状态。所以如果攻击者尝试着将输入数据编码成字符实体并将其放在script 块中,它将不会被执行。
像`\uXXXX`(例如`\u0000`,`\u000A`)这样的字符,JavaScript 会视情况而定解析这些字符来执行。具体的说就是要看被编码的序列到底是哪部分。首先,像`\uXXXX`一样的字符被称作 <u>*Unicode 转义序列*</u>。从上下文来看,你可以将转义序列放在3个部分:字符串中,标识符名称中和控制字符中。
#### 1、字符串中
当 Unicode 转义序列存在于字符串中时,它只会被解释为正规字符,而不是单引号,双引号或者换行符这些能够打破字符串上下文的字符。这项内容清楚地写在 ECMAScript 中。因此,*<u>Unicode 转义序列将永远不会破环字符串上下文,因为它们只能被解释成字符串常量。</u>*
#### 2、标识符名称中
当 Unicode 转义序列出现在标识符名称中时,它会被解码并解释为标识符名称的一部分,例如函数名,属性名等等。如果我们深入研究 JavaScript 细则,可以看到如下内容:
> Unicode转义序列(如\u000A\u000B)同样被允许用在标识符名称中,被当作名称中的一个字符。而将’\’符号前置在Unicode转义序列串(如\u000A000B000C)并不能作为标识符名称中的字符。将Unicode转义序列串放在标识符名称中是非法的。
#### 3、控制字符
当用 Unicode 转义序列来表示一个控制字符时,例如单引号、双引号、圆括号等等,它们将不会被解释成控制字符,而仅仅被解码并解析为标识符名称或者字符串常量。如果你去看 ECMAScript 的语法,就会发现没有一处会用Unicode 转义序列来当作控制字符。例如,如果解析器正在解析一个函数调用语句,圆括号部分必须为`(`和`)`,而不能是`\u0028`和`\u0029`。
总的来说,Unicode 转义序列只有在标识符名称里不被当作字符串,也只有在标识符名称里的编码字符能够被正常的解析。
### Example
#### Example 1<a href="javascript:%61%6c%65%72%74%28%32%29">test</a>
1
2
3
这段代码可以被执行,首先经过 HTML 解析器,把 HTML 实体部分解析了,变成<a href="javascript:%61%6c%65%72%74%28%32%29">test</a>
1
2
3
此时,由于 javascript 已经生成,不违反 URL 解析规则。所以,URL 解析正常。解析了 javascript ,最终进入 JS解析器。注意,URL 解析器还完成了 URL 解码工作。<a href="javascript:alert(2)">test</a>
1
2
3
4
5
所以可以成功执行代码弹窗。
#### Example 2<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29"></a>
1
2
3
4
5
其中 URL 编码的是`javascript:alert(1)`,其实这段代码放到 html 当中并不会执行,URL解码之后 Javascript 解析器完成解码操作,讲道理脚本应该会正常执行啊,这里就有一个 URL 解析过程中的一个细节了,**不能对协议类型进行任何的编码操作**,否则 URL 解析器会认为它无类型,就导致这里被编码的`javascript`没有解码,当然不会被 URL 解析器识别了。
#### Example 3<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(3)">test3</a>
1
2
3
4
5
以上为对`[test3](javascript:alert(3))`先做 JS 编码,然后做URL编码,再做HTML编码共3层。
所以这里符合编码其实在首先经过 HTML 解析器解析之后变成<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(3)">test3</a>
1
2
3
再经过 URL 解析器解析到了`javascript`,并解析后面的 url 编码变成<a href="javascript:\u0061\u006c\u0065\u0072\u0074(3)">test3</a>
1
2
3
4
5
URL 解析器传给 JS 解析器解析 javascript 代码,正常解析得到弹窗
#### Example 4<a onclick="window.open('value1')" href="javascript:window.open('value2')"></a>
1
2
3
4
5
6
7
`value1`处,先经过 HTML 解码,然后经过 javascript 解码,最后经过 url 解码
`value2`处则是先经过 HTML 解码,然后经过 url 解码,接着 javascript 解码,最后经过 url 解码
#### Example 5<img src="http://www.example.com">
<img src="http://www.example.com">
这里都不会加载图片,因为参考我们上面讲的三种状态,这里实体编码存在的地方并不属于任何一种状态,所以并不会被解码。
Examples
1、<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29"></a>
URL encoded “javascript:alert(1)”
Answer: The javascript will NOT execute.
Explanation: URL 解析器解析之后不会再掉用 js 解析器解析,所以不会使用 js 伪协议
2、<a href="javascript:%61 %6c%65%72%74%28%32%29">
Character entity encoded “javascript” and URL encoded “alert(2)”
Answer: The javascript will execute.
Explanation: 首先用 HTML 解析器解析实体字符,再用 URL 解析器解析,并调用 js 解析器进行 js 伪协议解析
3、<a href="javascript%3aalert(3)"></a>
URL encoded “:”
Answer: The javascript will NOT execute.
Explanation: URL 解析器解析之后并不会识别 js 伪协议
4、<div><img src=x onerror=alert(4)></div>
Character entity encoded < and >
Answer: The javascript will NOT execute.
Explanation: 参照 #数据状态中的字符引用
5、<textarea><script>alert(5)</script></textarea>
Character entity encoded < and >
Answer: The javascript will NOT execute AND the character entities will NOT
be decoded either
Explanation: 参照 #RCDATA 状态中的字符引用
6、<textarea><script>alert(6)</script></textarea>
Answer: The javascript will NOT execute.
Explanation: 参照 #RCDATA 状态中的字符引用
7、<button onclick="confirm('7');">Button</button>
Character entity encoded ‘
Answer: The javascript will execute.
Explanation: 属于属性值状态中的字符引用,会在 HTML 解析器中首先被解析成'
,闭合了单引号,得到执行
8、<button onclick="confirm('8\u0027);">Button</button>
Unicode escape sequence encoded ‘
Answer: The javascript will NOT execute.
Explanation: 存在字符串中,不会被解析成'
9、<script>alert(9);</script>
Character entity encoded alert(9);
Answer: The javascript will NOT execute.
Explanation: 由 js 解析器解析,并不会交由 HTML 解析器解析,所以不识别,不执行
10、<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
Unicode Escape sequence encoded alert
Answer: The javascript will execute.
Explanation: 由 js 解析器解析,属于 js 的编码,可以直接执行
11、<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
Unicode Escape sequence encoded alert(11)
Answer: The javascript will NOT execute.
Explanation: 由 js 解析器解析,属于 js 的编码,但是编码了(、),而这两个属于控制字符,不会被正常解析
12、<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
Unicode Escape sequence encoded alert and 12
Answer: The javascript will NOT execute.
Explanation: 要么是因为\u0031\u0032
不会被解释为字符串常量(因为它们没有用引号闭合)要么是因为它们是 ASCII 型数字。
13、<script>alert('13\u0027)</script>
Unicode escape sequence encoded ‘
Answer: The javascript will NOT execute.
Explanation: 在字符串中,被解析成字符串
14、<script>alert('14\u000a')</script>
Unicode escape sequence encoded line feed.
Answer: The javascript will execute.
Explanation: \u000a
会被解释成换行符文本,这并不会导致真正的换行从而引发 JavaScript 语法错误。
15、<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(15)"></a>
Answer: The javascript will execute.
Explanation: 参照 Example 3
转载自:https://blog.zeddyu.info/2019/03/13/Web%E5%AE%89%E5%85%A8%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B-XSS-I/
FROM :b0urne.top | Author:b0urne
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论