Comment rechercher une base de données MySQL avec des champs cryptés

15

Supposons que je doive crypter certains champs de table d'une base de données MySQL . De plus, je dois rechercher certains de ces champs que j'ai chiffrés.

Comment rechercherait-on ces champs de toute façon?

Le décryptage pas à pas de chaque enregistrement n'est pas une option: supposons que j'ai plusieurs milliers d'enregistrements. Il faudrait trop de temps et d'espace pour déchiffrer chaque enregistrement et vérifier si chaque enregistrement correspond à la recherche.

MISE À JOUR 2012-09-07

Ajouter plus de détails au schéma de la base de données serait OK , car je suis sur le point d'implémenter une nouvelle application. De plus, je dois étendre les applications en cours de production. Mais même pour ces applications, l'ajout de détails supplémentaires serait OK.

MISE À JOUR 2012-09-08

Le cryptage est le noyau de cette question.

Les restrictions d'accès, comme proposé par certaines réponses, s'appliquent déjà - mais ne correspondent pas à l'exigence formelle de chiffrer les données.

Cette exigence formelle n'est pas la norme de sécurité des données de l'industrie des cartes de paiement [PCI].

SteAp
la source

Réponses:

11

De toute évidence, ils ne sont pas destinés à être consultés, donc leur recherche serait problématique.

Une astuce que j'ai utilisée dans le passé consiste à hacher les données chiffrées avant de les chiffrer et à stocker le hachage dans une colonne indexée. Bien sûr, cela ne fonctionne que si vous recherchez la valeur entière; les valeurs partielles n'auront pas le même hachage.

Vous pouvez probablement étendre cela en créant un index de hachage "texte intégral", si vous en avez besoin, mais cela pourrait se compliquer très rapidement.

ADDENDA

Il a été suggéré d'ajouter une note de bas de page à ma réponse par un débat assez long dans le chat sur la vulnérabilité aux attaques par dictionnaire, donc je vais discuter de ce risque de sécurité potentiel pour l'approche ci-dessus.

Attaque par dictionnaire: une attaque par dictionnaire consiste à pré-hacher une liste de valeurs connues et à comparer les hachages à votre colonne hachée dans la base de données. S'ils peuvent trouver une correspondance, il est probable que la valeur connue est en fait ce qui est haché (ce n'est pas certain cependant, car les hachages ne sont pas garantis d'être uniques). Ceci est généralement atténué en hachant la valeur avec un "sel" aléatoire ajouté ou ajouté de manière à ce que le hachage ne corresponde pas au dictionnaire, mais la réponse ci-dessus ne peut pas utiliser de sel car vous perdez la possibilité de recherche.

Cette attaque est dangereuse lorsqu'il s'agit de choses comme les mots de passe: si vous créez un dictionnaire de hachages de mots de passe populaires, vous pouvez ensuite rechercher rapidement dans la table cette valeur de hachage et identifier un utilisateur qui possède un tel mot de passe et extraire efficacement les informations d'identification pour voler l'identité de cet utilisateur .

Il est moins dangereux pour les articles avec un haut degré de cardinalité, comme les SSN, les numéros de carte de crédit, les GUID, etc. (mais il y a différents risques [lire: légaux] associés à leur stockage, donc je ne suis pas enclin à vous conseiller sur leur stockage ).

La raison en est que pour qu'une attaque de dictionnaire fonctionne, vous devez avoir pré-construit un dictionnaire de valeurs possibles et leurs hachages. Vous pourriez, en théorie, créer un dictionnaire de tous les SSN possibles (un milliard de lignes, en supposant que toutes les permutations de formatage sont supprimées; plusieurs dizaines de milliers de milliards d'entrées pour les cartes de crédit) ... mais ce n'est généralement pas le but d'une attaque par dictionnaire, et devient fondamentalement comparable à une attaque par force brute où vous étudiez systématiquement chaque valeur.

Vous pouvez également rechercher un SSN ou un numéro de carte de crédit spécifique , si vous essayez de faire correspondre un SSN à une personne. Encore une fois, ce n'est généralement pas le but d'une attaque par dictionnaire, mais c'est possible, donc si c'est un risque que vous devez éviter, ma réponse n'est pas une bonne solution pour vous.

