Web登陸其實沒你想的那麼簡單

1. 一個簡單的HTML例子看看用戶信息安全

標準的HTML語法中,支持在form表單中使用<input></input>標籤來建立一個HTTP提交的屬性,現代的WEB登陸中,常見的是下面這樣的表單:前端

 

<form action = "http://localhost:8080/Application/login" method = "POST">
    用戶名:<input id="username" name="username" type="text" />
    密碼:<input id="password" name="password" type="password" />
    <button type="submit">登錄</button></form>

form表單會在提交請求時,會獲取form中input標籤存在name的屬性,做爲HTTP請求的body中的參數傳遞給後臺,進行登陸校驗。算法

 

 

例如個人帳號是user1,密碼是123456,那麼我在提交登陸的時候會給後臺發送的HTTP請求以下(Chrome或者FireFox開發者工具捕獲,需開啓Preserve log):數據庫

 

 

能夠發現即使password字段是黑點,可是本機仍以明文的形式截獲請求。後端

2. HTTP協議傳輸直接暴露用戶密碼字段

在網絡傳輸過程當中,被嗅探到的話會直接危及用戶信息安全,以Fiddler或Wireshark爲例,發現捕獲的HTTP報文中包含敏感信息:瀏覽器

 

3. 使用加密算法能保證密碼安全嗎?

WEB前端能夠經過某種算法,對密碼字段進行加密後,在將密碼做爲Http請求的內容進行提交,常見的包括對稱和非對稱加密。緩存

 

對稱加密:採用對稱密碼編碼技術,它的特色是文件加密和解密使用相同的密鑰加密。安全

非對稱加密:須要兩個密鑰,公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,若是用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;若是用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。服務器

 

3.1 使用對稱加密

加密解密在先後臺協商後,彷佛是個不錯的辦法,好比,前臺使用一個字符串位移+字符串反轉的簡單方法(舉個例子,固然不能這麼簡單)。那麼,若是原密碼123456先移位:網絡

123456-->456123

 

再進行反轉:併發

456123-->321654

 

那麼這樣簡單的方法彷佛能夠混淆原密碼,而且輕鬆由後臺進行相反操做復原。可是這有兩個缺點:

1.先後端加密解密須要同時修改代碼;

2.前端加密無非是寫在JS裏,可是JS有風險被直接破解從而識別加密方法。

 

3.2 非對稱加密HTTPS就必定是安全的嗎?

非對稱加密有着公鑰私鑰的存在,公鑰能夠隨意獲取,私鑰是用來對公鑰解密的本地存儲,經過公私鑰的機制彷佛能夠保證傳輸加密而且乃至如今還在使用的HTTPS就是基於這個原理。


可是HTTPS就必定安全嗎?HTTP存在兩種可能的風險:

 

1.HTTPS能夠保證傳輸過程當中的信息不被別人截獲,可是細細思考下,HTTPS是應用層協議,下層採用SSL保證信息安全,可是在客戶端和服務端,密文一樣是能夠被截獲的;

 

2.HTTPS報文在傳輸過程當中,若是客戶端被惡意引導安裝「中間人」的WEB信任證書,那麼HTTPS中的「中間人攻擊」同樣會將明文密碼泄露給別人。

4. 結論是,不管HTTP仍是HTTPS,密碼必須密文傳輸

想一想HTTPS也不能必定保障用戶密碼信息,那麼就應該考慮在應用層之上再繼續對密碼進行保護,也就是編寫代碼來進行控制,而不依賴特定協議,比較容易想到的就是利用不可逆加密散列函數MD5(string),用戶在註冊輸入密碼的時候,就存儲MD5(password)值,而且在WEB端先進行MD5(password),而後將密碼傳輸至後臺,與數據庫中的密文進行比較(PS:MD5函數在指定位數的狀況下,對相同字符串運算值相同)。

優勢比較明顯:

1.保證了用戶數據庫內部的密碼信息安全;

2.傳輸過程當中不管如何都不會使得用戶的密文被破解出原密碼;

3.簡單高效,執行以及編碼難度都不大,各類語言都提供MD5支持,開發快。

5. 那太好了!這樣能夠省下HTTPS的錢了,真是這樣嗎?

回到開頭的例子:用戶輸入的用戶名是:user1,密碼是:123456,那麼無論在什麼協議之下,能夠看到實際發送的HTTP/HTTPS報文在MD5處理後是這樣的:

沒錯,加密登陸成功了。可是,當咱們慶祝密碼安全的時候,發現帳戶的錢忽然不知去向。這是爲何呢?黑客卻笑的很開心:由於他們並不必定要獲取到你的密碼明文,若是直接截獲你的密碼密文,而後發送給服務器不是同樣能夠登陸嗎?由於數據庫裏的不也是MD5(password)的同樣的密文嗎?HTTP請求被僞造,同樣能夠登陸成功,從而攫取其餘的數據或者轉走餘額。

這怎麼辦?其實並不難,有不少種解決方法?其實原理都是相似的:那就是服務器緩存生成隨機的驗證字段,併發送給客戶端,當客戶端登陸時,把這個一併字段傳給服務器,用於校驗。

 

5.1 方案一:驗證碼

MVC場景。控制器將把數據的Model封裝到View中,這種存在Session的鏈接方式,容許了在Session中存取信息。那麼咱們能夠利用一些開源的驗證碼生成工具,例如JAVA中的Kaptcha,在服務端存放生成一個驗證碼值以及一個驗證碼的生成圖片,將圖片以Base64編碼,並返回給View,在View中解碼Base64並加載圖片,並於用戶下次登陸時再進行比對。

 

5.2 方案二:token令牌

