Skip to main content

História de terror da segurança: exposição acidental de dados pessoais

Escrito por
blog feature security alert purple

25 de outubro de 2021

0 minutos de leitura

Nada como uma boa história de terror... especialmente quando o assunto é desenvolvimento de software e segurança. Afinal, o que poderia dar errado ao desenvolver software??? E, mais importante, o que poderia dar errado quando você e sua equipe estão trabalhando em um pequeno aplicativo de P&D, enquanto o financiamento do projeto ainda está pendente...

Trabalhar sob imensa pressão para entregar funcionalidades em velocidade recorde e garantir o financiamento do próximo período é a receita perfeita para um desastre. Ainda mais quando não há uma visão clara do objetivo final do projeto e as ideias mudam a cada dia.

Deixe-me contar como as coisas deram errado do ponto de vista da segurança. Como esse pequeno projeto de P&D, tocado de forma improvisada, fazia parte de uma grande instituição — algo como um banco ou uma seguradora —, havia muito mais em jogo do que apenas um projetinho.

O projeto

O projeto começou como um aplicativo para pesquisar imóveis, como prédios e casas. Como a maior parte da lógica do sistema ficava no servidor, criamos uma excelente solução orientada a serviços (microserviços) em Java.

Um dos serviços era o servidor de perfis. Cada perfil continha um UUID gerado aleatoriamente e uma lista de preferências. Um dos principais recursos era permitir que as pessoas usassem o aplicativo anonimamente. Por isso, armazenávamos o UUID no armazenamento local do dispositivo e o usávamos para recuperar o perfil no servidor. Em resumo, o serviço era mais ou menos assim.

Diagrama que mostra as solicitações de criação de perfil, atualização de preferências e recuperação de perfil por UUID, encaminhadas a um serviço de perfil para acessar os dados do perfil.

Em determinado momento, surgiu a ideia de permitir que uma pessoa reivindicasse um imóvel no sistema. Isso acontecia principalmente quando ela era proprietária da casa ou do prédio. A pessoa poderia então complementar o imóvel com fotos e uma descrição. Cada imóvel só podia ser reivindicado por uma pessoa.

Esse novo recurso trouxe duas mudanças importantes para esta história.

  • Criamos um novo serviço chamado “MyHouse” para permitir que uma pessoa reivindicasse uma casa

  • O serviço de perfis precisava ser ampliado. Agora, a pessoa deveria poder fazer login e reivindicar uma casa. Por isso, adicionamos ao serviço de perfis existente a opção de cadastro.

Os serviços ficaram mais ou menos como abaixo: um objeto MyHouse estava vinculado a um perfil de usuário que continha o UUID, e agora o perfil também podia incluir um endereço de e-mail.

Diagrama que mostra os serviços Profile e MyHouse, com entradas, saídas e dados associados de perfil, e-mail, preferências, endereço e foto.

É importante observar que recebemos instruções para continuar oferecendo o uso anônimo como antes, e que esse recurso deveria ser adicionado ao que já existia.

O problema

O novo serviço MyHouse tinha um endpoint para listar todos os imóveis reivindicados. Ele expunha o objeto MyHouse completo em JSON, incluindo o UUID do perfil. Como precisávamos manter a funcionalidade anterior, ainda era possível encontrar um perfil apenas com o UUID correspondente.

Diagrama que mostra os serviços Profile e MyHouse, com solicitações de perfil e de residência associadas a campos de dados baseados em UUID.

Resumindo: o frontend do aplicativo móvel não precisava do UUID. Porém, com uma solicitação HTTP simples e o objeto MyHouse em mãos, era possível usar o UUID em uma segunda chamada para encontrar o perfil. A partir daí, as pessoas conseguiam associar o endereço físico de um imóvel a um endereço de e-mail. Como muitas vezes os e-mails seguem o formato firstname.lastname@provider.com (ou algo parecido), tivemos um vazamento de dados: era possível associar uma pessoa a um endereço físico. Ops, isso era um vazamento de informações de identificação pessoal, ou dados PII.

A correção e as consequências

O caso foi comunicado anonimamente ao departamento de segurança da empresa. Felizmente, uma pessoa ética assumiu a responsabilidade de fazer uma divulgação responsável. Assim que entendemos o problema, a correção levou cinco minutos, incluindo a publicação em produção. Ao adicionar uma anotação @JsonIgnore ao campo UUID do POJO MyHouse, impedimos a serialização do campo para JSON e eliminamos a associação entre um perfil e um endereço físico.

Do ponto de vista da engenharia, você poderia encerrar o artigo por aqui. Mas, apesar de a correção ter sido simples, as consequências desse tipo de incidente são extremamente invasivas. Tudo começou com uma enxurrada de perguntas sobre o ocorrido:

  • Quem teve os dados expostos?

  • Por quanto tempo eles ficaram expostos?

  • Qual é o impacto desse vazamento de dados?

  • Que tipo de dado foi vazado?

  • Quem foi vítima desse vazamento?

  • Por que não evitamos isso?

  • E por aí vai, e por aí vai...

Todas essas perguntas geraram uma enorme quantidade de documentação que minha equipe e eu tivemos de preencher. Algumas respostas eram óbvias, mas, por se tratar de um projeto de P&D sob muita pressão, ainda não tínhamos implementado o registro adequado de logs. Era impossível descobrir quem havia sido afetado. Talvez pessoas mal-intencionadas nem tivessem explorado a brecha. Simplesmente não sabíamos.

O pior é que a alta gestão passou a nos culpar com comentários como “é uma vergonha nossos engenheiros não terem nenhuma noção de segurança” ou “esta equipe é incompetente; vocês deveriam ter percebido isso”. Além da enorme quantidade de documentação, os gestores começaram a controlar cada detalhe sem ter conhecimento adequado de desenvolvimento ou segurança.

Lições aprendidas

A primeira coisa que fizemos foi registrar tudo em logs. Lidar com um problema de segurança é uma coisa; enfrentar as consequências e responder às perguntas é outra completamente diferente. Em seguida, analisamos cuidadosamente nosso modelo de dados para verificar se estávamos expondo no endpoint REST dados desnecessários para o frontend.

A equipe de engenharia também aproveitou o incidente para contestar as exigências e a pressão excessivas dos gerentes de produto. No entanto, conscientização sobre segurança significa incorporar a segurança ao processo de desenvolvimento, não culpar as pessoas. Na minha opinião sincera, a solução adequada teria sido investir na cultura e escolher as ferramentas certas para apoiar o processo de desenvolvimento. Pouco tempo depois, decidi sair da empresa…

Siga a gente no Twitter (@snyksec) para conferir mais histórias de terror da segurança como esta! #31DaysOfSecurity