# 乌云归档：Web前端攻防

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2014-07-31T02:42:00Z
Canonical: https://wepostx.com/topics/537

> 乌云历史资料归档
>
> **原始作者：** EtherDream
> **原始编号：** superkieran-wooyundrops:313
> **原始发布时间：** 2014-07-31 10:42
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

## 0x00 禁止一切外链资源

外链会产生站外请求，因此可以被利用实施 CSRF 攻击。
目前国内有大量路由器存在 CSRF 漏洞，其中相当部分用户使用默认的管理账号。通过外链图片，即可发起对路由器 DNS 配置的修改，这将成为国内互联网最大的安全隐患。
案例演示
百度旅游在富文本过滤时，未考虑标签的 style 属性，导致允许用户自定义的 CSS。因此可以插入站外资源：

![原文图片](/media/2016/06/834c8c2e15921d23fe3045250b5cf23e)

所有浏览该页面的用户，都能发起任意 URL 的请求：

![原文图片](/media/2016/06/4257e2f40641df87eaf0f6eb42813e57)

由于站外服务器完全不受控制，攻击者可以控制返回内容： 如果检测到是管理员，或者外链检查服务器，可以返回正常图片； 如果是普通用户，可以返回 302 重定向到其他 URL，发起 CSRF 攻击。例如修改路由器 DNS：

```text
http://admin: [email protected] /userRpm/PPPoECfgAdvRpm.htm?wan=0&lcpMru=1480&ServiceName=&AcName=&EchoReq=0&manual=2&dnsserver=黑客服务器&dnsserver2=4.4.4.4&downBandwidth=0&upBandwidth=0&Save=%B1%A3+%B4%E6&Advanced=Advanced
```

![原文图片](/media/2016/06/70a8b675d7cd0edfbb38e8c4d6a7f526)

演示中，随机测试了几个帖子，在两天时间里收到图片请求 500 多次，已有近 10 个不同的 IP 开始向我们发起 DNS 查询。

![原文图片](/media/2016/06/5338f57e7a62b62f0e32fe9d3a95bdec)

