Reversão de Versão de API: Quando uma Versão Antiga Devolve Dados Sem Mascaramento
O desafio
A API de pedidos é versionada por data através do cabeçalho X-Api-Version, e o gateway ainda aceita quatro delas: 2024-06-01, 2024-11-15, 2025-03-20 e 2025-09-10. O mascaramento de cartão foi adicionado em algum ponto desse histórico, mas nem toda versão aceita recebeu essa correção. Envie a mesma requisição uma vez por versão e compare as respostas. Uma delas devolve o número completo do cartão do cliente e o endereço de cobrança em vez do resumo mascarado. Não é a mais antiga, então você não consegue adivinhar. Envie a string da versão que vaza.
O que você vai aprender
- Enumerar um conjunto pequeno e conhecido de versões de API em vez de chutar uma
- Comparar as respostas campo a campo para identificar uma diferença no mascaramento
- Entender a reversão de versão como uma falha de controle de acesso e exposição de dados
- Perceber por que uma versão descontinuada e uma versão obsoleta não representam o mesmo risco
- Explicar por que uma correção de segurança precisa ser aplicada a todas as versões aceitas
Habilidades testadas
Pré-requisitos
- Leitura de uma requisição e resposta HTTP crua
- Noção básica de versionamento de API
Como funciona
O versionamento de API baseado em data permite que os clientes fixem o comportamento, e é um bom padrão. O risco aparece quando uma correção de segurança é lançada em uma versão e as versões mais antigas continuam ativas. A versão nova não é a superfície de ataque. Tudo que você ainda aceita é.
Aqui o gateway aceita quatro versões. A requisição é idêntica no resto, então qualquer diferença na resposta é causada apenas pelo cabeçalho de versão. Analisando cada uma: 2025-09-10 e 2025-03-20 devolvem um resumo de pagamento mascarado; 2024-06-01 está descontinuada e responde 410 Gone; e 2024-11-15 responde 200 com o número completo do cartão, a validade, o nome do titular, o telefone e o endereço de cobrança.
O vazamento está no meio da linha do tempo, e esse é justamente o ponto do exercício. Um chute baseado em intuição recai sobre a versão mais antiga, e a versão mais antiga é a segura, porque na verdade ela foi desativada. Só enviando as quatro e comparando o objeto de pagamento é que se encontra a resposta real. O mascaramento foi introduzido na revisão 2025-03-20 e nunca foi retroportado para 2024-11-15, que continuou aceita por compatibilidade.
Erros comuns
- Chutar 2024-06-01 por ser a mais antiga. Ela foi descontinuada e responde 410 Gone. Obsoleta e descontinuada são estados diferentes, e só um deles ainda serve dados.
- Testar uma versão e parar. A versão atual se comporta corretamente, o que não prova nada sobre as outras.
- Editar mais do que o cabeçalho de versão. Alterar o Host quebra o roteamento e retorna 404, e alterar o id do pedido muda o registro em vez do comportamento de mascaramento.
- Ler apenas a linha de status. Três versões respondem 200; a diferença está dentro do objeto de pagamento, entre
last4epan. - Enviar o número do cartão. A pergunta pede a string da versão que vaza, não os dados vazados.
Como se proteger
Trate o conjunto de versões aceitas como parte da sua superfície de ataque e mantenha-o o menor possível dentro do que você consegue defender.
- Aplique correções de segurança, como o mascaramento, em uma camada de serialização compartilhada por onde todas as versões passam, em vez de em um handler por versão.
- Mantenha um inventário explícito das versões aceitas, com uma data de descontinuação para cada uma, e aplique essa descontinuação automaticamente.
- Teste as versões antigas no CI. Execute as verificações de dados sensíveis contra todas as versões aceitas, não só a atual.
- Rejeite de forma explícita versões desconhecidas e expiradas, em vez de cair silenciosamente em um handler legado.
- Alerte sobre tráfego para versões obsoletas; um aumento repentino de requisições fixadas em uma versão antiga é um forte sinal de exploração.
- Nunca devolva um PAN completo em um endpoint de pedidos. Armazene e sirva um token, de forma que, mesmo no pior cenário de um bug no handler, os dados expostos ainda não sejam dados do titular do cartão.