HTTP抓包實戰


HTTP:超文本傳輸協議

  允許將HTTP文檔從Web服務器傳送到客戶端的瀏覽器。HTTP請求報文分為3部分。第一部分叫做起始行(Request line)。第二部分叫首部(Request Header)。第三部分叫主題(Body)。

  Response一樣,響應行(Response line),首部,主體。

  Fiddle本質是一個代理服務器,代理地址127.0.0.1,端口;8888

GET  /dongye95/home?wvr=5  HTTP/1.1

HTTP/1.1  200 OK

代理服務器

  1. 共享網絡
  2. 提高訪問速度,大部分代理服務器有緩沖功能
  3. 突破訪問限制
  4. 隱藏身份

 

Web通信安全

1.瀏覽器和Web服務器之間的內容應該只有瀏覽器和Web服務器能夠看到通信的真正內容。

2.HTTP請求的內容和HTTP請求的響應不會被第三方篡改。

Web服務器與每個客戶端使用不同的對稱加密算法。

 

HTTPS = HTTP + TLS 安全傳輸層協議或 SSL(Secure Sockets Layer 安全套接層)

 

HTTPS firefox 證書

包括IE、Chrome 和safari在內的大部分應用都使用Windows證書庫來驗證證書。firefox瀏覽器是自己維護證書列表,所以需要單獨安裝fiddle證書。

Tunnel to

  HTTP Tunnel(也叫HTTP隧道,HTTP穿梭)是這樣一種技術。它用HTTP協議在要通信的 client 和 server 建立起一條 “Tunnel”。然后client 和server之間的通信都是在這條Tunnel的基礎上實現的。簡單來說,當Fiddle當做代理轉發HTTPS請求的時候,就會產生“CONNECT Tunnels”。

  Fiddle可隱藏,Rules-》Hide CONNECTS

HTTP協議請求方法和狀態碼

HTTP 請求方法

GET 請求指定的頁面信息並返回實體主體
HEAD 類似於GET請求,只不過返回的響應中沒有具體的內容,用於獲取報頭
POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中,post請求可能會導致新的資源的建立和/或對已有資源的修改
PUT 從客戶端向服務端傳送的數據取代指定文檔的內容
DELETE 請求服務器刪除指定的頁面
OPTIONS 詢問支持的方法,用來查詢針對請求 URI 指定的資源支持的方法
TRACE 追蹤路徑,讓 Web 服務器端將之前的請求通信環回給客戶端的方法
CONNECT 要求用隧道協議連接代理,要求在與代理服務器通信時建立隧道,實現用隧道協議進行 TCP通信。

 

 

 

 

 

 

 

GET

  用於獲取資源,常用於向服務器查詢某些信息。打開網頁一般都是用GET方法,因為要以Web服務器獲取信息。

參數

  瀏覽器也可以在GET方法中把數據傳給服務器,數據放在URL的問號(?)后面,叫查詢字符串,也叫做Query String。查詢字符串以“名=值”這樣的形式出現,多個之間用“&”隔開

POST

  通常用來把表單中填好的數據發送給服務器

 

GET和POST區別

  1. GET提交的數據會放在URL之后。POST放在Body中。
  2. GET提交的數據大小是有限制的(URL長度有限制)。POST沒有限制。
  3. GET方式提交數據會帶來安全問題,比如用戶名和密碼出現在URL中。頁面被緩存或其他人訪問這台機器,可從歷史記錄中獲得該用戶的賬號和密碼。

 

HTTP/1.1 狀態碼

狀態碼 已定義范圍 分類
1XX 100 - 101 信息提示表示請求已被成功接收,繼續處理
2XX 200 - 206 成功表示請求已被成功接收、理解、接收
3XX 300 - 302 重定向,要完成請求,必須進行更進一步的處理
4XX 400 - 415 客戶端錯誤,請求有語法錯誤或請求無法實現
5XX 500 - 505 服務器錯誤,服務器未能實現合法的請求

 

常見的狀態碼

名稱 釋義
200 OK:服務器成功處理了請求(這個是我們見到最多的)
301/302 Moved Permanently(重定向):請求的URL已移走。Response中應該包含一個Location URL,說明資源現在所處的位置
304 Not Modified(未修改):客戶的緩存資源是最新的,需要客戶端使用緩存
404 Not Found:未找到資源
401 禁止訪問
501 Internal Server Error:服務器遇到一個錯誤,使其無法對請求提供服務

 

200(OK)

  表示該請求被成功地完成,所請求的資源成功地發送回客戶端。

