本节书摘来自华章计算机《web应用漏洞侦测与防御:揭秘鲜为人知的攻击手段和防御技术》一书中的第1章,第1.5节,作者:(美) 希马(shema, m.)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
当今的web应用程序开发人员找到了开创性的方法把传统的桌面软件转到浏览器中。这使得浏览器负担更重,需要管理对象(占用更多内存)、显示图像(要求更快的页面重绘)、处理更多事件(占用更多cpu)。把游戏转到浏览器的开发人员不想创建pong(雅达利在1972年11月29日推出的一款投币式街机游戏。——译者注),他们想创建成熟丰满的mmorpg(译者注:大型多人在线角色扮演游戏)。
不管开发人员想要web应用程序做什么,他们都希望web应用程序能做更多的事情。web worker规范(<code>http://dev.w3.org/html5/workers/</code>)通过向javascript开放并发编程api来解决这个问题。换句话说,把易于出错的线程编程引入到易于出错的web编程中。
实际上,没有理由对web worker如此悲观。规范对在浏览器中实现线程化及安全性做了明确的指导。因此,worker的设计(乃至实现)可以是安全的,但web应用程序对它们的使用可能会带来漏洞。
首先对worker进行概述。它们遵从其他javascript资源的同源策略。worker还有一些其他的限制,目的是减少对安全性的任何负面影响。
不能直接访问dom。因此它们无法枚举节点、查看cookie、访问window对象。worker的范围不与javascript上下文的正常全局范围共享。worker仍然根据一般的同源策略接收和返回与dom关联的数据。
可以使用xmlhttprequest对象。响应数据的可见性仍然受限于同源策略。应用跨源请求共享(cross-origin request sharing)时会产生例外。
可以使用websocket的对象,但支持程度根据浏览器的不同而变化。
worker对象的javascript源码是从传递给对象的构造函数的相对url获得的。该url会被解析为创建该对象的脚本的绝对url。这可以防止worker从其他的域加载javascript。
web worker使用消息传递事件来将数据从创建该worker的浏览上下文传递到worker本身。发送消息使用postmessage()方法,消息接收使用onmessage()事件处理程序。消息绑定到事件的data属性。下面的代码演示了一个web页面,该页面中有一个表单,用来同worker发送和接收消息。注意worker的javascript源码是从传递到worker构造函数的相对url加载的,本例中为“worker1.js”。

worker1.js的javascript源码如下所示。这个例子通过改变对onmessage事件的赋值示例了多个函数,当然也可以通过使用switch语句或if语句来获得相同的效果。本例的目标是示范动态可变接口的灵活性。
不要害怕对web worker的使用。它们的存在本身不会引起安全问题。不过,也有一些事情要注意(从黑客角度而言,则可以对这些方面进行测试):
构造函数必须始终使用相对url。如果worker的源码由于实现错误(例如对“<code>%00http://evil.site/”、“%ffhttp://evil.site/”或“@evil.site/</code>”等处理不当)可以从任意的域进行加载,将会成为安全性方面的bug。
cpu或内存的资源消耗。web worker很好地为javascript api隐藏了安全并发操作的实现细节。浏览器会强制限制允许创建的worker的数量、worker中的无穷循环、深度递归等问题。然而,实现错误可能会使得浏览器面临拒绝服务类型的攻击。例如,某个web worker试图做大量的后台处理(可能就是不断完成一些乘法计算)来耗尽移动设备的电量。
worker可能会加剧浏览器发起的基于网络的拒绝服务攻击。例如,假定某个html注入的有效负载生成数十个web worker,它们依次向黑客希望攻击的网站发起并行xhr连接。
并发问题。web worker api隐藏了加锁、死锁、竞态条件等多线程概念,但并不意味着使用web worker不会发生并发错误。例如,网站可能依赖某个worker来监视授权,而另一个worker执行被授权的动作。在执行某个动作之前,检查授权是否被撤销非常重要。多个worker不能保证它们之间的执行顺序。在worker的事件驱动模型中,某worker中实现得较差的授权检查可能会被重新排到另一个worker的调用之后,倘若先执行授权检查,该调用会被阻塞。