这本系列的第一篇,先解释浏览器的功能以及执行方式。由于大多数客户将通过浏览器与 web 应用程序进行交互,因此必须了解这些出色程序的基础知识。
浏览器是一个渲染引擎,它的工作是下载一个 web 页面,并以人类能够理解的方式渲染它。
虽然这几乎是一种过于简单的过分简化,但我们现在需要知道的全部内容。
用户在浏览器栏中输入一个地址。
浏览器从该 URL 下载“文档”并渲染它。
你可能习惯使用 Chrome,Firefox,Edge 或 Safari 等流行的浏览器之一,但这并不意味着没有不同的浏览器。
例如,lynx 是一种轻量级的、基于文本的浏览器,可以在命令行中工作。lynx 的核心原理与其他“主流”浏览器的原理完全相同。用户输入 web 地址 (URL),浏览器获取文档并呈现它——唯一的区别是 lynx 不使用可视化渲染引擎,而是使用基于文本的界面,这使得像谷歌这样的网站看起来像这样:
我们大致了解浏览器的功能,但是让我们仔细看看这些机智的应用程序为我们所做的步骤。
浏览器做了什么?
长话短说,浏览器的工作主要包括:
DNS 解析
HTTP 交换
渲染
重复以下步骤
DNS 解析
这个过程确保一旦用户输入 URL,浏览器就知道它必须连接到哪个服务器。浏览器联系 DNS 服务器,发现 google.com 翻译成 216.58.207.110,这是一个浏览器可以连接的 IP 地址。
HTTP 交换
一旦浏览器确定了哪个服务器将为我们的请求提供服务,它将启动与它的 TCP 连接并开始 HTTP 交换。这只是浏览器与服务器通信所需内容以及服务器回复的一种方式。
HTTP 只是用于在 Web 上进行通信协议的名称,而浏览器一般通过 HTTP 与服务器进行通信。HTTP 交换涉及客户端(我们的浏览器)发送请求,服务器回复响应。
例如,当浏览器成功连接到 google.com 背后的服务器后,它将发送一个如下所示的请求:
GET / HTTP/1.1
Host: google.com
Accept: */*
让我们一行一行地把请求分解:
GET / HTTP/1.1: 在第一行中,并补充说其余请求将遵循 HTTP/1.1 协议(它也可以使用 1.0 或 2)
Host: google.com:这是 HTTP/1.1 中唯一必须的 HTTP 报头。因为服务器可能服务多个域 (google.com, google.co.uk)。这里的客户端提到请求是针对特定的主机的。
Accept: */*:一个可选的标头,其中浏览器告诉服务器接受任何类型的响应。服务器可以拥有 JSON、XM L 或 HTML 格式的可用资源,因此它可以选择自己喜欢的格式。
作为客户端的浏览器发送请求之后,就轮到服务器进行响应了,这是响应的格式如下:
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
Server: gws
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Set-Cookie: NID=1234; expires=Fri, 18-Jan-2019 18:25:04 GMT; path=/; domain=.google.com; HttpOnly
<!doctype html><html”>
…
…
</html>
哇,有很多信息需要消化。服务器让我们知道请求是成功的 (200 OK),并向响应中添加一些头部信息,例如,它告知哪个服务器处理了我们的请求 (Server:gws),该响应的 X-XSS-Protection 策略是什么,等等。
现在,你不需要理解响应中的每一行,在本系列后面的文章中,我们将介绍 HTTP 协议及其头部等内容。
现在,你只需要了解客户端和服务器正在交换信息,并且它们是通过 HTTP 进行交换的。
渲染
<!doctype html><html”>
…
…
</html>
在响应的主体中,服务器根据 Content-Type 头包括响应类型来表示。在我们的例子中,内容类型设置为 text/ html,因此我们期待响应中的 HTML 标记 – 这正是我们在正文中找到的。
这才是浏览器真正的亮点所在。它解析 HTML,加载标记中包含的额外资源 (例如,可能需要获取 JavaScript 文件或 CSS 文档),并尽快将它们呈现给用户。
最终的结果是普通人能够理解的:
如果想要更详细地了解当我们在浏览器地址栏中按回车键时会发生什么,建议阅读“What happens when…”,这是一个非常精细的尝试来解释该过程背后的机制。
由于这是一个关注安全性的系列文章,从刚刚了解到的内容可以提到提示: 攻击者可以轻松地利用 HTTP 交换和渲染部分中的漏洞谋生。漏洞和恶意用户也潜伏在其他地方,但是这些级别上更好的安全方法已经允许你在改进安全性方面取得进展。
供应商
4 个最流行的浏览器属于不同的公司:
谷歌的 Chrome
Mozilla 的火狐
苹果的 Safari
微软的 Edge
除了为了增加市场渗透率而相互竞争之外,供应商也为了提高 web 标准而相互合作,这是对浏览器的一种“最低要求”。
W3C 是标准开发的主体,但是浏览器开发自己的特性并最终成为 web 标准的情况并不少见,安全性也不例外。
例如,Chrome 51 引入了 SameSite cookie,该功能允许 Web 应用程序摆脱称为 CSRF 的特定类型的漏洞(稍后将详细介绍)。其他供应商认为这是一个好主意,并纷纷效仿,导致 SameSite 成为 web 标准: 到目前为止,Safari 是唯一没有 SameSite cookie 支持的主流浏览器。
这告诉我们两件事:
Safari 似乎并不关心用户的安全性(开玩笑:Safari 12 中将提供 SameSite cookie,这可能在你阅读本文时已经发布)
修补一个浏览器上的漏洞并不意味着所有用户都是安全的
第一点是对 Safari 的一次尝试 (正如我提到的,开玩笑的!),而第二点非常重要。在开发 web 应用程序时,我们不仅需要确保它们在不同的浏览器中看起来是相同的,还需要确保我们的用户在不同的平台上受到相同的保护。
你的网络安全策略应根据浏览器供应商允许我们执行的操作而有所不同。如今,大多数浏览器都支持相同的功能集,并且很少偏离其常见的路线图,但是上面的实例仍然会发生,这是我们在定义安全策略时需要考虑的事情。
在我们的例子中,如果我们决定只通过 SameSite cookie 来减轻 CSRF 攻击,那么我们应该意识到我们正在将 Safari 用户置于危险之中。我们的用户也应该知道这一点。
最后但并非最不重要, 你应该记住, 你可以决定是否支持浏览器版本: 支持每一个浏览器版本将是不切实际的 (想想 Internet Explorer 6)。虽然确保最近几个版本的主流浏览器的支持通常是一个好的决定,但是如果你不打算在特定的平台上提供保护,一般建议让你的用户知道。
专业提示: 你不应该鼓励你的用户使用过时的浏览器,或积极支持他们。尽管你可能已经采取了所有必要的预防措施,但是其他 web 开发人员可能没有。鼓励用户使用主流浏览器支持的最新版本。
供应商还是标准 bug?
普通用户通过第三方客户端(浏览器)访问我们的应用程序这一事实增加了另一层次的间接性:浏览器本身可能存在安全漏洞。‘供应商通常会向能够发现浏览器自身漏洞的安全研究人员提供奖励 (即 bug 奖金)。这些 bug 与你的实现无关,而是与浏览器本身处理安全性的方式有关。
例如,Chrome 奖励计划可让安全工程师与 Chrome 安全团队联系,报告他们发现的漏洞。如果确认了这些漏洞,则会发布补丁,通常会向公众发布安全建议通知,研究人员会从该计划中获得(通常是财务上的)奖励。
像谷歌这样的公司在他们的 Bug 赏金项目中投入了相对较多的资金,这使得他们能够通过承诺在发现应用程序的任何问题时获得经济利益来吸引研究人员。
在一个漏洞赏金计划中,每个人都是赢家: 供应商设法提高其软件的安全性,研究人员也因此获得报酬。我们将在后面讨论这些程序,因为我相信 Bug 赏金计划应该在安全领域有自己的一节。
Jake Archibald 是谷歌的一名开发人员,他最近发现了一个影响多个浏览器的漏洞。他在一篇有趣的博客文章中记录了他的努力,他如何接触不同的供应商,以及他们的反应,建议你阅读 这篇文章。
开发人员的浏览器
到目前为止,我们应该理解一个非常简单但相当重要的概念:浏览器只是为普通网络冲浪者构建的 HTTP 客户端。
它们肯定比平台的纯 HTTP 客户端更强大 (例如,考虑 NodeJS 的 require(‘HTTP’)),但归根结底,它们“只是”更简单的 HTTP 客户端的自然演化。
作为开发人员,我们选择的 HTTP 客户机可能是 Daniel Stenberg 的 cURL,他是 web 开发人员每天使用的最流行的软件程序之一。它允许我们通过从命令行发送 HTTP 请求来实时执行 HTTP 交换:
$ curl -I localhost:8080
HTTP/1.1 200 OK
server: ecstatic-2.2.1
Content-Type: text/html
etag: “23724049-4096-“2018-07-20T11:20:35.526Z””
last-modified: Fri, 20 Jul 2018 11:20:35 GMT
cache-control: max-age=3600
Date: Fri, 20 Jul 2018 11:21:02 GMT
Connection: keep-alive
在上面的示例中,我们在 localhost:8080/ 上请求了文档,本地服务器成功响应。
在这里,我们没有将响应的主体显示在命令行,而是使用了 -I 标志,它告诉 cURL 我们只对响应头感兴趣。更进一步,我们可以指示 cURL 显示更多的信息,包括它执行的实际请求,以便更好地查看整个 HTTP 交换。需要使用的选项是 -v(详细):
$ curl -I -v localhost:8080
* Rebuilt URL to: localhost:8080/
* Trying 127.0.0.1…
* Connected to localhost (127.0.0.1) port 8080 (#0)
> HEAD / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< server: ecstatic-2.2.1
server: ecstatic-2.2.1
< Content-Type: text/html
Content-Type: text/html
< etag: “23724049-4096-“2018-07-20T11:20:35.526Z””
etag: “23724049-4096-“2018-07-20T11:20:35.526Z””
< last-modified: Fri, 20 Jul 2018 11:20:35 GMT
last-modified: Fri, 20 Jul 2018 11:20:35 GMT
< cache-control: max-age=3600
cache-control: max-age=3600
< Date: Fri, 20 Jul 2018 11:25:55 GMT
Date: Fri, 20 Jul 2018 11:25:55 GMT
< Connection: keep-alive
Connection: keep-alive
<
* Connection #0 to host localhost left intact
主流浏览器通过它们的 DevTools 可以获得几乎相同的信息。
正如我们所见,浏览器只不过是精心设计的 HTTP 客户端。当然,他们添加了大量的功能(想到凭据管理,书签,历史等),但事实是,它们是作为人类的 HTTP 客户端而诞生的。这很重要,因为在大多数情况下,不需要使用浏览器来测试 Web 应用程序的安全性,因为你可以简单的通过 curl 命令来查看响应信息。
进入 HTTP 协议
正如我们所提到的,HTTP 交换和渲染阶段是我们主要要涉及的阶段,因为它们为恶意用户提供了最大数量的攻击媒介。
在下一篇文章中,我们将深入研究 HTTP 协议,并尝试了解为了保护 HTTP 交换,我们应该采取哪些措施。
原文:
https://medium.freecodecamp.o…
你的点赞是我持续分享好东西的动力,欢迎点赞!
一个笨笨的码农,我的世界只能终身学习!
更多内容请关注公众号《大迁世界》!