Executando verificação de segurança...
24

Diferentes formas de anonimizar dados (e hash não é uma delas)

Anonimizar dados é essencial para proteger a privacidade, mas será que você está fazendo isso da forma correta? Muita gente acredita que gerar um simples hash, como transformar o nome rafael em 9135d8523ad3da99d8a4eb83afac13d1, já resolve o problema, mas ele não acaba aí.

Neste artigo eu vou te mostrar por que um hash sozinho não é suficiente para anonimizar dados, e quais cuidados você deve ter quando estiver trabalhando com a anonimização. É o tipo de conhecimento que só de entender a base, você já irá se diferenciar de muita gente, mesmo que o assunto seja muito mais profundo.

Gerar um hash torna o dado anônimo?

Essa foi a pergunta que o Edward Felten respondeu em 2012, no blog do FTC, quando estava no cargo de Chief Technologist.

Um hash é uma função matemática: você dá a ele um valor de entrada e a função emite um valor de saída; e a mesma entrada sempre produz a mesma saída. O que torna um hash especial é que ele é tão imprevisível quanto uma função matemática pode ser — ele é projetado para que não haja rima ou razão para seu comportamento, exceto pela regra de que a mesma entrada sempre produz a mesma saída.

Como exemplo, vamos considerar "anonimizar" um SSN (algo como nosso CPF, porém secreto) utilizando o SHA-1. Essa função retornará uma string similar à b0254c86634ff9d0800561732049ce09a2d003e1. Um SSN é composto por 9 números, então é bem diferente do resultado do SHA-1.

Apesar disso, é bem fácil descobrir qual é o SSN criptografado com uma função como o SHA-1. O analista simplesmente adivinha o SSN por força bruta: ele enumera todos os possíveis SSNs e faz o hash de cada um. Depois, pode comparar a string acima com a tabela de SSNs que ele gerou.

Nos comentários, o Edward Felten dá como alternativa usar um "salt longo e secreto" para o hash, e isso é abordado nos outros artigos que mencionarei.

Como anonimizar dados corretamente, se o hash não é o suficiente?

O texto anterior possivelmente te deixou com esta dúvida, e coincidentemente é exatamente uma pergunta feita no Security Stack Exchange. A resposta mais votada nos dá duas alternativas para a anonimização:

  1. Usar tokenização. Isso significa que você cria um banco de dados separado com IDs gerados aleatoriamente mapeando para o valor desejado. Você então insere o token em vez da identidade real.
  2. Se você não precisa mapear os dados de volta, pode usar, por exemplo, um HMAC com um segredo longo gerado aleatoriamente. Sem o segredo, você não pode utilizar força bruta para adivinhar os IDs originais, mesmo quando eles consistam em apenas 1 único caractere.

Usar um HMAC é, na verdade, a maneira correta de usar um "salt secreto" (um salt nunca é considerado secreto na criptografia). Ou seja, é o que Edward Felten mencionou no blog do FTC.

Essas são as respostas curtas, mas ainda assim, anonimizar dados não é algo tão simples, e mesmo seguindo essas recomendações, você pode não estar fazendo o suficiente. O próximo link é um mergulho profundo no assunto.

O falso fascínio do hash para anonimização

Este é o título do artigo publicado no blog da Teleport (uma empresa que não conheço, mas o artigo é bom).

Ao longo do artigo, vamos usar a seguinte tabela como "base de dados". Considere que são registros de login.

TimestampIPUsuário
2018-04-15 13:011.2.3.445d9908cf9f290f7097bf8152c288055275ebe93f2dc3781c8a1c60a43cd6ae5
2018-04-05 08:055.6.7.8e9e326d5f3b4741fe5967b5f9f3997e6275331ba18567ef9ef9e0e3a00e78371
2018-04-16 12:279.1.2.34135aa9dc1b842a653dea846903ddb95bfb8c5a10c504a7fa16e10bc31d1fdf0

A tabela acima utiliza o SHA256 para criptografar o nome do usuário. Apesar de parecer anônimo e difícil de adivinhar na força bruta, caso você esteja procurando por um usuário específico, como knisbet, fica fácil descobrir se ele está na base de dados ou não.