Alors voilà. Comme pour toutes les données cryptées, elles sont généralement cryptées pour une raison, alors soyez conscient de vos données et de ce contre quoi vous essayez de les protéger.

Jeremy Holovacs
la source
La discussion sur cette réponse a été déplacée vers le chat .
Paul White 9
5

Vous voudrez peut-être jeter un œil à CryptDB . C'est une interface pour MySQL et PostgreSQL qui permet un stockage transparent et une interrogation des données chiffrées. Il fonctionne en chiffrant et en déchiffrant les données lors de leur passage entre l'application et la base de données, réécrivant les requêtes pour fonctionner sur les données chiffrées. et en ajustant dynamiquement le mode de chiffrement de chaque colonne pour exposer uniquement autant d'informations que nécessaire pour les requêtes utilisées par l'application.

Les différentes méthodes de cryptage utilisées par CryptDB incluent:

  • RND , un schéma de cryptage sécurisé entièrement IND-CPA qui ne laisse passer aucune information sur les données (sauf leur présence et, pour les types de longueur variable, la longueur) mais permet uniquement le stockage et la récupération, pas de requêtes.

  • DET , une variante de RND qui est déterministe, de sorte que deux valeurs identiques (dans la même colonne) chiffrent le même texte chiffré. Prend en charge les requêtes d'égalité du formulaire WHERE column = 'constant'.

  • OPE , un schéma de chiffrement préservant l'ordre qui prend en charge les requêtes d'inégalité telles que WHERE column > 'constant'.

  • HOM , un schéma de cryptage partiellement homomorphe (Paillier) qui permet d'ajouter des valeurs cryptées ensemble en multipliant les textes chiffrés. Prend en charge les SUM()requêtes, l'ajout et l'incrémentation.

  • SEARCH , un schéma qui prend en charge les recherches par mot-clé du formulaire WHERE column LIKE '% word %'.

  • JOIN et OPE-JOIN , variantes de DET et OPE qui permettent de comparer les valeurs de différentes colonnes. Prend en charge l'égalité et les jointures de plage respectivement.

La vraie puissance de CryptDB est qu'il adapte dynamiquement la méthode de cryptage de chaque colonne aux requêtes qu'il voit, de sorte que les schémas plus lents et / ou moins sécurisés ne sont utilisés que pour les colonnes qui en ont besoin. Il existe également diverses autres fonctionnalités utiles, telles que l'enchaînement des clés de chiffrement aux mots de passe des utilisateurs.

Si vous êtes intéressé, vous êtes bien avisé de consulter les articles liés sur le site Web de CryptDB, en particulier "CryptDB: Protecting Confidentiality with Encrypted Query Processing" de Popa, Redfield, Zeldovich et Balakrishnan ( SOSP 2011 ). Ces articles décrivent également plus en détail les divers compromis de sécurité et de performances impliqués dans la prise en charge de différents types de requêtes.

Ilmari Karonen
la source
1
It works by encrypting and decrypting data as it passes between the application and the database: Cela peut sûrement causer des problèmes si les données recherchées sont déjà dans la base de données (cryptées) mais évidemment la requête elle-même en train de rechercher dans la base de données est ensuite transmise à la CryptDB (puis cryptée?). Je ne comprends pas comment cette méthode peut être efficace du tout?
Martin
3

Je ne comprends pas pourquoi les réponses actuelles n'ont pas complètement remis en question les exigences, alors je vais demander et laisser comme réponse.

Quelles sont les raisons commerciales? De quelles données avez-vous besoin pour crypter et pourquoi? Si vous recherchez la conformité PCI, je pourrais écrire un essai.

Questions sur votre besoin:

  • Aurez-vous besoin de renvoyer un résultat existant / inexistant ou les données réelles?
  • Avez-vous besoin d'une capacité LIKE '% OMG_SEKRIT%'?
  • Qui ne peut pas voir les données et pourquoi?

