API 中的数据暴露:预防与检测
通过 API 不当暴露数据是现代系统中的主要漏洞之一。配置错误或防护不足的 API 可能泄露敏感信息、危及用户数据,并违反 LGPD 和 GDPR 等隐私法规。
API 中数据暴露的类型
1. 过度数据暴露(API3:2023 - OWASP)
返回超出必要信息的 API:
- 仅需若干字段时,端点却返回完整对象
- 响应中包含敏感字段(密码哈希、内部 token)
- 错误信息中暴露系统元数据
// [ERRO] Exemplo RUIM - Expondo dados demais
GET /api/users/123
{
"id": 123,
"name": "João Silva",
"email": "[email protected]",
"password_hash": "$2b$10$...", // [AVISO] Nunca expor
"ssn": "123-45-6789", // [AVISO] Dado sensível
"internal_role_id": 42, // [AVISO] Dado interno
"created_at": "2025-01-01",
"last_login_ip": "192.168.1.1" // [AVISO] Informação sensível
}
// [OK] Exemplo BOM - Apenas dados necessários
GET /api/users/123/profile
{
"id": 123,
"name": "João Silva",
"avatar_url": "https://..."
}
2. 缺少资源过滤(Broken Object Level Authorization)
用户可以通过更改 ID 访问其他用户的数据:
// [ERRO] Vulnerável a IDOR (Insecure Direct Object Reference)
GET /api/orders/456 // Usuário A pode ver pedidos do Usuário B
// [OK] Protegido - Validar autorização
app.get('/api/orders/:id', async (req, res) => {
const order = await Order.findById(req.params.id);
// Verificar se o pedido pertence ao usuário autenticado
if (order.userId !== req.user.id) {
return res.status(403).json({ error: 'Acesso negado' });
}
res.json(order);
});
3. 在 URL 中暴露敏感信息
- 查询字符串中的认证 token
- 路径中的个人数据
- 服务器日志中的机密信息
预防策略
实现 Data Transfer Objects(DTOs)
// TypeScript - Definir claramente o que expor
interface UserPublicDTO {
id: number;
name: string;
avatar_url: string;
}
class UserService {
async getPublicProfile(userId: number): Promise<UserPublicDTO> {
const user = await db.users.findUnique({ where: { id: userId } });
// Retornar apenas campos permitidos
return {
id: user.id,
name: user.name,
avatar_url: user.avatar_url
};
}
}
应用序列化过滤器
- 使用诸如 class-transformer(TypeScript)之类的库
- 使用装饰器标记敏感字段(@Exclude)
- 为不同上下文设置序列化分组(公开 vs. admin)
授权校验
// Middleware de autorização
const checkResourceOwnership = (resourceType) => {
return async (req, res, next) => {
const resource = await db[resourceType].findById(req.params.id);
if (!resource) {
return res.status(404).json({ error: 'Recurso não encontrado' });
}
if (resource.ownerId !== req.user.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Acesso não autorizado' });
}
req.resource = resource;
next();
};
};
// Uso
app.get('/api/documents/:id',
authenticate,
checkResourceOwnership('documents'),
(req, res) => {
res.json(req.resource);
}
);
检测技术
Payload 分析
- 手动审查关键端点的响应
- 使用诸如 Burp Suite、OWASP ZAP 之类的工具
- 通过自动化测试验证暴露的字段
监控与告警
- 检测异常访问模式(enumeration)
- 对过多的拒绝访问发出告警
- 监控每个用户传输的数据量
Code Review 与静态分析
- 审查 DTOs 和序列化模型
- 验证授权的实现
- 使用 SAST 工具识别暴露问题
最佳实践
- 对暴露的数据采用最小权限原则
- 实施 rate limiting 以防止抓取
- 使用 UUID 而非顺序 ID
- 对传输中和静态存储的敏感数据进行加密
- 实施 API 版本管理以实现安全变更
- 定期进行安全测试
- 清晰记录每个端点暴露哪些数据
- 谨慎使用 GraphQL(可能助长 over-fetching)
合规与监管
- LGPD/GDPR:数据最小化、处理的法律依据
- PCI-DSS:信用卡数据保护
- HIPAA:健康信息保护(美国)
- SOC 2:访问控制与监控