É um caso parecido com o SSN mencionado no blog do FTC, mas aqui já sabemos de antemão o que estamos procurando (informações sobre um usuário específico), precisando apenas gerar o hash para o nome de usuário desejado e verificar se ele está na base de dados.

Tornar o hash mais lento, ao usar bcrypt, por exemplo, também não resolve esse problema, porque o dado que queremos descobrir é uma string pública e fácil de adivinhar, como o nome de usuário ou um endereço de e-mail. Para senhas, isso serve porque é uma string difícil de adivinhar.

Mas já sabemos resolver o problema do hash, certo?

Suponha que o problema do hash tenha sido resolvido e estamos usando ids aleatórios, como a resposta do Security Stack Exchange mencionou, ou HMACs. Ainda assim, temos outros problemas.

Imagine que um usuário declarou em alguma rede social, como o X, ou num site de status, que ocorreu um problema no sistema e ele precisou acessar no dia 15/04/2018, por volta das 13hrs, para resolver o problema. Se não houver muitos outros registros nesse momento, é fácil ver que é o primeiro usuário neste banco de dados.

E se você estava conversando com outra pessoa, que entrou de férias no dia 5 de abril, também consegue identificá-la, porque o último acesso foi no dia 5, e você só precisa identificar algum registro que atenda este requisito.

Caso outro conjunto de dados tenha sido comprometido, e nele é possível ver que o usuário alex utilizou o IP 9.1.2.3 no dia 12 de abril, também será possível identificá-lo na tabela acima.

Combinar dados anonimizados que podem ser correlacionados a outras partes dos seus dados que não são anonimizadas, em muitos casos torna trivial desmascarar usuários em conjuntos de dados anonimizados. Normalmente, você só precisa de alguns pontos de dados com precisão relativamente baixa para desmascarar um grande conjunto de dados.

Então, como anonimizar os dados?

No artigo, o autor diz que a forma de anonimizar depende inteiramente do conjunto de dados e de como ele deve ser usado.

Na Teleport, a maneira que escolheram anonimizar os dados é gerando HMACs com um segredo que é relevante apenas para o cluster Teleport. Isso significa que o algoritmo usado para calcular knisbet -> 45d99... depende de uma chave secreta e imprevisível que vive na rede dos clientes, e que a empresa não tem acesso à essa chave. Cada cluster também usa sua própria chave, então se houver um vazamento nos segredos, isso limita o potencial desmascaramento a apenas um único cliente.

E o mais importante, a empresa coleta apenas dados suficientes para cumprir o propósito declarado. Quanto menos pontos de dados são coletados, menor a oportunidade de alguém correlacionar os dados.

Há várias maneiras de melhorar isso, sendo algumas:

  • Fazer com que os clusters rotacionem seus segredos todo mês, para que os dados coletados não possam ser correlacionados mês a mês.
  • Armazenar apenas hashes parciais, o que tornaria um ataque de força bruta mais difícil.

Uma outra alternativa

Como mencionado na resposta do Security Stack Exchange, uma alternativa é, em vez de anonimizar os dados que você deseja proteger por meio de um algoritmo, gerar uma tabela de consulta de números de ID ou UUIDs para substituir o texto. Então knisbet = 1, alex = 2, etc. e armazenar isso em um banco de dados em um domínio de segurança separado com controles de acesso separados.

Dessa forma, você sempre tem que consultar a tabela de referência e fazer uma troca de dados reais por dados anonimizados. Isso tem a vantagem de não poder ser quebrado pelo próprio algoritmo, mas ainda tem a fraqueza de que se essa tabela for comprometida ou incluir informações que podem ser correlacionadas, o conjunto de dados pode ser trivialmente desmascarado.

Não é tão simples, mas melhorar não é tão complicado

Como vimos, usar um hash não é suficiente. Esse seria apenas o “primeiro passo”. Um HMAC já é algo melhor, mas a verdadeira proteção de dados exige uma abordagem mais completa, que leva em consideração as relações entre os dados e a possibilidade de outros vazamentos dentro do sistema. A chave aqui é entender que anonimizar dados não se trata apenas de aplicar uma função matemática, mas sim de garantir que as informações que você está protegendo não possam ser facilmente correlacionadas e desmascaradas.

