Skip to main content

Attaques cryptographiques

Introduction

Après avoir exploré les mécanismes de protection offerts par la cryptographie, il est temps de se pencher sur l'autre côté du miroir : les attaques cryptographiques. Comprendre comment les systèmes cryptographiques peuvent être attaqués est essentiel pour concevoir des systèmes plus sûrs et pour utiliser la cryptographie de manière appropriée.

note

La cryptographie n'est pas une solution miracle qui garantit une sécurité absolue. Tout système cryptographique peut être attaqué, avec plus ou moins de succès. La sécurité d'un système cryptographique dépend de la qualité de l'algorithme, de la longueur des clés, de la mise en œuvre, et de la gestion des clés.

Dans cette section, nous allons découvrir :

  • Les différents types d'attaques cryptographiques (attaque par force brute, attaque à texte clair connu, etc.).
  • Ce qu'est la cryptanalyse.
  • Les facteurs qui influencent la réussite d'une attaque.

Préparez-vous à entrer dans la peau d'un "casseur de codes" ! Mais rassurez-vous, l'objectif est de mieux comprendre les menaces pour mieux s'en protéger.

Types d'attaques

Il existe de nombreux types d'attaques cryptographiques, qui varient en fonction du système ciblé, des informations dont dispose l'attaquant, et des objectifs de l'attaque. Voici quelques exemples, en excluant l'attaque de l'homme du milieu (MitM) que nous avons déjà couverte :

