Come cercare un database MySQL con campi crittografati


15

Supponiamo di dover crittografare alcuni campi tabella di un database MySQL . Inoltre, devo cercare alcuni di questi campi che ho crittografato.

Come si cerca in quei campi comunque?

Decifrare ogni record passo dopo passo non è un'opzione: supponiamo che io abbia più di migliaia di record. Ci vorrebbe troppo tempo e spazio per decrittografare ogni record e verificare se ogni singolo record corrisponde alla ricerca.

AGGIORNAMENTO 2012-09-07

Aggiungere ulteriori dettagli allo schema del database sarebbe OK , poiché sto per implementare una nuova applicazione. Inoltre, ho bisogno di estendere le applicazioni attualmente in esecuzione in produzione. Ma anche per quelle applicazioni, aggiungere ulteriori dettagli sarebbe OK.

AGGIORNAMENTO 2012-09-08

La crittografia è il nocciolo di questa domanda.

Le restrizioni di accesso, come proposto da alcune risposte, si applicano già, ma non soddisfano il requisito formale di crittografare i dati.

Questo requisito formale non è lo standard di sicurezza dei dati del settore delle carte di pagamento [PCI].

Risposte:


11

Ovviamente non sono fatti per essere visti, quindi cercarli sarebbe problematico.

Un trucco che ho usato in passato è l'hash dei dati crittografati prima di crittografarli e archiviare l'hash in una colonna indicizzata. Naturalmente, questo funziona solo se stai cercando l'intero valore; i valori parziali non avranno lo stesso hash.

Probabilmente potresti estenderlo creando un indice di hash "full text", se necessario, ma potrebbe complicarsi molto velocemente.

ADDENDUM

Mi è stato suggerito di aggiungere una nota a piè di pagina alla mia risposta per un dibattito abbastanza lungo in chat sulla vulnerabilità agli attacchi del dizionario, quindi discuterò questo potenziale rischio per la sicurezza con l'approccio di cui sopra.

Attacco a dizionario: un attacco a dizionario si verifica quando qualcuno esegue il pre-hash di un elenco di valori noti e confronta gli hash con la colonna con hash nel database. Se riescono a trovare una corrispondenza, è probabile che il valore noto sia effettivamente ciò che viene sottoposto a hash (non è tuttavia definito, poiché gli hash non sono garantiti come unici). Questo di solito è mitigato dall'hash del valore con un "salt" casuale aggiunto o anteposto in modo che l'hash non corrisponda al dizionario, ma la risposta sopra non può usare un salt perché perdi la ricerca.

Questo attacco è pericoloso quando si tratta di cose come le password: se si crea un dizionario di hash di password popolari, è possibile quindi cercare rapidamente nella tabella quel valore di hash e identificare un utente che dispone di tale password ed estrarre efficacemente le credenziali per rubare l'identità dell'utente .

È meno pericoloso per gli articoli con un alto grado di cardinalità, come SSN, numeri di carta di credito, GUID, ecc. (Ma ci sono diversi rischi [leggi: legali] associati alla loro conservazione, quindi non sono propenso a consigliarli per conservarli ).

Il motivo di ciò è perché un attacco del dizionario funzioni, è necessario avere pre-costruito un dizionario di possibili valori e dei loro hash. In teoria, potresti costruire un dizionario di tutti i possibili SSN (un miliardo di righe, supponendo che tutte le permutazioni di formattazione siano rimosse; più dozzine di trilioni di voci per le carte di credito) ... ma di solito non è questo il punto di un attacco del dizionario, e fondamentalmente diventa paragonabile a un attacco a forza bruta in cui si sta studiando sistematicamente ogni valore.

Puoi anche cercare un SSN specifico o un numero di carta di credito, se stai cercando di abbinare un SSN a una persona. Ancora una volta, di solito non è il punto di un attacco del dizionario, ma è possibile farlo, quindi se questo è un rischio che devi evitare, la mia risposta non è una buona soluzione per te.

Così il gioco è fatto. Come per tutti i dati crittografati, di solito è crittografato per un motivo, quindi sii consapevole dei tuoi dati e da cosa stai cercando di proteggerli.


La discussione su questa risposta è stata spostata nella chat .
Paul White Ripristina Monica

5

Potresti dare un'occhiata a CryptDB . È un front-end per MySQL e PostgreSQL che consente l'archiviazione trasparente e l'interrogazione di dati crittografati. Funziona crittografando e decrittografando i dati mentre passa tra l'applicazione e il database, riscrivendo le query per operare sui dati crittografati. e regolando dinamicamente la modalità di crittografia di ogni colonna per esporre solo tutte le informazioni necessarie per le query utilizzate dall'applicazione.

I vari metodi di crittografia utilizzati da CryptDB includono:

  • RND , uno schema di crittografia sicura completamente IND-CPA che non perde informazioni sui dati (tranne la sua presenza e, per tipi di lunghezza variabile, lunghezza) ma consente solo l'archiviazione e il recupero, nessuna query.

  • DET , una variante di RND che è deterministica, in modo che due valori identici (nella stessa colonna) crittografino nello stesso testo cifrato. Supporta query sull'uguaglianza del modulo WHERE column = 'constant'.

  • OPE , uno schema di crittografia che preserva l'ordine che supporta query di disuguaglianza come WHERE column > 'constant'.

  • HOM , uno schema di crittografia parzialmente omomorfo (Paillier) che consente di aggiungere valori crittografati insieme moltiplicando i cifrati. Supporta SUM()query, addizioni e incrementi.

  • RICERCA , uno schema che supporta le ricerche per parole chiave del modulo WHERE column LIKE '% word %'.

  • JOIN e OPE-JOIN , varianti di DET e OPE che consentono di confrontare valori in colonne diverse. Supporta rispettivamente l'uguaglianza e l'intervallo di join.

