Cifratura degli indirizzi IP in un database MySQL

12

Vorrei crittografare gli indirizzi IP nel mio database MySQL, con i seguenti vincoli:

  • Non ha bisogno di essere resistente agli aggressori che possono eseguire interrogazioni.
  • Deve essere resistente agli aggressori che hanno accesso ai file sul disco.
  • Deve essere in grado di convalidare un IP contro il modulo crittografato, per verificare se corrisponde.
  • Anche il controllo dei caratteri jolly /24 (ad esempio 10.20.30.* ) sarebbe utile.
  • Non è possibile immettere alcuna forma di chiave o password all'avvio del sistema, poiché questa verrà eseguita su un server in un data center e l'accesso tramite SSH ogni riavvio è un problema di cui posso fare a meno.

Attualmente sto usando connessioni di database separate per dare migliori restrizioni sui privilegi, con una tabella separata per le password. Sto anche usando MySQLi e recensioni di codice semi-automatizzate per garantire che non ci siano buchi di SQL injection.

Con un meccanismo di hash non salato (cioè deterministico), sarebbe facile calcolare tutti gli hash IP possibili. Con un hash salato, questo problema si riduce, ma non è ancora molto meglio se un utente malintenzionato sta solo cercando di rompere un hash IP. Ovviamente, tutto ciò impedisce anche le ricerche con caratteri jolly.

C'è una soluzione a questo?

Aggiornamento:
Dopo qualche riflessione, ho trovato il seguente schema:

  • Webapp ha una chiave pubblica RSA 4096-bit incorporata nell'origine, tengo la chiave privata in un volume TrueCrypt sul mio computer di casa.
  • Quando si inseriscono voci nella tabella dei log, l'IP viene riempito con una stringa casuale e crittografato con la chiave pubblica. Ciò rende impossibile la decrittografia e rende la crittografia non deterministica.
  • La webapp fornisce un'API per esportare i log, a cui è possibile accedere solo tramite SSL da parte degli utenti amministratori autenticati.
  • Scrivo un'applicazione per utilizzare l'API per sfogliare i registri della mia macchina domestica, utilizzando la chiave privata per decrittografare gli indirizzi IP.
  • Quando un indirizzo IP è bannato, l'IP viene memorizzato in chiaro nella tabella dei ban.

Qualche commento o suggerimento?

    
posta Polynomial 20.04.2012 - 18:02
fonte

5 risposte

6

La crittografia della chiave pubblica / privata è lenta. È ideale per scrivere e amp; dimenticalo, ma non è un processo veloce.

Per motivi di velocità, considera questo: usa una chiave simmetrica generata a caso che viene scelta all'avvio del demone ed eventualmente ruotata ogni ora, giornalmente, settimanalmente o mensilmente (a seconda delle tue esigenze di traffico e sicurezza). Lasciare questa chiave solo in memoria e crittografare quella chiave simmetrica a una tabella di database con la chiave pubblica della propria coppia di chiavi. Quindi è possibile recuperare la chiave, ma non è possibile ottenerla da un utente malintenzionato se non scaricando la memoria dei processi. Anche in questo caso, l'utente malintenzionato può utilizzare solo la chiave più recente. Probabilmente vorrai usare qualcosa per collegare le chiavi ai dati o dovrai forzare la tua lista di chiavi contro ogni record. Quella registrazione potrebbe essere semplice come l'ora di inizio / fine se i registri sono timestamp, o numeri di sequenza, o l'inizio di voci crittografate con un campo ID chiave, ecc.

Indipendentemente dal metodo utilizzato, controlla il tuo IP prima di crittarlo. Vedo che da quando hai aggiornato la tua risposta questo è menzionato, ma è sicuramente importante per chiunque faccia riferimento a questo. Ciò impedirà l'indicizzazione, ma impedirà anche eventuali problemi di "incasellamento" e lo stesso IP avrà sempre lo stesso output crittografato.

    
risposta data 20.04.2012 - 20:20
fonte
3

Il tuo schema è una buona soluzione. Ben fatto!

Una possibile ottimizzazione delle prestazioni. Se hai bisogno di un modo per renderlo più efficiente, ci sono modi per migliorare l'efficienza. Ad esempio, eccone uno. L'applicazione può selezionare una chiave simmetrica casuale K , crittografare K sotto la chiave pubblica, quindi crittografare l'indirizzo IP in K e archiviare la crittografia Indirizzo IP e il valore crittografato di K nel database.

Più tardi quando esporti i log, se vuoi vietare un indirizzo IP, dato che hai la chiave privata, puoi recuperare il valore corrispondente di K , quindi decifrare usando K per recuperare l'indirizzo IP e aggiungere quell'indirizzo IP in chiaro all'elenco di ban.