Attaques contre le chiffrement

  • Attaque par force brute :

    • Principe : L'attaquant essaie toutes les clés possibles jusqu'à trouver la bonne (celle qui permet de déchiffrer le message).
    • Efficacité : Dépend de la longueur de la clé. Plus la clé est courte, plus l'attaque est rapide. Une clé de 56 bits (comme pour DES) peut être cassée en quelques heures, voire quelques minutes, avec des ordinateurs modernes. Une clé de 128 bits (comme pour AES) est hors de portée de la force brute avec la technologie actuelle (et future, selon nos connaissances actuelles).
    • Contre-mesures : Utiliser des clés suffisamment longues.
  • Attaque à texte clair connu :

    • Principe : L'attaquant dispose d'une ou plusieurs paires de texte clair et de texte chiffré correspondant (obtenues par espionnage, par exemple). Il essaie de trouver la clé (ou des informations sur la clé) à partir de ces paires.
    • Efficacité : Dépend de l'algorithme de chiffrement. Certains algorithmes sont plus vulnérables que d'autres à ce type d'attaque.
    • Exemple : Pendant la Seconde Guerre mondiale, les cryptanalystes alliés utilisaient des attaques à texte clair connu pour casser les codes générés par la machine Enigma. Ils exploitaient des messages dont ils connaissaient (ou devinaient) une partie du contenu (par exemple, les bulletins météorologiques allemands).
  • Attaque à texte clair choisi :

    • Principe : L'attaquant a la possibilité de choisir des textes clairs et d'obtenir les textes chiffrés correspondants (par exemple, s'il a un accès temporaire au système de chiffrement). Il essaie de trouver la clé (ou des informations sur la clé) à partir de ces paires.
    • Efficacité : Plus puissante que l'attaque à texte clair connu, car l'attaquant peut choisir des textes clairs spécialement conçus pour faciliter l'analyse.
    • Exemple d'attaques à texte clair choisi:
      • Attaque par rebond (Related-key attack)
      • Attaque par clé choisie
  • Attaque à texte chiffré seulement :

    • Principe : L'attaquant ne dispose que de textes chiffrés (interceptés, par exemple). Il essaie de déchiffrer les messages ou de trouver la clé.
    • Efficacité : C'est le type d'attaque le plus difficile, mais aussi le plus courant en pratique (car c'est souvent la seule information dont dispose un attaquant).
    • Techniques : Analyse statistique, recherche de motifs, exploitation de faiblesses dans l'algorithme ou dans son implémentation.
  • Attaque par canaux auxiliaires (side-channel attack) :

    • Principe : L'attaquant n'attaque pas directement l'algorithme de chiffrement, mais son implémentation physique. Il exploite des informations "fuites" par le système pendant le chiffrement ou le déchiffrement :
      • Consommation électrique : La consommation électrique d'un processeur varie en fonction des opérations qu'il effectue. En analysant ces variations, un attaquant peut déduire des informations sur la clé ou sur les données traitées.
      • Temps d'exécution : Le temps que met un algorithme pour chiffrer ou déchiffrer peut dépendre de la clé ou des données.
      • Émissions électromagnétiques : Les composants électroniques émettent des ondes électromagnétiques qui peuvent être captées et analysées.
      • Bruit : Dans de rares cas on peut analyser le bruit.
    • Efficacité : Ces attaques peuvent être très puissantes, car elles contournent complètement la sécurité théorique de l'algorithme.
    • Contre-mesures : Implémentations matérielles et logicielles spécifiques pour réduire les fuites d'informations, techniques de masquage, etc.

Attaques contre les fonctions de hachage

  • Attaque par force brute (pré-image) :

    • Principe : Étant donné un haché hh, l'attaquant essaie de trouver une entrée mm telle que hash(m)=h\text{hash}(m) = h.
    • Efficacité : Pour une fonction de hachage idéale de nn bits, la complexité est de 2n2^n opérations. Cela signifie qu'il faut essayer en moyenne 2n2^n entrées différentes avant de trouver une pré-image. Pour SHA-256 (n=256n=256), cette attaque est totalement infaisable avec la technologie actuelle.
  • Recherche de collisions :

    • Principe : L'attaquant essaie de trouver deux entrées différentes m1m_1 et m2m_2 telles que hash(m1)=hash(m2)\text{hash}(m_1) = \text{hash}(m_2).
    • Efficacité : Plus facile que l'attaque par force brute (pré-image) grâce au paradoxe des anniversaires.
  • Attaque anniversaire :

    • Principe : Exploite le paradoxe des anniversaires : dans un groupe de 23 personnes, il y a plus de 50% de chances que deux personnes aient la même date d'anniversaire. De même, pour une fonction de hachage de nn bits, il y a une probabilité élevée de trouver une collision après avoir essayé environ 2n/22^{n/2} entrées.
    • Exemple : Si on prend l'exemple d'un haché de 64 bits, il faudra 2322^{32} opérations en moyenne pour trouver une collision.
    • Efficacité : Permet de trouver des collisions beaucoup plus rapidement qu'avec une attaque par force brute "classique" (qui chercherait une pré-image). Pour une fonction de hachage idéale de nn bits, la complexité d'une attaque par force brute pour trouver une collision est d'environ 2n/22^{n/2} opérations (à comparer à 2n2^n pour une attaque par pré-image). Pour SHA-256, la complexité théorique d'une attaque anniversaire est donc de 21282^{128} opérations, ce qui reste infaisable en pratique, mais beaucoup plus faible que 22562^{256}.

Mots de passe, rainbow tables, et salt

La cryptographie joue un rôle essentiel dans la protection des mots de passe, l'un des mécanismes d'authentification les plus répandus (mais aussi l'un des plus faibles si mal mis en œuvre).

Le problème des mots de passe en clair

Stocker les mots de passe en clair (c'est-à-dire tels quels, sans aucune transformation) dans une base de données est une très mauvaise pratique. En cas de compromission de la base de données (par vol, piratage, fuite, etc.), tous les mots de passe seraient immédiatement exposés, permettant aux attaquants de se connecter aux comptes des utilisateurs.

Ne jamais stocker les mots de passe en clair !

C'est une règle fondamentale de sécurité.

Hachage des mots de passe

La solution standard est de stocker non pas les mots de passe eux-mêmes, mais leur haché.

  • Principe :

    1. Lorsqu'un utilisateur crée un compte (ou modifie son mot de passe), le système calcule le haché de son mot de passe en utilisant une fonction de hachage cryptographique (par exemple, SHA-256).
    2. Seul le haché est stocké dans la base de données. Le mot de passe en clair n'est jamais stocké.
    3. Lorsqu'un utilisateur se connecte, le système calcule le haché du mot de passe qu'il a saisi et le compare au haché stocké dans la base de données. Si les hachés correspondent, l'utilisateur est authentifié.
  • Avantages :

    • Si la base de données est compromise, les mots de passe ne sont pas directement lisibles (car les fonctions de hachage sont à sens unique : il est impossible de retrouver le mot de passe à partir du haché).
    • Le système n'a jamais besoin de stocker ou de manipuler les mots de passe en clair.

Attaques par dictionnaire

Même avec le hachage, les mots de passe restent vulnérables à certaines attaques, en particulier si les utilisateurs choisissent des mots de passe faibles (courts, prévisibles, présents dans des dictionnaires de mots de passe courants).

  • Principe :
    1. L'attaquant dispose d'un dictionnaire de mots de passe courants (par exemple, "password", "123456", "azerty", etc.) ou de mots de passe provenant de fuites de données antérieures.
    2. L'attaquant calcule le haché de chaque mot de passe du dictionnaire avec la même fonction de hachage que celle utilisée par le système ciblé.
    3. L'attaquant compare les hachés obtenus avec les hachés des mots de passe présents dans la base de données compromise. S'il trouve une correspondance, il a trouvé le mot de passe en clair.

Rainbow tables (tables arc-en-ciel)

Les rainbow tables sont une optimisation des attaques par dictionnaire. Elles permettent de gagner du temps de calcul au prix d'un espace de stockage important.

  • Principe :

    1. Précalcul : Au lieu de calculer les hachés à la volée lors de l'attaque, l'attaquant précalcule les hachés d'un grand nombre de mots de passe possibles et les stocke dans une table (la "rainbow table").
    2. Structure de la table : La table est organisée de manière astucieuse pour optimiser la recherche et réduire l'espace de stockage (utilisation de chaînes de hachage et de fonctions de réduction).
    3. Attaque : Lorsque l'attaquant veut trouver le mot de passe correspondant à un haché donné, il effectue une recherche dans la rainbow table. Cette recherche est beaucoup plus rapide qu'un calcul de haché à la volée.
  • Efficacité : Les rainbow tables peuvent être très efficaces contre les mots de passe faibles et les fonctions de hachage rapides (comme MD5 ou SHA-1). Elles le sont moins contre les fonctions de hachage lentes (comme bcrypt, scrypt, Argon2) et les mots de passe longs et complexes.

Salage (salting)

Le salage (salting) est une technique essentielle pour renforcer la sécurité des mots de passe hachés et contrer les attaques par dictionnaire et par rainbow tables.

  • Principe :

    1. Lorsqu'un utilisateur crée un compte (ou modifie son mot de passe), le système génère une chaîne de caractères aléatoire, appelée le sel (salt).
    2. Le sel est concaténé au mot de passe. L'ordre (sel + mot de passe, ou mot de passe + sel) n'a pas d'importance tant qu'il est constant. On peut aussi utiliser une fonction plus complexe qu'une simple concaténation (par exemple, une fonction HMAC).
    3. Le haché de la combinaison (mot de passe + sel) est calculé et stocké dans la base de données, ainsi que le sel lui-même (en clair). On stocke donc généralement une paire (sel, haché) pour chaque utilisateur.
    4. Lors de l'authentification, le système récupère le sel stocké pour cet utilisateur, le concatène au mot de passe saisi par l'utilisateur, calcule le haché de l'ensemble, et compare le résultat au haché stocké.
  • Avantages :

    • Unicité : Même si deux utilisateurs choisissent le même mot de passe, leurs hachés seront différents grâce au sel. Cela empêche les attaques par force brute simultanées sur plusieurs comptes.
    • Protection contre les attaques par dictionnaire précalculé : Les rainbow tables (ou les simples tables de hachés) précalculées ne sont plus utilisables, car elles ne contiennent pas les hachés des mots de passe combinés avec les sels (qui sont uniques pour chaque mot de passe).
    • Ralentissement des attaques par force brute : L'attaquant doit calculer un haché différent pour chaque sel, ce qui ralentit considérablement l'attaque, surtout si la fonction de hachage est lente (comme bcrypt, scrypt ou Argon2).
  • Bonnes pratiques :

    • Le sel doit être suffisamment long (au moins 128 bits, idéalement 256 bits ou plus). Plus le sel est long, plus il est difficile pour un attaquant de précalculer des tables.
    • Le sel doit être généré par un générateur de nombres aléatoires cryptographiquement sûr (CSPRNG).
    • Un sel unique doit être utilisé pour chaque mot de passe. Il ne faut jamais réutiliser le même sel pour plusieurs mots de passe.
  • Exemple (conceptuel) :

    Sans salage :

    Utilisateur 1 :
    Mot de passe : "password"
    Haché (SHA-256) : 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

    Utilisateur 2 :
    Mot de passe : "password"
    Haché (SHA-256) : 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

    Les deux utilisateurs ont le même haché, ce qui révèle qu'ils ont le même mot de passe. Une attaque par dictionnaire ou par rainbow table trouverait immédiatement le mot de passe "password".

    Avec salage :

    Utilisateur 1 :
    Mot de passe : "password"
    Sel : "a1b2c3d4e5f6" (aléatoire)
    Haché (SHA-256("a1b2c3d4e5f6" + "password")) : 82633c7439... (différent du haché sans sel)

    Utilisateur 2 :
    Mot de passe : "password"
    Sel : "f6e5d4c3b2a1" (aléatoire, différent du sel de l'utilisateur 1)
    Haché (SHA-256("f6e5d4c3b2a1" + "password")) : 39a77b215c... (différent du haché sans sel et du haché de l'utilisateur 1)

    Même si les deux utilisateurs ont le même mot de passe, leurs hachés sont différents grâce aux sels différents. Une attaque par dictionnaire ou par rainbow table devrait calculer le haché de "password" combiné avec chaque sel possible, ce qui est beaucoup plus coûteux.

  • Exemple (Python avec bcrypt, qui gère automatiquement le sel) :

    import bcrypt

# Hachage d'un mot de passe avec bcrypt (et génération automatique du sel)
password = b"motdepassesupersecret"
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
print(f"Haché (avec sel) : {hashed_password}")

# bcrypt stocke le sel avec le hash. Le format est:
# $2b$[cost]$[salt][hash]

# Vérification d'un mot de passe
entered_password = b"motdepassesupersecret"
if bcrypt.checkpw(entered_password, hashed_password):
print("Mot de passe correct !")
else:
print("Mot de passe incorrect.")
  • Dans cet exemple, bcrypt.gensalt() génère un sel aléatoire. bcrypt.hashpw() combine le sel avec le mot de passe et calcule le haché. Le sel est inclus dans le résultat (dans le haché lui-même). bcrypt.checkpw() extrait le sel du haché stocké, le combine avec le mot de passe saisi, calcule le haché et compare. Vous n'avez pas besoin de gérer le sel manuellement, bcrypt le fait pour vous.

  • Exemple Python:

import os
import hashlib

def hash_password(password):
"""Hachage d'un mot de passe avec un sel (exemple à but pédagogique)."""
salt = os.urandom(32) # Génère un sel aléatoire de 32 octets (256 bits)
salted_password = salt + password.encode('utf-8') # Concatène le sel et le mot de passe
hashed_password = hashlib.sha256(salted_password).hexdigest()
return (salt, hashed_password) # Retourne le sel et le haché

def check_password(password, salt, stored_hash):
"""Vérifie un mot de passe par rapport à un sel et un haché stocké."""
salted_password = salt + password.encode('utf-8')
hashed_password = hashlib.sha256(salted_password).hexdigest()
return hashed_password == stored_hash

# Exemple d'utilisation
password = "monmotdepasse"
salt, hashed_password = hash_password(password)
print(f"Sel : {salt.hex()}")
print(f"Haché : {hashed_password}")

# Vérification
if check_password("monmotdepasse", salt, hashed_password):
print("Mot de passe correct !")
else:
print("Mot de passe incorrect.")

if check_password("mauvaismotdepasse", salt, hashed_password):
print("Mot de passe correct !")
else:
print("Mot de passe incorrect.")

  • Dans cet exemple manuel, on génère un sel aléatoire avec os.urandom(), on le concatène au mot de passe, puis on calcule le haché avec SHA-256. On retourne à la fois le sel et le haché. Pour vérifier le mot de passe, on refait le même processus (concaténation du sel et calcul du haché) et on compare les hachés.

  • Important : Cet exemple manuel est à but pédagogique pour illustrer le principe du salage. Il ne faut pas l'utiliser en production. Utilisez toujours des bibliothèques éprouvées comme bcrypt, scrypt ou Argon2 pour la gestion des mots de passe. Elles implémentent le salage et d'autres mécanismes de sécurité de manière correcte et optimisée.

Testez vos connaissances !

La cryptographie garantit-elle une sécurité absolue ?
Quels facteurs influencent la sécurité d'un système cryptographique ? (Plusieurs réponses possibles)
Dans une attaque par force brute contre un chiffrement, que fait l'attaquant ?
L'efficacité d'une attaque par force brute dépend de :
Dans une attaque à texte clair connu, de quoi dispose l'attaquant ?
Quelle est la différence entre une attaque à texte clair connu et une attaque à texte clair choisi ?
Qu'est-ce qu'une attaque par canaux auxiliaires (side-channel attack) ?
Dans une attaque par force brute (pré-image) contre une fonction de hachage, que cherche l'attaquant ?
Qu'est-ce qui rend la recherche de collisions plus facile que l'attaque par pré-image ?
Quelle est la complexité théorique d'une attaque anniversaire réussie contre une fonction de hachage de n bits ?
Pourquoi est-il dangereux de stocker les mots de passe en clair dans une base de données ?
Quelle est la solution standard pour stocker les mots de passe de manière sécurisée ?
Qu'est-ce qu'une attaque par dictionnaire contre des mots de passe hachés ?
Que sont les Rainbow Tables
Qu'est-ce que le salage (salting) des mots de passe ?
Quels sont les avantages du salage des mots de passe ? (Plusieurs réponses possibles)
Quelles sont les bonnes pratiques pour le sel ? (Plusieurs réponses possibles)