Como pesquisar um banco de dados MySQL com campos criptografados

15

Suponha que eu precise criptografar certos campos de tabela de um banco de dados MySQL . Além disso, preciso pesquisar alguns desses campos que criptografei.

Como alguém pesquisaria esses campos de qualquer maneira?

Descriptografar cada registro passo a passo não é uma opção: suponha que eu tenha vários milhares de registros. Levaria muito tempo e espaço para descriptografar cada registro e verificar se cada registro único corresponde à pesquisa.

UPDATE 2012-09-07

Adicionar mais detalhes ao esquema do banco de dados seria bom , pois estou prestes a implementar um novo aplicativo. Além disso, preciso estender os aplicativos atualmente em execução na produção. Mas mesmo para esses aplicativos, adicionar mais detalhes seria bom.

UPDATE 2012-09-08

Criptografia é o núcleo desta questão.

As restrições de acesso, conforme proposto por algumas respostas, já se aplicam - mas não atendem ao requisito formal de criptografar dados.

Esse requisito formal não é o PCI ( padrão de segurança de dados do setor de cartões de pagamento ).

SteAp
fonte

Respostas:

11

Obviamente, eles não devem ser vistos, portanto, pesquisar neles seria problemático.

Um truque que usei no passado é fazer o hash dos dados criptografados antes de criptografá-los e armazenar o hash em uma coluna indexada. Obviamente, isso só funciona se você estiver pesquisando todo o valor; valores parciais não terão o mesmo hash.

Provavelmente, você pode estender isso criando um índice de hashes de "texto completo", se necessário, mas isso pode ficar complicado muito rápido.

TERMO ADITIVO

Foi sugerido que eu adicionasse uma nota de rodapé à minha resposta em um debate bastante longo no bate-papo sobre vulnerabilidade a ataques de dicionário, portanto discutirei esse risco potencial à segurança da abordagem acima.

Ataque de dicionário: um ataque de dicionário ocorre quando alguém pré-hashes uma lista de valores conhecidos e compara os hashes à sua coluna de hash no banco de dados. Se eles puderem encontrar uma correspondência, é provável que o valor conhecido seja realmente o que está sendo hash (embora não seja definitivo, porque não é garantido que os hashes sejam únicos). Isso geralmente é atenuado ao hash do valor com um "sal" aleatório anexado ou anexado, para que o hash não corresponda ao dicionário, mas a resposta acima não pode ser utilizada porque você perde a capacidade de pesquisa.

Esse ataque é perigoso ao lidar com coisas como senhas: se você criar um dicionário de hashes de senha populares, poderá pesquisar rapidamente na tabela esse valor de hash e identificar um usuário que tenha essa senha e extrair efetivamente credenciais para roubar a identidade do usuário. .

É menos perigoso para itens com um alto grau de cardinalidade, como SSNs, números de cartão de crédito, GUIDs etc. (mas existem riscos diferentes [leia-se: legal] associados ao armazenamento desses itens, portanto, não estou inclinado a aconselhá-los. )

O motivo disso é que, para que um ataque de dicionário funcione, você precisa ter um dicionário pré-construído de valores possíveis e seus hashes. Você poderia, em teoria, construir um dicionário de todos os SSNs possíveis (um bilhão de linhas, assumindo que todas as permutações de formatação foram removidas; várias dezenas de trilhões de entradas para cartões de crédito) ... mas isso não costuma ser o ponto de um ataque de dicionário, e basicamente se torna comparável a um ataque de força bruta, no qual você está investigando sistematicamente todos os valores.

Você também pode procurar um SSN específico ou número de cartão de crédito, se estiver tentando corresponder um SSN a uma pessoa. Novamente, geralmente não é o objetivo de um ataque de dicionário, mas é possível, por isso, se esse é um risco que você precisa evitar, minha resposta não é uma boa solução para você.

Então aí está. Como em todos os dados criptografados, eles geralmente são criptografados por um motivo; portanto, esteja ciente dos seus dados e do que você está tentando protegê-los.

