關(guān)于 API 安全你需要知道的那些事
一、前言
????????伴隨著移動(dòng)互聯(lián)網(wǎng)時(shí)代的飛速發(fā)展,人手一部智能機(jī)連接這個(gè)世界已經(jīng)成為現(xiàn)狀,隱私和安全問題也逐漸被越來越多的人重視。從 2021 年某滴安全信息泄露的消息公之于眾后,人們對(duì)于信息安全的呼聲和訴求也越發(fā)高漲。
????????回到正題,不管是 app,還是各個(gè)訪問終端的入口,作為最終承載交互數(shù)據(jù)的來源 — API 接口,無疑需要對(duì)數(shù)據(jù)的安全訪問提供最終的支撐和保障。接下來,讓我們花點(diǎn)時(shí)間來聊聊關(guān)于 API 接口安全的那些事吧。
二、API 安全常見問題
????????經(jīng)常聽人說,某某系統(tǒng)被黑了,某某 app 的短信 1 分鐘內(nèi)被狂刷了幾萬條,某某應(yīng)用的系統(tǒng)癱瘓了...諸如此類不一而足。追根溯源,從問題分析的經(jīng)驗(yàn)來看,不管系統(tǒng)攻擊者采用何種手段,多數(shù)情況下,最終攻擊的入口,或者說最終的受害者還是匯聚到了API 這一層,可見,API 可以說是系統(tǒng)的守衛(wèi)員,不容有失。
????????關(guān)于 API 的常見安全問題有哪些呢?小編這里結(jié)合多年的實(shí)踐經(jīng)驗(yàn),做了如下的一些總結(jié)以供參考。
2.1 接口被惡意調(diào)用
當(dāng)系統(tǒng)的某些接口被攻擊者或別有用心的人惡意調(diào)用時(shí),可能有如下表現(xiàn):
系統(tǒng)被狂刷短信...
某個(gè)頁面直接卡死,導(dǎo)致其他用戶無法訪問頁面...
系統(tǒng)服務(wù)器 CPU 瞬間飆升...
平臺(tái)內(nèi)關(guān)聯(lián)的其他應(yīng)用也無法正常使用...
為什么 API 接口會(huì)被惡意調(diào)用呢?經(jīng)驗(yàn)來看,無非就那點(diǎn),樹大招風(fēng),你的產(chǎn)品被競(jìng)爭(zhēng)對(duì)手盯上了,人家眼紅了。
2.2 接口數(shù)據(jù)被篡改
????????這也是一種比較場(chǎng)景的 API 安全問題,一個(gè)常見的場(chǎng)景就是,當(dāng)你登錄某個(gè)系統(tǒng)時(shí),你的會(huì)話信息,像存在瀏覽器中的 cookie 信息,被別有用心者劫持了,然后這個(gè)人拿著你的信息冒充你的身份去請(qǐng)求 API 的數(shù)據(jù),甚至修改你的數(shù)據(jù)返回給你進(jìn)行詐騙等目的。使用過 Fiddler 抓包工具的同學(xué)可以在自己公司的產(chǎn)品中模擬下這個(gè)過程。

2.3 接口敏感數(shù)據(jù)被竊取
通常在 B 端產(chǎn)品中,會(huì)對(duì)某些 API 返回的部分字段數(shù)據(jù)進(jìn)行脫敏,比如手機(jī)號(hào),郵箱等,以保證用戶的信息隱私。
????????盡管 API 層面對(duì)敏感數(shù)據(jù)做了脫敏處理,但敏感數(shù)據(jù)如果未進(jìn)行加密處理,或加密的強(qiáng)度不夠,或者沒有安全的存儲(chǔ)加密數(shù)據(jù),以至于攻擊者仍然能夠獲得敏感信息,進(jìn)而攻擊者可能利用此漏洞對(duì)客戶端,或服務(wù)器發(fā)送特殊構(gòu)造的數(shù)據(jù),發(fā)出攻擊,從而了解后臺(tái)數(shù)據(jù)庫表等信息,對(duì)系統(tǒng)安全構(gòu)成威脅。這也就是接口敏感數(shù)據(jù)被竊取了。
2.4 XSS 攻擊
????????深究起來,XSS 攻擊更多偏向于前端這一層,但是對(duì)于一個(gè)能夠提供充分安全保障的系統(tǒng)來說,API 的對(duì)于參數(shù)的安全校驗(yàn)也是非常重要的一環(huán),對(duì)于系統(tǒng)來說,應(yīng)該確保核心 API 的業(yè)務(wù)對(duì)于所有的入?yún)⒍紤?yīng)該是安全,可信且經(jīng)過校驗(yàn)之后才能進(jìn)行數(shù)據(jù)存儲(chǔ)的。這樣可以從源頭上保障 XSS 攻擊影響的范圍進(jìn)一步縮小。
三、系統(tǒng)層面的安全防護(hù)解決措施
????????在系統(tǒng)架構(gòu)設(shè)計(jì)之初,系統(tǒng)安全一定是一個(gè)重要的考量因素被納入到架構(gòu)設(shè)計(jì)規(guī)劃中,系統(tǒng)安全關(guān)乎著既關(guān)乎公司的生存,也關(guān)乎產(chǎn)品的盈利,更進(jìn)一步說,更關(guān)乎著法律法規(guī)對(duì)公司的監(jiān)管合規(guī)性依據(jù)。下圖所示,為一個(gè)通用的微服務(wù)業(yè)務(wù)架構(gòu)圖。