La sécurité du SGBDR se fait normalement sur la base des autorisations qui sont appliquées par l'utilisateur / le rôle. Les données sont normalement chiffrées par le SGBDR sur disque, mais pas dans les données en colonnes elles-mêmes, car cela n'a pas vraiment de sens pour une application conçue pour stocker et récupérer efficacement des données.

Restreindre par utilisateur / rôle / api. Chiffrer sur le disque. Si vous stockez des données plus importantes, j'aimerais savoir pourquoi vous utilisez MySQL.

Philᵀᴹ
la source
Surtout, je dois trouver existe / n'existe pas et puis localiser l'enregistrement spécifique. Un support LIKE complet serait bien. Mais je me demande, que tout autre chose que l'appariement des mots sera possible. L'utilisateur autorisé est autorisé à voir les données. L'application déchiffre ces éléments, un utilisateur légitime a le droit de les voir. Les schémas de base d'autorisation ne sont pas une option.
SteAp
Quels sont les critères pour "des données plus importantes?"
arcanine
2

J'examine la question et suis tombé sur votre question. Je penche pour l'approche décrite dans la section 5.4 du document "Techniques pratiques pour les recherches sur les données cryptées" http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

L'essentiel est de créer un index qui contient des mots clés chiffrés qui sont présents dans le document de recherche chiffré. L'astuce consiste également à chiffrer les emplacements dans le document (ou la base de données) où ces mots clés sont présents.

M. Scott Ford
la source
1

Par programme, une solution efficace consiste à

  1. récupérer TOUS les enregistrements pour SEULEMENT le champ que vous recherchez avec l'ID d'enregistrement
  2. les décrypter dans une table temporaire
  3. effectuer la recherche sur cette table
  4. utilisez les identifiants pour récupérer les enregistrements complets (tous les champs) qui correspondent aux critères de recherche
  5. les décrypter et les renvoyer à l'utilisateur

Le fait est que 1 et 4 sont des ensembles de données beaucoup plus petits que la récupération et le décryptage de tous les champs de tous les enregistrements au début.

J'espère que cela pourra aider.

Paul B. Hartzog
la source
Les tables temporaires en texte brut sont relativement (c'est-à-dire très) faciles à saisir et à lire, perturbent le serveur au bon moment ou simplement copient le temp/dossier et bang, les valeurs en texte clair pour toute la colonne sont là, ce n'est pas un moyen sûr de fonctionner
Martin
1

Ceci est possible avec une fonctionnalité de recherche complète en utilisant les fonctions de cryptage interne de MYSQL.

Voici un exemple:

!!! J'UTILISE ENCODE MYSQL () ICI POUR LA SIMPLICITÉ, MYSQL_ENCODE EST MAINTENANT CONSIDÉRÉ COMME SÉCURISÉ, UTILISEZ L'UNE DES AUTRES FONCTIONS MYSQL INTERNES À LA PLACE !!!

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';

Comme le commentaire ci-dessus le suggère, n'utilisez PAS ENCODE (), utilisez l' une des autres fonctions de cryptage J'utilise uniquement ENCODE dans cet exemple en raison de sa simplicité

Si vous le faites dans une application telle que php, vous pouvez le faire dans votre passerelle db ou vos classes de référentiel en stockant une liste / tableau des colonnes chiffrées de chaque table dans sa classe de passerelle respective.

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";
    }
}

Bien sûr, il s'agit d'un code très approximatif et peu sûr qui ne doit pas être utilisé en production sans amélioration significative. Mais il doit servir son objectif en donnant l'idée générale.

Leigh Bicknell
la source
-1

En supposant que vous recherchez dans SQL et par rapport à la valeur totale et non partielle (par exemple LIKE 'value%') ... lors de la capture des données de recherche, chiffrez ces données en utilisant le même algorithme utilisé lorsque les données ont été chiffrées et recherchez-les.

Par exemple:

Ce qui aurait été:

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

Pourrait plutôt ressembler à:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'
WellyBoot
la source
1
Non. Un cryptage décent fonctionnera avec une valeur de sel, donc si, par exemple, vous avez un sel unique pour chaque ligne, alors chaque sel de lignes devra être utilisé dans la chaîne de recherche, cela va devenir complexe et coûteux, assez rapidement
Martin