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:访问控制与监控