????????從實(shí)踐經(jīng)驗(yàn)來看,安全在一個(gè)系統(tǒng)的架構(gòu)設(shè)計(jì)中占據(jù)著舉足輕重的地位,從上圖來看,可以說,安全考慮在架構(gòu)設(shè)計(jì)的每一環(huán)都有著落地的目標(biāo),拆開來看,具體如下所述。
3.1 前端安全
涉及到前端安全的技術(shù),比如:
頁面表單的防重提交(功能上限制防刷的可能性);
接口請(qǐng)求前關(guān)鍵參數(shù)的校驗(yàn),脫敏,XSS 不安全字符的自動(dòng)識(shí)別;
使用參數(shù)加密,Base64 處理,禁止明文傳輸;
3.2 系統(tǒng)級(jí)防火墻
防火墻本身具有較強(qiáng)的抗攻擊能力,它是提供信息安全服務(wù)、實(shí)現(xiàn)網(wǎng)絡(luò)和信息安全的基礎(chǔ)設(shè)施之一。
????????防火墻對(duì)于一個(gè)互聯(lián)網(wǎng)公司的重要意義毋庸置疑,尤其是金融類,銀行類等 B 端產(chǎn)品,防火墻的作用可以說是不可替代的,盡管這個(gè)技術(shù)已經(jīng)不是什么新鮮的東西,但基本上所有的軟件公司在產(chǎn)品發(fā)布到線上環(huán)境之后,所有來自外部的請(qǐng)求,都會(huì)經(jīng)過服務(wù)器廠商的防火墻,只有通過了防火墻這一層請(qǐng)求才能繼續(xù)往下進(jìn)行。
????????關(guān)于防火墻的作用,這里簡(jiǎn)單列舉如下:
防止來自被保護(hù)區(qū)域外部的攻擊,保護(hù)易受攻擊的網(wǎng)絡(luò)服務(wù)資源和客戶資源;
集中安全管理,通過集中的安全策略配置,以便統(tǒng)一管理和執(zhí)行安全政策;
防止信息外泄和屏蔽有害信息,執(zhí)行安全檢查,嚴(yán)格控制進(jìn)出網(wǎng)絡(luò)的數(shù)據(jù),過濾和屏蔽有害信息,防止信息外泄;
安全審計(jì)和告警,通過對(duì)網(wǎng)絡(luò)存取訪問進(jìn)行監(jiān)控審計(jì),有效跟蹤各類網(wǎng)絡(luò)活動(dòng),及時(shí)發(fā)現(xiàn)問題和及時(shí)報(bào)警。
3.3 網(wǎng)關(guān)
????????關(guān)于網(wǎng)關(guān),基本上所有的人都多少有一定的了解,網(wǎng)關(guān)在一個(gè)安全的系統(tǒng)架構(gòu)設(shè)計(jì)中的作用,可以說是承上啟下,至關(guān)重要,大體來說,從安全的角度來講,主要體現(xiàn)在如下幾個(gè)方面:
屏蔽真實(shí)的API地址
????????拿 nginx 來說,如果后端的接口真實(shí)地址是:/API/v2/user/get/1,為了確保接口安全,屏蔽真實(shí)的地址,通過nginx 的反向代理之后,接口可能變成這樣:/platform/biz/API/v2/user/get/1。
負(fù)載均衡,均衡流量
????????從系統(tǒng)安全和系統(tǒng)可用性的角度講,為了確保系統(tǒng)的高可用性,通常應(yīng)用服務(wù)集群部署,這樣可以避免單節(jié)點(diǎn)壓力過大而造成業(yè)務(wù)高峰時(shí)系統(tǒng)不可用,有了網(wǎng)關(guān)這一層,就可以通過網(wǎng)關(guān)的配置動(dòng)態(tài)實(shí)現(xiàn)負(fù)載均衡,以達(dá)到均衡流量的效果,從而對(duì)系統(tǒng)過載形成防護(hù)。
攔截惡意請(qǐng)求,定向黑白名單
????????以 nginx 來說,提供了可編程式的配置,通過編寫腳本代碼,對(duì)經(jīng)過 nginx 的請(qǐng)求進(jìn)行監(jiān)控,尤其是對(duì)于那些惡意刷接口的請(qǐng)求,可以很好的進(jìn)行識(shí)別,甚至可以在 nginx 這一層對(duì)那些惡意請(qǐng)求的 IP,IP 段進(jìn)行黑名單的設(shè)置,從而對(duì)后臺(tái)的服務(wù)進(jìn)行第一層的安全防護(hù)。
限流
????????對(duì)一個(gè)系統(tǒng)來說,可用性已然成了系統(tǒng)是否穩(wěn)定的考量因素的重要標(biāo)準(zhǔn),當(dāng)業(yè)務(wù)高峰期時(shí),不管是外部的惡意請(qǐng)求,還是類似搶單這樣的瞬間大流量來說,為了保障系統(tǒng)的整體可用性,必要的限流措施也是確保系統(tǒng)安全的重要手段,而網(wǎng)關(guān)作為承載系統(tǒng)流量的入口,在網(wǎng)關(guān)這一層做一定的限流管控是很有必要的。
四、API 層面安全設(shè)計(jì)的常用解決方案
????????以上從架構(gòu)設(shè)計(jì)層面聊了一下常用的安全防護(hù)措施,而作為系統(tǒng)對(duì)外提供數(shù)據(jù)來源的 API 接口,也就是系統(tǒng)的核心后臺(tái)服務(wù),可以說,關(guān)于 API 的安全考慮,可以說很多開發(fā)者在設(shè)計(jì)過程中尚未引起足夠的重視。這里小編說一個(gè)有意思的現(xiàn)象,在小編過往的工作經(jīng)歷中,那些甲方公司最終對(duì)項(xiàng)目進(jìn)行驗(yàn)收時(shí),通常需要對(duì)整個(gè)源碼進(jìn)行安全審計(jì),其中審計(jì)最容易出問題的地方,就是很多 API 接口的安全問題,比如 XSS 攻擊,CSRF 攻擊,接口有被刷的風(fēng)險(xiǎn)...
????????接下來,針對(duì)上述談到的問題,以及日常開發(fā)中對(duì)于 API 安全的一些規(guī)范性要求,一起探討下在 API 安全設(shè)計(jì)的一些處理措施。
4.1 控制 API 的訪問邊界
????????以當(dāng)下流行的微服務(wù)來說,后臺(tái)提供出去的 API 一定要規(guī)范訪問邊界,哪些接口可以暴露出去,哪些接口一定要通過鑒權(quán)才能訪問,關(guān)于這一點(diǎn),依照經(jīng)驗(yàn)來說,做好下面幾點(diǎn)即可:
接口設(shè)計(jì)之初,與前端同學(xué)約定好接口的使用場(chǎng)景;
對(duì)外暴露且不需要鑒權(quán)的接口做好流控,避免被刷,比如有些登錄接口中需要用到短信驗(yàn)證碼的場(chǎng)景;
對(duì)外暴露且不需要鑒權(quán)的接口做好嚴(yán)格的參數(shù)校驗(yàn),避免 XSS 字符的入庫存儲(chǔ);
需要走鑒權(quán)的接口,最好走統(tǒng)一的安全校驗(yàn)邏輯,比如 SDK 或者內(nèi)部封裝的組件;
4.2 嚴(yán)格規(guī)范 API 的使用類型
????????對(duì)于某些比較大的平臺(tái)來說,比如 pass 平臺(tái),通常都是十幾個(gè)甚至幾十上百個(gè)內(nèi)部服務(wù)組成的,如此龐大的系統(tǒng)統(tǒng)一對(duì)外提供服務(wù)時(shí),各應(yīng)用服務(wù)之間必然存在著互相的調(diào)用,這些可以是 dubbo 調(diào)用,或者 http 的調(diào)用,通常不同的應(yīng)用之間調(diào)用時(shí),走 rest 接口非常多,同時(shí),不同應(yīng)用之間互相調(diào)用時(shí),場(chǎng)景也是多樣,有些需要認(rèn)證,有些不需要,有些需要嚴(yán)格的認(rèn)證,有些需要寬容的認(rèn)證,這該怎么辦呢?
????????針對(duì)上面的場(chǎng)景,這里可以考慮定義不同的 API 使用類型,針對(duì)不同類型的 API,在調(diào)用的時(shí)候策略也不一樣,具體實(shí)踐來說,可以參照如下設(shè)計(jì)原則;
系統(tǒng)外部可調(diào)用的 API
????????這種 API,即內(nèi)部應(yīng)用和外部應(yīng)用都可以調(diào)用的 API,這類 API 的設(shè)計(jì),通常需要通過一個(gè)統(tǒng)一的憑證頒發(fā)入口,調(diào)用者拿到這個(gè)憑證,在調(diào)用 API 時(shí)傳過去,認(rèn)證通過后,API 給與數(shù)據(jù)響應(yīng),由于憑證是系統(tǒng)內(nèi)部的服務(wù)頒發(fā),可以認(rèn)為是安全的,同時(shí),如果更進(jìn)一步的話,可以對(duì)憑證做有效期的設(shè)定,甚至是加密處理等措施。
系統(tǒng)內(nèi)部可調(diào)用的 API
????????即平臺(tái)各個(gè)微服務(wù)應(yīng)用之間調(diào)用的 API,由于內(nèi)部的應(yīng)用在使用之前,都需要一定的注冊(cè)或者其他的認(rèn)證措施,對(duì)于內(nèi)部的 API 調(diào)用來說,可以在 API 接口中添加關(guān)鍵參數(shù)信息識(shí)別即可,比如,在請(qǐng)求內(nèi)部 API 的時(shí)候添加一個(gè) appName 這樣的標(biāo)識(shí),一旦 API 校驗(yàn)這個(gè) appName 合法有效,就可以給與響應(yīng)。
無需認(rèn)證的 API
????????比如請(qǐng)求系統(tǒng)的首頁,或者上面談到的請(qǐng)求短信驗(yàn)證碼,再就是某些需要對(duì)接平臺(tái)的外部第三方應(yīng)用,這些第三方應(yīng)用需要拿到一些非敏感的數(shù)據(jù)作為業(yè)務(wù)標(biāo)識(shí)等,這種情況下,針對(duì)這樣的 API,在設(shè)計(jì)時(shí),要做好關(guān)鍵參數(shù)的校驗(yàn),接口防刷的處理,以及可信 IP 的識(shí)別。
4.3 API 敏感參數(shù)加密處理
????????類似于登錄,獲取用戶信息的 API 接口,一定要做加密處理,防止因會(huì)話劫持造成數(shù)據(jù)傳輸過程中敏感信息的泄露,關(guān)于加密,常用的加密方式包括:
密碼的 MD5 加密,甚至可以混合鹽值提高加密的安全等級(jí);
對(duì)稱或非對(duì)稱加密(根據(jù)業(yè)務(wù)需要選擇);
JWT,也是當(dāng)下流行的一種輕量化的加解密方案;
4.4 API 請(qǐng)求 header 中混合特殊參數(shù)
????????一種常見的場(chǎng)景就是,前端請(qǐng)求 API 接口時(shí),需要在請(qǐng)求的 header 中添加后臺(tái)辦法的 token 或者其他的令牌等參數(shù),而請(qǐng)求到達(dá) API 之前(有的在 API 中做),解析并統(tǒng)一校驗(yàn) API 請(qǐng)求中的 header 是否攜帶了這個(gè)參數(shù),且有效的情況下才予以返回。如果你的 API 安全等級(jí)更高,可以考慮在請(qǐng)求 header 中混合其他的定制化參數(shù),這也是一種有效的保護(hù) API 的手段。