In che modo migliora le prestazioni? Il trucco chiave è che è possibile riutilizzare lo stesso valore di K per molti diversi indirizzi IP. Al momento del lancio, può selezionare K , crittografarlo con la chiave pubblica e memorizzare il valore di K e la crittografia di K . Ora può riutilizzarlo per molte voci di registro. Puoi periodicamente cancellare la cache e creare un nuovo K se lo desideri. (Assicurati solo di memorizzare il valore memorizzato nella cache di K solo in memoria, non nel database.) In questo modo, devi solo eseguire una singola crittografia a chiave pubblica ogni tanto. Ogni volta che vuoi registrare un nuovo indirizzo IP, devi solo eseguire una crittografia simmetrica sotto K , che dovrebbe essere molto efficiente.

Perché l'ottimizzazione potrebbe non essere necessaria. Detto questo, se si sceglie correttamente l'algoritmo di crittografia a chiave pubblica, anche lo schema di base potrebbe già essere molto efficiente. Ad esempio, se utilizzi la crittografia RSA utilizzando esponente pubblico e = 3, la crittografia è molto veloce e lo schema che proponi potrebbe essere abbastanza veloce.

    
risposta data 21.04.2012 - 07:33
fonte
2

La tua descrizione non è completa, perché non dici chi / cosa sta per "convalidare gli indirizzi IP contro il modulo crittografato". Dal tuo aggiornamento, suppongo che tu voglia:

  • per poter registrare gli indirizzi IP in entrata, in modo tale che un utente malintenzionato che ottiene l'accesso completo in lettura sui file del server non sia in grado di ricostruire gli indirizzi IP registrati, ma in modo tale che un utente autorizzato l'amministratore (tu) potrebbe farlo;
  • per mantenere un insieme di indirizzi IP "vietati", possibilmente compresi intervalli, e il server deve essere in grado di abbinare un indirizzo IP a tale insieme.

Dato che tu (comprensibilmente) non vuoi digitare una passphrase o inserire una chiave ogni volta che il server si riavvia, devi presupporre che un utente malintenzionato che ottiene pieno accesso alla lettura sui file completi del server sappia tutto ciò che il server conosce subito dopo un nuovo inizio. In particolare, l'attaccante può quindi simulare il server sulla propria macchina. Poiché un tale server può decidere se un determinato indirizzo IP è bannato o meno, l'utente malintenzionato può facilmente ottenere le stesse informazioni con la sua simulazione (dopo tutto sono solo quattro miliardi di indirizzi IPv4). Corollario: puoi anche mantenere gli indirizzi vietati (intervalli di) in chiaro , poiché non puoi renderlo più sicuro in ogni caso.

Per l'utilizzo della registrazione , la crittografia asimmetrica sembra essere lo strumento giusto. La corretta crittografia asimmetrica include già il padding casuale (per evitare una ricerca esaustiva sui dati stessi - ci sono davvero solo quattro miliardi di indirizzi IPv4). RSA-4096 è un completo overkill, però; 1024 bit sarebbero sufficienti per informazioni di basso valore come gli indirizzi IP (vedere questa risposta per i dettagli). Ancora una volta, RSA-1024 significa che ogni indirizzo IP crittografato utilizzerà 128 byte, e potresti voler ottimizzare un po 'le cose, per risparmiare spazio.