Um dos grandes insights que eu tive lendo os artigos foi sobre o uso de HMAC com uma chave secreta exclusiva para cada cliente, permitindo que o processo de anonimização ocorra sem que seu sistema precise conhecer a chave, além da sugestão de rotacionar o segredo, minimizando os danos em caso de vazamentos. A análise de correlação entre os dados também foi um ponto bem relevante.

Anonimizar dados corretamente não é simples, mas sair do zero é fácil. Pense de forma estratégica sobre como proteger as informações sensíveis, antecipando possíveis pontos de falha. Esse conhecimento é um diferencial que pode não só melhorar a segurança dos seus dados, mas também destacar você como profissional. Não é comum encontrar profissionais com essa preocupação por aí, ainda mais num momento onde tantos desenvolvedores “são formados em seis meses”.

Carregando publicação patrocinada...
3

Recentemente eu estava pensando exatamente nessa questão. Não sabia dos nomes exatos de alguns termos que você usou, mas tenho alguma noção dos conceitos principais. Estava pensando em fazer um banco de dados pra lidar somente com dados sensíveis. Ele usaria um esquema de rotação de chaves derivadas de uma chave mestre que fica em armazenada em um lugar sem conexão com a internet. Essas chaves são rotacionadas semanalmente (elas são geradas previamente por um algoritmo). Dai pra armazenar essas chaves seria usado uma blockchain que guarda partes dessas chaves de em blocos não ligados de forma consecutiva (a ideia seria fazer um tipo de randomização aqui). (Nessa parte eu também pensei em guardar os dados em si dessa forma, quebrando eles em blocos de binários e randomizando na blockchain, mas acho que algo assim, apesar de poder funcionar, gera tradeoffs colaterais, que dificultam o gerenciamento dos dados - mas que também é possível resolver). Enfim, viajei bastante nisso, dai vi que tem algumas soluções que fazem mais ou menos isso:

BlockchainDB e Storj.

Seria um projeto interessante, e talvez fosse bem útil pra outras pessoas e empresas. Cheguei a pensar nisso porque estou querendo resolver outro problema, dai queria ter um banco de dados bem seguro e vi que as soluções que tem hoje não fazem troca de chaves de criptografia (recriptografar os dados) de forma automatizada. Seria interessante. Claro que um sistema como esse exigiria um alto grau de computação por ter recriptografia sendo feita, mas acho que o esquema de blockchain e distribuição de trabalho poderia ser usado também aqui nesse caso pra conseguir fazer isso de forma rápida (paralelismo e assincronismo). Enfim, uma ideia bacana, mas ainda precisaria ser analisados vários pontos.

2

Concordo contigo, viniciusbrito, é uma ideia bacana mas ainda carece que vários pontos sejam reavaliados com mais cuidado. Inclusive, na matéria que cita a postagem principal, escrevem (lá em 2018) que:

Anonymizing data is extremely hard and most of us are doing it wrong. To me, it feels like we're back in the era before bcrypt, where everyone was charting their own course on how to store passwords in databases.

I think that as an industry, we need to be aware that cryptography is not anonymity, and there doesn't yet exist a right answer, library, or tool, to simply apply to your anonymization problem (without in-depth knowledge).
Fonte: https://goteleport.com/blog/hashing-for-anonymization

Ou seja, o processo de anonimização é difícil e muitos estão realizando esse processo de maneira incorreta (segundo a matéria). Segundo os comentários que li, parecem confundir criptografia e anonimização. Enquanto no primeiro o conteúdo do pacote de dados existente é reversível com uso das chaves corretas, no segundo é teoricamente irreversível. A possibilidade remota de recriação do pacote de dados inexistente por completo, via força bruta, vai precisar contar com as vulnerabilidades conhecidas, dicas, além arcar com os custos elevados de computação. Entendo que anonimização em computação deveria algo semelhante a incinerar um documento ou mesmo transformá-lo em pasta de celulose para gerar papel reciclável.

