重放攻擊,好生猛的家伙!

1.小黑的煩惱
大白和小黑是一對好工友,前陣子小黑跳槽到了一家做電商的頭部互聯(lián)網(wǎng)公司,目前還在試用期,整天戰(zhàn)戰(zhàn)兢兢搬磚,都累瘦了。
前幾天小黑因?yàn)橐粋€(gè)接口安全問題,差點(diǎn)沒過試用期,真是不容易呀。
我們來看看是咋回事:


原來小黑寫的接口遇到了重放攻擊,讓我們一起來幫幫小黑吧!
2.什么是重放攻擊
2.1 重放攻擊的定義
重放攻擊(Replay Attacks)又稱重播攻擊、回放攻擊,是指
攻擊者發(fā)送一個(gè)服務(wù)端已接收過的包,來達(dá)到欺騙系統(tǒng)的目的,主要用于身份認(rèn)證過程,破壞認(rèn)證的正確性。
重放攻擊可以由
發(fā)起者,也可以由攔截并重發(fā)該數(shù)據(jù)的敵方進(jìn)行,攻擊者利用網(wǎng)絡(luò)監(jiān)聽或者其他方式盜取認(rèn)證憑據(jù),之后再把它重新發(fā)給認(rèn)證服務(wù)器。
重放攻擊在任何網(wǎng)絡(luò)通信過程中都可能發(fā)生,是計(jì)算機(jī)世界黑客
常用的攻擊方式之一。
這個(gè)定義我最開始讀的時(shí)候沒太理解,看了幾遍才看懂,其實(shí)表達(dá)了三層意思:
重放攻擊就是攻擊者把服務(wù)端收到過的數(shù)據(jù)包反復(fù)請求,由于是已經(jīng)收到的合法包,如果服務(wù)端防范不當(dāng)就可以順利通過身份認(rèn)證。
重放攻擊的攻擊者可以是合法的客戶端,比如你的外部合作方搞錯(cuò)了循環(huán)了100次發(fā)相同的數(shù)據(jù),還有一種是客戶端和服務(wù)端交互時(shí)被竊取了,由中間人發(fā)起了攻擊。
重放攻擊很普遍,是一種常見的攻擊防范,接口安全設(shè)計(jì)必須要考慮進(jìn)去。
了解重放攻擊概念之后,先看看小黑是如何設(shè)計(jì)接口的,再看問題在哪里以及解決方案是什么。
2.2小黑的設(shè)計(jì)方案
小黑設(shè)計(jì)的接口是為了接入外部數(shù)據(jù),接入方比較多,數(shù)據(jù)推送量也比較大。
小黑是這么設(shè)計(jì)的:
每一個(gè)接入方分配唯一賬號標(biāo)記? data_from字段 每一個(gè)接入方分配唯一接入密鑰? 32位長的secret_key字段 接口中有幾個(gè)必填字段,按照字典序排列生成字符串seg_str
data_from=abc&data_type=input&data_time=1634365534&interface_name=xyz
計(jì)算簽名sign值,并轉(zhuǎn)換為16進(jìn)制小寫
md5(seg_str&secret_key=xxxxxx).hex().lower()
接入方按照規(guī)則進(jìn)行進(jìn)行明文傳輸,小黑的服務(wù)端收到之后將必填字段按照同樣的字典序生成seg_str,再拼上對應(yīng)賬號的secret_key,計(jì)算出sign值。
小黑根據(jù)服務(wù)端計(jì)算出的sign和請求中帶的sign進(jìn)行對比,如果一致則認(rèn)為是合法請求,開始正常處理。
這個(gè)方案主體是沒問題的,和數(shù)字證書的驗(yàn)證邏輯很相似,但是還是有一些漏洞。
2.3小黑的方案漏洞
其實(shí)這里接入方數(shù)據(jù)包是否進(jìn)行對稱加密并不能解決重放攻擊的問題。
因?yàn)橹胤殴粽咄耆魂P(guān)心內(nèi)容是什么,只是簡單的把請求數(shù)據(jù)重新發(fā)一次就可以,這也是重放攻擊命名的由來。
考慮重放攻擊的特點(diǎn),我們繼續(xù)看:
漏洞一
接口沒有對請求時(shí)間范圍的進(jìn)行限制,比如一些接入方很偷懶每次請求都只傳一個(gè)固定的data_time,這樣無法區(qū)分是老請求還是新請求。漏洞二
驗(yàn)證身份只有sign值,即使sign對比是正確的,仍然無法確定就是接入方的合理行為,也就是無法確定該請求是否出現(xiàn)過,有點(diǎn)像接口冪等的感覺。
可能有的朋友會問,重復(fù)請求有啥問題嗎?
事實(shí)上,有的接口重復(fù)請求沒問題,但是小黑的數(shù)據(jù)交互接口,重復(fù)請求是有問題的,一來給系統(tǒng)負(fù)載帶來影響,二來數(shù)據(jù)會被反復(fù)在數(shù)據(jù)庫更新,如果明文被篡改,問題會更明顯。
綜上,結(jié)合重放攻擊的定義、小黑設(shè)計(jì)方案、方案漏洞等,我們明確了小黑的接口存在重放攻擊風(fēng)險(xiǎn),并且被攻擊了。
那么該如何避免和解決重放攻擊呢?
3.重放攻擊的解決方案
如果重放攻擊是被攔截?cái)?shù)據(jù)的中間人實(shí)施的,那么也可以算一種中間人攻擊。
重放攻擊一般來說不涉及數(shù)據(jù)包內(nèi)容的篡改,因此屬于比較簡單的中間人攻擊,合理使用密文傳輸可以有效解決密文被篡改的問題,不過本文暫不討論輕請求包加密傳輸?shù)膯栴}。
根據(jù)重放攻擊的特點(diǎn),解決之道也非常明顯:確定請求是否已經(jīng)存在過,存在過拒絕,新請求則放行。
3.1方案一:唯一標(biāo)記 每個(gè)請求
這種方案最直白,讓請求方增加一個(gè)全局唯一標(biāo)記uniqe_key,服務(wù)端收到之后只需要確定uniqe_key是否存在就可以了。
如果uniqe_key已經(jīng)出現(xiàn)過,就認(rèn)為是老請求,直接拒絕。 如果uniqe_key沒有出現(xiàn)過,就認(rèn)為是新請求,直接通過。
但是這個(gè)方案聽著簡單,實(shí)際操作起來有點(diǎn)費(fèi)勁,不信你看:
請求端如何生成全局唯一標(biāo)記,肯定不能單獨(dú)向服務(wù)端請求接口分配,這樣就套娃了,雞生蛋問題,所以需要服務(wù)端給一個(gè)sdk讓請求方離線生成,或者約定生成方案讓客戶端來生成uniqe_key。
服務(wù)端需要保存所有的uniqe_key,并且是持續(xù)增長的,考慮這種O(1)查詢要求,一般要用NoSQL來實(shí)現(xiàn),對存儲要求很高。
所以這種方案的存儲和查詢成本比較高,請求量大的場景或許行不通。
3.2方案二:嚴(yán)格限制 請求時(shí)間
這個(gè)方案的意思就是服務(wù)端從請求中獲取data_time時(shí)間戳,如果請求時(shí)間戳和服務(wù)器時(shí)間戳之差超過某個(gè)范圍,比如60s,就認(rèn)為是不合法的,可以拒絕。
或許有朋友問,為啥要設(shè)置60s的波動呢?
客戶端和服務(wù)端的時(shí)間基準(zhǔn)可能不同,這涉及NTP時(shí)間同步、時(shí)區(qū)等場景的存在,客戶端和服務(wù)端時(shí)間很難嚴(yán)格一致。
即使二者時(shí)鐘同步一致,客戶端和服務(wù)端的網(wǎng)絡(luò)交互也需要時(shí)間,在ms級別二者不可能完全一致,使用秒級時(shí)間戳,也還是可以接受的。
這種方案可行性稍微好一些,但是無法實(shí)際上并不能保證客戶端時(shí)鐘和服務(wù)端時(shí)鐘的一致性,同時(shí)合理設(shè)置波動時(shí)間是1分鐘還是1小時(shí),也需要大量實(shí)踐,波動時(shí)間設(shè)置太大太小都會有影響。
假設(shè)設(shè)置的時(shí)間差容忍度是10分鐘,則在10分鐘內(nèi)的重放攻擊是無法避免的,超過10分鐘則可以直接拒絕,此時(shí)方案是有效的。
3.3方案三:時(shí)間限制+唯一/隨機(jī)字符串
雖然方案一和方案二有明顯的問題,但是思想?yún)s是可以借鑒的。
結(jié)合方案一和方案二,就出現(xiàn)了新的方案:
假如設(shè)置請求時(shí)間和服務(wù)器時(shí)間的容忍范圍為15分鐘,超過15分鐘的請求直接拒絕 客戶端時(shí)間和服務(wù)端時(shí)間差在15分鐘之內(nèi)的情況,則借助于唯一標(biāo)記或者隨機(jī)字符串sep_key來進(jìn)行限制,如果該賬號下15分鐘內(nèi)出現(xiàn)過sep_key則直接拒絕,否則認(rèn)為是新請求,予以通過
隨機(jī)字符串或者唯一標(biāo)記的實(shí)際方案比較多,有的是借助于已經(jīng)生成的sign值,有的是增加nonceStr新字段,把這些值按照賬號來區(qū)分存儲在redis增加過期時(shí)間就可以了。
這個(gè)方案的亮點(diǎn)就在于使用隨機(jī)字符串或者唯一標(biāo)記杜絕了時(shí)間波動范圍內(nèi)的重放攻擊,存儲量和生成隨機(jī)數(shù)的方案都很簡單。
實(shí)際場景中這個(gè)方案應(yīng)用非常多,算是一種有效的手段。
3.4阿里云api網(wǎng)關(guān)的解決方案
客戶端調(diào)用API時(shí),需要在請求中添加計(jì)算的簽名。API網(wǎng)關(guān)在收到請求后會使用同樣的方法計(jì)算簽名,同用戶計(jì)算的簽名進(jìn)行比較,相同則驗(yàn)證通過,不同則認(rèn)證失敗。
在API網(wǎng)關(guān)的簽名中,提供X-Ca-Timestamp、X-Ca-Nonce兩個(gè)可選HEADER,客戶端調(diào)用API時(shí)一起使用這兩個(gè)參數(shù),可以達(dá)到防止重放攻擊的目的。
X-Ca-Timestamp
發(fā)起請求的時(shí)間,可以取自機(jī)器的本地實(shí)現(xiàn)。當(dāng)API網(wǎng)關(guān)收到請求時(shí),會校驗(yàn)這個(gè)參數(shù)的有效性,誤差不超過15分鐘。X-Ca-Nonce
這個(gè)是請求的唯一標(biāo)識,一般使用UUID來標(biāo)識。API網(wǎng)關(guān)收到這個(gè)參數(shù)后會校驗(yàn)這個(gè)參數(shù)的有效性,同樣的值,15分內(nèi)只能被使用一次。
綜上,小黑在自己方案的基礎(chǔ)上加上重放攻擊防范,就基本可用了,如果加上對數(shù)據(jù)的對稱加密,以及整個(gè)內(nèi)容的sign計(jì)算就可以防范高級別的中間人攻擊,對抗篡改內(nèi)容的惡意情況。
4.小結(jié)
本文從一個(gè)生產(chǎn)環(huán)境的接口安全性設(shè)計(jì)案例進(jìn)行展開,先介紹了已有接口方案、接口潛在漏洞,讓大家對案例有更深的理解。
進(jìn)一步介紹了重放攻擊常見解決方案和各自優(yōu)缺點(diǎn),同時(shí)介紹了阿里云api網(wǎng)關(guān)的方案,最終順利幫小黑解決了重放攻擊問題。
就聊到這里吧,祝大家周末愉快!
推薦閱讀:
字節(jié)二面:優(yōu)化 HTTPS 的手段,你知道幾個(gè)?