4.5 API 自身的防刷措施
????????對(duì)于一個(gè)成熟穩(wěn)定的系統(tǒng)來說,盡管請(qǐng)求在真正到達(dá) API 時(shí)有各種防護(hù)措施,比如限流,惡意請(qǐng)求 IP 識(shí)別等統(tǒng)一的措施,但是作為打通數(shù)據(jù)后臺(tái)到前臺(tái)的最后一關(guān),針對(duì)系統(tǒng)中的某些核心業(yè)務(wù)的 API,還是有必要做針對(duì)性的接口防刷機(jī)制,具體來說,可參考下面的思路進(jìn)行實(shí)施;
根據(jù)來源 IP,核心業(yè)務(wù)字段的組合進(jìn)行惡意請(qǐng)求的識(shí)別,限制這類請(qǐng)求頻次,減少對(duì)服務(wù)端的壓力;
API 采用限流組件,或者引入開源限流 SDK,或者自己編寫限流算法工具包,對(duì)熱點(diǎn) API 進(jìn)行限流;
日志追蹤,針對(duì)那些惡意刷接口的 IP,記錄在日志,并接入告警平臺(tái),定向的上報(bào)監(jiān)控告警;
4.6 盡量對(duì)請(qǐng)求參數(shù)進(jìn)行封裝
????????一般來說,從 rest 請(qǐng)求安全的角度來說,post 請(qǐng)求的安全性要好于 get 請(qǐng)求,這是因?yàn)榇蠖鄶?shù)情況下,get 請(qǐng)求暴露在請(qǐng)求 url 中,而 post 請(qǐng)求的參數(shù)相對(duì)來說會(huì)隱蔽一些。這里給出的建議是,當(dāng)查詢請(qǐng)求參數(shù)超過 5 個(gè)時(shí),可以對(duì)請(qǐng)求參數(shù)進(jìn)行封裝,然后將親請(qǐng)求類型調(diào)整為 post。
4.7 API 參數(shù)校驗(yàn)
????????為什么這一點(diǎn)放在最后來說,小編認(rèn)為這是大多數(shù)開發(fā)者能夠想到但在實(shí)際工作中又不能做得很好的一點(diǎn)。參數(shù)校驗(yàn)可以說是 API 層面最后一道基礎(chǔ)但是重要的安全保障了,但是在參數(shù)校驗(yàn)這個(gè)度的把握上,很多開發(fā)人員顯得有些不知所措,這里小編提出下面幾點(diǎn)建議以供參考:
區(qū)分 API 的重要程度
????????并不是所有的 API 都需要一大堆的參數(shù)校驗(yàn),為什么這么說呢?要知道,參數(shù)對(duì)于一個(gè)系統(tǒng)安全的影響隨著鏈路的傳遞是逐漸增加的,假如說一段xss的字符作為參數(shù)傳入到 API 接口中,假如不做處理最終會(huì)入庫,后面再查詢出來渲染到頁面時(shí)候,這個(gè)危害性就大了,影響的不僅是用戶的體驗(yàn),甚至?xí)ヒ粋€(gè)潛在的有價(jià)值的用戶。
????????說到這里,相信大家能夠了解,假如在 save 數(shù)據(jù)的接口中就能夠識(shí)別非法參數(shù),從而進(jìn)行攔截的話,后續(xù)所有的麻煩都可以提前避免掉。從這個(gè)角度來說,一個(gè)通用的做法就是,針對(duì)那些需要保存表單的數(shù)據(jù),或者是涉及到修改,刪除之類的 API,一定要做好參數(shù)的校驗(yàn)和控制。
不要過度對(duì)參數(shù)進(jìn)行校驗(yàn)
????????看到過不少開發(fā)者在一個(gè)存儲(chǔ)數(shù)據(jù)的接口中對(duì)參數(shù)進(jìn)行了相當(dāng)篇幅的代碼校驗(yàn),并不是說這樣不好,而是需要區(qū)分一個(gè)度的問題,舉例來說,有人在編寫一個(gè)保存用戶的 API 接口時(shí),對(duì)用戶名稱做校驗(yàn)時(shí),大概有幾十行代碼,涉及的規(guī)則如下:
校驗(yàn)賬戶中是否有特殊字符,比如 $% 這樣的字符;
校驗(yàn)賬戶名稱長(zhǎng)度是否超過限制;
校驗(yàn)系統(tǒng)中是否有重復(fù)的賬戶名;
校驗(yàn)賬戶名中是否有違禁的詞;
校驗(yàn)賬戶名中是否有多音字;
...
????????我就想不通了,一個(gè)賬戶名的校驗(yàn)需要搞那么多花樣嗎,開個(gè)玩笑,這當(dāng)然不是我的過激行為,我要表達(dá)的意思是,API 設(shè)計(jì)時(shí),在考慮安全性的同時(shí)盡可能兼顧使用者的習(xí)慣,簡(jiǎn)化因參數(shù)校驗(yàn)帶來的交互流程上的麻煩。
五、寫在文末
????????安全無小事,這句話應(yīng)該來說對(duì)所有的行業(yè)都適用。希望從事開發(fā)的伙伴們?cè)谌粘i_發(fā)中對(duì)系統(tǒng)安全多一份敬畏,從而少一些因安全事故帶來的不必要的麻煩。當(dāng)然,系統(tǒng)的安全性建設(shè)是一項(xiàng)長(zhǎng)期的工作,需要自頂而下,做好長(zhǎng)遠(yuǎn)的規(guī)劃,并逐步落實(shí)并貫穿到日常的每一個(gè)開發(fā)、測(cè)試、運(yùn)維以及實(shí)施過程中,這樣這才是長(zhǎng)久之計(jì),與君共勉。