3.2 JavaScript
现代Web页面使用JavaScript来响应用户动作。JavaScript是一种成熟的编程语言,在呈现网页时由浏览器的JavaScript引擎执行。JavaScript可以通过使用<script>
标签合并到HTML文档中;代码可以内联地包含在HTML文档中,或者更典型地,<script>
标签可以引用要从外部URL加载的JavaScript文件。
默认情况下,只要将相关的<script>
标签解析为DOM节点,浏览器便会执行任何JavaScript代码。对于从外部URL加载的JavaScript代码,这意味着该代码在加载后立即执行。
如果呈现管道尚未完成对HTML文档的解析,则此默认行为会导致出现问题;JavaScript代码将尝试与DOM中可能不存在的页面元素进行交互。为此,<script>
标签通常带有defer属性。这将使JavaScript仅在整个DOM构建完成后才执行。
正如你所想象的,浏览器急切地执行它们遇到的任何JavaScript代码这一事实会带来安全隐患。黑客的最终目标通常是在另一个用户的机器上远程执行代码,而互联网使这一目标变得容易很多,因为很难找到一台没有连接到网络的计算机。基于这个原因,现代浏览器严格限制JavaScript的浏览器安全模型。这意味着JavaScript代码必须在沙箱中执行,并且不允许执行以下任何操作:
- 启动新进程或访问其他现有进程。
- 读取系统内存的任意块。作为一种托管内存语言,JavaScript无法在其沙箱外部读取内存。
- 访问本地磁盘。现代浏览器允许网站在本地存储少量数据,但是这种存储是从文件系统本身抽象出来的。
- 访问操作系统的网络层。
- 调用操作系统功能。
允许JavaScript在浏览器沙箱中执行的动作:
- 读取和操作当前网页的DOM。
- 通过注册事件侦听器来侦听并响应当前页面上的用户动作。
- 代表用户进行HTTP调用。
- 打开新网页或刷新当前页面的URL,但这仅仅是为了响应用户动作。
- 将新条目写入浏览器的历史记录,并在历史记录中前进和后退。
- 询问用户的位置,例如:“Google地图想使用您的位置。”
- 寻求权限以发送桌面通知。
即使有这些限制,可以将恶意JavaScript注入你的网页中的攻击者仍然可以通过跨站点脚本在用户输入信用卡详细信息或凭据时读取它们,从而造成很大的危害。即使少量注入恶意JavaScript也会构成威胁,因为注入的代码可以在DOM中添加<script>
标签以加载恶意载荷。在第7章中,我们将介绍如何防范这种跨站点脚本攻击。