# 十、跨站脚本攻击
> 作者:Peter Yaworski
> 译者:[飞龙](https://github.com/)
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
## 描述
跨站脚本,或者 XSS,涉及到站定包含非预期的 JavaScript 脚本代码,它随后传给用于,用户在浏览器中执行了该代码。它的一个无害示例为:
```js
alert('XSS');
```
这会调用 JavaScript 函数`alert`,并创建一个简单的弹出窗口,带有文本`XSS`。现在,在这本书的前一个版本中,我推荐你在报告中使用这个例子。但是,一个非常成功的黑客告诉我这是个糟糕的例子,因为漏洞的接收者通常没有意识到这个问题的严重性,并且可能由于无害的示例而得到较低的奖金。
所以,考虑到这种情况,使用示例开判断 XSS 是否存在,但是报告时,考虑漏洞如何影响站点,并解释它。通过这样,我并不是告诉厂商什么事 XSS,而是解释你可以使用它做什么事,来影响他们的站点。
这应该包含识别你报告了何种 XSS,它们包括:
+ 反射型 XSS:这些攻击并不是持久的,意思是 XSS 传递后通过简单的请求和响应执行。
+ 存储型 XSS:这些攻击是持久的,或已保存,之后在页面加载时执行给无意识的用户。
+ Self XSS:这些攻击也不是持久的,通常作为戏弄用户的一部分,使它们自己执行 XSS。
当你搜索漏洞时,你会经常发现,厂商不关心 Self XSS,它们只关心,它们的用户是否自身存在缺陷,就像反射和存储 XSS 的例子那样。但是,这并不是说,你应该完全忽略 Self XSS。
如果你发现了一个场景,其中 Self XSS 可以执行,但是不会存储,你需要考虑该漏洞是否可以利用,是否有些东西可以结合起来,使其不再是 Self XSS?
最著名的 XSS 利用示例之一,就是 Samy Kamkar 执行的 MySpace Samy 蠕虫。在 2005 年 10 月,Samy 利用了一个 MySpace 上的存储型 XSS 漏洞,允许它上传 JavaScript 脚本。这个代码随后在任何人浏览它的 MySpace 主页时执行,因此使任何 Samy 用户资料的浏览者成为其好友。但是,更多的是,这个代码也复制其自身到 Samy 新朋友的页面,所以受感染页面的浏览者使用下面这段话更新了它们的资料页面:“but most of all, samy is my hero”(最重要的是,Samy 是我的英雄)。
虽然 Samy 的利用并不完全是恶意的,XSS 利用使其能够盗取用户、密码、银行信息以及其他。虽然具有潜在的影响,修复 XSS 漏洞通常很简单,只需要软件开发者在渲染时转义用户输入(就像 HTML 注入那样)。在攻击者提交它们的时候,一些站点也会截断可能的恶意字符。
> 链接
> 查看 [OWASP XSS 过滤器绕过速查表](https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet)。
## 示例
### 1\. Shopify Wholesale
难度:低
URL:` wholesale.shopify.com `
报告链接:`https://hackerone.com/reports/106293`
报告日期:2015.12.21
奖金:$500
描述:
Shopify Wholesale 站点是一个简单的页面,拥有不同的操作调用 -- 输入商品名称并且点击“搜索商品”,这里是截图:
![](https://img.kancloud.cn/8d/d0/8dd0f2c54d8a194d54f0cf3205b02e54_736x709.jpg)
Shopify Wholesale 站点截图
这里的 XSS 漏洞是你可以找到的最基本的漏洞 - 输入到搜索框中的文本并没有转移,所以任何输入的 JavaScript 都会执行。这里是漏洞披露中的提交文本:`test’;alert(‘XSS’);’ `。
它生效的原因是,Shopify 接收用户输入,执行搜索查询,当没有结果返回时,Shopify 会打印一条消息,说该名称下没有找到任何商品,之后重新打印出用户输入,而没有任何转义。因此,提交的 JavaScript 打印到了页面上,浏览器将其解释为 JavaScript 并执行。
> 重要结论
> 测试任何东西,特别要关注一些场景,其中你所输入的文本渲染给了你。测试来判断你是否可以包含 HTML 或者 JavaScript,来观察站点如何处理它。同时尝试编码输入,就像在 HTML 注入一章中描述的那样。
> XSS 漏洞并不需要很复杂。这个漏洞是你能找到的最基本的东西 - 一个简单的输入文本字段,这个漏洞并不处理用户输入。它在 2015 年 12 月 21 日发现,并获得了 $500 的奖金。它所需要的所有东西,就是黑客的思维。
### 2\. Shopify 礼品卡购物车
难度:低
URL:` hardware.shopify.com/cart `
报告链接:`https://hackerone.com/reports/95089`
报告日期:2015.10.21
奖金:$500
描述:
Shopify 礼品卡站点允许用户使用 HTML 表单设计它们自己的礼品卡,具体来说,这包括一个上传输入框,一些文本框,以及其他。这里是一个截图:
![](https://img.kancloud.cn/30/da/30daf9cb084c57b7953c83b686e3ce71_502x702.jpg)
Shopify 礼品卡表单截图
这里的 XSS 漏洞在 JavaScript 输入到了表单图像名称字段时出现。在使用 HTML 代理完成之后,会出现一个不错的简单任务。所以这里,原始的表单提交会包含:
```
Content-Disposition: form-data; name="properties[Artwork file]"
```
这会被解释和修改为:
```
Content-Disposition: form-data; name="properties[Artwork file<img src='test' onm\ ouseover='alert(2)'>]";
```
> 重要结论
> 这里有两个东西要注意,这会在寻找 XSS 漏洞时帮助你:
> 1. 这里的漏洞实际上并不在文件输入字段本身 -- 它在字段的名称属性中。所以当你寻找 XSS 漏洞的机会时,要记住玩转所有可用的输入值。
> 2. 这里的值在通过代理操作之后提交。在一些场景中这是关键,其中在任何值实际提交给服务器之前,客户端(你的浏览器)可能存在 JavaScript 来验证值。
> **实际上,任何时候你看到验证实时发生在你的浏览器中,这都是一个信号,你需要测试这个字段!**开发者可能犯下这个错误,一旦这些值提交给了服务器,它们不验证提交的值是否存在恶意代码,因为它们认为浏览器的 JavaScript 代码已经在输入接收之前验证过了。
### 3\. Shopify 货币格式
难度:低
URL:`SITE.myshopify.com/admin/settings/generalt `
报告链接:`https://hackerone.com/reports/104359`
报告日期:2015.12.9
奖金:$1000
描述:
Shopify 的商店设置包含修改货币格式的功能。在 12 月 9 日,有报告称,这些输入框的值在建立社交媒体页面时,没有合理处理。
换句话说,恶意用户可以建立一个商店,并将货币设置修改为下面这个:
![](https://img.kancloud.cn/da/7a/da7a48293547691a4989e20d498a24b2_1614x871.jpg)
Shopify 货币格式截图
之后,用户就可以开启社交媒体售卖频道。报告中的例子是 Fackbook 和 Twitter,以及当用户点击这个售卖频道的选项卡之后,JavaScript 会执行,产生 XSS 漏洞。
> 重要结论
> XSS 漏洞在 JavaScript 文本不安全渲染时产生。文本可能用于站点的多个位置,所以每个位置都应该测试。这里,Shopify 并没有在商店和收款页面包含 XSS,因为用户允许在它们的商店中使用 JavaScript。在考虑字段是否用于外部社交媒体站点之前,很容易把这个漏洞补上。
### 4\. 雅虎邮件存储型 XSS
难度:低
URL:Yahoo Mail
报告链接:`https://klikki.fi/adv/yahoo.html`
报告日期:2015.12.26
奖金:$10000
描述:
雅虎邮件编辑器允许人们将图片通过 HTML IMG 标签嵌入到邮件中。这个漏洞在 HTML IMG 标签格式错误或者无效时出现。
多数 HTML 标签接受属性,它是有关 HTML 标签的额外信息。例如,IMG 标签接受`src`属性,指向要渲染的图像的地址。此外一些属性是布尔属性,意思是如果他们存在,他们在 HTML 表现为真值,而当他们被忽略时,他们表现为假值。
对于这个漏洞,Jouko Pynnonen 发现,如果它将布尔属性添加到 HTML 标签中,并带有一个值,雅虎邮件就会移除该值但保留等号。这里是来自`Klikki.fi`的一个例子:
```html
<INPUT TYPE="checkbox" CHECKED="hello" NAME="check box">
```
这里,输入标签可能包含`checked`属性,表示复选框是否渲染为选中。根据上面描述的歇息,这会变成:
```html
<INPUT TYPE="checkbox" CHECKED= NAME="check box">
```
要注意 HTML 从拥有`checked`值变成了没有值但是仍然包含等号。
这看起来是无害的,但是根据 HTML 规范,浏览器将这个`CHECKED`看做拥有值`NAME=”check`,并且该`input`标签有用第三个属性`box`,它没有值。这是对于没有引号的属性值,因为 HTML 允许零个或多个空格字符在等号周围。
为了利用它,Jouko 提交了下面的 IMG 标签:
```html
<img ismap='xxx' itemtype='yyy style=width:100%;height:100%;position:fixed;left:0px;top:0px; onmouseover=alert(/XSS/)//'>
```
雅虎邮件会把它变成:
```html
<img ismap=itemtype=yyy style=width:100%;height:100%;position:fixed;left:0px;top:0px; onmouseover=alert(/XSS/)//>
```
因此,浏览器会渲染 IMG 标签,它占据整个浏览器的窗口,当鼠标移到图片上的时候,会执行 JavaScript。
> 重要结论
> 传递格式错误或损坏的 HTML 是个不错的方法,来测试站点如何解析输入。作为一个黑客,考虑到开发者没有考虑的东西十分重要。例如,使用常规的图片标签,如果你传递两个`src`属性会怎么样?它会如何渲染?
### 5\. Google 图片搜索
难度:中
URL:` images.google.com `
报告链接:`http://zombiehelp54.blogspot.ca/2015/09/how-i-found-xss-vulnerability-in-google.html`
报告日期:2015.9.12
奖金:未知
描述:
2015 年 9 月,Mahmoud Jamal 使用 Google 图像来为它的 HackerOne 资料寻找一个图片。在浏览的时候,它注意到 Google 图片的 URL 中有一些有趣的东西。
```
http://www.google.com/imgres?imgurl=https://lh3.googleuser.com/...
```
注意到实际的 URL 中存在 `imgurl`的引用。在鼠标移到缩略图上的时候,Mahoumd 注意到了锚标签的`href`属性包含了相同的 URL。因此,它尝试将参数改为` javascript:alert(1)`,并且注意到锚标签的`href`也改为了相同值。
它这个时候非常激动,点击了链接,但是没有执行 JavaScript,因为 Google URL 改为了别的东西。结果,Google 的代码在鼠标按下时,通过`onmousedown` JavaScript 回调修改了 URL。
考虑到这个,Mahmoud 决定使用它的键盘,尝试使用 TAB 键在页面上切换。当他来到`View Image`按钮时,触发了 JavaScript,产生了 XSS 漏洞。这里是图片:
![](https://img.kancloud.cn/7e/87/7e8787a3178284f941a48f8c5b8f14e8_1107x591.jpg)
Google XSS 漏洞
> 重要结论
> 始终留意这种漏洞。很轻易就能假设,仅仅由于公司太大或者太知名,任何东西都被找到了。但是,公司始终会修改代码。
> 此外,有大量方法来执行 JavaScript,这里在看到 Google 使用`onmousedown`事件处理器修改值之后,很容易就放弃了。这意味着任何时候使用鼠标点击了链接,值都会改变。
### 6\. Google Tagmanager 存储型 XSS
难度:中
URL:`tagmanager.google.com`
报告链接:`https://blog.it-securityguard.com/bugbounty-the-5000-google-xss`
报告日期:2014.10.31
奖金:$5000
描述:
2014 年 10 月,Patrik Fehrehbach 在 Google 上发现了存储型 XSS 漏洞。这个报告的有趣部分是,他如何设法绕过 Google 获取载荷。
Google Tagmanager 是一个 SEO 工具,使营销人员添加和更新站点标签变得容易 -- 包含转化追踪、站点分析、重营销、以及更多。为此,它拥有大量的表单,便于用户交互。所以,Patrik 以尝试将 XSS 载荷输入到表单字段中开始,类似于`#>imgsrc=/ onerror=alert(3)>`。如果接受了,这就会闭合现有的 HTML `>`,之后尝试加载不存在的图片,这会执行`onerror` JavaScript,`alert(3)`。
但是,这没有效果。Google 合理处理了输入。Patrik 注意到了一个替代方案 -- Google 提供了上传带有多个标签的 JSON 文件的功能。所以,它下载了样例并上传:
```json
"data": {
"name": "#"><img src=/ onerror=alert(3)>",
"type": "AUTO_EVENT_VAR",
"autoEventVarMacro": {
"varType": "HISTORY_NEW_URL_FRAGMENT"
}
}
```
这里,你会注意到,标签的名称就是他的 XSS 载荷。结果,Google 没有处理来自上传文件的输入,并执行了载荷。
> 重要结论
> 这里有两个有趣的事情。首先Patrik 发现了替代方案来提供输入 -- 要留意这个东西,并测试目标提供的所有方法来输入数据。其次,Google 处理了输入,但是在渲染时没有转义。假设它转义了 Patrik 的输入,载荷就不会生效,因为 HTML 会被转换成无害的字符。
## 总结
XSS 漏洞对站点开发者展现了真实的风险,并且仍然在站点上流行,通常显而易见。通常简单提交 JavaScript `alert`方法的调用,`alert('test')`,你可以检查输入字段是否存在漏洞。此外,你可以将它与 HTML 注入组合,并提交 ASCII 编码的字符来观察文本是否被渲染和解释。
在搜索 XSS 漏洞时,这里是要记住的一些事情:
1. 测试任何东西
无论你在浏览什么站点以及什么时候浏览,总是要保持挖掘!不要觉得站点太大或者太复杂,而没有漏洞。机会正在注视着你并请求你的测试,就像`wholesale.shopify.com`那样。Google Tagmanager 存储型 XSS 漏洞就是寻找替代方案来向站点添加标签的结果。
2. 漏洞可能存在于任何表单值
例如,Shopify 的礼品卡站点上的漏洞,通过利用和上传文件相关的名称字段来时间,并不是实际的文件字段本身。
3. 总是在测试时使用 HTML 代理
当你尝试提交来自网站自身的恶意值时,当站点的 JavaScript 检查出你的非法值时,你可能会碰到假阳性。不要浪费你的时间。通过浏览器提供合法值,之后使用你的代理修改这些值来执行 JavaScript 并且提交。
> 译者注:对于所有前端(包括移动和桌面)渗透,都应该这样。就算不存在 XSS,也有可能挖到绕过和越权漏洞。
4. XSS 漏洞发生在渲染的时候
由于 XSS 在浏览器渲染文本时发生,要确保复查了站点的所有地方,其中使用了你的输入值。逆天家的 JavaScript 可能不会立即渲染,但是会出现在后续的页面中。这非常麻烦,但是你要留意站点何时过滤输入,以及转义输出。如果是前者,寻找办法来绕过输入过滤器,因为开发者可能会犯懒,并且不会转义渲染的输入。
5. 测试非预期的值
不要总是提供预期类型的值。当 HTML 雅虎邮件的漏洞被发现时,提供了非预期的 HTML IMG 属性。要跳出思维定式,思考开发者要寻找什么,并且之后尝试提供一些不匹配这些预期的东西。这包含寻找新的方式来执行潜在的 JavaScript,例如绕过 Google 图片的`onmousemove`事件。