以下是當你在設計, 測試以及釋出你的 API 的時候所需要核對的重要安全措施。
身份認證
- 不要使用
Basic Auth
使用標準的認證協議 (如 JWT, OAuth). - 不要再造
Authentication
,token generating
,password storing
這些輪子, 使用標準的. - 在登入中使用
Max Retry
和自動封禁功能. - 加密所有的敏感資料.
JWT (JSON Web Token)
- 使用隨機複雜的金鑰 (
JWT Secret
) 以增加暴力破解的難度. - 不要在請求體中直接提取資料, 要對資料進行加密 (
HS256
或RS256
). - 使 token 的過期時間儘量的短 (
TTL
,RTTL
). - 不要在 JWT 的請求體中存放敏感資料, 它是可破解的.
OAuth 授權或認證協議
- 始終在後臺驗證
redirect_uri
, 只允許白名單的 URL. - 每次交換令牌的時候不要加 token (不允許
response_type=token
). - 使用
state
引數並填充隨機的雜湊數來防止跨站請求偽造(CSRF). - 對不同的應用分別定義預設的作用域和各自有效的作用域引數.
訪問
- 限制流量來防止 DDoS 攻擊和暴力攻擊.
- 在服務端使用 HTTPS 協議來防止 MITM 攻擊.
- 使用
HSTS
協議防止 SSLStrip 攻擊.
過濾輸入
- 使用與操作相符的 HTTP 操作函式,
GET (讀取)
,POST (建立)
,PUT (替換/更新)
以及DELETE (刪除記錄)
, 如果請求的方法不適用於請求的資源則返回405 Method Not Allowed
. - 在請求頭中的
content-type
欄位使用內容驗證來只允許支援的格式 (如application/xml
,application/json
等等) 並在不滿足條件的時候返回406 Not Acceptable
. - 驗證
content-type
的釋出資料和你收到的一樣 (如application/x-www-form-urlencoded
,multipart/form-data
,application/json
等等). - 驗證使用者輸入來避免一些普通的易受攻擊缺陷 (如
XSS
,SQL-注入
,遠端程式碼執行
等等). - 不要在 URL 中使用任何敏感的資料 (
credentials
,Passwords
,security tokens
, orAPI keys
), 而是使用標準的認證請求頭. - 使用一個 API Gateway 服務來啟用快取、訪問速率限制 (如
Quota
,Spike Arrest
,Concurrent Rate Limit
) 以及動態地部署 APIs resources.
處理
- 檢查是否所有的終端都在身份認證之後, 以避免被破壞了的認證體系.
- 避免使用特有的資源 id. 使用
/me/orders
替代/user/654321/orders
- 使用
UUID
代替自增長的 id. - 如果需要解析 XML 檔案, 確保實體解析(entity parsing)是關閉的以避免
XXE
攻擊. - 如果需要解析 XML 檔案, 確保實體擴充套件(entity expansion)是關閉的以避免通過指數實體擴充套件攻擊實現的
Billion Laughs/XML bomb
. - 在檔案上傳中使用 CDN.
- 如果需要處理大量的資料, 使用 Workers 和 Queues 來快速響應, 從而避免 HTTP 阻塞.
- 不要忘了把 DEBUG 模式關掉.
輸出
- 傳送
X-Content-Type-Options: nosniff
頭. - 傳送
X-Frame-Options: deny
頭. - 傳送
Content-Security-Policy: default-src 'none'
頭. - 刪除指紋頭 -
X-Powered-By
,Server
,X-AspNet-Version
等等. - 在響應中強制使用
content-type
, 如果你的型別是application/json
那麼你的content-type
就是application/json
. - 不要返回敏感的資料, 如
credentials
,Passwords
,security tokens
. - 在操作結束時返回恰當的狀態碼. (如
200 OK
,400 Bad Request
,401 Unauthorized
,405 Method Not Allowed
等等).
持續整合和持續部署
- 使用單元測試和整合測試來審計你的設計和實現.
- 引入程式碼審查流程, 不要自行批准更改.
- 在推送到生產環境之前確保服務的所有元件都用防毒軟體靜態地掃描過, 包括第三方庫和其它依賴.
- 為部署設計一個回滾方案.
許可權系統 (註冊/註冊/二次驗證/密碼重置)
- 任何地方都使用 HTTPS.
- 使用
Bcrypt
儲存密碼雜湊 (沒有使用鹽的必要 -Bcrypt
乾的就是這個事). 登出
之後銷燬會話 ID .- 密碼重置後銷燬所有活躍的會話.
- OAuth2 驗證必須包含
state
引數. - 登陸成功之後不能直接重定向到開放的路徑(需要校驗,否則容易存在釣魚攻擊).
- 當解析使用者註冊/登陸的輸入時,過濾 javascript://、 data:// 以及其他 CRLF 字元.
- 使用 secure/httpOnly cookies.
- 移動端使用
OTP
驗證時,當呼叫generate OTP
或者Resend OTP
API 時不能把 OTP(One Time Password) 直接返回。(一般是通過傳送手機驗證簡訊,郵箱隨機 code 等方式,而不是直接 response) - 限制單個使用者
Login
、Verify OTP
、Resend OTP
、generate OTP
等 API 的呼叫次數,使用 Captcha 等手段防止暴力破解. - 檢查郵件或簡訊裡的重置密碼的 token,確保隨機性(無法猜測)
- 給重置密碼的 token 設定過期時間.
- 重置密碼成功後,將重置使用的 token 失效.
使用者資料和許可權校驗
- 諸如
我的購物車
、我的瀏覽歷史
之類的資源訪問,必須檢查當前登入的使用者是否有這些資源的訪問許可權. - 避免資源 ID 被連續遍歷訪問,使用
/me/orders
代替/user/37153/orders
以防你忘了檢查許可權,導致資料洩露。 修改郵箱/手機號碼
功能必須首先確認使用者已經驗證過郵箱/手機是他自己的。- 任何上傳功能應該過濾使用者上傳的檔名,另外,為了普適性的原因(而不是安全問題),上傳的東西應該存放到例如 S3 之類的雲端儲存上面(用 lambda 處理),而不是儲存在自己的伺服器,防止程式碼執行。
個人頭像上傳
功能應該過濾所有的EXIF
標籤,即便沒有這個需求.- 使用者 ID 或者其他的 ID,應該使用 RFC compliant 的
UUID
而不是整數. 你可以從 github 找到你所用的語言的實現. - JWT(JSON Web Token)很棒.當你需要構建一個 單頁應用/API 時使用.
安卓和 iOS APP
- 支付閘道器的
鹽(salt)
不應該被硬編碼 - 來自第三方的
secret
和auth token
不應該被硬編碼 - 在伺服器之間呼叫的 API 不應該在 app 裡面呼叫
- 在安卓系統下,要小心評估所有申請的 許可權
- 在 iOS 系統下,使用系統的鑰匙串來儲存敏感資訊(許可權 token、api key、 等等) 不要 把這類資訊儲存在使用者配置裡面
- 強烈推薦證照繫結(Certificate pinning)
操作
- 如果你的業務很小或者你缺乏經驗,可以評估一下使用 AWS 或者一個 PaaS 平臺來執行程式碼
- 在雲上使用正規的指令碼建立虛擬機器
- 檢查所有機器沒有必要開放的
埠
- 檢查資料庫是否沒有設定密碼或者使用預設密碼,特別是 MongoDB 和 Redis
- 使用 SSH 登入你的機器,不要使用密碼,而是通過 SSH key 驗證來登入
- 及時更新系統,防止出現 0day 漏洞,比如 Heartbleed、Shellshock 等
- 修改伺服器配置,HTTPS 使用 TLS1.2,禁用其他的模式。(值得這麼做)
- 不要線上上開啟 DEBUG 模式,有些框架,DEBUG 模式會開啟很多許可權以及後門,或者是暴露一些敏感資料到錯誤棧資訊裡面
- 對壞人和 DDOS 攻擊要有所準備,使用那些提供 DDOS 清洗的主機服務
- 監控你的系統,同時記錄到日誌裡面 (例如使用 New Relic 或者其他 ).
- 如果是 2B 的業務,堅持順從需求。如果使用 AWS S3,可以考慮使用 資料加密 功能. 如果使用 AWS EC2,考慮使用磁碟加密功能(現在系統啟動盤也能加密了)
關於人
- 開一個郵件組(例如:security@coolcorp.io)和蒐集頁面,方便安全研究人員提交漏洞
- 取決於你的業務,限制使用者資料庫的訪問
- 對報告 bug、漏洞的人有禮貌
- 把你的程式碼給那些有安全編碼觀念的同伴進行 review (More eyes)
- 被黑或者資料洩露時,檢查資料訪問前的日誌,通知使用者更改密碼。你可能需要外部的機構來幫助審計
- 使用 Netflix Scumblr 及時瞭解你的組織(公司)在社交網路或者搜尋引擎上的一些討論資訊,比如黑客攻擊、漏洞等等
出處 Hack-with-Github/Awesome-Hacking Fallible