API Security Top 10 概述
OWASP API Security Top 10 是專門針對 API 安全的風險列表,首次發布於 2019 年,並於 2023 年更新至最新版本。隨著微服務架構與 RESTful API 的普及,API 已成為現代應用程式的核心,同時也成為攻擊者的主要目標。
與傳統的 OWASP Top 10 不同,API Security Top 10 專注於 API 特有的安全風險,包括授權、認證、資源管理等面向。以下將詳細介紹各項風險及其攻擊與防護方式。
API1:2023 - 物件層級授權失效 (Broken Object Level Authorization)
風險說明
當 API 端點未正確驗證使用者是否有權存取特定物件時,攻擊者可透過修改物件 ID 存取他人資料。
攻擊範例
1
2
3
4
5
6
7
8
9
| # 正常請求 - 查看自己的訂單
GET /api/v1/orders/1001 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Host: api.example.com
# 攻擊請求 - 嘗試存取他人訂單
GET /api/v1/orders/1002 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Host: api.example.com
|
攻擊者只需遞增訂單 ID,即可能獲取其他使用者的訂單資訊。
防護措施
1
2
3
4
5
6
7
8
9
| # 正確的授權檢查實作
def get_order(order_id, current_user):
order = Order.query.get(order_id)
if order is None:
raise NotFoundError()
# 驗證物件所有權
if order.user_id != current_user.id:
raise ForbiddenError("Access denied")
return order
|
API2:2023 - 身份驗證失效 (Broken Authentication)
風險說明
API 的身份驗證機制若存在缺陷,攻擊者可冒充合法使用者或取得未授權存取權限。常見問題包括弱密碼政策、JWT 驗證不當、Token 無效期限等。
攻擊範例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # JWT 無簽名驗證攻擊
# 原始 Token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMDAxLCJyb2xlIjoidXNlciJ9.xxx
# 竄改後的 Token (將 algorithm 改為 none)
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyX2lkIjoxMDAxLCJyb2xlIjoiYWRtaW4ifQ.
# 暴力破解 API Key
POST /api/v1/login HTTP/1.1
Content-Type: application/json
{"username": "admin", "password": "password123"}
{"username": "admin", "password": "admin123"}
{"username": "admin", "password": "123456"}
|
防護措施
- 實施強密碼政策與多因素驗證 (MFA)
- 使用安全的 Token 驗證機制
- 實施 Rate Limiting 防止暴力破解
- Token 需設定合理的過期時間
API3:2023 - 物件屬性層級授權失效 (Broken Object Property Level Authorization)
風險說明
此類別結合了過度資料暴露 (Excessive Data Exposure) 與大量賦值 (Mass Assignment)。API 可能回傳過多敏感資訊,或允許使用者修改不應修改的屬性。
攻擊範例 - 過度資料暴露
1
2
3
4
5
6
7
8
9
10
| // API 回應包含過多資訊
GET /api/v1/users/1001
{
"id": 1001,
"username": "john_doe",
"email": "john@example.com",
"password_hash": "$2b$12$xxx...", // 不應暴露
"ssn": "123-45-6789", // 不應暴露
"credit_card": "4111-xxxx-xxxx-1234" // 不應暴露
}
|
攻擊範例 - 大量賦值
1
2
3
4
5
6
7
8
9
10
11
| # 正常更新個人資料
PUT /api/v1/users/1001 HTTP/1.1
Content-Type: application/json
{"username": "john_new", "email": "john_new@example.com"}
# 攻擊 - 嘗試修改角色權限
PUT /api/v1/users/1001 HTTP/1.1
Content-Type: application/json
{"username": "john_new", "role": "admin", "is_verified": true}
|
防護措施
1
2
3
4
5
6
7
8
9
| # 使用白名單限制可更新欄位
ALLOWED_UPDATE_FIELDS = ['username', 'email', 'avatar']
def update_user(user_id, data):
user = User.query.get(user_id)
for key, value in data.items():
if key in ALLOWED_UPDATE_FIELDS:
setattr(user, key, value)
user.save()
|
API4:2023 - 無限制資源消耗 (Unrestricted Resource Consumption)
風險說明
API 若未限制請求頻率、回應大小或資源使用量,可能遭受 DoS 攻擊或資源耗盡攻擊。
攻擊範例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 請求大量資料
GET /api/v1/users?limit=999999999 HTTP/1.1
# 複雜查詢消耗資源
POST /api/v1/graphql HTTP/1.1
Content-Type: application/json
{
"query": "{ users { orders { items { product { reviews { author { orders { ... } } } } } } } }"
}
# 大檔案上傳
POST /api/v1/upload HTTP/1.1
Content-Type: multipart/form-data
Content-Length: 10737418240 # 10GB 檔案
|
防護措施
1
2
3
4
5
6
7
8
9
10
11
| # Rate Limiting 實作
from flask_limiter import Limiter
limiter = Limiter(app, key_func=get_remote_address)
@app.route("/api/v1/users")
@limiter.limit("100/minute")
def get_users():
# 限制回傳數量
limit = min(request.args.get('limit', 20), 100)
return User.query.limit(limit).all()
|
API5:2023 - 功能層級授權失效 (Broken Function Level Authorization)
風險說明
不同權限等級的使用者應只能存取其對應的功能。若 API 未正確實施功能層級的存取控制,一般使用者可能存取管理功能。
攻擊範例
1
2
3
4
5
6
7
8
9
10
11
| # 一般使用者嘗試存取管理員 API
DELETE /api/v1/admin/users/1002 HTTP/1.1
Authorization: Bearer <regular_user_token>
# 修改 HTTP Method 繞過檢查
# 原本被阻擋
DELETE /api/v1/users/1002 HTTP/1.1 -> 403 Forbidden
# 嘗試使用其他方法
POST /api/v1/users/1002 HTTP/1.1
X-HTTP-Method-Override: DELETE
|
防護措施
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| from functools import wraps
def admin_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not current_user.is_admin:
raise ForbiddenError("Admin access required")
return f(*args, **kwargs)
return decorated
@app.route("/api/v1/admin/users/<int:user_id>", methods=["DELETE"])
@admin_required
def delete_user(user_id):
# 管理員專用功能
pass
|
API6-10 簡述
API6:2023 - 不受限存取敏感業務流程
攻擊者可自動化存取敏感業務流程,例如大量購買限量商品、自動註冊帳號等。
API7:2023 - 伺服器端請求偽造 (SSRF)
API 接受使用者提供的 URL 並向其發送請求時,可能被利用存取內部服務。
1
2
3
4
| POST /api/v1/fetch-url HTTP/1.1
Content-Type: application/json
{"url": "http://169.254.169.254/latest/meta-data/"}
|
API8:2023 - 安全組態錯誤
包括未禁用的 Debug 模式、過於寬鬆的 CORS 設定、錯誤訊息暴露敏感資訊等。
API9:2023 - 不當的資產管理
未維護的舊版 API、測試環境暴露於公網、API 文件未更新等問題。
API10:2023 - 不安全的 API 消費
應用程式在呼叫第三方 API 時,未驗證回應資料的完整性與安全性。
測試方法
使用 Burp Suite 進行 API 測試
1
2
3
4
5
6
| # 1. 設定代理攔截 API 請求
# 2. 使用 Intruder 進行參數遍歷
# 自動化 BOLA 測試
# 收集不同使用者的物件 ID
# 交叉測試存取權限
|
使用 OWASP ZAP
1
2
3
4
5
| # 匯入 OpenAPI/Swagger 文件
zap-cli quick-scan -s all -o '-config api.key=xxx' http://api.example.com
# 使用 API Scan 規則
zap-cli active-scan --scanners api http://api.example.com
|
使用命令列工具
1
2
3
4
5
6
7
8
9
10
| # 使用 curl 測試 BOLA
for i in {1000..1010}; do
curl -s -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/api/v1/orders/$i" | jq .
done
# 使用 ffuf 進行 API 端點探索
ffuf -u https://api.example.com/api/v1/FUZZ \
-w /usr/share/wordlists/api-endpoints.txt \
-H "Authorization: Bearer $TOKEN"
|
防護措施總結
1. 實施嚴格的授權機制
- 每個 API 端點都應驗證使用者權限
- 採用最小權限原則
- 使用集中式授權模組
2. 強化身份驗證
1
2
3
4
5
6
7
8
9
| # API Gateway 設定範例
security:
authentication:
type: JWT
secret: ${JWT_SECRET}
expiration: 3600
rate_limiting:
requests_per_minute: 100
burst: 20
|
3. 輸入驗證與輸出過濾
1
2
3
4
5
6
7
| # 使用 Schema 驗證輸入
from marshmallow import Schema, fields, validate
class UserUpdateSchema(Schema):
username = fields.Str(validate=validate.Length(min=3, max=50))
email = fields.Email()
# 不允許 role 欄位
|
4. 實施監控與日誌
- 記錄所有 API 存取
- 設定異常行為告警
- 定期審計 API 存取紀錄
參考資料