HTTP協議冷知識大全
如果不用HTTPS,HTTP協議如何安全的傳輸密碼信息?
HTTP協議是純文本協議,沒有任何加密措施。通過HTTP協議傳輸的數據都可以在網路上被完全監聽。如果用戶登陸時將用戶名和密碼直接明文通過HTTP協議傳輸過去了,那麼密碼可能會被黑客竊取。
一種方法是使用非對稱加密。GET登陸頁面時,將公鑰以Javascript變數的形式暴露給瀏覽器。然後用公鑰對用戶的密碼加密後,再將密碼密文、用戶名和公鑰一起發送給伺服器。伺服器會提前存儲公鑰和私鑰的映射信息,通過客戶端發過來的公鑰就可以查出對應的私鑰,然後對密碼密文進行解密就可以還原出密碼的明文。
為了加強公鑰私鑰的安全性,伺服器應該動態生成公鑰私鑰對,並且使用後立即銷毀。但是動態生成又是非常耗費計算資源的,所以一般伺服器會選擇Pool方法提供有限數量的公鑰私鑰對池,然後每隔一段時間刷新一次Pool。
文件路徑攻擊
很多操作系統都會使用..符號表示上層目錄。如果黑客在URL的路徑裡面使用..符號引用上層目錄,而伺服器沒有做好防範的話就有可能導致黑客可以直接訪問許可權之外的文件。比如使用多級..符號就可以引用到根目錄,進一步就可以訪問任意文件。
所以很多伺服器都禁止在URL路徑里出現..符號以避免被攻擊。
文件路徑攻擊也是很多黑客非常喜愛使用的攻擊方法之一。如果你的伺服器有一定的訪問量,打開你的nginx日誌,你就會偶爾發現有一些奇怪的URL裡面有一堆..符號,這種URL的出現就表示網路上的黑客正在嘗試攻擊你的伺服器。
DNS欺騙
HTTP協議嚴重依賴於DNS域名解析。任意一個域名類網址的訪問都需要經過域名解析的過程得到目標服務的IP地址才能成功繼續下去。
如果掌管DNS服務的運營商作惡將域名解析到不正確的IP,指向一個釣魚的網頁服務。用戶如果沒有覺察,就可能會將自己的敏感信息提交給冒牌的伺服器。
謹慎使用外部的HTTP代理
HTTP代理作為客戶端到伺服器之間的中間路由節點,它起到傳話人和翻譯官的角色。
如果這個翻譯官不靠譜的話,客戶端是會拿到錯誤的返回數據的。它同DNS欺騙一樣,是可以對客戶端進行釣魚攻擊的。
如果這個翻譯官口風不嚴的話,它可能會將它聽到的敏感信息泄露給別人
413 Request Entity Too Large
客戶端上傳圖片太大超過伺服器限制時,伺服器返回413錯誤。
414 Request-URI Too Long
客戶端訪問的URI太長,超出了伺服器允許限制,伺服器返回414錯誤。
202 Accepted
常用於非同步請求。客戶端發送請求到伺服器,伺服器立即返回一個202 Accepted表示已經成功接收到客戶端的請求。
後面怎麼處理由伺服器自己決定,一般伺服器會給客戶端預留一個可以查詢處理狀態的介面,客戶端可以選擇輪訓該介面來知道請求的處理進度和結果。
POST提交數據的方式
application/x-www-form-urlencoded
提交數據表單時經常使用,Body內部存放的是轉碼後的鍵值對。
application/json
提交結構化表單時使用,Body內部存放的是JSON字元串。ElasticSearch的查詢協議使用的是這種方式。
multipart/form-data
上傳文件時經常使用。這種格式比較複雜,它是為了支持多文件上傳混合表單數據而設計的一種特殊的格式。
用戶填充了表單設置了待上傳的文件,點擊Submit,傳輸數據大致如下
Cookie
瀏覽器請求的Cookie中往往會攜帶敏感信息。伺服器一般會將當前用戶的會話ID存在cookie里,會話的具體內容存在伺服器端,會話的內容很敏感。
瀏覽器請求時會攜帶Cookie信息,伺服器根據Cookie信息中的會話ID找到對應的會話內容。會話內容里可能存儲了用戶的許可權信息,拿到這部分許可權信息後就可能隨意控制修改用戶的數據。
因為HTTP協議的不安全性,請求數據包很容易被竊聽,Cookie中的會話信息很容易被盜。解決方案之一就是在會話中記錄用戶的終端信息和IP地址信息,如果這些信息突然發生改變,需要強制用戶重新認證。
不過高級的黑客是可以偽造出和用戶真實請求一摸一樣的數據包的。最徹底的解決方案還是採用HTTPS協議。
普通的Cookie信息可以通過Javascript腳本獲取到。如果黑客通過某種方式在網頁中植入不安全的腳本,將用戶的Cookie拿到然後發送到遠程的第三方伺服器中,那麼Cookie中的信息就被泄露了。
Cookie的兩個重要屬性
被標記為Secure的Cookie信息在HTTP請求中不會被傳送,它只會在HTTPS請求中傳送,避免數據被泄露。
被標記為HttpOnly的Cookie信息是無法通過Javascript API獲取到的,它只會在請求中傳送。這樣可以避免黑客通過網頁腳本方式竊取Cookie中的敏感信息。
Cookie(甜點)如此好吃,黑客們總想通過Cookie做各種文章。
CSRF(Cross-Site Request Forgery)
CSRF跨站請求偽造有很多別名,比如One-Click Attack(一鍵攻擊),比如Session Riding(搭便車攻擊)
假設在在一個社區博客網站中,刪除個人的文章只需要一個URL就可以,Cookie中的會話許可權信息會自動附加到請求上。
那麼當別人偽造了一個上面的鏈接地址誘惑你去點擊,比如通過站內信件、私聊、博客評論、圖片鏈接或者在別的什麼網站上隨機製造的一個鏈接。你不經意點了一下,就丟了你的文章。所以它被稱為一鍵攻擊。因為這是借用了你當前登陸的會話信息來搞事,所以也被稱為搭便車攻擊。
如果在一個金融系統中,轉賬要是也可以通過一個簡單的URL進行的話,那這種危險就非同小可。
這就要求修改性的操作務必不得使用簡單的GET請求進行處理。但是即使這種情況下你改成了POST請求,黑客依然有辦法偽造請求,那就是通過iframe。
黑客在別的什麼網站上偽造了一個POST表單,誘惑你去submit。如果只是普通的內嵌進HTML網頁的表單,用戶提交時會出現跨域問題。因為當前網站的域名和表單提交的目標域名不一致。但是如果通過iframe來內嵌表單,則可以繞過跨域的問題,而用戶卻完全沒有任何覺察。
為了防範CSRF攻擊,聰明的網站的POST表單里都會帶上CSRF_TOKEN這個隱藏欄位。CSRF_TOKEN是根據用戶的會話信息生成的。當表單提交時,會將token和用戶的會話信息做比對。如果匹配就是有效的提交請求。
黑客必須拿到CSRF_TOKEN才可以借用用戶的會話信息實施CSRF攻擊,但是CSRF_TOKEN又必須由用戶的會話信息才可以生成。黑客沒有用戶的會話信息,從而無法實施CSRF攻擊。
XSS(Cross Site Scripting)
如果黑客可以在你的網頁中植入任意Javascript腳本,那他就可以隨意魚肉你的賬戶。通過Javascript可以獲取Cookie的信息,可以借用你的會話去調用一些隱秘的API,而這一些行為都是在偷偷的進行,你根本完全不知道。
這類攻擊在一些UGC網站中非常常見,常見的博客類網站就是UGC網站,用戶可以通過編輯內容來生成網頁。
黑客也是用戶。他可以編輯一段Javascript腳本作為內容提交上去。如果伺服器沒有做好防範,這段腳本就會在生成的網頁中運行起來。當其它用戶在登陸的狀態下來瀏覽這個網頁的時候,就悲劇了。
防範XSS一般是通過對輸出的內容進行內容替換做到的。在HTML頁面中不同的位置會有不同的內容替換規則。
比較常見的是使用HTML entity編碼將HTML標籤之間的內容中的一些特殊的字元進行轉碼。
還有些UGC內容在HTML標籤的屬性中、Javascript的變數中、URL、css代碼中,他們轉碼的規則並不一樣,具體方法可以去Google相關文檔。
跨域
跨域是個很頭痛的問題。
當你有多個後端服務,但是只有一個前端的時候,你想做前後端分離,就會遇到跨域問題。你發現你的前端js調用後端服務時控制台告訴你不ok。然後只好把這些服務都掛在了同一個nginx域名下面,通過url前綴區分。
這時候你會想,跨域太TM討厭了。既然跨域這麼討厭,那為什麼瀏覽器非要限制跨域呢?
還是安全原因。
讓我們回到上文的搭便車攻擊(Session Riding),也就是騎著別人的會話來搞事情。
假設現在你的瀏覽器開了一個站點A,登陸了進去,於是cookie變記錄了會話id。
然後你又不小心開了另一個站點B,這個站點頁面一打開就開始執行一些惡意代碼。這些代碼的邏輯是調用站點A的API來獲取站點A的數據,因為可以騎著(Ride)站點A的會話cookie。而這些數據正好是用戶私密性的。於是用戶在站點A上的私有信息就被站點B上的代碼竊走了。這就是跨域的風險。
但是有時候我們又希望共享數據給不同的站點,該怎麼辦呢?
答案是JSONP & CORS
JSONP(JSON Padding)
JSONP通過HTML的script標記實現了跨域共享數據的方式。JSON通過在網頁里定義一個回調方法,然後在頁面上插入一個動態script標籤,指向目標調用地址。伺服器會返回一段javascript代碼,一般是這種形式的回調。該段代碼會在瀏覽器里自動執行,於是網頁就得到了跨域伺服器返回的數據。
因為JSONP是不攜帶cookie信息的,所以能有效避免搭便車攻擊。JSONP是否可以獲取到數據還需要伺服器對這種調用提供顯示支持,伺服器必須將數據以javascript代碼的形式返回才可以傳遞給瀏覽器。
CORS(Cross-Origin Resource Sharing)
JSONP的不足在於它只能發送GET請求,並且不能攜帶cookie。而CORS則可以發送任意類型的請求,可以選擇性攜帶cookie。
CORS是通過Ajax發送的跨域請求技術。CORS的請求分為兩種,一種是簡單請求,一種是複雜請求。簡單請求就是頭部很少很簡單的GET/HEAD/POST請求。複雜請求就是非簡單請求。
瀏覽器發現Ajax的請求時跨域的,就會在請求頭添加一個Origin參數,指明當前請求的發起站點來源。伺服器根據Origin參數來決定是否授權。
如果是簡單請求,Ajax直接請求伺服器。伺服器會當成普通的請求直接返回內容,不同的是還會在響應頭部添加幾個重要的頭部,其中最重要的頭部是。
瀏覽器如果在響應中沒有讀到這個頭部,就會通知Ajax請求失敗。雖然伺服器返回了數據,瀏覽器也不讓腳本讀到數據,這就保證了跨域的安全。伺服器就是通過請求的Origin參數來決定要不要響應Access-Control-Allow-Origin頭部來決定是否允許指定網站的跨域請求。
如果是複雜請求,要走一個預檢的流程。預檢就是瀏覽器先向伺服器發送一個Method為Options的請求,如果伺服器允許跨域請求,瀏覽器再發起這個Ajax請求。所以CORS的複雜請求會比簡單請求額外耗費一個TTL的時間。
CORS的細節請參見大神阮一峰的博文《跨域資源共享CORS詳解》


※鮮為人知的HTTP協議頭欄位詳解大全
※天下無難試之HTTP協議面試刁難大全
TAG:碼洞 |