Jeremy Holovacs
fonte
A discussão sobre esta resposta foi movida para o bate-papo .
Paul White Restabelece Monica
5

Você pode dar uma olhada no CryptDB . É um front end para MySQL e PostgreSQL que permite armazenamento transparente e consulta de dados criptografados. Ele funciona criptografando e decodificando dados à medida que passa entre o aplicativo e o banco de dados, reescrevendo consultas para operar nos dados criptografados. e ajustando dinamicamente o modo de criptografia de cada coluna para expor apenas as informações necessárias para as consultas que o aplicativo usa.

Os vários métodos de criptografia usados ​​pelo CryptDB incluem:

  • RND , um esquema de criptografia segura totalmente IND-CPA que não vaza informações sobre os dados (exceto sua presença e, para tipos de comprimento variável, comprimento), mas apenas permite armazenamento e recuperação, sem consultas.

  • DET , uma variante do RND que é determinística, de modo que dois valores idênticos (na mesma coluna) criptografam no mesmo texto cifrado. Oferece suporte a consultas de igualdade do formulário WHERE column = 'constant'.

  • OPE , um esquema de criptografia de preservação de pedidos que suporta consultas de desigualdade, como WHERE column > 'constant'.

  • HOM , um esquema de criptografia parcialmente homomórfica (Paillier) que permite adicionar valores criptografados multiplicando os textos cifrados. Suporta SUM()consultas, adição e incremento.

  • SEARCH , um esquema que suporta pesquisas de palavras-chave no formulário WHERE column LIKE '% word %'.

  • JOIN e OPE-JOIN , variantes de DET e OPE que permitem comparar valores em colunas diferentes entre si. Apoie as associações de igualdade e intervalo, respectivamente.

O poder real do CryptDB é que ele adapta o método de criptografia de cada coluna dinamicamente às consultas que vê, para que os esquemas mais lentos e / ou menos seguros sejam usados ​​apenas para as colunas que os exigem. Existem também vários outros recursos úteis, como encadear chaves de criptografia para senhas de usuários.

Se você estiver interessado, é recomendável dar uma olhada nos documentos vinculados no site do CryptDB, particularmente "CryptDB: Protegendo a confidencialidade com o processamento de consultas criptografadas" por Popa, Redfield, Zeldovich e Balakrishnan ( SOSP 2011 ). Esses documentos também descrevem as várias compensações de segurança e desempenho envolvidas no suporte a diferentes tipos de consulta com mais detalhes.

Ilmari Karonen
fonte
1
It works by encrypting and decrypting data as it passes between the application and the database: Certamente isso pode causar problemas se os dados que estão sendo pesquisados já estiverem no banco de dados (criptografados), mas obviamente a própria consulta que está pesquisando no banco de dados só é passada ao CryptDB (e depois criptografada?). Não consigo entender como esse método pode ser eficiente?
Martin
3

Não entendo por que as respostas atuais não questionaram completamente os requisitos, portanto, perguntarei e deixarei como resposta.

Quais são os motivos de negócios? Quais dados você precisa criptografar e por quê? Se você procura conformidade com PCI, eu poderia escrever um ensaio.

Perguntas sobre sua exigência:

  • Você precisará retornar um existe / não existe como resultado ou os dados reais?
  • Você precisa de um recurso LIKE '% OMG_SEKRIT%'?
  • Quem não pode ver os dados e por quê?

A segurança do RDBMS é normalmente feita com base nas permissões impostas pelo usuário / função. Os dados são normalmente criptografados pelo RDBMS no disco, mas não nos próprios dados colunares, pois isso realmente não faz sentido para um aplicativo projetado para armazenar e recuperar dados com eficiência.

Restringir por usuário / função / API. Criptografar no disco. Se você estiver armazenando dados mais importantes, eu adoraria saber por que você está usando o MySQL.

