三零二六年之 API 安全:实攻毁制系统
每周,又有一公司宣告数据泄露。攻者非用零日或精妙之毒——实乃利用年岁久远之 API 缺陷。三零二六年,API 安全犹为众团队之末思,而攻者知之。
吾昔半载,究析世间 API 之失。此乃实击生产系统之状也。
OWASP API 之十最,未尝易也;业界应之,亦无改焉。
OWASP API 安全是十之状,视之几同于己亥年:
- 物权授权之失(BOLA)
- 认证之失
- 物权属性授权之失
- 无节制资源消耗
- 功能层级授权失效
- 批量赋值
- 安全配置不当
- 注入攻击
- 库存管理失当
- API不安全使用
此非空谈。十八月内,每一项皆已见于重大安全事件。
攻伐之始:BOLA——默然之数据窃取者
破物层级授权之弊,为诸患之最。其状恒同:一API端点示物之ID,而API不验其认证者果为物之主否。
实例(简自实患)
// VULNERABLE API
app.get('/api/orders/:orderId', authMiddleware, async (req, res) => {
const order = await Order.findById(req.params.orderId);
res.json(order); // No ownership check!
});
// ATTACK: Iterate through order IDs
// curl https://api.example.com/api/orders/1
// curl https://api.example.com/api/orders/2
// curl https://api.example.com/api/orders/3
// ... extracted 50,000 customer records
如何解决
// SECURE API
app.get('/api/orders/:orderId', authMiddleware, async (req, res) => {
// Explicit ownership check
const order = await Order.findOne({
_id: req.params.orderId,
userId: req.user.id // Always filter by owner
});
if (!order) {
return res.status(404).json({
error: 'Order not found'
});
}
res.json(order);
});
要害之训:常验其主,非惟验其真。验真不即授权于其物也
攻击之二:认证有缺——JWT之失
JSON Web Tokens 普遍存在,且常被错误实现。此乃吾于生产API中发现之真实JWT漏洞样本。
弱点:算法混淆
// VULNERABLE: Server accepts any algorithm
const decoded = jwt.verify(token, publicKey, {
algorithms: ['HS256', 'RS256'] // DON'T DO THIS
});
// ATTACK: Change RS256 to HS256 and sign with the public key
// Since the server uses the SAME key for both symmetric and asymmetric,
// the attacker can forge tokens by signing HS256 with the RSA public key
// SECURE: Explicit algorithm allowlist
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'] // Only allow the intended algorithm
});
无患:无术
// VULNERABLE: Some libraries accept 'none' algorithm
jwt.verify(token, '', { algorithms: ['none'] });
// Produces: {"alg":"none","typ":"JWT"}
// becomes: eyJhbGciOiJub25lIiwidHlwIjoiand0In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
// SECURE: Explicitly reject 'none'
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
alloweds: { algorithms: ['HS256', 'RS256'] } // Reject none
});
// Or use a library that defaults to rejecting 'none'
const decoded = jwt.verify(token, publicKey);
攻击之三者:无节制之资源消耗——钱包之拒
此术常被轻视,渐成常态。攻击者无需使汝之服务崩坏,但需令其运行昂贵即可.
现实之境
# VULNERABLE: No pagination, no limits
@app.get("/api/search")
def search(q: str):
results = db.query(f"SELECT * FROM products WHERE name LIKE '%{q}%'")
return results # Returns ALL matches, attacker controls result set size
# Attack: Search for "a" - returns 2.3M rows
# Your database does a full table scan
# You pay $0.02 per query × 10,000 queries/minute = $200/minute
# SECURE: Strict pagination and query limits
@app.get("/api/search")
def search(
q: str,
limit: int = Query(default=20, ge=1, le=100), # Max 100
offset: int = Query(default=0, ge=0, le=10000) # Max offset
):
# Parameterized query prevents injection
results = db.query(
"SELECT * FROM products WHERE name LIKE %s LIMIT %s OFFSET %s",
(f"%{q}%", limit, offset)
)
# Also add query complexity limits
if len(q) > 100:
raise HTTPException(400, "Query too long")
return results
重置密码之拒绝服务攻击
# VULNERABLE: Email sending has no rate limit
@app.post("/api/password-reset")
def request_reset(email: str):
user = db.find_user(email)
if user:
send_email(user.email, generate_token()) # No throttle
return {"message": "If email exists, reset was sent"}
# Attack: Script 1000 emails/second to your SMTP provider
# Cost: $0.10 per email × 86,400,000 emails/day = $8.6M/day
# SECURE: Strict rate limiting per IP and email
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
@app.post("/api/password-reset")
@limiter.limit("3/hour") # 3 attempts per hour per IP
def request_reset(email: str, request: Request):
user = db.find_user(email)
if user:
send_email(user.email, generate_token())
# Always return same message to prevent enumeration
return {"message": "If email exists, reset was sent"}
攻击之四:批量赋值——隐秘参数
// VULNERABLE: Trusting client input blindly
app.post('/api/profile', authMiddleware, async (req, res) => {
await User.updateOne(
{ _id: req.user.id },
{ $set: req.body } // Client can set ANY field
);
});
// ATTACK: Send this request
// POST /api/profile
// {"name": "John", "role": "admin", "isVerified": true, "creditLimit": 1000000}
//
// Suddenly the regular user is an admin with unlimited credit
// SECURE: Explicit field allowlist
app.post('/api/profile', authMiddleware, async (req, res) => {
const allowedFields = ['name', 'bio', 'avatarUrl', 'timezone'];
const updates = {};
for (const field of allowedFields) {
if (field in req.body) {
updates[field] = req.body[field];
}
}
await User.updateOne(
{ _id: req.user.id },
{ $set: updates }
);
res.json({ success: true });
});
攻伐之五:无防护之管理员端
# VULNERABLE: Admin endpoint without role check
@app.post("/api/admin/users/delete")
def delete_user(user_id: str):
db.delete_user(user_id)
return {"success": True}
# Attack: Anyone who finds this endpoint can delete any user
# No authentication, no authorization check
# SECURE: Explicit role requirement
from functools import wraps
def require_admin(f):
@wraps(f)
async def decorated(*args, **kwargs):
if not request.user or request.user.role != 'admin':
return {"error": "Forbidden"}, 403
return await f(*args, **kwargs)
return decorated
@app.post("/api/admin/users/delete")
@require_admin
@require_auth
def delete_user(user_id: str):
db.delete_user(user_id)
return {"success": True}
当世所宜之测试框架
import httpx
import pytest
class TestAPISecurity:
"""API Security Test Suite - Run these against staging before every deploy"""
def test_bola_object_level_access(self):
"""Test that users can't access other users' resources"""
user1_token = self.get_token("user1@example.com")
user2_resource = self.create_resource("user2@example.com")
# User 1 tries to access User 2's resource
response = httpx.get(
f"{BASE_URL}/api/resources/{user2_resource.id}",
headers={"Authorization": f"Bearer {user1_token}"}
)
assert response.status_code == 403, "BOLA vulnerability: User can access others' resources!"
def test_jwt_algorithm_confusion(self):
"""Test JWT algorithm confusion attack"""
token = self.get_valid_token()
# Tamper with the algorithm
header_b64 = base64.b64encode(b'{"alg":"HS256","typ":"JWT"}').decode()
# Re-sign with a known key
tampered = f"{header_b64}.{token.split('.')[1]}.{fake_signature}"
response = httpx.get(
f"{BASE_URL}/api/protected",
headers={"Authorization": f"Bearer {tampered}"}
)
assert response.status_code == 401, "JWT algorithm confusion succeeded!"
def test_mass_assignment_protection(self):
"""Test that users can't set admin fields"""
user_token = self.get_token("regular@example.com")
response = httpx.post(
f"{BASE_URL}/api/profile",
headers={"Authorization": f"Bearer {user_token}"},
json={"name": "Test", "role": "admin", "isVerified": True}
)
# Verify admin fields weren't changed
profile = self.get_profile("regular@example.com")
assert profile["role"] != "admin", "Mass assignment vulnerability!"
def test_rate_limiting(self):
"""Test that rate limiting prevents abuse"""
for _ in range(100):
response = httpx.post(
f"{BASE_URL}/api/password-reset",
json={"email": "test@example.com"}
)
# 101st request should be rate limited
response = httpx.post(
f"{BASE_URL}/api/password-reset",
json={"email": "test@example.com"}
)
assert response.status_code == 429, "Rate limiting not enforced!"
部署之前之安全检点
□ Object-level authorization tested for every endpoint
□ All JWT implementations use explicit algorithm allowlists
□ Rate limiting on all public endpoints
□ Pagination limits on all list endpoints
□ Mass assignment protection via field allowlists
□ Admin endpoints protected by role checks
□ No sensitive data in URL parameters (tokens, IDs)
□ SQL injection protection (parameterized queries)
□ No stack traces or internal errors in responses
□ CORS properly configured
□ Security headers present (CSP, X-Frame-Options, etc.)
严酷之实情
二零二六年API安全犹滞于应用安全数载。众团队多:
- 无API安全测试于CI/CD
- 无API清单(汝有多少端点?汝竟不知耶?)
- 八成端点无速率限制
- 无授权检查之认证
攻者知之。彼等规模化扫描此等脆弱,自动化,昼夜不息。
佳音:治此非难。惟需将安测试尊为开发之元首耳。
汝之最大API安全之困也?于世间曾见有趣之漏洞乎?吾等共论之。
博览群籍:OWASP API Security Top 10— 仍为 API 安全之根本要义之最佳发端。












