História de terror da segurança: exposição acidental de dados pessoais
25 de outubro de 2021
0 minutos de leituraNada 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.

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.

É 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.

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