通过中间人代理，用户的所有隐私都能被捕捉到。还有更严重的后果，查考[流量劫持危害探讨](http://fex.baidu.com/blog/2014/04/traffic-hijack-2/)
要是在热帖里『火前留名』，那么数量远不止这些。
如果使用发帖脚本批量回复，将有数以万计的用户网络被劫持。
防范措施
杜绝用户的一切外链资源。需要站外图片，可以抓回后保存在站内服务器里。 对于富文本内容，使用白名单策略，只允许特定的 CSS 属性。 尽可能开启 Content Security Policy 配置，让浏览器底层来实现站外资源的拦截。

## 0x01 富文本前端扫描

富文本是 XSS 的重灾区。
富文本的实质是一段 HTML 字符。由于历史原因，HTML 兼容众多不规范的用法，导致过滤起来较复杂。几乎所有使用富文本的产品，都曾出现过 XSS 注入。
案例演示
旅游发帖支持富文本，我们继续刚才的演示。

![原文图片](/media/2016/06/499862312c800e46dd9e752d1859f596)

由于之前已修复过几次，目前只能注入 embed 标签和 src 属性。 但即使这样，仍然可以嵌入一个框架页面：

![原文图片](/media/2016/06/74fff911328fa2d5e8ad0b6862c1e01f)

因为是非同源执行的 XSS，所以无法获取主页面的信息。但是可以修改 top.location，将页面跳转到第三方站点。
将原页面嵌入到全屏的 iframe 里，伪造出相同的界面。然后通过浮层登录框，进行钓鱼。

![原文图片](/media/2016/06/642b3f54dc090a20c7cb83a3bfd45c21)

总之，富文本中出现可执行的元素，页面安全性就大打折扣了。
防范措施
这里不考虑后端的过滤方法，讲解使用前端预防方案： 无论攻击者使用各种取巧的手段，绕过后端过滤，但这些 HTML 字符最终都要在前端构造成元素，并渲染出来。
因此可以在 DOM 构造之后、渲染之前，对离屏的元素进行风险扫描。将可执行的元素（script，iframe，frame，object，embed，applet）从缓存中移除。
或者给存在风险的元素，加上沙箱隔离属性。
例如 iframe 加上 sandbox 属性，即可只显示框架内容而不运行脚本 例如 Flash 加上 allowScriptAccess 及 allowNetworking，也能起到一定的隔离作用。
DOM 仅仅被构造是不会执行的，只有添加到主节点被渲染时才会执行。所以这个过程中间，可以实施安全扫描。
实现细节可以参考：[http://www.etherdream.com/FunnyScript/richtextsaferender.html](http://www.etherdream.com/FunnyScript/richtext%5C_safe%5C_render.html)
如果富文本是直接输入到静态页面里的，可以考虑使用 MutationEvent 进行防御。详细参考：[http://fex.baidu.com/blog/2014/06/xss-frontend-firewall-2/](http://fex.baidu.com/blog/2014/06/xss-frontend-firewall-2/)
但推荐使用动态方式进行渲染，可扩展性更强，并且性能消耗最小。

## 0x02 跳转 opener 钓鱼

浏览器提供了一个 opener 属性，供弹出的窗口访问来源页。但该规范设计的并不合理，导致通过超链接打开的页面，也能使用 opener。
因此，用户点了网站里的超链接，导致原页面被打开的第三方页面控制。
虽然两者受到同源策略的限制，第三方无法访问原页面内容，但可以跳转原页面。
由于用户的焦点在新打开的页面上，所以原页面被悄悄跳转，用户难以觉察到。当用户切回原页面时，其实已经在另一个钓鱼网站上了。
案例演示
百度贴吧目前使用的超链接，就是在新窗口中弹出，因此同样存在该缺陷。
攻击者发一个吸引用户的帖子。当用户进来时，引诱他们点击超链接。
通常故意放少部分的图片，或者是不会动的动画，先让用户预览一下。要是用户想看完整的，就得点下面的超链接：

![原文图片](/media/2016/06/72131561f7ebd10ade2a07de64553241)

由于扩展名是 gif 等图片格式，大多用户就毫无顾虑的点了。
事实上，真正的类型是由服务器返回的 MIME 决定的。所以这个站外资源完全有可能是一个网页：

![原文图片](/media/2016/06/5597c904e87e68a7210f752c3e7e5b6f)

当用户停留在新页面里看动画时，隐匿其中的脚本已悄悄跳转原页面了。
用户切回原页面时，其实已在一个钓鱼网站上：

![原文图片](/media/2016/06/2a47c24d95dc00562437bc7d33ebedce)

在此之上，加些浮层登录框等特效，很有可能钓到用户的一些账号信息。
防范措施
该缺陷是因为 opener 这个属性引起的，所以得屏蔽掉新页面的这个属性。
但通过超链接打开的网页，无法被脚本访问到。只有通过 window.open 弹出的窗口，才能获得其对象。
所以，对页面中的用户发布的超链接，监听其点击事件，阻止默认的弹窗行为，而是用 window.open 代替，并将返回窗体的 opener 设置为 null，即可避免第三方页面篡改了。
详细实现参考：[http://www.etherdream.com/FunnyScript/opener_protect.html](http://www.etherdream.com/FunnyScript/opener_protect.html)
当然，实现中无需上述 Demo 那样复杂。根据实际产品线，只要监听用户区域的超链接就可以。

## 0x03 用户内容权限

支持自定义装扮的场合，往往是钓鱼的高发区。
一些别有用心者，利用装扮来模仿系统界面，引诱用户上钩。
案例演示 - 空间越界
百度空间允许用户撰写自定格式的内容。
其本质是一个富文本编辑器，这里不演示 XSS 漏洞，而是利用样式装扮，伪装一个钓鱼界面。
百度空间富文本过滤元素、部分属性及 CSS 样式，但未对 class 属性启用白名单，因此可以将页面上所有的 CSS 类样式，应用到自己的内容上来。

![原文图片](/media/2016/06/1764abffa9db8c8dbb386a06835a9897)

防范措施
规定用户内容尺寸限制，可以在提交时由用户自己确定。
不应该为用户的内容分配无限的尺寸空间，以免恶意用户设置超大字体，破坏整个页面的浏览。
最好将用户自定义的内容嵌套在 iframe 里，以免影响到页面其他部位。
如果必须在同页面，应将用户内容所在的容器，设置超过部分不可见。以免因不可预测的 BUG，导致用户能将内容越界到产品界面上。
案例演示 - 功能越界
自定义装扮通常支持站外超链接。
相比贴吧这类简单纯文字，富文本可以将超链接设置在其他元素上，例如图片。
因此这类链接非常具有迷惑性，用户不经意间就点击到。很容易触发之前提到的修改 opener 钓鱼。

![原文图片](/media/2016/06/6ee9162ef92a995030928dd81e56c14e)

如果在图片内容上进行伪装，更容易让用户触发一些危险操作。

![原文图片](/media/2016/06/2ee41beab7c9c88f6530b84139da2af5)

要是和之前的区域越界配合使用，迷惑性则更强：

![原文图片](/media/2016/06/524c37853c5c67306b39d8828c5b8b8d)

![原文图片](/media/2016/06/dc7d913fa3cc1298e5816d4cae896898)

防范措施
和之前一样，对于用户提供的超链接，在点击时进行扫描。如果是站外地址，则通过后台跳转进入，以便后端对 URL 进行安全性扫描。
如果服务器检测到是一个恶意网站，或者目标资源是可执行文件，应给予用户强烈的警告，告知其风险。

## 0x04 点击劫持检测

点击劫持算是比较老的攻击方式了，基本原理大家也都听说过。就是在用户不知情的前提下，点击隐藏框架页面里的按钮，触发一些重要操作。
但目前在点击劫持上做防御的并不多，包括百度绝大多数产品线目前都未考虑。
案例演示
能直接通过点击完成的操作，比较有意义的就是关注某用户。例如百度贴吧加关注的按钮：

![原文图片](/media/2016/06/c891f90f170b5e4a53dd5c11f25653df)

攻击者事先算出目标按钮的尺寸和坐标，将页面嵌套在自己框架里，并设置框架的偏移，最终只显示按钮：

![原文图片](/media/2016/06/11ab37ea6415534bfcb4a6995a6f1d10)

接着通过 CSS 样式，将目标按钮放大，占据整个页面空间，并设置全透明。

![原文图片](/media/2016/06/5eb6b18d7239c070c94b768dd00d31dd)

这时虽看不到按钮，但点击页面任意位置，都能触发框架页中加关注按钮的点击：

![原文图片](/media/2016/06/6f3011054d960c7c2261bfafb68afdcd)

防范措施
事实上，点击劫持是很好防御的。
因为自身页面被嵌套在第三方页面里，只需判断 self == top 即可获知是否被嵌套。
对一些重要的操作，例如加关注、删帖等，应先验证是否被嵌套。如果处于第三方页面的框架里，应弹出确认框提醒用户。
确认框的坐标位置最好有一定的随机偏移，从而使攻击者构造的点击区域失效。

## Replies
