在實(shí)現(xiàn)接口鑒權(quán)功能的時(shí)候侣灶,我們應(yīng)該防止出現(xiàn)重放攻擊,可以借助 OAuth 的驗(yàn)證思路來解決缕碎。
一褥影、概念:
接口鑒權(quán):對外開放的接口在使用的時(shí)候須鑒定訪問者是否有權(quán)訪問接口,為了防止API調(diào)用過程中被惡意篡改咏雌,調(diào)用任何一個(gè)API都需要攜帶請求簽名凡怎,簽名不合法的請求都將被拒絕校焦。
重放攻擊(Replay Attacks):顧名思義,重復(fù)的會(huì)話請求就是重放攻擊统倒≌洌可能是因?yàn)橛脩糁貜?fù)發(fā)起請求,也可能是因?yàn)檎埱蟊还粽攉@取房匆,然后重新發(fā)給服務(wù)器耸成。
二、重放攻擊的防御方法
1浴鸿、加時(shí)間戳:請求時(shí)token加上客戶端當(dāng)前時(shí)間戳井氢,同時(shí)簽名(簽名是為了防止會(huì)話被劫持,時(shí)間戳被修改)岳链,服務(wù)端對請求時(shí)間戳進(jìn)行判斷花竞,如超過一分鐘,認(rèn)定為重放攻擊掸哑,請求無效约急。
缺點(diǎn):時(shí)間戳無法完全防止重放攻擊。未認(rèn)證系統(tǒng)還是可以在這一分鐘的 token 失效窗口內(nèi)苗分,通過截獲請求厌蔽、重放請求來調(diào)用接口。并且認(rèn)證雙方需要準(zhǔn)確的時(shí)間同步摔癣,同步越好奴饮,受攻擊的可能性就越小。但當(dāng)系統(tǒng)很龐大供填,跨越的區(qū)域較廣時(shí)拐云,要做到精確的時(shí)間同步并不是很容易罢猪。
2近她、加序列號(hào)(流水號(hào)):
在客戶端和服務(wù)端通訊時(shí),先定義一個(gè)初始序號(hào)膳帕,每次遞增粘捎。這樣,服務(wù)端就可以知道是否是重復(fù)發(fā)送的請求危彩。
缺點(diǎn):但是一旦攻擊者對報(bào)文解密成功攒磨,就可以獲得序列號(hào),從而每次將序列號(hào)遞增欺騙認(rèn)證端汤徽。
3娩缰、加隨機(jī)數(shù)(nonce):該方法優(yōu)點(diǎn)是認(rèn)證雙方不需要時(shí)間同步,雙方記住使用過隨機(jī)數(shù)如發(fā)現(xiàn)報(bào)文中有以前使用過的隨機(jī)數(shù)谒府,就認(rèn)為是重放攻擊拼坎。
缺點(diǎn):缺點(diǎn)是需要額外保存使用過的隨機(jī)數(shù)浮毯,若記錄的時(shí)間段較長,則保存和查詢的開銷較大泰鸡。
4债蓝、挑戰(zhàn)與應(yīng)答的方式:
客戶端請求服務(wù)器時(shí),服務(wù)器會(huì)首先生成一個(gè)隨機(jī)數(shù)盛龄,然后返回給客戶端饰迹,客戶端帶上這個(gè)隨機(jī)數(shù),訪問服務(wù)器余舶,服務(wù)器比對客戶端的這個(gè)參數(shù)啊鸭,若相同,說明正確欧芽,不是重放攻擊莉掂。
這種方式下,客戶端每次請求時(shí)千扔,服務(wù)端都會(huì)先生成一個(gè)挑戰(zhàn)碼憎妙,客戶端帶上應(yīng)答碼訪問,服務(wù)端進(jìn)行比對曲楚,若挑戰(zhàn)碼和應(yīng)答碼不對應(yīng)厘唾,視為重放攻擊。
5龙誊、HTTPS防重放攻擊
對于HTTPS抚垃,每個(gè)socket連接都會(huì)驗(yàn)證證書,交換密鑰趟大。攻擊者截獲請求鹤树,重新發(fā)送,因?yàn)閟ocket不同逊朽,密鑰也不同罕伯,后臺(tái)解密后是一堆亂碼,所以HTTPS本身就是防止重放攻擊的叽讳,除非能復(fù)制socket追他,或者進(jìn)行中間人攻擊。
三岛蚤、實(shí)現(xiàn)
為了防御重放攻擊邑狸,我在實(shí)際開發(fā)中見到的方法是增加token參數(shù),舉個(gè)例子:
1涤妒、如果某應(yīng)用需要請求服務(wù)器端接口单雾,需要服務(wù)器端給分配一個(gè)app_key和一個(gè)app_secret給這個(gè)應(yīng)用,并且服務(wù)器端需要備份一份,方便后續(xù)查找硅堆;
2蜂奸、為了防止重放攻擊,在參數(shù)中加入時(shí)間戳等參數(shù)(可參照上面防御方法)硬萍;
3扩所、然后使用加密算法MD5或者SHA進(jìn)行加密,生成token朴乖,在請求的URL中加入這個(gè)token參數(shù)祖屏,生成方式如下;
SHA(app_key=abc&app_secret=123&timeStamp=1669855515)
URL:https://xxx.xx.com/index.do?app_key=abc&token=xxx&timeStamp=1669855515
4买羞、服務(wù)器端收到請求后解析出參數(shù):app_key袁勺、token、timeStamp畜普;
5期丰、根據(jù)時(shí)間戳timeStamp判斷請求是否失效(我們暫定為一分鐘),超一分鐘為失效吃挑,如失效直接拒絕钝荡;
6、然后從服務(wù)器端根據(jù)app_key獲取app_secret舶衬;
7埠通、使用app_key、app_secret逛犹、timeStamp三個(gè)參數(shù)生成服務(wù)器端token端辱,方式同上;
8虽画、比較服務(wù)器端token和請求參數(shù)中token的是否一致舞蔽,一致就鑒權(quán)通過,否則拒絕码撰。