Não penso levar a ideia em diante, viniciusbrito, entretanto faço experimentos quando posso para entender esses artifícios e suas vulnerabilidades após me espantar com os processos que facilitaram os vazamento de dados. Todas as vezes que tento criar uma "criptografia nova" vem um anjinho me lembrar do conselho de vários especialistas da área. O resultado pode ficar parecido com isso e não funcionar! Aprecio a discussão para trocar ideias sobre o que os desenvolvedores pensam a respeito e quão preocupados estão em proteger nossos dados pessoais, transações etc. Acredito que a próxima geração já estará ciente de que os dados são dos clientes, diferente como pensa uma pequena parte da geração atual de profissionais que acreditam ser donos do DB e seu conteúdo. Na ocorrência de vazamento de dados, o estagiário é o culpado 8-) pela imperícia (a ação equivocada por falta de técnica, de inaptidão), imprudência (a ação sem cautela), negligência (a omissão da conduta esperada para uma determinada situação), irresponsabilidade (característica da pessoa a quem não se deve conceder responsabilidade pela realização de alguma ação ilegal) do superior ao deixar informações sensíveis sob os cuidados de quem não deveria sequer ter acesso a elas.

PS: Ainda não descobri o CPF que o rafael cita após passar pela função de hash SHA1. Alguém descobriu por força bruta?

Como exemplo, vamos considerar "anonimizar" um SSN (algo como nosso CPF, porém secreto) utilizando o SHA-1. Essa função retornará uma string similar à b0254c86634ff9d0800561732049ce09a2d003e1. Um SSN é composto por 9 números, então é bem diferente do resultado do SHA-1.

1

PS: Ainda não descobri o CPF que o rafael cita após passar pela função de hash SHA1. Alguém descobriu por força bruta?

Eu não tive o trabalho de fazer isso! Hahaha. O SHA-1 foi copiado diretamente do artigo. Veja o texto original:

If you hash my SSN, the result is b0254c86634ff9d0800561732049ce09a2d003e1.

Então realmente não é um CPF.

Clique aqui para ver o que o hash representa.

Conforme o próprio artigo:

[In case you’re wondering, the b02 value is not really the hash of my SSN. It is the hash of the text string “my SSN”. There is no way I would publish the hash of my actual SSN.]

1

Agradeço o esclarecimento, rafael!!


Aproveitando, agradeço também a dica, pois a partir de sua mensagem original aprendi a usar o recurso details:summary. Ainda apanhando um pouco aqui para dar uma "repaginada" nos contéudos que escrevi. Uma postagem com muitas imagens, listas, gerava um impacto negativo (texto muito carregado) para quem as acessava.

Estou deixando explícito o código markdown para outros leigos, como eu, interessados em encurtar suas longas publicações, pelo menos as seções de bla-bla-bla (no bom sentido), opiniões e animações que tiram a atenção do leitor.

O código acima deve gerar algo parecido com isso:

<details>
    <summary>Um texto de chamada</summary>

Um texto.
> Uma citação _ipsis litteris_, por exemplo.
    
</details>

O código acima deve gerar algo parecido com isso:

Um texto de chamada

Um texto.

Uma citação ipsis litteris, por exemplo.

3

rafael, sei que a ideia não faz mais sentido devido aos diversos vazamentos de dados que ocorreram recentemente, enriquecendo bancos de dados clandestinos por aí. Pensando numa maneira de dificultar, imaginei o seguinte conjunto de dados pessoais de um cliente (fictício) de uma empresa (fictícia).

NOME COMPLETO     : JOAO DA SILVA SÓ
DATA DE NASCIMENTO: 29/02/2000
CPF               : 987.654.321-00
RG                : 12.234.567-X SSP/RR
ENDEREÇO          : AVENIDA ESPERANÇA SEM FIM, 789, BAIRRO LOGO ALI
CEP               : 97531-024 - 5105507 - VILA BELA DA SANTÍSSIMA TRINDADE - MT
CELULAR           : +5565987654321
EMAIL             : [email protected]
PASSPHRASE CLIENTE: QUALQUER COISA VALE DESDE QUE SO O CLIENTE SE LEMBRE
SALT              : 5d60adc890a3dc0bd7b9b621edac9272
ÚLTIMA ATUALIZAÇÃO: 01/02/2024 14:15:16

