面試官:設(shè)計一個安全的登錄都要考慮哪些?我一臉懵逼。。
來源:www.cnblogs.com/letcafe/p/loginSecurity.html
大家有沒有被問過?反正我有一次是被問的一臉懵逼。。
1. 一個簡單的HTML例子看看用戶信息安全
標(biāo)準(zhǔn)的HTML語法中,支持在form表單中使用 <input></input> 標(biāo)簽來創(chuàng)建一個HTTP提交的屬性,現(xiàn)代的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標(biāo)簽存在name的屬性,作為HTTP請求的body中的參數(shù)傳遞給后臺,進行登錄校驗。

例如我的賬號是user1,密碼是123456,那么我在提交登錄的時候會給后臺發(fā)送的HTTP請求如下(Chrome或者FireFox開發(fā)者工具捕獲,需開啟Preserve log):

2. HTTP協(xié)議傳輸直接暴露用戶密碼字段
在網(wǎng)絡(luò)傳輸過程中,被嗅探到的話會直接危及用戶信息安全,以Fiddler或Wireshark為例,發(fā)現(xiàn)捕獲的HTTP報文中包含敏感信息:

WEB前端可以通過某種算法,對密碼字段進行加密后,在將密碼作為Http請求的內(nèi)容進行提交,常見的包括對稱和非對稱加密。
對稱加密:采用對稱密碼編碼技術(shù),它的特點是文件加密和解密使用相同的密鑰加密。另外,加密算法系列面試題和答案全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺發(fā)送:2T,可以在線閱讀。
非對稱加密:需要兩個密鑰,公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數(shù)據(jù)進行加密,只有用對應(yīng)的私有密鑰才能解密;如果用私有密鑰對數(shù)據(jù)進行加密,那么只有用對應(yīng)的公開密鑰才能解密。
3.1 使用對稱加密
123456-->456123
再進行反轉(zhuǎn):
456123-->321654
那么這樣簡單的方法似乎可以混淆原密碼,并且輕松由后臺進行相反操作復(fù)原。但是這有兩個缺點:
3.2 非對稱加密HTTPS就一定是安全的嗎?
HTTPS可以保證傳輸過程中的信息不被別人截獲,但是細(xì)細(xì)思考下,HTTPS是應(yīng)用層協(xié)議,下層采用SSL保證信息安全,但是在客戶端和服務(wù)端,密文同樣是可以被截獲的; HTTPS報文在傳輸過程中,如果客戶端被惡意引導(dǎo)安裝“中間人”的WEB信任證書,那么HTTPS中的“中間人攻擊”一樣會將明文密碼泄露給別人。
4. 結(jié)論是,無論HTTP還是HTTPS,密碼必須密文傳輸
想想HTTPS也不能一定保障用戶密碼信息,那么就應(yīng)該考慮在應(yīng)用層之上再繼續(xù)對密碼進行保護,也就是編寫代碼來進行控制,而不依賴特定協(xié)議,比較容易想到的就是利用不可逆加密散列函數(shù)MD5(string),用戶在注冊輸入密碼的時候,就存儲MD5(password)值,并且在WEB端先進行MD5(password),然后將密碼傳輸至后臺,與數(shù)據(jù)庫中的密文進行比較(PS:MD5函數(shù)在指定位數(shù)的情況下,對相同字符串運算值相同)。優(yōu)點比較明顯:
保證了用戶數(shù)據(jù)庫內(nèi)部的密碼信息安全; 傳輸過程中無論如何都不會使得用戶的密文被破解出原密碼; 簡單高效,執(zhí)行以及編碼難度都不大,各種語言都提供MD5支持,開發(fā)快。
5. 那太好了!這樣可以省下HTTPS的錢了,真是這樣嗎?
回到開頭的例子:用戶輸入的用戶名是:user1,密碼是:123456,那么不管在什么協(xié)議之下,可以看到實際發(fā)送的HTTP/HTTPS報文在MD5處理后是這樣的:

沒錯,加密登錄成功了。但是,當(dāng)我們慶祝密碼安全的時候,發(fā)現(xiàn)賬戶的錢突然不翼而飛。
這是為什么呢?黑客卻笑的很開心:因為他們并不一定要獲取到你的密碼明文,如果直接截獲你的密碼密文,然后發(fā)送給服務(wù)器不是一樣可以登錄嗎?因為數(shù)據(jù)庫里的不也是MD5(password)的一樣的密文嗎?HTTP請求被偽造,一樣可以登錄成功,從而攫取其他的數(shù)據(jù)或者轉(zhuǎn)走余額。
這怎么辦?其實并不難,有很多種解決方法?其實原理都是類似的:那就是服務(wù)器緩存生成隨機的驗證字段,并發(fā)送給客戶端,當(dāng)客戶端登錄時,把這個一并字段傳給服務(wù)器,用于校驗。
5.1 方案一:驗證碼
5.2 方案二:token令牌
總而言之,就是我拿到了賬號以及密碼的密文也登陸不了,因為,如果請求不包含后臺認(rèn)證的令牌token,是個非法請求。
6. 太不容易了!可是還別高興的太早,當(dāng)心數(shù)據(jù)被篡改
密碼也加密了,黑客看不到明文了。加上Token了,登陸過程也沒法再被截獲重放了。可是想想這種情況,你在進行某寶上的網(wǎng)絡(luò)支付,需要賬號,密碼,金額,token這四個字段進行操作,然后支付的時候你付了1塊錢買了一袋包郵的小浣熊干脆面,某寶結(jié)算結(jié)束后,你發(fā)現(xiàn)你的賬戶余額被扣了1萬元。這又是怎么回事呢?
因為即便黑客不登錄,不操作,一樣要搞破壞:當(dāng)請求路由到黑客這邊的時候,截獲數(shù)據(jù)包,然后也不需要登錄,反正賬號密碼都是對的,token也是對的,那么把數(shù)據(jù)包的字段改改,搞破壞就可以了,于是把money改成了1萬,再傳給服務(wù)器,作為受害者就莫名其妙踩了這個坑。可這該怎么解決呢?其實原理類似于HTTPS里的數(shù)字簽名機制,首先科普下什么是數(shù)字摘要以及數(shù)字簽名:
6.1 什么是“數(shù)字摘要”
其實,數(shù)字摘要就是采用單項Hash函數(shù)將需要加密的明文“摘要”成一串固定長度(128位)的密文,這一串密文又稱為數(shù)字指紋,它有固定的長度,而且不同的明文摘要成密文,其結(jié)果總是不同的,而同樣的內(nèi)容信息其摘要必定一致。
因此,“數(shù)字摘要“叫”數(shù)字指紋“可能會更貼切一些。“數(shù)字摘要“是HTTPS能確保數(shù)據(jù)完整性和防篡改的根本原因。
6.2 數(shù)字簽名--水到渠成的技術(shù)
接收方首先用與發(fā)送方一樣的哈希函數(shù)從接收到的原始報文中計算出報文摘要,接著再用發(fā)送方的公用密鑰來對報文附加的數(shù)字簽名進行解密,如果這兩個摘要相同、那么接收方就能確認(rèn)報文是從發(fā)送方發(fā)送且沒有被遺漏和修改過!
7. 總結(jié)
看似非常簡單的WEB登錄,其實里面也存在著非常多的安全隱患。這些安全完善的過程是在一個實際WEB項目中遇到的,上面的分析演化是在應(yīng)對項目安全的檢查中所提出的解決方案,多少會有很多不足的地方,希望一起交流探討,共同進步!
補充1:JS加密函數(shù)存在被破解
感謝園友mysgk指出完整性檢驗中關(guān)于JS加密函數(shù)存在被破解的問題:
問題描述:
如果黑客通過閱讀前端js源碼,發(fā)現(xiàn)加密算法,是否意味他可以構(gòu)造可以 被服務(wù)端解密的checkCode 來欺騙服務(wù)端呢 ?
我想了下,應(yīng)該也是很多網(wǎng)站也在采取的策略:
摘要或加密JS算法不直接以靜態(tài)文件的形式存在瀏覽器中,而是讓W(xué)EB端去請求Server,服務(wù)器可以根據(jù)隨機令牌token值決定返回一個相應(yīng)隨機的加密策略,以JS代碼響應(yīng)的方式返回,在異步請求響應(yīng)中,加載JS摘要算法,這樣客戶端就可以動態(tài)加載數(shù)字摘要策略,保證無法仿造。
補充2:MD5存在隱患的問題
感謝園友EtherDream提出MD5已經(jīng)過時,并且存在不安全的問題:
問題描述:
用MD5、SHA256 處理密碼的過時了。。。現(xiàn)在 PBKDF、bcrypt 都在過時中。
對于MD5的破解,實際上都屬于【碰撞】。比如原文A通過MD5可以生成摘要M,我們并不需要把M還原成A,只需要找到原文B,生成同樣的摘要M即可。設(shè)MD5的哈希函數(shù)是MD5(),那么:MD5(A) = M MD5(B) = M 任意一個B即為破解結(jié)果。B有可能等于A,也可能不等于A。
大概意思也就是,截獲了MD5加密后的密文,一樣可以,找到一個不是原密碼,但是加密后可以登陸成功的“偽原文”。
從中可以看到一點,MD5函數(shù)確實能被反向“破解”,但是這個“破解”只是找到一個經(jīng)過MD5運算后得到相同結(jié)果的原文,并非是用戶的明文密碼。但是這樣會被破解登錄的可能,確實是需要采用更完善的算法進行加密,再次感謝!
看完這篇文章,你有什么收獲?歡迎在留言區(qū)與10w+Java開發(fā)者一起討論~
最后,關(guān)注公眾號互聯(lián)網(wǎng)架構(gòu)師,在后臺回復(fù):2T,可以獲取我整理和創(chuàng)作的 Java 系列教程非常齊全。
1、2019 年 9 月全國程序員工資統(tǒng)計,你是什么水平?
3、從零開始搭建創(chuàng)業(yè)公司后臺技術(shù)棧
5、37歲程序員被裁,120天沒找到工作,無奈去小公司,結(jié)果懵了...
6、滴滴業(yè)務(wù)中臺構(gòu)建實踐,首次曝光
