API團隊須知的十大安全威脅
譯文【51CTO.com快譯】如今,無論是以API為主營服務(API-first)的公司,或是單頁面應用/JAMStack,都通過各種豐富的API對外公布著大量的數據。不過,由于這些數據能夠被直接地訪問到,而且繞過了瀏覽器的預防機制。因此,我們需要擔心的不再是SQL注入和XSS等“入向”問題,而是敏感數據記錄可能被竊取等API“出向”安全性問題。此外,由于API被設計為能夠向單個客戶端提供大量的API訪問,因此諸如驗證碼(Captchas)和瀏覽器指紋識別之類的典型預防機制,也不再能夠起到明顯的效果。
那么,我們該如何開始做好API的安全防護呢?在此,讓自己從攻擊者的角度來檢查目標API,以阻斷常見的未知對象攻擊,并參照OWASP安全API列表
(請參見--https://owasp.org/www-project-api-security/),來防范各種零日漏洞的利用。
1. 限制不安全的資源訪問
大多數API都提供了對于實體列表(例如/users或/widgets)的資源訪問。諸如瀏覽器之類的客戶端通常會使用如下方式,來進行過濾和分頁(pagination),以限制返回給客戶端的條目數:
- First Call: GET /items?skip=0&take=10
- Second Call: GET /items?skip=10&take=10
但是,如果該實體中含有任何PII(個人身份信息)或其他敏感信息,那么攻擊者就可能通過該端點,獲取數據庫中的所有實體信息。一旦這些實體的PII被意外泄露,競爭對手就能夠推斷出貴企業的采購信息和客戶狀況,甚至是大量的郵件列表。如果您對此有興趣的話,可以參看《如何清除Venmo數據》
(https://22-8miles.com/public-by-default/)一文。
常規的保護機制是記錄那些大于100或1000條的條目,并拋出異常信息。下面是兩種常見的默認保護方法:
- 對于數據型API,合法客戶可能需要獲取并同步大量的記錄,并通過各種cron作業來實現。那么人為地限制分頁的大小,會迫使API頻繁地進行同一種操作,進而降低了整體吞吐量。可以說,此類最大條目限制方法主要是為了滿足內存和可擴展性的要求,以及防止某些DDoS攻擊。
- 如下代碼段所示,通過編寫簡單的腳本,在重復的訪問之間,隨機休眠一段時間。當然,此類防護對于攻擊者來說,并非總是奏效。
- skip = 0
- while True: response = requests.post('https://api.acmeinc.com/widgets?take=10&skip=' + skip), headers={'Authorization': 'Bearer' + ' ' + sys.argv[1]}) print("Fetched 10 items") sleep(randint(100,1000)) skip += 10
2. 防止分頁攻擊
為了防止分頁攻擊,您應該跟蹤在一定時間段內,用戶或API密鑰訪問某個資源的數量,而不是僅僅停留在請求本身。您可以在用戶或API密鑰達到閾值時(例如:每個用戶或API密鑰在一個小時內之允許調用1,000,000條記錄)阻止它們。當然,具體閾值的設定取決于您的API用例,以及它們的訂閱方式。就像每分鐘只能發送一次驗證碼那樣,此舉減緩了黑客調用目標API的速度。對此,攻擊者不得不手動創建更多新的帳戶或API密鑰。
3. 保護API密鑰池
大多數API會受密鑰或JWT(JSON Web令牌)的保護。由于API安全工具可以檢測到異常的API行為,并自動阻止對于API密鑰的訪問,因此這是跟蹤和保護API的原生方式。但是,攻擊者往往會使用大量的IP地址,來規避DDoS的檢查;并通過生成大量的賬戶,來獲取大量的API密鑰。
抵御此類攻擊的最簡單方法是要求用戶注冊自己的服務,并生成對應的API密鑰。我們可以通過使用驗證碼和雙因素身份驗證,來阻止各種僵尸(Bot)流量。除非是合法的業務用例,否則新注冊服務的用戶不能夠以程序的方式,生成API密鑰。相反,只有那些受信任的用戶,才具有生成API密鑰的能力。據此,我們可以確保在帳戶級別(不僅僅針對每個API密鑰)上,對異常行為進行異常檢測。
4. 防止意外的密鑰泄露
總的說來,如下使用API的方式會增加密鑰泄漏的可能性:
- 如果您將該API密鑰保存在服務器的環境變量中,并提供侍候型的訪問方式,那么就會增加黑客獲得有效且未過期的密鑰的可能性。這顯然不及用戶在登錄交互式網站時,在會話中使用較短時間到期的API密鑰安全。
- API的使用者可以直接訪問到密鑰,例如通過Postman或CURL進行調試。那么任何一個開發人員都可以將含有API密鑰的CURL命令,意外地復制/粘貼到諸如GitHub Issues或Stack Overflow之類的公共論壇中。
- 如果不采用一次性令牌或雙因素身份驗證,API將無法保護其密鑰。
防止密鑰泄露的最簡單方法是利用兩個令牌而非一個。刷新令牌(refresh token)被存儲為環境變量,并且只能用于產生短暫的訪問令牌(short lived access tokens)。與刷新令牌不同,這些短暫的令牌可以訪問到資源,但是有著時間的限制,例如數小時或數天。
客戶存儲刷新令牌和其他API密鑰。SDK會在其初始化時、或是最后一個訪問令牌到期時,生成新的訪問令牌。如果CURL命令被粘貼到GitHub中,那么攻擊者必須在數小時內使用短暫的訪問令牌,不然就會過期(畢竟他獲取到刷新令牌的可能性極低)。
5. 阻止DDoS攻擊
API開辟了全新的業務模式,用戶可以在其中以編程的方式訪問到目標API平臺。但是,這也會使得針對DDoS保護變得十分棘手。大多數DDoS的保護機制是清洗或拒絕攻擊者發來的大量請求。但是為了讓混淆在僵尸流量中正常請求能夠順利通過,我們需要對HTTP請求進行指紋識別。但是對于API服務而言,這是極其困難的,畢竟所有的流量都看上去像僵尸流量,而非來自瀏覽器的Cookie。
如今,絕大多數的關于API的訪問和調用都需要用到API密鑰。如果某個請求中沒有API密鑰,則會被自動拒絕。那么,我們該如何處置那些經過驗證的請求呢?目前,最簡單的方法是利用每個API密鑰的速率限制計數器,例如:我們可以預先設定每分鐘可以處置X個請求,那么對于超過這個數量級的請求,則以帶有HTTP 429的響應方式予以拒絕。目前,我們可以采用諸如漏斗和固定窗口計數器等多種算法,來實現這一點。
6. 通過正確的SSL來確保服務器安全
其實在服務器安全方面,API與Web服務器并無太大差別。錯誤配置的SSL證書,或默認允許非HTTPS的流量通過,都可能導致數據的泄漏。如今,非HTTPS請求雖然已經逐漸被HTTPS所取代,但是用戶仍然可能錯誤地從其應用程序、或泄露了API密鑰的CURL中發出非HTTPS的請求。而且API是無法實現HSTS(HTTP Strict Transport Security,HTTP嚴格傳輸安全協議)、或HTTPS重定向之類的瀏覽器級保護的。
目前比較普遍的做法是通過Qualys SSL Test(請參見--https://www.ssllabs.com/ssltest/)或類似的工具,來實施并測試SSL。無論您的API是僅供自己的應用來訪問,還是要在服務器端被訪問到,您都可以通過負載均衡設備來阻斷所有非HTTPS頭的請求。具體請參見《REST API跨域資源共享權威指南》
(https://www.moesif.com/blog/technical/cors/Authoritative-Guide-to-CORS-Cross-Origin-Resource-Sharing-for-REST-APIs/?utm_source=dzone&utm_medium=blog&utm_campaign=placed-article&utm_term=top-10-api-security-threats)一文。
7. 確保正確地配置緩存頭
API通過不同的密鑰,提供了對于既定范圍內動態數據的訪問。那么任何緩存機制的實現,都應該基于API密鑰的范圍,以防止出現數據的“交叉污染”。例如:某個用戶通過代理服務器正在使用多個API密鑰,其中一個被用于開發環境,另一個被用于生產環境,那么兩個環境中的數據就可能產生相互泄露。此方面的一個真實案例是:Twitter曾在數據安全事件后證實泄漏了賬號相關信息(請參見:
https://www.bleepingcomputer.com/news/security/twitter-discloses-billing-info-leak-after-data-security-incident/)。
通常情況下,許多API并不使用標準的認證頭,而是類似于X-Api-Key的自定義頭。如下代碼段所示,緩存服務器在并不知曉此類請求是否已通過驗證的情況下,只能選擇對其進行緩存。可見,我們應該正確地配置緩存控制(Cache-Control)頭。
- app.use((req, res, next) => { res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate'); res.setHeader('Pragma', 'no-cache'); // ...
- });
8. 正確地添加API日志記錄
通過對大多數入侵案例的研究,OWASP層發現:企業通常需要超過200天,才能檢測到數據發生了泄漏事件。而且,如果未能采用適當的API日志記錄和監控,攻擊者可能會持續使用相同的漏洞,進而探測到更多的漏洞。
我們不但應該確保API日志記錄能夠跟蹤API的請求本身,而且需要通過綁定以實現對用戶行為的分析。與此同時,此類系統應當受到相應的保護,以確保數據記錄不會被意外地刪除,或過早地銷毀掉(應至少存儲一年)。為了安全起見,GDPR和CCPA都允許系統開展API審計。如下圖的API審計日志所示,像Moesif API Security
(https://www.moesif.com/solutions/api-security?utm_source=dzone&utm_medium=blog&utm_campaign=placed-article&utm_term=top-10-api-security-threats)之類的方案,能夠為API產品提供了一整套監視和分析功能,并且用戶只需數分鐘就能夠快速上手。
9. 正確地處理授權
雖然大多數API開發人員都會自覺地添加諸如API密鑰、或OAuth之類的全局性認證方案、來驗證調用方的身份。但是,我們也需要通過授權的方式,來檢查他們是否可以訪問某些特定的資源。對此,我們往往會借用訪問控制列表(ACL),并為相關對象分配不同的角色,來實現基于角色的訪問控制。您可以參考《為RESTful API構建身份驗證和授權的步驟》一文(請參見--https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/?utm_source=dzone&utm_medium=blog&utm_campaign=placed-article&utm_term=top-10-api-security-threats),以了解具體的防護方法。
10. 保護內、外部端點
同一項API服務有可能具有內、外不同的使用端點。那么,除了使用身份驗證和授權等基本保護方案之外,我們還應通過啟用負載均衡器或API網關,以確保這些端點不會完全暴露于公共互聯網上。此外,我們也可以通過提供多級安全性(一種常見的預防策略),來進行API的防護與加持。
原標題:Top 10 API Security Threats Every API Team Should Know ,作者:Derric Gilling
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】