Hoje, corre o risco de cadastros assim estarem sendo subidos para sistemas na nuvem. Porém, em vez subir esses ~600 bytes, poderiam ser apenas 32 bytes gerados pelo SHA256: be6034da95b490d59eb881c06b18e2092913985155bfb56d3c1e0b06eab99b2b

As colisões de hash são evitadas devido a existência da passphrase e do salt mesmo que o cliente forneça poucos dados pessoais. A desanonimização, quando necessária, ocorre em sistema offline fora das vistas de qualquer ataque online. Se ocorrer a atualização dos dados, um novo hash é gerado. E ainda, se esses hashes fizerem parte de uma blockchain, o campo ÚLTIMA ATUALIZAÇÃO torna-se redundante.

De uma maneira geral, os únicos campos que realmente são livres para alteração a qualquer tempo e quantas vezes precisar são PASSPHRASE CLIENTE, SALT e, consequentemente, o campo ÚLTIMA ATUALIZAÇÃO. Destes, o primeiro é guardado com o cliente, os demais com a empresa junto com o hash. Perdendo-se a passphrase, um novo cadastro pode ser gerado. Conforme prevê a LGPD em seu artigo 18, "o titular poderá a qualquer momento e mediante requisição, a eliminação dos dados pessoais tratados com o consentimento do titular, exceto nas hipóteses previstas no art. 16 desta lei". Com tal método, a simples omissão ou perda da passphrase dá ao titular dos dados o poder de praticamente anonimizá-los para sempre.

Talvez tenha ficado a dúvida, como o cliente ficará com esse cadastro? Assinando digitalmente o hash.

2

Cara, excelente sua ideia. Se tivesse ainda um sistema que atualiza o SALT de forma recorrente e faz uma nova criptografia dos dados, fica bem difícil descobrir os dados iniciais. Eu tava pensando em fazer um SGBD pra fazer isso, mas dai me esbarrei em todo resto que um SGDB precisa implementar pra funcionar bem (indexação, busca e tals). Mas muito boa sua ideia, parabéns.

Ela só tem um problema, ela comprime os dados em uma única string, impossibilitando estudos sobre informações do cliente. Mas acho que isso poderia ser resolvido gerando de alguma forma alguma outra sequência de hash de cada um dos campos (sem colisão), dai vai ser possível fazer estudos (analise de dados e ciência de dados) mesmo em informações sensíveis, ao mesmo tempo que garante a segurança das informações (com chaves que são informadas pelo próprio cliente), e se ainda incorporar por exemplo algum tipo de 2FA que também gera uma segunda chave pra incorporar na ananomização dos dados, fica ainda mais difícil.

Fiquei empolgado com essa ideia agora. kkkkk

Quer levar isso adiante? Você pensou em incorporar blockchain também, eu pensei em algo semelhante, mas esqueci da possibilidade de usar informações vindas do próprio cliente pra anonimizar os dados.

2

Estou em um projeto no trabalho e minha maior preocupação tem sido justamente a anonimização dos dados. Só de ler o seu post já foi o suficiente para abrir mais a minha mente ^-^

2

Eu já tinha pensado sobre o segredo do hash ficar apenas sobre o domínio do cliente, mas caso talvez por leiguismo:
1 - Me pareceu que o cliente não poderia se responsabilizar por uma informação tão importante.
2 - Como criar uma aplicação onde a informação está com o cliente, e se ele trocar de dispositivo como faria para recuperar os dados.

Não sou da área de segurança então talvez sejam perguntas bobas, mas foram as duas que eu mais fiquei assim pensando.

2

Boa pergunta. Não vou conseguir te responder, mas acredito que no exemplo da Teleport, que armazena a chave no cliente, é para casos onde não é necessário recuperar a informação, como dito na segunda opção da resposta do Security Stack Exchange:

  1. Se você não precisa mapear os dados de volta, pode usar, por exemplo, um HMAC com um segredo longo gerado aleatoriamente. Sem o segredo, você não pode utilizar força bruta para adivinhar os IDs originais, mesmo quando eles consistam em apenas 1 único caractere.
1

Dado que a ideia é anonimizar creio que degradar a informação deveria ser uma opção, como por exemplo substituir o nome "rafael" por "anonimo". Existe alguma razão para isso não ser uma opção?