Potresti, ad esempio, fare la crittografia ibrida con Elliptic Curve Diffie-Hellman : a crittografare un indirizzo IPv4, eseguire un ECDH in relazione a una chiave pubblica (lo stesso principio della chiave RSA: solo l'amministratore conserva la chiave privata) e utilizzare il segreto condiviso risultante per crittografare l'indirizzo IPv4. Utilizza Formattazione della crittografia di conservazione per crittografare l'indirizzo IPv4 in quattro byte (ad es. Con il Thorp shuffle o, più semplicemente, con un codice stream inizializzato con il tasto DH). Per "sicurezza a 128 bit", è necessaria una curva ellittica a 256 bit e una chiave pubblica ECDH può quindi essere codificata su 32 byte. Insieme all'indirizzo IP crittografato, sono 36 byte per indirizzo.

Per ridurlo ulteriormente, applica il consiglio di @ D.W.: avvia la procedura ECDH all'avvio del server e converti l'utilizzo della chiave condivisa. Si avrebbe una tabella di chiavi pubbliche ECDH, che cresce lentamente (una nuova voce per riavvio) e ogni indirizzo IP crittografato farebbe semplicemente riferimento alla chiave da utilizzare (un campo a 32 bit sarebbe sufficiente). Si noti, tuttavia, che in questo caso, è necessario fare attenzione a rendere casuale la crittografia simmetrica degli indirizzi IP. Ad esempio, tampona l'indirizzo IP (4 byte) con 12 byte di casuale e crittografa i 16 byte come un blocco con AES . Insieme al riferimento alla chiave pubblica, questo costo inferiore scende a circa 20 byte per IP. Senza randomizzazione, un utente malintenzionato potrebbe dedurre quali indirizzi IP vengono ripetuti attraverso i registri. Poiché questo schema riutilizza la chiave simmetrica, anche la crittografia deve essere eseguita con maggiore attenzione (ad esempio un codice di flusso come RC4 diventerebbe una pessima idea).

Informazioni sulle prestazioni della CPU: come @ D.W. sottolinea, questo è un non-problema. Con ECDH, sei inferiore a 0,1 ms per indirizzo IP. La crittografia RSA sarà persino inferiore a tali costi. Ecco perché mi concentro sulle prestazioni di spazio sopra, non sulla CPU.

    
risposta data 03.09.2012 - 18:59
fonte
1

Bella domanda!

Ci sono 256 ^ 4 possibili indirizzi IPv4. Se usi un algoritmo che non produce collisioni (un ip produce un hash unico), puoi riferirlo al principio Pigeonhole dove hai la stessa quantità o più buche piccioni (hash) dei piccioni (IP). In genere avresti > 256 ^ 4 pigeonholes per archiviare gli indirizzi IP crittografati con un algoritmo hash che non produce collisioni.

Un utente malintenzionato potrebbe facilmente eseguire una ricerca bruteforce sul proprio database per vedere quale hash corrisponde a ciascun indirizzo IP, poiché sarebbe facile trovare un hash one-to-one con l'entropia bassa di 256 ^ 4 possibili indirizzi IP (anche con più iterazioni di algoritmi). Se non è necessario essere in grado di abbinare un IP al database con un'accuratezza del 100%, un approccio potrebbe essere quello di ridurre la quantità di buchi dei piccioni. Ciò introdurrà anche le collisioni hash all'algoritmo scelto.

Quindi, se usi una dimensione hash di 256. 3 (3 byte), ogni indirizzo ip avrà 256 possibili collisioni.

Non hai menzionato la possibilità di false collisioni nella tua lista di vincoli, quindi non so se ti è stato utile.

Un altro approccio da considerare è l'uso della crittografia completa del disco con l'uso del server di autenticazione remoto. Credo che troverai una soluzione utilizzando la crittografia del disco pre-avvio come PBConnex sufficiente se usi server Windows. Al momento non ricordo il nome della soluzione linux, ma so che ce n'è almeno uno.

    
risposta data 20.04.2012 - 18:55
fonte
0

Non una bella domanda !!!!!!!

Sembra che il tuo desiderio di rendere il sistema sicuro stia guidando il design qui piuttosto che bilanciare funzionalità, prestazioni, capacità e sicurezza.

La crittografia dei dati nei database è una lattina di worm. Il modo in cui si cripta dipende da come si intende accedere ai dati. Se si desidera solo trovare corrispondenze esplicite, quindi sicuro, è possibile crittografare all'esterno del database e scrivere i dati crittografati nel database. È inoltre possibile comporre query basate su predicati crittografati. Ma le cose cominciano a diventare disordinate quando si inizia a cercare di trovare un valore in un intervallo: un intervallo nella query o un intervallo nel record del database.

Checking against /24 wildcards (e.g. 10.20.30.*) would be useful too

Ciò implica che si desidera utilizzare intervalli nel proprio database. Descrivere i dati in termini di notazione CIDR significa che non è possibile utilizzare gli indici per trovare i dati (a meno che non si utilizzi una maschera di rete fissa). Il modo corretto per risolvere il problema è utilizzare INET_ATON (from_address) e INETATON (to_address) nel database - ci sono diversi buoni motivi per farlo anche se si desidera memorizzare solo un indirizzo specifico per record nel database. Ma per trovare i record in modo efficiente, devi mappare questi (valori unidimensionali) su uno spazio bidimensionale e usare indicizzazione geospaziale per trovare i record.

Quindi, dove lascia il requisito di crittografia?

Does not need to be resistant to attackers that can execute queries

Must be resistant to attackers that have access to files on disk

... facile, crittografa il filesystem su cui si trova il database.

Any form of key or password cannot be entered on system startup

È molto più difficile

La risposta accettata qui è molto scarsa nei dettagli - e potresti essere in grado di mantenere la chiave in shmop di PHP - ma è necessario popolare i dati all'avvio del server delle applicazioni.

C'è qualche discussione su soluzione potenziale qui al problema di mantenere la crittografia di archiviazione ekys.

    
risposta data 22.02.2018 - 13:19
fonte

Leggi altre domande sui tag