Web應(yīng)用安全性: 瀏覽器是如何工作的
這里先解釋瀏覽器的功能以及執(zhí)行方式。由于大多數(shù)客戶將通過(guò)瀏覽器與 web 應(yīng)用程序進(jìn)行交互,因此必須了解這些出色程序的基礎(chǔ)知識(shí)。
瀏覽器是一個(gè)渲染引擎,它的工作是下載一個(gè)web頁(yè)面,并以人類能夠理解的方式渲染它。
雖然這幾乎是一種過(guò)于簡(jiǎn)單的過(guò)分簡(jiǎn)化,但我們現(xiàn)在需要知道的全部?jī)?nèi)容。
- 用戶在瀏覽器欄中輸入一個(gè)地址。
- 瀏覽器從該 URL 下載“文檔”并渲染它。
你可能習(xí)慣使用 Chrome,F(xiàn)irefox,Edge或Safari等流行的瀏覽器之一,但這并不意味著沒(méi)有不同的瀏覽器。
例如,lynx 是一種輕量級(jí)的、基于文本的瀏覽器,可以在命令行中工作。lynx 的核心原理與其他“主流”瀏覽器的原理完全相同。用戶輸入 web 地址(URL),瀏覽器獲取文檔并呈現(xiàn)它——僅有的區(qū)別是 lynx 不使用可視化渲染引擎,而是使用基于文本的界面,這使得像谷歌這樣的網(wǎng)站看起來(lái)像這樣:
我們大致了解瀏覽器的功能,但是讓我們仔細(xì)看看這些機(jī)智的應(yīng)用程序?yàn)槲覀兯龅牟襟E。
瀏覽器做了什么?
長(zhǎng)話短說(shuō),瀏覽器的工作主要包括:
- DNS 解析
- HTTP 交換
- 渲染
- 重復(fù)以下步驟
DNS 解析
這個(gè)過(guò)程確保一旦用戶輸入 URL,瀏覽器就知道它必須連接到哪個(gè)服務(wù)器。瀏覽器聯(lián)系 DNS 服務(wù)器,發(fā)現(xiàn)google.com 翻譯成 216.58.207.110,這是一個(gè)瀏覽器可以連接的 IP 地址。
HTTP 交換
一旦瀏覽器確定了哪個(gè)服務(wù)器將為我們的請(qǐng)求提供服務(wù),它將啟動(dòng)與它的 TCP 連接并開(kāi)始 HTTP 交換。 這只是瀏覽器與服務(wù)器通信所需內(nèi)容以及服務(wù)器回復(fù)的一種方式。
HTTP 只是用于在 Web 上進(jìn)行通信協(xié)議的名稱,而瀏覽器一般通過(guò) HTTP 與服務(wù)器進(jìn)行通信。 HTTP 交換涉及客戶端(我們的瀏覽器)發(fā)送請(qǐng)求,服務(wù)器回復(fù)響應(yīng)。
例如,當(dāng)瀏覽器成功連接到 google.com 背后的服務(wù)器后,它將發(fā)送一個(gè)如下所示的請(qǐng)求:
- GET / HTTP/1.1
- Host: google.com
- Accept: */*
讓我們一行一行地把請(qǐng)求分解:
- GET / HTTP/1.1:在第一行中,并補(bǔ)充說(shuō)其余請(qǐng)求將遵循 HTTP/1.1 協(xié)議(它也可以使用1.0或2)
- Host: google.com:這是 HTTP/1.1 中必須的 HTTP 報(bào)頭。因?yàn)榉?wù)器可能服務(wù)多個(gè)域(google.com, google.co.uk) 。這里的客戶端提到請(qǐng)求是針對(duì)特定的主機(jī)的。
- Accept: */*:一個(gè)可選的標(biāo)頭,其中瀏覽器告訴服務(wù)器接受任何類型的響應(yīng)。服務(wù)器可以擁有 JSON、XM L或HTML 格式的可用資源,因此它可以選擇自己喜歡的格式。
作為客戶端的瀏覽器發(fā)送請(qǐng)求之后,就輪到服務(wù)器進(jìn)行響應(yīng)了,這是響應(yīng)的格式如下:
- 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>
哇,有很多信息需要消化。服務(wù)器讓我們知道請(qǐng)求是成功的(200 OK),并向響應(yīng)中添加一些頭部信息,例如,它告知哪個(gè)服務(wù)器處理了我們的請(qǐng)求(Server:gws),該響應(yīng)的 X-XSS-Protection 策略是什么,等等。
現(xiàn)在,你不需要理解響應(yīng)中的每一行,在本系列后面的文章中,我們將介紹 HTTP 協(xié)議及其頭部等內(nèi)容。
現(xiàn)在,你只需要了解客戶端和服務(wù)器正在交換信息,并且它們是通過(guò) HTTP 進(jìn)行交換的。
渲染
- <!doctype html><html">
- ...
- ...
- </html>
在響應(yīng)的主體中,服務(wù)器根據(jù) Content-Type 頭包括響應(yīng)類型來(lái)表示。 在我們的例子中,內(nèi)容類型設(shè)置為 text/ html,因此我們期待響應(yīng)中的 HTML 標(biāo)記 - 這正是我們?cè)谡闹姓业降摹?/p>
這才是瀏覽器真正的亮點(diǎn)所在。它解析 HTML,加載標(biāo)記中包含的額外資源(例如,可能需要獲取JavaScript文件或CSS文檔),并盡快將它們呈現(xiàn)給用戶。
最終的結(jié)果是普通人能夠理解的:
如果想要更詳細(xì)地了解當(dāng)我們?cè)跒g覽器地址欄中按回車鍵時(shí)會(huì)發(fā)生什么,建議閱讀“What happens when…”,這是一個(gè)非常精細(xì)的嘗試來(lái)解釋該過(guò)程背后的機(jī)制。
由于這是一個(gè)關(guān)注安全性的系列文章,從剛剛了解到的內(nèi)容可以提到提示:攻擊者可以輕松地利用 HTTP 交換和渲染部分中的漏洞謀生。漏洞和惡意用戶也潛伏在其他地方,但是這些級(jí)別上更好的安全方法已經(jīng)允許你在改進(jìn)安全性方面取得進(jìn)展。
供應(yīng)商
4 個(gè)非常流行的瀏覽器屬于不同的公司:
- 谷歌的 Chrome
- Mozilla 的火狐
- 蘋果的 Safari
- 微軟的 Edge
除了為了增加市場(chǎng)滲透率而相互競(jìng)爭(zhēng)之外,供應(yīng)商也為了提高 web 標(biāo)準(zhǔn)而相互合作,這是對(duì)瀏覽器的一種非常低的要求。
W3C是標(biāo)準(zhǔn)開(kāi)發(fā)的主體,但是瀏覽器開(kāi)發(fā)自己的特性并最終成為 web 標(biāo)準(zhǔn)的情況并不少見(jiàn),安全性也不例外。
例如,Chrome 51 引入了 SameSite cookie,該功能允許 Web 應(yīng)用程序擺脫稱為 CSRF 的特定類型的漏洞(稍后將詳細(xì)介紹)。其他供應(yīng)商認(rèn)為這是一個(gè)好主意,并紛紛效仿,導(dǎo)致 SameSite 成為 web 標(biāo)準(zhǔn):到目前為止,Safari 是僅有的沒(méi)有 SameSite cookie 支持的主流瀏覽器。
這告訴我們兩件事:
- Safari似乎并不關(guān)心用戶的安全性(開(kāi)玩笑:Safari 12中將提供SameSite cookie,這可能在你閱讀本文時(shí)已經(jīng)發(fā)布)
- 修補(bǔ)一個(gè)瀏覽器上的漏洞并不意味著所有用戶都是安全的
第一點(diǎn)是對(duì) Safari 的一次嘗試(正如我提到的,開(kāi)玩笑的!),而第二點(diǎn)非常重要。在開(kāi)發(fā)web應(yīng)用程序時(shí),我們不僅需要確保它們?cè)诓煌臑g覽器中看起來(lái)是相同的,還需要確保我們的用戶在不同的平臺(tái)上受到相同的保護(hù)。
你的網(wǎng)絡(luò)安全策略應(yīng)根據(jù)瀏覽器供應(yīng)商允許我們執(zhí)行的操作而有所不同。 如今,大多數(shù)瀏覽器都支持相同的功能集,并且很少偏離其常見(jiàn)的路線圖,但是上面的實(shí)例仍然會(huì)發(fā)生,這是我們?cè)诙x安全策略時(shí)需要考慮的事情。
在我們的例子中,如果我們決定只通過(guò) SameSite cookie 來(lái)減輕 CSRF 攻擊,那么我們應(yīng)該意識(shí)到我們正在將 Safari 用戶置于危險(xiǎn)之中。我們的用戶也應(yīng)該知道這一點(diǎn)。
然后,你應(yīng)該記住,你可以決定是否支持瀏覽器版本:支持每一個(gè)瀏覽器版本將是不切實(shí)際的(想想 Internet Explorer 6)。雖然確保最近幾個(gè)版本的主流瀏覽器的支持通常是一個(gè)好的決定,但是如果你不打算在特定的平臺(tái)上提供保護(hù),一般建議讓你的用戶知道。
專業(yè)提示:你不應(yīng)該鼓勵(lì)你的用戶使用過(guò)時(shí)的瀏覽器,或積極支持他們。盡管你可能已經(jīng)采取了所有必要的預(yù)防措施,但是其他web開(kāi)發(fā)人員可能沒(méi)有。鼓勵(lì)用戶使用主流瀏覽器支持的新版本。
供應(yīng)商還是標(biāo)準(zhǔn)bug?
普通用戶通過(guò)第三方客戶端(瀏覽器)訪問(wèn)我們的應(yīng)用程序這一事實(shí)增加了另一層次的間接性:瀏覽器本身可能存在安全漏洞。‘
供應(yīng)商通常會(huì)向能夠發(fā)現(xiàn)瀏覽器自身漏洞的安全研究人員提供獎(jiǎng)勵(lì)(即 bug獎(jiǎng)金)。這些bug與你的實(shí)現(xiàn)無(wú)關(guān),而是與瀏覽器本身處理安全性的方式有關(guān)。
例如,Chrome 獎(jiǎng)勵(lì)計(jì)劃可讓安全工程師與 Chrome 安全團(tuán)隊(duì)聯(lián)系,報(bào)告他們發(fā)現(xiàn)的漏洞。 如果確認(rèn)了這些漏洞,則會(huì)發(fā)布補(bǔ)丁,通常會(huì)向公眾發(fā)布安全建議通知,研究人員會(huì)從該計(jì)劃中獲得(通常是財(cái)務(wù)上的)獎(jiǎng)勵(lì)。
像谷歌這樣的公司在他們的Bug賞金項(xiàng)目中投入了相對(duì)較多的資金,這使得他們能夠通過(guò)承諾在發(fā)現(xiàn)應(yīng)用程序的任何問(wèn)題時(shí)獲得經(jīng)濟(jì)利益來(lái)吸引研究人員。
在一個(gè)漏洞賞金計(jì)劃中,每個(gè)人都是贏家:供應(yīng)商設(shè)法提高其軟件的安全能力,研究人員也因此獲得報(bào)酬。我們將在后面討論這些程序,因?yàn)槲蚁嘈臖ug賞金計(jì)劃應(yīng)該在安全領(lǐng)域有自己的一節(jié)。
Jake Archibald 是谷歌的一名開(kāi)發(fā)人員,他最近發(fā)現(xiàn)了一個(gè)影響多個(gè)瀏覽器的漏洞。他在一篇有趣的博客文章中記錄了他的努力,他如何接觸不同的供應(yīng)商,以及他們的反應(yīng),建議你閱讀 這篇文章。
開(kāi)發(fā)人員的瀏覽器
到目前為止,我們應(yīng)該理解一個(gè)非常簡(jiǎn)單但相當(dāng)重要的概念:瀏覽器只是為普通網(wǎng)絡(luò)沖浪者構(gòu)建的 HTTP 客戶端。
它們肯定比平臺(tái)的純HTTP客戶端更強(qiáng)大(例如,考慮NodeJS的require(‘HTTP’)),但歸根結(jié)底,它們“只是”更簡(jiǎn)單的 HTTP客戶端的自然演化。
作為開(kāi)發(fā)人員,我們選擇的HTTP客戶機(jī)可能是 Daniel Stenberg 的 cURL,他是 web 開(kāi)發(fā)人員每天使用的十分流行的軟件程序之一。它允許我們通過(guò)從命令行發(fā)送 HTTP 請(qǐng)求來(lái)實(shí)時(shí)執(zhí)行 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
在上面的示例中,我們?cè)?localhost:8080/ 上請(qǐng)求了文檔,本地服務(wù)器成功響應(yīng)。
在這里,我們沒(méi)有將響應(yīng)的主體顯示在命令行,而是使用了 -I 標(biāo)志,它告訴 cURL 我們只對(duì)響應(yīng)頭感興趣。更進(jìn)一步,我們可以指示 cURL 顯示更多的信息,包括它執(zhí)行的實(shí)際請(qǐng)求,以便更好地查看整個(gè)HTTP交換。需要使用的選項(xiàng)是-v(詳細(xì)):
- $ 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
主流瀏覽器通過(guò)它們的 DevTools 可以獲得幾乎相同的信息。
正如我們所見(jiàn),瀏覽器只不過(guò)是精心設(shè)計(jì)的HTTP客戶端。 當(dāng)然,他們添加了大量的功能(想到憑據(jù)管理,書(shū)簽,歷史等),但事實(shí)是,它們是作為人類的 HTTP 客戶端而誕生的。 這很重要,因?yàn)樵诖蠖鄶?shù)情況下,不需要使用瀏覽器來(lái)測(cè)試Web應(yīng)用程序的安全性,因?yàn)槟憧梢院?jiǎn)單的通過(guò) curl 命令來(lái)查看響應(yīng)信息。
進(jìn)入 HTTP 協(xié)議
正如我們所提到的,HTTP交換和渲染階段是我們主要要涉及的階段,因?yàn)樗鼈優(yōu)閻阂庥脩籼峁┝舜髷?shù)量的攻擊媒介。
在下一篇文章中,我們將深入研究HTTP協(xié)議,并嘗試了解為了保護(hù)HTTP交換,我們應(yīng)該采取哪些措施。