Il vero potere di CryptDB è che adatta il metodo di crittografia di ogni colonna in modo dinamico alle query che vede, in modo che gli schemi più lenti e / o meno sicuri vengano utilizzati solo per le colonne che li richiedono. Esistono anche altre utili funzioni, come il concatenamento delle chiavi di crittografia alle password degli utenti.

Se sei interessato, ti consigliamo di dare un'occhiata ai documenti collegati dal sito Web di CryptDB, in particolare "CryptDB: proteggere la riservatezza con l'elaborazione di query crittografate" di Popa, Redfield, Zeldovich e Balakrishnan ( SOSP 2011 ). Tali articoli descrivono anche i vari compromessi di sicurezza e prestazioni coinvolti nel supportare diversi tipi di query in modo più dettagliato.


1
It works by encrypting and decrypting data as it passes between the application and the database: Sicuramente questo può causare problemi se i dati cercati sono già nel database (crittografati) ma ovviamente la query stessa che cerca nel database viene solo passata a CryptDB (e quindi crittografata?). Non riesco a capire come questo metodo possa essere affatto efficiente?
Martin,

3

Non capisco perché le risposte attuali non abbiano messo completamente in discussione i requisiti, quindi lo chiederò e lo lascerò come risposta.

Quali sono le ragioni commerciali? Di quali dati hai bisogno per crittografare e perché? Se stai cercando la conformità PCI, potrei scrivere un saggio.

Domande sulla tua esigenza:

  • Sarà necessario restituire un esiste / non esiste come risultato o i dati effettivi?
  • È richiesta una funzionalità LIKE '% OMG_SEKRIT%'?
  • Chi non può vedere i dati e perché?

La sicurezza RDBMS viene normalmente eseguita su una base di autorizzazioni che viene applicata dall'utente / ruolo. I dati vengono normalmente crittografati dall'RDBMS su disco, ma non nei dati colonnari stessi, poiché ciò non ha alcun senso per un'applicazione progettata per archiviare e recuperare i dati in modo efficiente.

Limitazione per utente / ruolo / api. Crittografa su disco. Se stai memorizzando dati più importanti, mi piacerebbe sapere perché stai usando MySQL.


In primo luogo, ho bisogno di trovare esiste / non esiste e quindi individuare il record specifico. Il pieno supporto di LIKE andrebbe bene. Ma mi chiedo che sarà possibile qualsiasi cosa oltre alla corrispondenza delle parole. L'utente autorizzato è autorizzato a visualizzare i dati. L'app decodifica tali elementi, un utente legittimo ha i diritti di vedere. Gli schemi di base delle autorizzazioni non sono disponibili.
SteAp

Quali sono i criteri per "dati più importanti?"
arcanina,

2

Sto esaminando questo e ho trovato la tua domanda. Mi sto avvicinando all'approccio delineato nella sezione 5.4 del documento "Tecniche pratiche per ricerche su dati crittografati" http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

L'essenza di base è creare un indice che contenga parole chiave crittografate presenti nel documento di ricerca crittografato. Il trucco è anche crittografare le posizioni nel documento (o database) in cui sono presenti tali parole chiave.


1

A livello di programmazione, una soluzione efficiente è

  1. recuperare TUTTI i record SOLO per il campo che si sta cercando con l'ID record
  2. decodificarli in una tabella temporanea
  3. eseguire la ricerca su quella tabella
  4. usa l'id per recuperare i record completi (tutti i campi) che corrispondono ai criteri di ricerca
  5. decodificarli e restituirli all'utente

Il punto è che 1 e 4 sono insiemi di dati significativamente più piccoli rispetto al recupero e alla decrittografia di tutti i campi di tutti i record all'inizio.

Spero possa aiutare.


Le tabelle temporanee in testo normale sono relativamente (cioè molto) facili da afferrare e leggere, interrompere il server al momento giusto o semplicemente copiare la temp/cartella e sbattere, i valori di testo in chiaro per l' intera colonna sono lì, questo non è un modo sicuro di operare
Martin,

1

Ciò è possibile con la funzionalità di ricerca completa utilizzando le funzioni di crittografia interna di MYSQL.

Ecco un esempio:

!!! STO UTILIZZANDO MYSQL ENCODE () QUI PER SEMPLICITÀ, MYSQL_ENCODE È ORA CONSIDERATO INSECURO, UTILIZZARE UNA DELLE ALTRE FUNZIONI MYSQL INTERNE 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';

Come suggerisce il commento sopra, NON utilizzare ENCODE (), utilizzare una delle altre funzioni di crittografia che sto usando ENCODE solo in questo esempio per la sua semplicità

Se lo stai facendo all'interno di un'applicazione come php, puoi farlo all'interno del tuo gateway db o delle classi di repository memorizzando un elenco / array delle colonne crittografate di ciascuna tabella all'interno della rispettiva classe 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";
    }
}

Naturalmente questo è un codice molto approssimativo e insicuro che non dovrebbe essere usato nella produzione senza un miglioramento significativo. Ma dovrebbe servire al suo scopo nel dare l'idea generale.


-1

Supponendo che si stia effettuando una ricerca in SQL e rispetto al valore completo e non parziale (ad esempio LIKE 'valore%') ... durante l'acquisizione dei dati di ricerca, crittografarli utilizzando lo stesso algoritmo utilizzato quando i dati sono stati crittografati e cercarli.

Per esempio:

Cosa sarebbe stato:

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

Potrebbe invece apparire come:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'

1
No. La crittografia decente funzionerà con un valore salt, quindi se per esempio hai un salt unico per ogni riga, allora ogni salt righe dovrà essere usato sulla stringa di ricerca, questo diventerà complesso, costoso, abbastanza veloce
Martin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.