IE安全系列:IE浏览器的技术变迁(上)
聲明:為了更好地向讀者輸出更優(yōu)質(zhì)的內(nèi)容,InfoQ將精選來(lái)自國(guó)內(nèi)外的優(yōu)秀文章,經(jīng)過(guò)整理審校后,發(fā)布到網(wǎng)站。本篇文章作者為烏云白帽子blast,原文鏈接。本文是《IE安全系列》第一篇,已由烏云網(wǎng)授權(quán)InfoQ中文站轉(zhuǎn)載。歡迎轉(zhuǎn)發(fā),但請(qǐng)保留原作者信息!
\\作者 blast
\\前言
\\本系列將簡(jiǎn)單介紹一下IE的安全問(wèn)題,限于篇幅和自己的認(rèn)知,其中必有不足之處,歡迎大家指正。
\\系列中每篇文章分為三個(gè)部分,第一部分通常是背景介紹,第二部分是總結(jié)性的描述,第三部分則是詳細(xì)介紹或者實(shí)踐。
\\Internet Explorer的歷史變遷
\\在記憶中,從1999年開(kāi)始接觸網(wǎng)絡(luò),從那時(shí)跟隨著Windows 95一起而來(lái)的Internet Explorer 4算起,微軟已經(jīng)發(fā)布了8個(gè)不同版本的IE了(如果Spartan算作是Internet Explorer 12的話)。這之中Internet Explorer(以下簡(jiǎn)稱IE)都做了哪些變更呢?
\\- IE1、IE2(1995年):家族中最簡(jiǎn)單的“瀏覽器”,只支持靜態(tài)的頁(yè)面,現(xiàn)在你能用得到的許多功能它都不支持;但現(xiàn)在你用到的許多功能他卻都有了雛形。\\\ \\t
- IE3(1996年):對(duì)早期版本的改進(jìn),支持了ActiveX控件,支持了JavaScript和VBScript(當(dāng)時(shí)稱為Microsoft JScript和Microsoft VBScript,因?yàn)樯虡?biāo)問(wèn)題)。從這時(shí)開(kāi)始支持Web Browser這個(gè)被人熟知的ActiveX控件,這保證了瀏覽器的可重用性。\\t
- IE4(1997年):引入了DHTML功能,支持?jǐn)?shù)據(jù)綁定,同時(shí)增強(qiáng)了WebBrowser的功能,添加了一些新特性,增加了側(cè)邊欄以及BHO。\\t
- IE5(1999年):隨著Windows 98一起發(fā)售,支持持久會(huì)話,緊接著誕生了XMLHttpRequest,促使了AJAX的發(fā)展(盡管此時(shí)AJAX一詞都還沒(méi)誕生……),引入了HTA,還有自動(dòng)填表等功能。IE5.5版本起還支持了128位的加密。\\t
- IE6(2001年):緊接著Windows XP一起發(fā)售,是給大家留下印象最深刻的瀏覽器,在2002~2003年中,IE6的市場(chǎng)份額達(dá)到了90%,IE全家族的市場(chǎng)份額達(dá)到了95%。同時(shí),這也是最飽受詬病的一款瀏覽器,因?yàn)樗陌踩珕?wèn)題實(shí)在是很嚴(yán)重。這一版本中增加的大多是網(wǎng)頁(yè)渲染相關(guān)的功能,例如CSS1、DOM1等的部分支持。\\t
- IE7(2006年)、IE8(2009年):IE6市場(chǎng)份額被火狐搶走之后微軟推出的新版本瀏覽器,這兩個(gè)版本大部分都是性能調(diào)整和渲染修整以及增強(qiáng)。\\t
- IE9(2011年),穩(wěn)定版本,性能提升和HTML5支持,多進(jìn)程支持,這使得網(wǎng)頁(yè)假死或者崩潰時(shí)不會(huì)影響到其他頁(yè)面。\
IE9之后的版本大家很容易就能搜到產(chǎn)品截圖。
\\- \\t
IE10(2011年)/IE11(2013年),性能有較大的增強(qiáng),渲染及兼容性也得以增強(qiáng),增加DNT支持。IE10的性能已經(jīng)和之前有較大的不同,但是頂著IE的名號(hào),依然得承受著IE6帶來(lái)的深刻影響。
\\t\\t - \\t
Spartan(2015年),代號(hào)IE12。整合了語(yǔ)音助手,性能提升等。從程序上看,它確實(shí)和IE用的不是同一套DLL庫(kù)。
\\t\
IE的構(gòu)成
\\在早期的單進(jìn)程IE中,IE的結(jié)構(gòu)大致如下:
\\ \\圖:以IE6為代表的單進(jìn)程無(wú)Tab模式
\\ \\隨著多進(jìn)程的引入,IE的網(wǎng)頁(yè)部分結(jié)構(gòu)還是類似這樣,但是界面宿主已經(jīng)有變化了,看起來(lái)像是:
\\ \\請(qǐng)注意上圖中外殼網(wǎng)頁(yè)分屬于不同進(jìn)程。
\\在IE7中,一個(gè)進(jìn)程中可以運(yùn)行一組網(wǎng)頁(yè)窗口了,但是新窗口不代表在新進(jìn)程里面運(yùn)行。(比如你用Ctrl+N新建窗口,其實(shí)它還是在當(dāng)前進(jìn)程里面創(chuàng)建的),可以自己安裝一個(gè)IE7來(lái)試驗(yàn),如果沒(méi)用過(guò)的話看我這個(gè)描述應(yīng)該會(huì)很奇怪。開(kāi)啟了保護(hù)模式的進(jìn)程會(huì)運(yùn)行在低完整性級(jí)別下,通過(guò)一個(gè)代理進(jìn)程來(lái)進(jìn)行通信。
\\簡(jiǎn)化的進(jìn)程模型如下:
\\ \\ \\下圖:IE7的進(jìn)程模式
\\ \\在IE8中,微軟引入了IE8松散耦合進(jìn)程框架(LCIE),它使用Jobs來(lái)限制進(jìn)程權(quán)限(筆者試著用Jobs控制權(quán)限,實(shí)際應(yīng)用在IE中的話深知不易,微軟也是下了不少功夫),這個(gè)時(shí)候,開(kāi)啟了保護(hù)模式與未開(kāi)啟保護(hù)模式的IE8的結(jié)構(gòu)類似與:
\\ \ \\可以看到的是這個(gè)版本中IE的UI Frame和一些管理功能所在的進(jìn)程運(yùn)行在中完整性級(jí)別上,而保護(hù)模式下,Tab和網(wǎng)頁(yè)進(jìn)程運(yùn)行在低完整性級(jí)別中(禁用保護(hù)模式的域下依然是中完整性級(jí)別)。
\\如上,HTML和ActiveX控件都在網(wǎng)頁(yè)進(jìn)程里面,還有一個(gè)比較特殊的是工具欄,它也在網(wǎng)頁(yè)進(jìn)程里面。
\\采用這種模式的好處都有啥?首先是每個(gè)Tab都獨(dú)立出去了,其中一個(gè)崩了也不會(huì)影響其他的;至于把UI Frame移動(dòng)到了代理進(jìn)程那邊,理由是加快啟動(dòng)速度。
\\而且由于采用了網(wǎng)頁(yè)分進(jìn)程的模式,所以不同完整性級(jí)別的網(wǎng)頁(yè)、Tab都可以歸屬于同一個(gè)UI Frame,管理起來(lái)也比較方便。如果你使用過(guò)mordenie、metroie,你會(huì)發(fā)現(xiàn)也許它的網(wǎng)頁(yè)進(jìn)程都是64位的,這是因?yàn)檫@個(gè)版本中不加載任何插件。即便現(xiàn)在許多插件都有了64位版本,比如Adobe Flash Player,但是如果一味的追求64位化還是會(huì)導(dǎo)致各種插件不兼容。所以在IE10、IE11的64位版本中,瀏覽器的UI Frame以64位運(yùn)行,而網(wǎng)頁(yè)進(jìn)程為了保證插件的兼容性,依然默認(rèn)采用了32位進(jìn)程。換句話說(shuō),即使你打開(kāi)的是64位的IE,但網(wǎng)頁(yè)進(jìn)程還是32位的。
\\所以,也許你會(huì)看到有64位的IE和32位IE同時(shí)存在你電腦里面的樣子:
\\ \\以及,啟動(dòng)IE后出現(xiàn)一個(gè)64位進(jìn)程和n個(gè)32位進(jìn)程的樣子:
\\ \\圖:IE11 64bit Frame進(jìn)程和32bit Content進(jìn)程
\\相對(duì)于IE7的模式,在IE11中,即使你手動(dòng)執(zhí)行兩次iexplore http://www.wooyun.org,出來(lái)的也僅僅只有一個(gè)64位的UI進(jìn)程。
\\ \\圖:IE11的進(jìn)程模式
\\當(dāng)然,如果你開(kāi)啟了增強(qiáng)保護(hù)模式,那網(wǎng)頁(yè)進(jìn)程也會(huì)變成64位的。
\\ \\圖:IE11啟用增強(qiáng)保護(hù)模式
\\在Windows 7下開(kāi)啟這個(gè)模式,唯一的用處就是把進(jìn)程變成了64位,但是Windows 8下則會(huì)引入AppContainer這個(gè)進(jìn)程隔離模式,具體的可以參考這里。
\\限于篇幅,與之相關(guān)的內(nèi)容之后再敘述。
\\重要概念:什么是Markup Service?
\\回到IE的核心功能上來(lái),作為網(wǎng)頁(yè)的渲染器,超文本標(biāo)記語(yǔ)言HTML想必是離不開(kāi)Markup,那這個(gè)Markup到底是什么呢?歷史上來(lái)說(shuō),Markup其實(shí)是給演員看的,簡(jiǎn)單的說(shuō)就是劇本,通常還會(huì)給它畫(huà)一道藍(lán)色的標(biāo)記,標(biāo)明這個(gè)東西應(yīng)該誰(shuí)怎么演才合適。在瀏覽器中,Markup通常可以看作是一個(gè)個(gè)的標(biāo)簽。關(guān)于Markup Service的內(nèi)容,建議大家最開(kāi)始只了解個(gè)大概即可。
\\ \\圖:Markup Script,當(dāng)然,這個(gè)是演員用的,圖像來(lái)自Google Image
\\ \\圖:IE可以識(shí)別的Hyper Text Markup Langauge
\\例如,一個(gè)HTML文件可能有如下內(nèi)容:
\\ \u0026lt;DIV\u0026gt;blast\u0026lt;DIV\u0026gt;off\\\當(dāng)瀏覽器解析這個(gè)文本時(shí),瀏覽器會(huì)對(duì)內(nèi)容做一次標(biāo)準(zhǔn)化(我比較習(xí)慣這么稱呼),之后,DOM內(nèi)容看起來(lái)像是:
\\ \u0026lt;HTML\u0026gt;\u0026lt;HEAD\u0026gt;\u0026lt;TITLE\u0026gt;\u0026lt;/TITLE\u0026gt;\u0026lt;/HEAD\u0026gt;\u0026lt;BODY\u0026gt;\u0026lt;DIV\u0026gt;blast\u0026lt;DIV\u0026gt;off\u0026lt;/DIV\u0026gt;\u0026lt;/DIV\u0026gt;\u0026lt;/BODY\u0026gt;\u0026lt;/HTML\u0026gt;\\\這個(gè)過(guò)程你可以自己去網(wǎng)頁(yè)DOM看:
\\ \\圖:IE11的文檔標(biāo)準(zhǔn)化
\\由于有元素的插入,因此這一項(xiàng)功能可能會(huì)引入額外的安全風(fēng)險(xiǎn),例如我之前發(fā)的內(nèi)容。
\\或者可以說(shuō),解析器經(jīng)過(guò)這一輪后,將HTML文本轉(zhuǎn)為了元素。而且為了內(nèi)容的完整,有一些原來(lái)沒(méi)有的元素也加進(jìn)去了,例如html、head、title、body等會(huì)自動(dòng)地被解析器構(gòu)造出來(lái)。
\\同時(shí),解析器遇到第二個(gè)div(分塊)的時(shí)候,會(huì)自動(dòng)的把第一個(gè)div給封閉起來(lái)(怎么封閉要取決于瀏覽器的實(shí)現(xiàn))。還有之前加入的必要(但是你沒(méi)寫(xiě))的標(biāo)簽,比如\u0026lt;html\u0026gt;、\u0026lt;body\u0026gt;,都會(huì)自動(dòng)地被IE添上并封閉。
\\第二個(gè)需要注意的概念是tree和stream(樹(shù)、流)的區(qū)別,比如:
\\ This\u0026lt;B\u0026gt;is\u0026lt;/B\u0026gt;atest\\\這組“this is a test”和一對(duì)b標(biāo)簽的例子,將會(huì)被轉(zhuǎn)化為如下的樹(shù)。text被當(dāng)為樹(shù)葉,element被作為內(nèi)節(jié)點(diǎn)。
\\ ROOT\ |\ +-------+--------+\ | | |\\"this\" B \"a test\"\ |\ \"is\"\\\把文檔轉(zhuǎn)為tree之后,所有的操作都會(huì)變?yōu)轭愃茖?duì)樹(shù)的操作,例如增刪子節(jié)點(diǎn)。提供此類操作的API被稱為T(mén)ree Service。
\\當(dāng)然,自IE4.0之后,元素的模型操作比簡(jiǎn)單的樹(shù)更強(qiáng)悍,比如這個(gè)例子:
\\ An \u0026lt;B\u0026gt;exmaple \u0026lt;I\u0026gt; of \u0026lt;/B\u0026gt; elements \u0026lt;/I\u0026gt; cross\\\B、I的范圍互相交叉,在HTML里面這個(gè)很常見(jiàn),用樹(shù)來(lái)描述則十分困難。因此,Markup Services對(duì)這個(gè)內(nèi)容不再提供類似樹(shù)的操作,而是為方便控制內(nèi)容暴露了一個(gè)基于流操作的模型。
\\ \圖:相互交叉的范圍
\\所以,Markup Service的作用實(shí)際上是用來(lái)避免產(chǎn)生這種讓人迷惑的模型層間的。
\\當(dāng)無(wú)法用Tree Service時(shí),瀏覽器就轉(zhuǎn)而使用Markup Service來(lái)控制基于流操作的模型。
\\在基于樹(shù)的模型中,網(wǎng)頁(yè)內(nèi)容被當(dāng)作樹(shù)的節(jié)點(diǎn)來(lái)處理,每個(gè)元素,或者一塊Text都是一個(gè)節(jié)點(diǎn)。節(jié)點(diǎn)通過(guò)這種類似對(duì)樹(shù)的操作方式來(lái)操作,例如從父節(jié)點(diǎn)中增刪一個(gè)子節(jié)點(diǎn)。
\\在基于流的模型的內(nèi)容操作方式中(比如通過(guò)Markup Service來(lái)操作),文檔的內(nèi)容會(huì)通過(guò)使用類似迭代器的對(duì)象來(lái)操作。這個(gè)就像是在處理上面那個(gè)元素交叉的例子一樣,這些帶有部分重疊的元素通過(guò)兩個(gè)Markup Pointer來(lái)區(qū)分,每個(gè)Markup Pointer指定著Tag從哪兒開(kāi)始、到哪兒結(jié)束。所以,基于流的模型是基于樹(shù)的模型的一個(gè)超集。
\\說(shuō)了這么多,要引入我們的Markup Pointer了。在這之前,舉一個(gè)類似的例子,C++中,如果要操作一個(gè)vector,使用迭代器是非常方便的做法:
\\ \\圖:使用迭代器向vector插入一個(gè)元素
\\也如你所見(jiàn),Markup Pointer也有些神似迭代器。可以通過(guò)創(chuàng)建和操作無(wú)效文檔的過(guò)程來(lái)理解一下。
\\注意之前“This is a test”的例子,瀏覽器可能不會(huì)被認(rèn)為這是一個(gè)有效的HTML文檔。
\\最小的有效HTML文檔至少要有html、head、title和body四個(gè)元素,當(dāng)你提供的內(nèi)容中沒(méi)有這些元素時(shí),解析器會(huì)自動(dòng)建立,然后把它們放到合適的位置上。
\\在文檔解析過(guò)程中,使用Markup Service即可刪除或者重新排列DOM。例如,你可以整塊刪除html、body元素。你可以把head移動(dòng)到body里面(但是這么做的話,文檔會(huì)被當(dāng)作是無(wú)效文檔)。
\\在IE中,提供這個(gè)服務(wù)的類有很多,最普遍的類即CMarkup。負(fù)責(zé)“指向元素、區(qū)域”的Markup指針類名字是CMarkup Pointer,它們都派生自CBase。
\\如果有關(guān)注類似的內(nèi)容的話,之前發(fā)的一個(gè)CMarkup Pointer空指針引用的問(wèn)題其實(shí)就與此相關(guān)。
\\關(guān)于CMarkup Pointer,需要注意的地方是可能會(huì)導(dǎo)致IE崩潰或者出其他錯(cuò)誤,比如:
\\(1)Markup Pointer剛創(chuàng)建,或者以一個(gè)無(wú)效對(duì)象為構(gòu)造函數(shù)的參數(shù)創(chuàng)建的時(shí)候是未指向狀態(tài),也就是說(shuō)啥都沒(méi)指,通常這個(gè)值是0,這個(gè)很可能會(huì)導(dǎo)致空指針引用;
\\(2)Markup Pointer設(shè)置了指針粘滯(當(dāng)當(dāng)前指針?biāo)趨^(qū)域發(fā)生移動(dòng)之后,區(qū)域內(nèi)的指針是否也跟著計(jì)算新位置)的時(shí)候,如果同時(shí)也設(shè)置重力(重力分為左右重力,簡(jiǎn)單來(lái)說(shuō),就是在指針處插入一個(gè)內(nèi)容,操作完之后,指針是應(yīng)該貼著左邊的內(nèi)容還是右邊的內(nèi)容),且在經(jīng)過(guò)某些操作后發(fā)生了歧義,在對(duì)Markup Pointer指向的部分進(jìn)行移動(dòng)、刪除過(guò)程后,Markup Pointer有可能會(huì)重新變成未指向狀態(tài)。這是因?yàn)橹羔樦赶虻膬?nèi)容不存在或無(wú)效了,指針已經(jīng)從文檔中移除(注意是remove)了,但是指針自身還沒(méi)有被刪除(delete),以后如果重用這個(gè)指針又沒(méi)做校驗(yàn)的話,很可能就會(huì)出錯(cuò)。
\\(3)Markup Pointer左右移動(dòng)的時(shí)候也有可能出錯(cuò)。
\\還有就是一個(gè)經(jīng)驗(yàn)條例,IE中代碼很依賴比較上層的有效性檢查,所以一旦中底層代碼接收到了無(wú)效數(shù)據(jù),IE就很可能會(huì)出現(xiàn)異常。
\\還是重提一下關(guān)于Markup Service的內(nèi)容,如果之前沒(méi)接觸過(guò)的話,最開(kāi)始只了解個(gè)大概即可,之后等了解了更多IE相關(guān)的內(nèi)容時(shí),這一塊的東西才容易和其他部分聯(lián)系起來(lái)。
\\參考資料
\\(1) 騰訊反病毒實(shí)驗(yàn)室:深度解析 AppContainer 工作機(jī)制
\\(2) Q\u0026amp;A: 64- Bit Internet Explorer
\\(3) Windows 8 Metro/Modern Style IE 10
\\(4) Enhanced Memory Protections in IE10
\\感謝魏星對(duì)本文的策劃和審校。
\給InfoQ中文站投稿或者參與內(nèi)容翻譯工作,請(qǐng)郵件至editors@cn.infoq.com。也歡迎大家通過(guò)新浪微博(@InfoQ,@丁曉昀),微信(微信號(hào):InfoQChina)關(guān)注我們,并與我們的編輯和其他讀者朋友交流(歡迎加入InfoQ讀者交流群)。
總結(jié)
以上是生活随笔為你收集整理的IE安全系列:IE浏览器的技术变迁(上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 错过了淘宝、拼多多,今年的电商风口抖音小
- 下一篇: 前端小白奋斗史03(css)