Philᵀᴹ
fonte
Primeiramente, preciso descobrir que existe / não existe e depois localizar o registro específico. O suporte total do LIKE ficaria bem. Mas eu me pergunto, que qualquer coisa além da correspondência de palavras será possível. Usuário autorizado pode ver dados. O aplicativo descriptografa esses itens, um usuário legítimo tem direitos para ver. Esquemas de base de permissão não são uma opção.
SteAp 8/09/12
Quais são os critérios para "dados mais importantes?"
Arcanine
2

Estou analisando isso e me deparei com sua pergunta. Estou me inclinando para a abordagem descrita na seção 5.4 do artigo "Técnicas práticas para pesquisas em dados criptografados" http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

A essência básica é criar um índice que contenha palavras-chave criptografadas presentes no documento de pesquisa criptografado. O truque é também criptografar os locais no documento (ou banco de dados) em que essas palavras-chave estão presentes.

Scott Ford
fonte
1

Programaticamente, uma solução eficiente é

  1. recuperar TODOS os registros APENAS para o campo que você está pesquisando com o ID do registro
  2. descriptografar aqueles em uma tabela temporária
  3. realizar a pesquisa nessa tabela
  4. use os IDs para recuperar os registros completos (todos os campos) que correspondem aos critérios de pesquisa
  5. descriptografá-las e devolvê-las ao usuário

O ponto é que 1 e 4 são conjuntos de dados significativamente menores do que recuperar e descriptografar todos os campos de todos os registros no início.

Espero que ajude.

Paul B. Hartzog
fonte
As tabelas temporárias em texto sem formatação são relativamente (muito) fáceis de capturar e ler, interrompem o servidor no momento certo ou simplesmente copiam a temp/pasta e bang, os valores de texto sem formatação para toda a coluna estão lá, essa não é uma maneira segura de operar
Martin
1

Isso é possível com a funcionalidade completa de pesquisa usando as funções de criptografia interna do MYSQL.

Aqui está um exemplo:

!!! EU ESTOU USANDO O MYSQL ENCODE () AQUI POR SIMPLICIDADE, MYSQL_ENCODE AGORA É CONSIDERADO INSEGURO, USE UMA DAS OUTRAS FUNÇÕES INTERNAS DO MYSQL INSTEAD !!!

UPDATE my_table
SET field=ENCODE('my_data', 'my_password')
WHERE ID=1;

SELECT DECODE(field, 'my_password') as field FROM my_table
WHERE field LIKE 'data';

Como o comentário acima sugere, NÃO use ENCODE (), use uma das outras funções de criptografia . Estou usando apenas ENCODE neste exemplo devido à sua simplicidade.

Se você estiver fazendo isso em um aplicativo como php, poderá fazê-lo nas classes de gateway ou repositório db armazenando uma lista / matriz das colunas criptografadas de cada tabela na respectiva classe de gateway.

class UserGateway
{
    protected $encrypted_fields = array(
        'username',
        'email'
    );

    public function get($fields, ...)
    {
        foreach ($fields as $k => $field) {
            if (in_array($field, $fields)) {
                $fields[$k] = $this->decodeSelect($field);
            }
        }

        $sql = 'SELECT '.implode(',', $fields);

        //......
    }

    protected function decodeSelect($field)
    {
        return "DECODE($field, $pass) AS $field";
    }
}

É claro que este é um código muito grosseiro e inseguro que não deve ser usado na produção sem melhorias significativas. Mas deve servir ao seu propósito ao fornecer a idéia geral.

Leigh Bicknell
fonte
-1

Supondo que você esteja pesquisando no SQL e com relação ao valor total e não parcial (por exemplo, LIKE 'value%') ... ao capturar os dados da pesquisa, criptografe esses dados usando o mesmo algoritmo usado quando os dados foram criptografados e procure por eles.

Por exemplo:

O que teria sido:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'Value'

Em vez disso, pode parecer com:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'
WellyBoot
fonte
1
Não. A criptografia decente funcionará com um valor salt. Portanto, se, por exemplo, você tiver um sal exclusivo para cada linha, cada um deles precisará ser usado na cadeia de pesquisa, isso ficará complexo, caro e muito rápido
Martin