先後端分離場景。如今很是流行的先後端分離的開發模式大大提升了項目的開發效率。職責、分工明確,可是因爲HTTP是無狀態的(就是這一次請求並不知道上一次請求的內容),當用戶登陸時,根據用戶的username做爲key,生成隨機令牌(例如UUID)做爲value緩存在Redis中,而且將token返回給客戶端,當客戶端登陸時,將完成校驗,而且刪除Redis中的那條緩存記錄。

那麼每次從服務器中獲取認證的token,確實能保證HTTP請求是由前端傳回來的了,由於token在每次登錄後都會刪除並被重置,會致使黑客嘗試重放帳號密碼數據信息來登錄的時候致使沒法成功登錄。

總而言之,就是我拿到了帳號以及密碼的密文也登錄不了,由於,若是請求不包含後臺認證的令牌token,是個非法請求。

6. 太不容易了!但是還別高興的太早,小心數據被篡改

密碼也加密了,黑客看不到明文了。加上Token了,登錄過程也無法再被截獲重放了。但是想一想這種狀況,你在進行某寶上的網絡支付,須要帳號,密碼,金額,token這四個字段進行操做,而後支付的時候你付了1塊錢買了一袋包郵的小浣熊乾脆面,某寶結算結束後,你發現你的帳戶餘額被扣了1萬元。這又是怎麼回事呢?

由於即使黑客不登陸,不操做,同樣要搞破壞:當請求路由到黑客這邊的時候,截獲數據包,而後也不須要登陸,反正帳號密碼都是對的,token也是對的,那麼把數據包的字段改改,搞破壞就能夠了,因而把money改爲了1萬,再傳給服務器,做爲受害者就莫名其妙踩了這個坑。可這該怎麼解決呢?其實原理相似於HTTPS裏的數字簽名機制,首先科普下什麼是數字摘要以及數字簽名:

6.1 什麼是「數字摘要」

咱們在下載文件的時候常常會看到有的下載站點也提供下載文件的「數字摘要「,供下載者驗證下載後的文件是否完整,或者說是否和服務器上的文件」如出一轍「。其實,數字摘要就是採用單項Hash函數將須要加密的明文「摘要」成一串固定長度(128位)的密文,這一串密文又稱爲數字指紋,它有固定的長度,並且不一樣的明文摘要成密文,其結果老是不一樣的,而一樣的內容信息其摘要一定一致。

所以,「數字摘要「叫」數字指紋「可能會更貼切一些。「數字摘要「是HTTPS能確保數據完整性和防篡改的根本緣由。

6.2 數字簽名--水到渠成的技術

假如發送方想把一份報文發送給接收方,在發送報文前,發送方用一個哈希函數從報文文本中生成報文摘要,而後用本身的私人密鑰對這個摘要進行加密,這個加密後的摘要將做爲報文的」簽名「和報文一塊兒發送給接收方,接收方首先用與發送方同樣的哈希函數從接收到的原始報文中計算出報文摘要,接着再用發送方的公用密鑰來對報文附加的數字簽名進行解密,若是這兩個摘要相同、那麼接收方就能確認報文是從發送方發送且沒有被遺漏和修改過!這就是結合「非對稱密鑰加解密」和「數字摘要「技術所能作的事情,這也就是人們所說的「數字簽名」技術。在這個過程當中,對傳送數據生成摘要並使用私鑰進行加密地過程就是生成」數字簽名「的過程,通過加密的數字摘要,就是」數字簽名「。

所以,咱們能夠在WEB端對以前案例中提到的username+MD5(password)+token經過簽名,獲得一個字段checkCode,並將checkCode發送給服務器,服務器根據用戶發送的checkCode以及自身對原始數據簽名進行運算比對,從而確認數據是否中途被篡改,以保持數據的完整性。

7. 總結

看似很是簡單的WEB登陸,其實裏面也存在着很是多的安全隱患。這些安全完善的過程是在一個實際WEB項目中遇到的,上面的分析演化是在應對項目安全的檢查中所提出的解決方案,多少會有不少不足的地方,但願一塊兒交流探討,共同進步!

補充1:JS加密函數存在被破解

感謝園友mysgk指出完整性檢驗中關於JS加密函數存在被破解的問題:

問題描述:

若是黑客經過閱讀前端js源碼,發現加密算法,是否意味他能夠構造能夠
被服務端解密的checkCode 來欺騙服務端呢 ?

我想了下,應該也是不少網站也在採起的策略:

摘要或加密JS算法不直接以靜態文件的形式存在瀏覽器中,而是讓WEB端去請求Server,服務器能夠根據隨機令牌token值決定返回一個相應隨機的加密策略,以JS代碼響應的方式返回,在異步請求響應中,加載JS摘要算法,這樣客戶端就能夠動態加載數字摘要策略,保證沒法仿造。

補充2:MD5存在隱患的問題

感謝園友EtherDream提出MD5已通過時,而且存在不安全的問題:

問題描述:

用MD五、SHA256 處理密碼的過期了。。。如今 PBKDF、bcrypt 都在過期中。

 

1.本文重點側重於方法思路的介紹,並不必定是要使用MD5函數,可使用其餘的方式。

 

2.MD5存在隱患,以前確實沒有考慮太多,不過很是感謝園友指出,確實是這樣的,主要思想是:

 

 

對於MD5的破解,實際上都屬於【碰撞】。好比原文A經過MD5能夠生成摘要M,咱們並不須要把M還原成A,只須要找到原文B,生成一樣的摘要M便可。 設MD5的哈希函數是MD5(),那麼: MD5(A) = M MD5(B) = M 任意一個B即爲破解結果。 B有可能等於A,也可能不等於A。

相關文章
相關標籤/搜索