編碼與解碼 -- 瀏覽器做了什么

阿里云上的域名總是讓我備案,實在是懶得備蹦骑。還是用github上的博客吧慈省,刀背藏身

無論是作為開發(fā),還是作為黑客眠菇,企圖從Web 端注入SQL边败,或者是XSS 的時候袱衷,編碼和解碼都是一個重要的問題、作為一個瀏覽器笑窜,有URL解析引擎致燥,有HTML解析引擎,還有JS 解析引擎排截。其執(zhí)行的先后順序往往決定了輸出的結果嫌蚤。這種多標簽語言互相嵌入的,同時又需要客戶端服務器交互的技術断傲,正是給了XSS 可趁之機搬葬。下面我們要做的,是去了解瀏覽器到底如何解碼艳悔,該如何在解碼過程中避免漏洞的產生急凰。在此之上,我更愿意揭開整個瀏覽器的工作流程猜年,了解其本質抡锈。

這里有篇神文How browsers work, 也是本篇文章的重要參考乔外。

瀏覽器基本的工作流程

進入主話題之前床三,先閑扯一些廢話,先羅列一下瀏覽器的主要構成:

  1. 用戶界面- 包括地址欄杨幼、后退/前進按鈕撇簿、書簽目錄等,也就是你所看到的除了用來顯示你所請求頁面的主窗口之外的其他部分
  2. 瀏覽器引擎- 用來查詢及操作渲染引擎的接口
  3. 渲染引擎- 用來顯示請求的內容差购,例如四瘫,如果請求內容為html,它負責解析html及css欲逃,并將解析后的結果顯示出來
  4. 網(wǎng)絡- 用來完成網(wǎng)絡調用找蜜,例如http請求,它具有平臺無關的接口稳析,可以在不同平臺上工作
  5. UI 后端- 用來繪制類似組合選擇框及對話框等基本組件洗做,具有不特定于某個平臺的通用接口,底層使用操作系統(tǒng)的用戶接口
  6. JS解釋器- 用來解釋執(zhí)行JS代碼
  7. 數(shù)據(jù)存儲- 屬于持久層彰居,瀏覽器需要在硬盤中保存類似cookie的各種數(shù)據(jù)诚纸,HTML5定義了web database技術,這是一種輕量級完整的客戶端存儲技術

其組件架構是這樣的:


值得一提的是陈惰,對于Chrome 瀏覽器來說畦徘,Chrome 為每個Tab 都分配了各自的渲染引擎,每個Tab 都是一個獨立的進程。

實際上旧烧,我們重點關注的就是其中的Rendering engine 和 JavaScript Interpreter ,渲染引擎和解釋器画髓。說了那么多廢話掘剪,我們開始了解瀏覽器的主流程。


這是瀏覽器從接收代碼奈虾,到渲染完成的過程夺谁,從開頭我們能看到它有三個主要部分:

  1. HTML/SVG/XHTML 解析,事實上肉微,Webkit有三個C++的類對應這三類文檔匾鸥。解析這三種文件會產生一個DOM Tree。
  2. CSS 解析碉纳,解析CSS會產生CSS規(guī)則樹勿负。
  3. Javascript DOM,主要是通過DOM API和CSSOM API來操作DOM Tree和CSS Rule Tree.

瀏覽器最早開始解析HTML劳曹,將標簽轉化為內容樹中的DOM 節(jié)點奴愉,此時識別標簽的時候,HTML 解析器是無法識別哪些被實體編碼的內容的铁孵,只有建立起DOM 樹锭硼,才能對每個節(jié)點的內容進行識別,如果出現(xiàn)實體編碼蜕劝,則會進行實體解碼檀头。在此基礎上,JavaScript DOM API 參與進來岖沛,可以對DOM 樹進行修改暑始,改變DOM樹的結構和內容。而此時婴削,CSS解析器則解析外部CSS 文件以及Style 標簽中的樣式內容蒋荚,這些信息將搭配HTML 中的可見指令構建起一個Rendering Tree。

這里CSS 解析器在構造Redering Tree 之前馆蠕,為了輔助會有CSS Rule Tree期升,他是為了完成匹配,然后把CSS Rule 附加給Rendering Tree 上的每個element互躬,也就是每個DOM 節(jié)點播赁。其中有一個layout/reflow 的過程,就是為了計算每個frame 位置等信息吼渡。

當然容为,個人并不是一個Web 開發(fā)者,無意在CSS 這一塊花費巨大的時間,下面這個視頻會很形象的讓你感受到layout/reflow 的過程坎背。Gecko reflow visualization

完成布局之后替劈,使用UI 后端完成每個節(jié)點的繪制,完成顯示得滤。

編碼和解碼發(fā)生的順序

在看完瀏覽器工作流程之后(當然陨献,這個流程講的有點簡單了),我們來看一下編碼和解碼的順序懂更,對應著工作流程就很容易記清楚了眨业。

URL 解析

在這些所有工作流程開始之前,瀏覽器一定需要有一個URL 來指示資源的位置沮协,為什么剛才沒有說呢龄捡,因為這個URL 是瀏覽器發(fā)送給服務器的請求信息,其處理工作并不是瀏覽器的工作慷暂。比如我們考慮一段簡單的代碼:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<a href="javascript:alert('<?php echo $_GET['input'];?>');">test</a>
</body>
</html>

input 內容參數(shù)為: %26lt%5cu4e00%26gt

該值構造在URL 里聘殖,瀏覽器直接發(fā)送給服務器,服務器接收之后行瑞,先進行URL 解析就斤,看到了% 這個符號,于是URL 解碼,input 內容變成了&lt\u4e00&gt,所以對于瀏覽器從服務器端獲取的頁面數(shù)據(jù)來說浆西,此時test 對應的標簽變成了如下:

<a href="javascript:alert('&lt\u4e00&gt');">test</a>

這一步完成在所有的工作之前,URL 解碼發(fā)生在第一部绷旗,而且它基本上都發(fā)生在服務器上。

HTML 解析

瀏覽器接收到頁面數(shù)據(jù)副砍,于是開始進行HTML 解析衔肢,構造DOM樹。構造的過程與語言的編譯過程是相似的豁翎,接收文檔角骤,先進行詞法分析,然后語法分析心剥,構建解析樹邦尊。

解析過程是迭代的,解析器從詞法分析器處取道一個新的符號优烧,并試著用這個符號匹配一條語法規(guī)則蝉揍,如果匹配了一條規(guī)則,這個符號對應的節(jié)點將被添加到解析樹上畦娄,然后解析器請求另一個符號又沾。如果沒有匹配到規(guī)則弊仪,解析器將在內部保存該符號,并從詞法分析器取下一個符號杖刷,直到所有內部保存的符號能夠匹配一項語法規(guī)則励饵。如果最終沒有找到匹配的規(guī)則,解析器將拋出一個異常滑燃,這意味著文檔無效或是包含語法錯誤役听。

而最后輸出的樹,也就是這里的解析樹不瓶,是由DOM元素及屬性節(jié)點組成的禾嫉。對于以下一個最常見的例子:

<html>
    <body>
        <p>
          Hello DOM
        </p>
        <div><img src=”example.png” /></div>
    </body>
</html>

它將轉換為下面的DOM 樹:


所以灾杰,HTML 的分析器只能識別特定的詞法規(guī)則蚊丐,才能構建起DOM 樹,這一塊艳吠,HTML 不會做解碼的工作麦备,因為它做不了。所以昭娩,試圖這樣構造利用漏洞凛篙,是不可能的:

<img src&#x3d;"http://www.example.com">

因為在構建DOM 樹的時候,這樣是無法識別的栏渺,也就破壞了標簽本身的結構呛梆。而HTML 解碼,是在DOM樹結構OK磕诊,對節(jié)點內容解析的時候填物,會進行轉碼,所以以下兩種寫法霎终,是完全一樣的:

![](http://www.example.com)
[站外圖片上傳中……(5)]

所以滞磺,在DOM 樹構建完畢之后,這些HTML 實體編碼的內容就會被解碼莱褒。JS 的解釋器還沒有走進戰(zhàn)場击困。不過由于DOM 的存在,JavaScript還是參與了DOM Tree 的構建過程广凸,這時候阅茶,編碼的解析就變得繞了一些。在此我們先忽略掉這一個谅海,先繼續(xù)講主過程講完目派,繼續(xù)考慮這個代碼:

<a href="javascript:alert('&lt\u4e00&gt');">test</a>

HTMl 解析器構建DOM Tree, href中的內容,如果識別為實體編碼的胁赢,會透明的解碼企蹭,于是它就變成了這樣:

<a href="javascript:alert('<\u4e00>')">test</a>

CSS 的編碼問題

一般來說白筹,CSS 解析器會做接下來的工作,不過一般來說谅摄,為了考慮到更好的體驗和性能徒河,并不會等到所有的html都解析完成之后再去構建和布局render樹。它是解析完一部分內容就顯示一部分內容送漠,同時顽照,可能還在通過網(wǎng)絡下載其余內容。

當然CSS不會干擾到DOM 樹的建立闽寡,他會結合CSS文件和style 標簽代兵,以及HTML中的課件指令來構建起reder tree。這里JavaScrit 的 CSSOM api 也會出一些力爷狈。

CSS 編碼解析是用了一套不太正統(tǒng)的轉義策略:用一個反斜杠植影,后邊跟1~6位十六進制數(shù)字構成。涎永,所以字母e 可以編碼為 \65, \065,\000065思币。而因為這樣,后邊就不能直接緊跟數(shù)字或字母羡微,否則會被當成轉義里的內容處理谷饿,所以CSS 選擇了空格作為終止標識,在解碼的時候妈倔,再將空格去除博投。

同時,CSS還支持直接使用反斜杠對非十六進制字符進行轉義的方式盯蝴,就按緊跟著反斜杠后邊的字符的字面意思進行解釋毅哗,這種機制可用來轉義引號和反斜杠本身,不過不能轉義HTML 控制的字符结洼,比如尖括號黎做,那是因為HTML 解析器總是先于CSS 解析器。

由于CSS 轉義規(guī)定的語焉不詳松忍,許多解析器會對本該用引號括起來的字符串進行任意的轉義蒸殿,特別的,在IE 瀏覽器里鸣峭,這種轉義優(yōu)先級高于偽函數(shù)語法宏所,于是下邊兩種情況的寫法是一樣的:

color:expression(alert(1))
color:expression\028 alert \028 1 \029 \029

如果對該部分內容感興趣,可以閱讀開始提到的那篇文章摊溶,或者是我之前寫的一些文章爬骤。

JS 解釋器

上邊提到了style ,是建立reder tree 的時候使用的莫换,它怎么工作的呢霞玄≈枇澹考慮到我們的瀏覽器為了讓不同的解析器來工作處理不同的內容,實際上坷剧,在處理諸如< script> < style> 這樣的標簽惰爬,解析器會自動切換到特殊解析模式,而src href 后邊加入的JavaScript 偽URL惫企,也會進入JS 的解析模式撕瞧。而進入該解析模式的時候,該DOM節(jié)點已經(jīng)建立起來了狞尔。

還是上邊的例子丛版,經(jīng)過HTML 的解碼,代碼已經(jīng)變成這樣:

<a href="javascript:alert('<\u4e00>')">test</a>

javascript 出發(fā)了JS 解釋器偏序,JS會先對內容進行解析页畦,里邊有一個轉義字符\u4e00,前導的 \u 表示他是一個Unicode 字符,根據(jù)后邊的數(shù)字禽车,解析為'一'寇漫,于是在完成JS的解析之后變成了:

<a href="javascript:alert('<一>')">test</a>

然后JS 解釋器執(zhí)行alert("< 一>")刊殉,這句話會交給瀏覽器渲染殉摔,最終彈窗。

這里邊會有一個看起來讓人有些疑惑的東西记焊,仍以上一段代碼為例逸月,假如我們編碼的位置不是括號里,而是在alert上遍膜,我們知道碗硬,js 是會對它進行逆轉義的:

<a href="javascript:\u0061lert('<一>')">test</a>

而另一方面,如果想用這種方式來替換掉圓括號瓢颅,或者引號恩尾,會判定為失敗。同時挽懦,主要注意的是翰意,上邊這種直接在字符串外進行轉義的方式,只有Unicode 轉義方式支持信柿,其他轉義方式則不行冀偶。其實,這樣的策略是正確的渔嚷,因為對于JavaScript进鸠,轉義編碼應當只出現(xiàn)在標示符部分,不能用于對語法有真正影響的符號形病,也就是括號客年,或者是引號霞幅。其實,這樣的處理方法量瓜,反而是比CSS 更加合理的蝗岖。

在一個頁面中,可以出發(fā)JS 解析器的方式有這么幾種:

  • 直接嵌入< script> 代碼塊榔至。
  • 通過< script sr=... > 加載代碼抵赢。
  • 各種HTML CSS 參數(shù)支持JavaScript:URL 觸發(fā)調用。
  • CSS expression(...) 語法和某些瀏覽器的XBL 綁定唧取。
  • 事件處理器(Event handlers),比如 onload, onerror, onclick等等铅鲤。
  • 定時器,Timer(setTimeout, setInterval)
  • eval(...) 調用枫弟。

我們看到邢享,這些藏匿在HTML 便簽中的各種JS 調用,就可以想到Web 開發(fā)者的頭有多大了淡诗,我們舉一個簡單的栗子:

比如定時器那里骇塘,考慮以下代碼:

< script>
var value = "user_string";
...
setTimeout("do_stuff('"+value+"')", 1000);
< /script>

表面上看他沒有問題,對 value 只做一次轉義就好了韩容,但實際呢款违,考慮其解析過程,首先是HTML 解析出script 塊群凶,然后JavaScript 做第一次解析插爹,檢查setTimeout 語法,而等到1秒之后请梢,才會解析do_stuff赠尾,如果不多做一次轉義,就有可能構造成一次注入毅弧,比如user_string 中插入一個JavaScript編碼的構造气嫁,截斷前邊函數(shù),然后構造自己的攻擊部分够坐。

下面我們說一說DOM寸宵,我們知道常見的DOM 操作:

DOM 常見的方法有:

  • 獲取節(jié)點
    • getElementsById()
    • getElementsByTagName()
    • getElementsByClassName()
  • 新增結點
    • document.createElement() 創(chuàng)建節(jié)點對象,參數(shù)是字符串也就是html標簽
    • createTextNode 創(chuàng)建文本節(jié)點咆霜,配合上一個使用
    • appendChild(element) 把新的結點添加到指定節(jié)點下邓馒,參數(shù)是一個節(jié)點對象
    • insertChild() 在指定結點錢插入新的節(jié)點
  • 修改節(jié)點
    • replaceChild() 節(jié)點交換
    • setAttribute() 設置屬性
  • 刪除節(jié)點
    • removeChild(element) 刪除節(jié)點,要先獲得父節(jié)點然后再刪除子節(jié)點
  • 一些屬性
    • innerHTML 節(jié)點內容蛾坯,可以獲取或者設置
    • parentNode 當前節(jié)點的父節(jié)點
    • childNode 子節(jié)點
    • attributes 節(jié)點屬性
    • style 修改樣式

這樣就有一些疑惑了光酣,之前,我們說了脉课,基本的解析順序是這樣的救军,URL 解析器财异,HTML 解析器, CSS 解析器唱遭,JS解析器戳寸,如果安安靜靜的按照這個順序下去,應該很容易理清楚拷泽。然而DOM 操作里我們可以看到可以新增節(jié)點疫鹊,也可以修改節(jié)點屬性,節(jié)點的內容和樣式都可以修改司致。那么假如我們使用innerHTML 修改了某節(jié)點的內容拆吆,讓其構成了一個新的節(jié)點,那么會有什么效果呢脂矫?我在Chrome 上做了一些實驗枣耀,代碼如下:

<html>
<body>

<p id="1">hello</p>

<img src=# onerror="&#97;lert(1)" />
<script>
document.getElementById("1").innerHTML = "<img src=&#35; on\u0065rror=&#97;lert&#40;1)>";  

</script>
<!--<script>
document.getElementById("1").innerHTML = "&#60;img src=&#34;1&#34; onerror=&#34;alert(1)&#34;&#62;";  
&#38;&#35;&#57;&#55;&#59;
</script>-->

</body>
<html>

一個正常的容易理解的過程是這一行:

<img src=# onerror="&#97;lert(1)" />

HTML 解析到標簽,建立DOM 樹庭再,然后對節(jié)點內容進行實體解碼捞奕,&#97; 就變成a, 隨后在js 解析階段拄轻,正常的觸發(fā)了彈窗颅围,先后順序OK。

但對于下面這段代碼:

<script>
document.getElementById("1").innerHTML = "<img src=&#35; on\u0065rror=&#97;lert&#40;1)>";  
</script>

使用了DOM 操作哺眯,修改前邊標簽中的內容谷浅,添加了一個img 內容扒俯,因為進入了script 進入了JavaScript的特殊解析模式奶卓,所以此處HTML 不得干擾,首先JavaScript解析器撼玄,會先對其中編碼的內容解碼夺姑,于是onerror 就還原回來了,于是正常的執(zhí)行了JS 語句掌猛,在HTML 文檔中盏浙,將hello 變成了img。

那么問題來了荔茬,如上那樣废膘,對onerror 的內容作了HTML 實體編碼,會不會彈窗呢慕蔚? 答案是顯然的丐黄,該標簽傳回給HTML,HTML 建立DOM節(jié)點孔飒,透明的解碼節(jié)點內容灌闺,onerror 又會執(zhí)行其中的JS 腳本艰争,彈出窗口。

其實桂对,這里也不難理解甩卓,因為HTML 是從上到下解析,遇到< script> 于是進入了特殊的解析模式蕉斜,使用JS 解析器逾柿,做了一個DOM 操作,該DOM 操作修改了前邊的DOM 樹宅此,該塊內容鹿寻,需要使用HTML 解析重塑DOM 樹,那么節(jié)點內容中的實體編碼就會被解碼诽凌,然后onerror 中觸發(fā)腳本毡熏,JS 又會對內容進行一次解析。

這一點很好理解:

[站外圖片上傳中……(6)]

如上侣诵,內容中有HTML實體編碼痢法,還有js 的Unicode 編碼,正常彈窗沒有問題杜顺。

總結說來财搁,實際上,DOM 操作實際上是js強勢介入 HTML 和CSS 的結果躬络,使用DOM 操作尖奔,對DOM Tree 造成了改變,會調用到HTML 解析器重新對其解析穷当,于是流程又會返回到最開始說的那個解析流程里去提茁。這樣反復的情況,再加上編碼的重疊馁菜,很容易讓開發(fā)者無所適從茴扁,考慮下面的代碼:

<p id="1">hello</p>

[站外圖片上傳中……(7)]
<script>
document.getElementById("1").innerHTML = "bye";

function a(){
document.getElementById("1").innerHTML = "<img src=# on\u0065rror=&#97;&#108;&#101;&#114;&#116;(1)>";
}

function timedMsg()
{
var t=setTimeout("a()",5000)
}
</script>
<input type="button" value="111" onClick = "timedMsg()" />

整個頁面渲染完畢,而當點擊按鈕之后汪疮,會觸發(fā)DOM操作的腳本峭火,五秒鐘之后,彈窗智嚷。

如果想要修改的內容中有腳本卖丸,內容中的腳本部分使用JS編碼,再使用HTML 編碼盏道,然后再使用JS Unicode編碼稍浆,那么解碼的過程就是先JS 解碼,再HTML 解碼,再JS 解碼粹湃,然后執(zhí)行恐仑。

總結

其實總的來說,其道理還是易于理解的为鳄,只是由于一些特別的操作裳仆,造成了一些困擾,于是在編碼上孤钦,會理不清頭緒歧斟,如果再此基礎上我們再使用String.fromCharCode() 這個一直以來容易被開發(fā)者忽略的功能,更會摸不清頭腦偏形。

而正是由于這種摸不清頭腦的開發(fā)之下静袖,黑客們才有可趁之機,制造各種變體俊扭,繞過孱弱的過濾器队橙。

總體來說,在編碼這件事上萨惑,只要理清楚捐康,URL解碼,HTML解碼庸蔼,CSS解碼解总,JS解碼,以及DOM 操作在其中扮演的角色姐仅,就基本上能理清楚了花枫。作為一個開發(fā)者,安全編碼是必須要重視的內容掏膏,所以劳翰,對于編碼,不可以逃避壤追,在構建安全的過濾規(guī)則的時候磕道,一定要考慮清楚各種可能的編碼繞過的方式,以避免損失。

如何避免這些漏洞的產生行冰,我會再以后繼續(xù)寫,關于瀏覽器的解碼過程就寫到這里吧伶丐。對這一問題悼做,仍然還有一些問題有待解決,個人能力有限哗魂,其中也有可能存在錯誤和疏漏肛走,請諒解~

PS. 參考:開頭提到的文章,W3cschool 上各種函數(shù)录别,各種編碼朽色×谕蹋《The Tangled Web》這本神書,和一堆谷歌搜索葫男。
pps. 因為近視眼抱冷,打字時候,不怎么喜歡盯著屏幕梢褐,所以旺遮。。盈咳。耿眉。錯別字可能有點多。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末鱼响,一起剝皮案震驚了整個濱河市鸣剪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丈积,老刑警劉巖西傀,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異桶癣,居然都是意外死亡拥褂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門牙寞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饺鹃,“玉大人,你說我怎么就攤上這事间雀』谙辏” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵惹挟,是天一觀的道長茄螃。 經(jīng)常有香客問我,道長连锯,這世上最難降的妖魔是什么归苍? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮运怖,結果婚禮上拼弃,老公的妹妹穿的比我還像新娘。我一直安慰自己摇展,他們只是感情好吻氧,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般盯孙。 火紅的嫁衣襯著肌膚如雪鲁森。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天振惰,我揣著相機與錄音歌溉,去河邊找鬼。 笑死报账,一個胖子當著我的面吹牛研底,可吹牛的內容都是我干的。 我是一名探鬼主播透罢,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼榜晦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了羽圃?” 一聲冷哼從身側響起乾胶,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎朽寞,沒想到半個月后识窿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡脑融,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年喻频,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肘迎。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡甥温,死狀恐怖,靈堂內的尸體忽然破棺而出妓布,到底是詐尸還是另有隱情姻蚓,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布匣沼,位于F島的核電站狰挡,受9級特大地震影響,放射性物質發(fā)生泄漏释涛。R本人自食惡果不足惜加叁,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枢贿。 院中可真熱鬧殉农,春花似錦、人聲如沸局荚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耀态。三九已至轮傍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間首装,已是汗流浹背创夜。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仙逻,地道東北人驰吓。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像系奉,于是被迫代替她去往敵國和親檬贰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內容

  • 轉載說明 一缺亮、介紹 瀏覽器可以被認為是使用最廣泛的軟件翁涤,本文將介紹瀏覽器的工作原理,我們將看到萌踱,從你在地址欄輸入g...
    17碎那年閱讀 2,448評論 0 22
  • 簡介瀏覽器可以被認為是使用最廣泛的軟件并鸵,本文將介紹瀏覽器的工 作原理鸳粉,我們將看到,從你在地址欄輸入google.c...
    聽風閣閱讀 3,287評論 0 7
  • 目錄一园担、介紹二届谈、渲染引擎三、解析與DOM樹構建四粉铐、渲染樹構建五疼约、布局六、繪制七蝙泼、動態(tài)變化八程剥、渲染引擎的線程九、CS...
    饑人谷_米彌輪閱讀 2,457評論 0 10
  • 之前積累了XSS 有一段時間汤踏,因為目前開始了一件有趣的工程织鲸,需要整合非常多的知識,其中Web 安全這一塊出現(xiàn)最多的...
    刀背藏身閱讀 9,059評論 0 16
  • 趁著假期完的最后一個晚上 來音樂廳看 情書 其實不称偬撸看日本小說的 因為有時候會覺得 表達方式很別扭 所以看的書也很...
    lallallla閱讀 148評論 0 0