我已經爲部分遵循this very good blog post by Riyad Kalla的項目創建了一個簡單的RESTful API。現在,我已經閱讀了堆棧溢出的幾十個類似問題,但我似乎無法找到我的安全問題的答案。保護無會話RESTful API端點
簡單地說,我的要求是這樣的:
- 客戶端有一個公共的API密鑰(純文本,任何人嗅探網絡流量或正確地檢查代碼源訪問)
- 客戶端發送對服務器的請求,與公衆的API密鑰
- 該服務器有一個祕密的API密鑰(祕密到任何人,但開發者)
- 服務器創建客戶端的請求數據組成的HMAC-SHA1散列和祕密API密鑰
- 服務器發送相同的客戶端的請求,API服務器的請求,但其中所產生的HMAC-SHA1
- 的API服務器查找基於公共API密鑰收到
- 在其數據庫中的祕密API密鑰API服務器重新創建使用作爲開發者的服務器相同的數據
- 如果哈希匹配,該請求被認爲是有效的,並且通常處理
我擔心用我的服務了別人HMAC-SHA1哈希可能獲取公共API密鑰(通過嗅探網絡流量),然後簡單地捲曲sam e請求客戶最初通過使用AJAX的瀏覽器直接向開發人員的服務器完成。因此,惡意用戶可以被認證爲合法用戶並使用其他人的祕密API密鑰訪問API。
我會試着舉一個具體的例子。通常我會這樣做:
- AJAX a get request to my server。
- 我的服務器用我的API密鑰散列我的請求並將它發送到API服務器。
- API服務器驗證我的請求並返回有效負載。
但我很害怕,:
- 邪惡博士將嗅出我的公開API密鑰。
- Dr. Evil將使用我的公共API密鑰向我的服務器發送請求。
- 我的服務器會將Dr. Evil的請求與我的API祕密一起打散併發送給API服務器。
- API服務器驗證並返回有效載荷以完成Dr. Evil的惡意計劃。
- Dr. Evil笑一個邪惡的笑。
我什麼都不知道,或者這只是RESTful API遊戲的一部分?
更新:我自願忽略任何形式的時間戳驗證,以保持簡單,只關注身份驗證問題。
更新2:我已經爲該過程添加了一個$_SERVER['HTTP_REFERER']
驗證。這裏的目標是客戶端必須發送一個referrer和請求,並且它必須匹配API側的數據庫中列出的引用者。不幸的是,HTTP引用者很容易僞造。這是另一個安全級別,但仍不完美。
更新3:我已更改我的服務器端代碼以將引用鏈接設置爲遠程IP地址。這會強制發送到我的服務器的每個請求都要使用祕密API密鑰進行散列,最終會使用原始請求IP地址訪問API服務器。這個IP然後可以被驗證並且請求可以通過。我相信它還有可能僞造$_SERVER['REMOTE_ADDR']
,但它比假冒$_SERVER['HTTP_REFERER']
更復雜...我猜還是不完美。
UPDATE 4:根據這些帖子:How to fake $_SERVER['REMOTE_ADDR'] variable?和https://serverfault.com/questions/90725/are-ip-addresses-trivial-to-forge,僞造的$_SERVER['REMOTE_ADDR']
是可能的,雖然困難。但是,由於您無法控制僞造的網絡,因此無法收到來自僞造請求的回覆。這個請求可以被成功驗證,但是它的迴應不會落入惡意的手中。
謝謝。我主動排除時間戳部分以使事情變得簡單,因爲在我當前的代碼中實現並不是什麼大事,我應該提到這一點。我不確定我是否正確理解SSL的功能。它是否使交通嗅探不可能?惡意用戶仍然可以從JavaScript源代碼中竊取它,不是嗎?我絕對錯過了這裏的東西...... –
SSL是傳輸加密。它使得嗅探更加困難。即使使用API,這也是一個好主意。 – datasage
但是如果惡意用戶可以從源頭獲取公共API密鑰,我仍然會遇到同樣的問題,對吧? –