204(No Content,沒有內容

  返回的HTTP響應中只有一些Header和一個狀態行,沒有實體的主體內容(沒有響應Body)

204 狀態碼作用如下:

  1. 在不獲取資源的情況下了解資源的情況(比如判斷其類型)、
  2. 通過查看HTTP響應中的狀態碼看某個對象是否存在
  3. 通過常看Header測試資源是否被修改

206(Partial Content,部分內容)

  表示服務器已經成功處理了部分GET請求(只有發送GET方法的HTTP請求,Web服務器才可能返回206)

  1. FlashGet、迅雷或者HTTP下載工具都是使用206狀態碼來實現斷點續傳
  2. 將一個大文檔分解為多個下載段同時下載,比如在線看視頻。

http://tv.sohu.com/20121011/n354681393.shtml

301(Moved Permanently)

  表示請求的網頁已經永久性地轉移到另一個地址

如下情況需要用到301:

  1. 防止用戶輸錯域名。
  2. 網站更換域名。比如www.360buy.com改為www.jd.com
  3. 有多個權重不錯的域名,需要把所有的權重都傳遞到新域名上,這就需要301重定向了。如果不設置301,多個域名綁定在一個主機頭上,會被搜索引擎認為是兩個相同的站點,不利於網站的排名。綁定的域名越多,內容重復度也就越高,排名越低。

302(Found)

  當我們訪問一個URL的時候,服務器要我們訪問另一個資源,這回收瀏覽器會繼續發一個HTTP,請求訪問新的資源。

  比如為登陸狀態下,直接訪問需要登陸才能訪問的頁面,會被服務器返回302,跳轉到登陸頁面。

 

301和302區別

  1. 301表示舊地址的資源已經被永久的移除了(這個資源不可訪問了),搜索引擎會把權重算到新地址。
  2. 302表示舊地址的資源還在(仍然可以訪問),這個重定向只是臨時地從舊地址跳轉到新地址,搜索引擎會把權重算到舊地址。

304(Not Modified)

  304狀態碼代表上次的文檔已經被緩存了,還可以繼續使用

如果不想使用本地緩存,用【Ctrl + F5】強制刷新

400(Bad Request)

  表示客戶端請求有語法錯誤

401(Unauthorized)

  狀態碼401是指未授權錯誤,有些網頁采用的是HTTP基本認證(Basic Authentication),需要在HTTP請求中帶上 Authentication Header,否則服務器會返回狀態碼401

403(Forbidden)

  表示Web客戶端發送的請求被Web服務器拒絕了。如果想說明原因,可以在body中說明,但是這個狀態碼通常表示服務器不想說明拒絕原因

404(Not Found)

  資源不存在。本來就不存在,或者被刪了,或者被牆了。

500(Internal Server Error)

  服務器內部錯誤。比如代碼錯誤,數據庫連接語句出錯,空指針等。

503(Server Unavailable)

  服務器暫不可用。由於服務器維護或者過載,服務器當前無法處理請求;這個狀況是臨時的,並且將在一段時間以后恢復。

HTTP協議Header介紹

  Header翻譯成中文,叫“首部”或者“頭域”。

  Header語法格式是:“key:value”,一行一個Header

Cache:緩存相關。如果本地有“已緩存的”副本,就可以從本地存儲設備而不是從原始服務器中提取這個文檔。
Accept:表示瀏覽器客戶端可以接受的媒體類型。

Accept:text/html,*/*;q=0.8 代表瀏覽器可以處理所有的類型。一般瀏覽器客戶端給Web服務器發送的都是這個。

Accept-Encoding:跟壓縮有關。Accept-Encoding: gzip, deflate, br   

Accept-Language:瀏覽器聲明自己接受的語言。

User-Agent:瀏覽器用來告訴服務器,客戶端使用的操作系統及版本、CPU類型、瀏覽器及版本,瀏覽器渲染引擎、瀏覽器語言、瀏覽器插件等。

Referer:用來讓服務器判斷來源頁面,即用戶是從哪個頁面來的。網站通常用其來統計用戶來源,看用戶是從搜索頁面來的,還是從其他網站鏈接來的,或是從書簽等訪問的,以便合理定義網站。

Referer有時也被用作防盜鏈,即下載時判斷來源地址是不是在網站域名之內,否則就不能下載或顯示。

Connection:從HTTP/1.1起,系統默認都開啟了Connection:Keep-Alive,保持連接特性

HTTP協議是基於TCP協議的。當一個網頁完全打開后,客戶端和服務器之間用於傳輸HTTP數據的TCP連接不會關閉;如果客戶端再次訪問這個服務器上的網頁,將會連續使用這一條已經建立的連接。

Keep-Alive不會永久保持連接,它有一個保持時間。

Host:這個Header是必需的,它的作用是指定被請求的主機和端口號。

Web網頁抓包和Fiddler修改包

打開一個網頁,瀏覽器需要發送很多個請求。

  1. 在瀏覽器輸入http://www.cnblogs.com
  2. 瀏覽器會發送第一個HTTP請求去獲取頁面布局的HTML,這個請求叫做“父請求”。然后服務器把HTTP響應發回給瀏覽器。
  3. 瀏覽器會分析HTTP響應中的HTML,然后發現HTML中引用了其他文件:比如圖片,CSS,JS,JSON。瀏覽器會自動再次發送很多HTTP請求,去獲取圖片,CSS文件或者JS文件。這些HTTP請求叫做“子請求”。
  4. 當所有自請求的響應都返回后,瀏覽器會把1個父請求加上多個子請求渲染出來。這樣就形成了一個頁面。

 

用Fiddler選擇子請求

先找到父請求,鼠標右鍵選擇Select -> Child Requests

用Fiddler選擇父請求

先找到子請求,鼠標右鍵選擇Select -> Parent Requests

用Fiddler選擇相同請求

選擇一個請求,鼠標右鍵選擇Select -> Duplicate Requests

 

簡單性能測試

  1. 子請求出現了404或者500之類的錯誤,會嚴重影響整個網頁的加載速度。
  2. 子請求的響應速度慢也會影響網頁加載的速度。

可以清楚看到每個HTTP請求的響應時間

修改HTTP請求單個斷點:bpu www.baidu.com。取消:bpu

修改HTTP響應單個斷點:bpafter www.baidu.com。取消 bpafter

HTTP協議中的緩存

HTTP中具有緩存功能的是瀏覽器緩存和代理服務器緩存。

HTTP緩存是指當Web請求抵達緩存時,如果本地有“已緩存的”副本,就可以從本地存儲設備而不是從原始服務器中提取這個文檔。

緩存優點

  • 減少了冗余的數據傳輸,節省了傳輸時間
  • 減少了服務器的負擔,大大提高了網站性能
  • 加快了客戶端加載網頁的速度

Web服務器通過以下2種方式來判斷瀏覽器緩存是否最新

  1. 瀏覽器把緩存文件的最后修改時間通過Header“If-Modified-Since”告訴Web瀏覽器
  2. 瀏覽器把緩存文件的ETag通過Header“If-None-Match”告訴服務器

通過最后修改時間來判斷緩存新鮮度

瀏覽器可以通過緩存文件的修改時間來判斷緩存的新鮮度,具體的步驟如下:

  1. 如果瀏覽器客戶端想請求一個文檔,它首先檢查本地緩存,發現存在這個文檔的緩存,獲取緩存中文檔的最后修改時間,通過“If-Modified-Since”發送HTTP請求給Web服務器。
  2. Web服務器收到HTTP請求,將服務器的文檔修改時間(Last-Modified)跟HTTP請求Header中的If-Modified-Since相比較。如果時間是一樣的,說明緩存還是最新的。Web服務器將發送狀態碼304(Not Modified)給瀏覽器客戶端,告訴客戶端直接使用緩存里的版本。

HTTP請求中跟緩存相關的Header

名稱 釋義
Cache-Control:max-age=0 以秒為單位
If-Modified-Since:Mon,19 Nov 2012 08:38:01 GMT 緩存文件的最后修改時間
If-None-Match:"0693f67a67cc1:0" 緩存文件的ETag
Cache-Control:no-cache 不使用緩存
Pragma:no-cache 不使用緩存

 

HTTP響應中跟緩存相關的Header

名稱 釋義

Cache-Control:public

響應被緩存,並且在多用戶間共享
Cache-Control:private 響應只能作為私有緩存,不能再用戶之間共享
Cache-Control:no-cache 提醒瀏覽器要從服務器提取文檔進行驗證
Cache-Control:no-store 絕對禁止緩存(用於機密、敏感文件)
Cache-control:max-age=60 60s之后緩存過期(相對時間)

Date:Mon,19 Nov 2012 08:39:00 GMT

當前響應發送的時間
Expires:Mon,19 Nov 2012 08:40:01 GMT 緩存過期的時間(絕對時間)
Last-Modified:Mon,19 Nov 2012 08:38:01 GMT 服務器端文件的最后修改時間

ETag:"20b1add7ec1sd1:0"

服務器端文件的ETag值

 

如果同時存在cache-control和Expires怎么辦?瀏覽器總是優先使用cache-control。

ETag

是Entity Tag(實體標簽)的縮寫,是根據實體內容生成的一段hash字符串(類似於MD5或者SHA1之后的結果)

使用ETag主要是為了解決一些Last-Modified無法解決的問題。

  1. 某些服務器不能精確得到文件的最后修改時間,這樣就無法通過最后修改時間來判斷文件是否更新了。
  2. 某些文件的修改非常頻繁,在以秒為單位以下的時間內進行修改,而Last-Modified只能精確到秒
  3. 一些文件的最后修改時間改變了,但是內容並非改變,我們不希望客戶端認為這個文件修改了。

使用【Ctrl + F5】可以強制刷新瀏覽器,可以讓瀏覽器不使用緩存。

Pragma:no-cache的作用和“Cache-Control:no-cache”一模一樣,都是不使用緩存。Pragma:no-cache是HTTP1.0中定義的,所以為了兼容HTTP1.0會同時使用Pragma:no-cache和Cache-Control:no-cache

HTTP協議壓縮和URL Encode

HTTP采用通用的壓縮算法,比如用gzip來壓縮HTML、JavaScript、CSS文件,能大大減少網絡傳輸的數據量,提高了用戶顯示網頁的速度。當然,這同時也會增加一點點服務器的開銷。

HTTP壓縮的過程

  1. 瀏覽器發送HTTP請求給Web服務器,請求中的Header能Accept-Encoding:gzip,deflate(告訴服務器,瀏覽器支持gzip壓縮)
  2. Web服務器接到HTTP請求后,生成原始的HTTP響應,其中有原始的 Content-TypeContent-Length
  3. Web服務器通過gzip來對HTTP響應進行編碼,編碼后Header中有 Content-Type 和 Content-Length(壓縮后的大小),並且增加了Content-Encoding:gzip,然后把HTTP響應發送給瀏覽器。
  4. 瀏覽器接到HTTP響應后,根據Content-Encoding:gzip來對HTTP響應進行解碼,獲取到原始HTTP響應后顯示出網頁。

內容編碼類型:

Content-Encoding header 就是用這些標准化的代號來說明編碼時使用的算法

  1. gzip 表明實體采用 GNU zip 編碼
  2. compress 表明實體采用 UNIX的文件壓縮程序
  3. deflate 表明實體是用 zlib 的格式壓縮的
  4. identity 表明沒有對實體進行編碼;當沒有 Contetn-Encoding header 時,就默認為這種情況。

gzip、compress以及deflate編碼都是無損壓縮算法,用於減少傳輸報文的大小,不會導致信息損失。其中 gzip 通常效率最高,使用最為廣泛。

gzip是如何壓縮的

簡單來說,gzip壓縮實在一個文本文件中找出類似的字符串,並臨時替換它們,從而使整個文件變小。這種形式的壓縮對Web來說非常適合,因為HTML和CSS文件通常包含大量重復的字符串,例如空格、標簽等。也正是因為這樣,gzip對JPEG這類文件壓縮效果不好。

HTTP內容編碼和HTTP壓縮的區別

用其他編碼方式把內容攪亂或者加密,以此來防止未被授權的第三方開到文檔的內容。所以,我們說HTTP壓縮其實就是HTTP內容編碼的一種。

URL Encode介紹

URL只能用英文字母、數字或者某些標點符號,不能使用其他文字和符號。

URL Encode(URL編碼)就是把所有非英文字母、數字字符都替換成百分號(%)后加兩位十六進制數。

比如在搜狗搜索里輸入中文,點擊查找

中文對應為%E4%B8%AD%E6%96%87

在Fiddler中可以使用TextWizard工具來進行轉換

Fiddler使用技巧

1.【Ctrl + X】清空列表

2.Fiddler異常退出后無法上網,重新啟動Fiddler然后再關閉。

3.Fiddler中查詢對話,【Ctrl + F】就可以了。

4.Fiddler中保存抓到的包

  先選中session,然后右鍵 -> Save -> Selected Sessions。保存后的文件后綴名是.saz。文件會保存完整的HTTP請求和HTTP響應

  雙擊.saz文件,或者單機Fiddler菜單欄中的File -> Load Archive,就能打開.saz文件。

Fiddler常用快捷鍵

快捷鍵 用途
Ctrl + X 刪除所有的Session
Ctrl + A 選擇所有的Session
ESC 不選擇任何的Session
Ctrl + I 反選Session
Delete 刪除選擇的Session
Shift + Delete 刪除未選擇的Session
R 重放選擇的Session(可以重放多個Session)
Shift + R 多次重放選擇的Session(隨后會提示你輸入,重放幾次)
U

無條件的重放選擇的Session(不會發送If-Modified-Since 和 If-None-Match-Headers)

Shift + U

無條件的重放選擇的Session(隨后會提示你輸入,重放幾次)
P 選擇“當前Session”的“父Session”(這個功能取決於Referer Header)
C 選擇“當前Session”的“子Session”
D 選擇“重復的Session”(有相同的URL和相同的method)
BackSpace或鼠標上的“Back” 選擇“上次選擇的Session”
Insert  

Ctrl + 1

Ctrl + 2

Ctrl + 3

Ctrl + 4

Ctrl + 5

Ctrl + 6

用粗體和顏色標記選擇的Session
M 給選擇的Session添加注釋

 

Fiddler插件

Fiddler插件下載地址:www.telerik.com/fiddler/add-ons

比較會話的不同:Windiff

格式化JS代碼:JavaScript Formatter

圖片縮略圖:Gallery

Fiddler的Script用法

Fiddler Script是一個可以自動修改HTTP請求和HTTP響應的腳本文件,使你不用手動地去下“斷點”來修改。

Fiddler Script的本質其實是用JScript.NET語言寫的一個腳本文件CustomRules.js,其語法類似於C#。

Fiddler Script Editor

或者

CustomRules.js中的主要方法

static function OnBeforeRequest(oSession:Session)

OnBeforeRequest函數在每次請求之前調用。在這個方法中修改Request的內容,我們用的最多

static function OnBeforeResponse(oSession:Session)

OnBeforeResponse函數在每次響應之前調用,在這個方法中修改Response的內容。

static function OnExexAction(sParams:String[])

這個方法中包含Fiddler命令。命令是在Fiddler界面中左下方的QuickExec中執行的。

Fiddler定制菜單

Rules -> User-Agents菜單中好像沒有Iphone-4S safari,我們現在可以定制一個。上網查詢user-Agents,添加代碼:

RulesStringValue(23,"Iphone 4S safari","Mozilla/5.0(iPhone;U;CPU iPhone OS 4_0 like Mac OS X;en-us)AppleWebKit/532.9(KHTML,like Gecko) Version/4.0.5 Mobile/8A293Safari/6531.22.7")

重啟Fiddler就行

修改Session在Fiddler的顯示樣式

把以下腳本放在OnBeforeRequest(oSession:Session)方法下,並且單機“Save script”,這樣所有的cnblogs會話都會顯示為紅色

if (oSession.HostnameIs("www.cnblogs.com")) {
  oSession["ui-color"] = "red"
}

修改HTTP請求

如果要修改HTTP請求,代碼應該放在OnBeforeRequest(oSession:Session)方法下面。

我們可以修改HTTP請求中的任何數據,如HOST、Header、Cookie等

修改HTTP請求中的Cookie

if(oSession.uriContains("cnblogs.com")
{
    //1.刪除所有的cookie
    oSession.oRequest.headers.Remove("Cookie");
    
    //2.新建cookie
    oSession.oRequest.headers.Add("Cookie","username=testname;testpassword=P@ssword1");

    //修改Cookie,不能刪除或者編輯單獨的一個Cookie,需要替換Cookie字符串
    var oldCookie = oSession.oRequest["Cookie"];
    oldCookie = oldCookie.Replace("cookieName=","ignoreme=")
    oSession.oRequest["Cookie"] = oldCookie;

    //4.全新的Cookie
    var newCookie = "your cookie String";
    oSession.oRequest["Cookie"] = newCookie;  
}

 

替換HTTP請求的Host地址

我們最初發送給A站點的HTTP請求,都被Fiddler轉發到B站點,而在瀏覽器中毫無感覺。測試或者debug過程中經常會有這種需求。

例如用 www.sina.com 代替 www.baidu.com

if (oSession.HostnameIs("www.sina.com"))
{
    oSession.hostname = "www.baidu.com";
}

修改HTTP請求中的Header

if (oSession.uriContains("cnblogs.com"))
{
    // 添加Header
    oSession.oRequest.headers.Add("headerName1","headerValue1");

    // 刪除Header
oSession.oRequest.headers.Remove("headerName2");

    // 修改Header
oSession.oRequest["Referer"] = "www.baidu.com/TestReferer";
}

修改HTTP請求中發的Body

方法一:先把Body的字符串讀取出來,修改后再塞回去。

static function OnBeforeRequest(oSession:Session)
{
    if (oSession.uriContains("http://www.cnblogs.com/TankXiao/"))
    {
        oSession.utilDecodeRequest();
        // 獲取Request中的body字符串
        var strBody=oSession.GetRequestBodyAsString();
        // 用正則表達式或者 replace 方法修改string
        strBody=strBody.replace("1111","2222");
        // 彈個對話框檢查下修改后的body
        FiddlerObject.alert(strBody);
        // 將修改后的body,重新寫會Request中
       oSession.utilSeRequestBody(strBody);
    }
}

 第二種方法:也可以采用非常簡單地方法,即直接替換body中的數據

if (oSession.uriContains("cnblogs.com"))
{
    oSession.utilReplaceInRequest("1111","2222");
}

修改HTTP響應

在Script中修改HTTP響應的方法,代碼應該放在OnBefroeResponse(oSession:Session)方法下面。

修改HTTP響應的方法和修改HTTP請求的方法差不多。

實例:使用如下代碼,修改博客園網頁中的數據

if (oSession.uriContains("cnblogs.com"))
{
    oSession.utiReplaceInResponse("小坦克","大坦克 肖佳");  
}

打開瀏覽器,輸入 www.cnblogs.com/tankxiao/

讀寫txt文件

先引用命名空間

import System。IO;
    // Read
    var txtPath = "c:\\tank.txt"
    var allNumbers = File.ReadAllLines(txtPath);
    var exist = 0;
    for(var i = 0; i<allNumbers.length;i++)
    {
        FiddlerObject.alert(allNumbers[i]);
    }

    // write
    var txtPath = "c:\\tank.txt"
    var txtWrite = File.AppendText(textPath);
    txtWriteLine("www.cnblogs.com/tankxiao");
    txtWrite.Close();

使用正則表達式

先引用命名空間

import System.Text.RegularExpressions;

var resBody = "<String>tankxiao.cnblogs.com</string>";
var r = new Regex("<string>(.*?)</string>");
var mc = r.Match(resBody);
FiddlerObject.alert(mc.Groups[1].Value);

保存Session

var sazFile = "c:\\aff\\"+number;
var sessionList : Session[] = [oSession];
Utilities.WriteSessionArchive(sazFile,sessionList,null,true)

讀取Session,並且使用Fiddler來發送

var sazFile="c:\\aff\\"+number;
var sessionList : Session[] = Utilities.ReadSessionArchive(sazFile,true);
FiddlerApplication.oProxy.SendRequest(sessionList[0].oRequest.headers,sessionList[0].requestBodyBytes,null);

深入理解Cookie機制

HTTP協議是無狀態的

對於瀏覽器的每一次請求,服務器都會獨立處理。不與之前或之后的請求發生關聯。即使同一個瀏覽器發送了3個請求,服務器也會獨立處理這3個請求,服務器並不知道這3個請求是來自同一個瀏覽器。

服務器需要識別瀏覽器請求,就必須弄清楚瀏覽器的請求狀態。既然HTTP協議是無狀態的,那就讓服務器和瀏覽器共同維護一個狀態,這就是會話機制。

會話機制

瀏覽器第一次請求服務器時,服務器創建一個會話,並將會話的id作為響應的一部分發送給瀏覽器。

瀏覽器存儲會話id,並在后續第二次和第三次請求中帶上會話id。服務器取得請求中的會話id就知道是不是同一個用戶了。

Cookie機制

服務器在內存中保存會話對象。瀏覽器可以使用Cookie機制保存會話id。

Cookie機制是一種會話機制。Cookie是瀏覽器用來存儲少量數據的一種機制,數據以“key=value”形式存儲,瀏覽器發送HTTP請求時,自動附帶cookie信息。

Cookie是什么

Cookie是一小段文本信息,伴隨着用戶請求和頁面在瀏覽器和Web服務器之間傳遞。

Cookie是一種HTTP Header,以“key=value”的形式組成,比如ip_country=CN

兩個Cookie之間用分號隔開,比如ip_country=CN;mbox=check#true#1499311989

瀏覽器把Cookie通過HTTP請求中的Header,比如“Cookie:ip_country=CN”發送給Web服務器。Web服務器通過HTTP響應中的Header,比如“Set-Cookie:ip_country=CN”,把Cookie發送給瀏覽器。

Cookie的作用

Cookie最主要的作用是用來做用戶認證,還可以用於保存用戶的一些其他信息。

Cookie也可以用於互聯網精確廣告定向技術,比如用戶瀏覽了某些商品,就可以用Cookie將其記錄下來。

Cookie的屬性

從Fiddler的抓包中,我們可以看到Web服務器返回了下面這一段數據給瀏覽器。

Set-Cookie:cookie_user_token=C5CBD6FBDJO5HGH324OV452;Expires=Thu,06-Jul-2017 09:17:46 GMT;Path=/;HttpOnly

Expires屬性:Expires的值是一個時間,代表過期時間。過了這個時間,該Cookie就失效了。如果不指定Expire time,表示關閉瀏覽器/頁面的時候,此Cookie就應該被瀏覽器刪除了。

Path屬性:表示Cookie所屬的路徑,asp.net默認為“/”,就是根目錄。在同一個服務器上的目錄如下:/test/、/test/cd/、/test/dd/。現假設一個Cookie1的path為/test/,Cookie2的path為/test/cd/,那么test下的所有頁面都可以訪問到Cookie1,而/test/cd/的子頁面不能訪問Cookie2。

HttpOnly屬性:這是個關於安全方面的屬性,將一個Cookie設置為HttpOnly后,通過JavaScript腳本將無法讀取到Cookie信息,這能有效地防止黑客用XSS發起攻擊。一般來說,跟登陸相關的Cookie必須設置為HttpOnly。

Cookie的分類

會話Cooike:臨時地Cookie,它記錄了用戶訪問站點時的設置和偏好;關閉瀏覽器,會話Cookie就被刪除了

持久Cookie:存儲在硬盤上,不管瀏覽器退出或者計算機重啟,持久cookie都繼續存在,持久Cookie有過期時間。

網站自動登錄的原理

在登錄頁面輸入用戶名、密碼,選擇保存密碼單機登錄(這時候,其實在你的機器上已保存好了登錄的Cookie),下次訪問的時候。

  1. 用戶打開IE瀏覽器,在地址欄輸入www.cnblogs.com
  2. IE首先會在硬盤中查找關於cnblogs.comde Cookie,然后把Cookie放到HTTP Request中,再把Request發給Web服務器。
  3. Web服務器返回博客園首頁,這時你會看到自己已經登錄了。

Fiddler實現Cookie劫持攻擊

通常有兩種方法可以截獲他人的Cookie

  1. 通過跨站腳本攻擊(XSS)獲取他人的Cookie。
  2. 想辦法獲取別人電腦上保存的Cookie文件。

找到登錄的Cookie

  首先,我們需要使用 Fiddler 找到跟登錄相關的 Cookie,具體的操作步驟如下。

打開豆瓣網 www.douban.com,用賬號和密碼登錄。

啟動Fiddler,在豆瓣網中單擊右上角的用戶名,在菜單欄中單機“賬號管理”,就跳轉到了這個頁面:https://www.douban.com/accounts/。

在Fiddler中選擇https://www.douban.com/accounts/這個Session,然后用鼠標右鍵選擇Replay -> Reissue and Edit。在Raw選項卡下,找到一個名叫dbcl2的Cookie,比如我這里的是:dbcl2=“163572032:csUO41kxRDg”;刪除這個 dbcl2 的Cookie,然后單機“Run to Completion”放行。

我們可以發現跳轉到了登錄頁面。這說明dbcl2這個Cookie是跟登錄相關的,將其刪除后就處於未登錄狀態,Web服務器會返回302狀態碼,會自動重定向到登錄界面。

網站退出的作用

網站退出是明確地告訴服務器立即刪除服務器端的Session對象,這樣客戶端登錄的Cookie就失效了。如果用戶登錄某個網站,然后離開的時候直接關閉瀏覽器,那么登錄的Cookie還在,存在被冒用的風險。保險的辦法是單擊退出而不是直接關閉瀏覽器。

HTTP基本認證

  HTTP協議是無狀態的,瀏覽器和Web服務器之間可以通過Cookie來識別身份。一些桌面應用程序(比如新浪桌面客戶端)跟Web服務器之間是如何識別身份呢?

  HTTP協議中還有兩種認證方式,分別是基本認證摘要認證。認證就是客戶端要給服務器出示一些自己的身份證明,來證明自己是誰,一旦服務器知道了客戶端的身份,就可以判定客戶端可以進行訪問了。通常是通過提供用戶名和密碼來進行認證的。

什么是HTTP基本認證

  一些網站和Web服務使用的是HTTP基本認證。有些桌面應用程序也通過HTTP協議跟Web服務器交互,桌面應用程序一般不會使用Cookie,而是把“用戶名+冒號+密碼”用Base64編碼放在HTTP請求中的 Header Authorization 中發送給服務器,這種方式叫HTTP基本認證(Basic Authentication)

  在基本認證中,Web服務器可以拒絕一個事物,要求客戶端提供有效地用戶名和密碼。服務器會返回401狀態碼來初始化認證質詢,並用WWW-Authenticate響應首部指定要訪問的安全域。瀏覽器收到質詢時,會打開一個對話框,請求用戶輸入用戶名和密碼,然后將用戶名和密碼用Base64編碼,再用 Authorization 請求首部發送給服務器。

在Fiddler中可以在Inspectors中的Auth選項卡中查看實際用戶名和密碼。

HTTP基本認證的缺點

把“用戶名+冒號+密碼”用Base64編碼,可逆,所以不能用HTTP在網絡上傳輸,一定要用HTTPS傳輸,因為HTTPS是加密的,稍微安全一點。

  1. HTTP協議是無狀態的,同一個客戶端對服務器的每個請求都要求認證。
  2. 基本認證會通過網絡發送用戶名和密碼,這些用戶名和密碼以Base64編碼。Base64編碼是一種可逆編碼,容易被第三方攔截。
  3. 使用基本認證登錄后,除非關閉瀏覽器或者清楚歷史記錄,否則將無法登出。
  4. 無法防止重放攻擊。即使基本認證的密碼是經過加密傳輸的,第三方仍然可以捕獲被修改過的用戶名和密碼,並將修改過的用戶名和密碼反復多次地重放給原始服務器,以獲得對服務器的訪問權,基本認證沒有什么措施可以防止這些重放攻擊。

摘要認證

摘要認證是針對基本認證存在的諸多問題而進行改良的方案。摘要認證是另外一種HTTP認證協議,它試圖修復基本認證的嚴重缺陷,進行如下改進。

  1. 通過傳遞用戶名、密碼等計算出來的摘要來解決以明文方式在網絡上發送密碼的問題。
  2. 通過服務器產生隨機數 nonce 的方式防止惡意用戶捕獲並重放認證的握手過程。
  3. 通過客戶端產生隨機數 cnonce 的方式支持客戶端對服務器的認證。
  4. 通過對內容也加入摘要計算的方式,可以有選擇地防止對報文內容的篡改。

Fiddler發送HTTP請求

Fiddler可以使用重放功能或者Fiddler Composer來發送HTTP請求。

Fiddler Composer發送HTTP請求

Fiddler有個功能組件叫Composer,可以用來發送HTTP請求。Fiddler的作者把HTTP Request發送器取名為Composer,中文意思是樂曲的創造者,很有詩意。

Composer發送Get請求

Composer的編輯模式

Composer有兩種編輯模式

  1. Parsed模式。這個模式比較常用,把HTTP請求分為3個部分:請求起始行,請求Header和請求Body。通過該模式,創建一個HTTP請求變得很容易。
  2. Raw模式。該模式需要一行一行地寫一個HTTP請求。

Composer發送Post請求

禪道的演示網站 http://demo.zendao.net,用戶名是demo,密碼是123456。手動登錄抓包如下:

用Fiddler發送一個登錄的Post請求

Composer編輯之前捕獲的HTTP請求

  在Web會話列表中,可以將捕獲到的HTTP請求拖拽到Composer中,編輯后再發送出去。

Fiddler重新發送HTTP請求

  Fiddler可以將捕獲的HTTP請求重新發送出去。Fiddler工具欄上有一個Replay按鈕,單擊該按鈕可以向Web服務器重新發送選中的HTTP請求。當選中多個Session,並且按下Replay按鈕后,Fiddler會用多線程同時發送請求。此功能可以用來做並發性能測試。

Replay菜單

  按下Shift鍵的同時單擊該按鈕,會彈出提示框,要求指定每個請求被重新發送的次數。

  按下Ctrl鍵的同時單擊該按鈕,在HTTP請求中不會包含IF-Modified-Since和If-None-Match。

  在會話列表中,選中一個或者多個Session,右鍵菜單我們可以看到一個Replay菜單。

Reissue Requests 重新發送請求,和菜單欄上Replay按鈕是一樣的功能
Reissue Unconditionally 無條件反復發送選中的請求
Reissue and Edit 把選中的請求以原來的形式重新發送,在每個新的Session中設置斷點,在請求發送給服務器之前,可以修改請求
Reissue and Verify 重新發送請求,檢查響應,如果響應和上一個請求一樣,就會變成綠色
Reissue Sequentially 選中多個Session會按順序一個一個重新發送請求,是單線程模式
Reissue from Composer 在Composer中編輯該請求 
Revisit in IE 在IE瀏覽器中用Get方法訪問這個請求 

 

簡單地性能測試

  在Web Sessions列表中,選中一個或者多個Session,然后按下Shift鍵的同時單擊“Replay”按鈕,會彈出提示框,要求指定每個請求被重新發送的次數。Fiddler會用多線程同時發送該請求,相當於模擬了很多用戶同時訪問該請求。

先編輯再發送

  在Web Sessions列表中,選中一個Session,單擊鼠標右鍵選擇Replay - Reissue and Edit。該功能可以把一個HTTP請求重新發送出去,並且攔截住,將其進行編輯,然后再發出去。

安全測試之重放攻擊

  重放攻擊(Replay Attacks)又稱重播攻擊、回放攻擊。

  攻擊者發送一個目的主機已接收過的包,特別是在認證的過程中,用於認證用戶身份所接收的包,來達到欺騙系統的目的。該包主要用於身份認證過程,破壞認證的安全性。

重放攻擊是怎么發生的

  重放攻擊是指黑客通過抓包的方式,得到客戶端的請求數據及請求連接,重復地向服務器發送請求的行為。

重放攻擊的危害

  比如APP中有一個“下單”的操作,當你單擊購買按鈕時,APP向服務器發送購買的請求。而這時黑客對你的請求進行了抓包,得到了你的傳輸數據,黑客把數據再往服務器提交一次。這就導致了你可能只想購買一個產品,結果由於黑客重放攻擊,你就購買了多次。

  很多網站的投票或者點贊功能也要防止重放。黑客會對投票或者點贊進行抓包,然后重復發送來進行刷票。

重放攻擊的解決方案

  在HTTP請求中添加時間戳(stamp)數字簽名(sign),可以防止重放攻擊。

  數字簽名是為了確保請求的有效性。因為簽名是經過加密的,只有客戶端和服務器知道加密方式及Key,第三方模擬不了。

  時間戳是為了確保請求的時效性。我們將上一次請求的時間戳進行存儲。

Fiddler實現弱網測試

  網速慢和網絡中斷的情況,我們稱之為弱網。

  使用Fiddler能讓弱網測試變得非常簡單,Fiddler是通過延遲發送或接收數據的時間來模擬限速的。

什么是弱網

  驗證在弱網的情況下軟件的處理機制,從而避免因用戶體驗不友好造成用戶的流失。弱網測試屬於健壯性測試。在弱網測試條件下,要測試產品的運行狀態、處理機制、提示信息,以及網絡恢復后的重連等。

弱網環境帶來的問題

  1、操作時間慢。用戶在地鐵里操作手機APP,由於網絡慢,頁面加載不出來。原因可能是API在網絡慢的情況下性能很差。用戶在公交車上用手機APP看新聞,當公交車進入隧道的時候,網絡變得很慢,APP上的新聞一直沒法加載出來。我們需要測試每個API消耗的時間,這個指標可以衡量APP性能的好壞。

  2、用戶體驗不好。一個安卓手機用戶使用一款看小說的APP在地鐵里看小說,當地鐵進入隧道的時候,手機信號中斷了。用戶單擊翻頁,想看下一頁的時候,因為網絡中斷,APP的界面卡死並且閃退。原因是APP不穩定,沒有處理好網絡中斷的情況。

  3、非正常情況下,出現Bug的可能性會增加。如一個電商的手機APP有秒殺優惠券的功能。一些APP用戶在乘坐電梯的時候,使用APP來秒殺優惠券。單擊秒殺優惠券的按鈕后,APP響應緩慢。於是,用戶重復單擊秒殺優惠券按鈕。這就造成了幾乎同一時間,同一個用戶有多個HTTP請求發送服務器,形成了並發,結果用戶搶到了多張優惠券。

弱網測試的目的

  弱網測試的目的是讓APP在任何網絡下都能表現自如,讓開發人員能夠預知APP在較差網絡環境下的表現,提前發現問題,進行有針對性的優化

弱網的場景

  1、網絡慢或者延遲,導致加載時間長。

  2、網絡中斷,Web服務器返回500等狀態碼。

  3、網絡超時,HTTP請求發出去后,很久都沒有響應。

Fiddler模擬網絡延遲

  1、啟動Fiddler,選擇Rules - Performances - Simulate Modem Speeds

  2、打開瀏覽器,訪問網站。

精確控制網速

可參考:https://www.jianshu.com/p/b9e349b8f411

 

  1、啟動Fiddler,選擇Rules - Performances - Simulate Modem Speeds

  2、在FiddlerScript中找到如下一段代碼

        if (m_SimulateModem) {
            // Delay sends by 300ms per KB uploaded.  每上傳1KB數據,延時0.3秒
            oSession["request-trickle-delay"] = "300"; 
            // Delay receives by 150ms per KB downloaded.  每下載1KB數據,延時0.15秒
            oSession["response-trickle-delay"] = "150"; 
        }

  改動數值,保存Script即可。

  3、保存完之后,原本已經勾選的Simulate Modem Speeds會被取消勾選:再次選中 Rules - Performances - Simulate Modem Speeds

  4、再次打開瀏覽器,訪問網頁

如果你習慣用kbps 去算的話,那么我們的算法就是 1KB/下載速度 = 需要delay的時間(毫秒),比如50KBps 需要delay20毫秒來接收數據。

request-trickle-delay中的值代表每KB的數據被上傳時會被延時多少毫秒;response-trickle-delay則對應下載時每KB的數據會被延時多少毫秒。
比如你要模擬上傳速度100KBps的網絡,那上傳延遲就是1KB/100KBps=0.01s=10ms,就改成10。

比如默認設置下上傳延時為300ms下載延時為150ms,可以推算出大致的模擬帶寬為:
上傳帶寬 = 1KB/300ms = (1 * 8/1000) /0.300 ≈ 0.027Mbps
下載帶寬 = 1KB/150ms = (1 * 8/1000) /0.150 ≈ 0.053Mbps
(1MB = 1024 KB ≈ 1000 KB 這里為了運算簡便就用了1000的倍數,忽略誤差)

 

方法二,下面的腳本實現了一個隨機延時量設置,使得網絡帶寬不是恆定為一個低速的值,而是會在一定范圍內隨機抖動:

if (m_SimulateModem) {
    // Delay sends by 300ms per KB uploaded.
    oSession["request-trickle-delay"] = ""+randInt(1,50);
    // Delay receives by 150ms per KB downloaded.
    oSession["response-trickle-delay"] = ""+randInt(1,50);
}

方法三:

點擊fiddlerScript 在代碼里找到onBeforeRequest,這里定義了在發送請求前做什么。加入如下代碼可以實現延遲:

oSession["request-trickle-delay"]="3000";  //請求階段延遲3秒
oSession["response-trickle-delay"]="3000";  //響應階段延遲3秒

Fiddler模擬網絡中斷

  用Fiddler可以下斷點,偽造HTTP響應。移動端發出的HTTP請求根本沒有到達服務器,而是被Fiddler直接返回了一個偽造的HTTP響應。

  具體做法是用Fiddler攔截住移動端發出來的HTTP請求,然后在“Choose Response”選中需要返回的狀態碼並返回給移動客戶端。

或者可以在桌面新建一個txt文檔:

HTTP/1.1 500 Internal Server Error
Date: Fri, 11 Aug 2019 07:25:35 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Vary: Accept-Encoding

this is 500 internal Server Error by Fiddler! tank

Fiddler模擬網絡超時

  利用Fiddler下斷點的功能攔截移動客戶端發出的HTTP請求,這樣就相當於網絡超時了,然后再檢查客戶端有沒有重發或者超時的機制。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM