AppSec|Formation Développement Sécurisé
← Retour aux cas
04
A04:2025

Cryptographic Failures

Java 8 · Servlet · JSP

Mots de passe hashés en MD5 sans sel. IBAN stockés en clair. Clés de chiffrement codées en dur.

A04:2025 - Cryptographic Failures

ansible-playbook -i inventory.ini playbook.yml --tags switch -e project=04
ansible-playbook -i inventory.ini playbook.yml --tags switch -e project=04 -e variant=secure

Référence OWASP

TODO

démos vidéo

pas de démo pour ce projet

Vue d'ensemble

Ce module illustre les defaillances cryptographiques (anciennement "Sensitive Data Exposure"), categorie A04 du classement OWASP Top 10 2025.

L'application simule un portail assure qui permet la connexion et l'affichage du profil (incluant les coordonnees bancaires IBAN).

Note : La vulnérabilité liée au cookie de session sans flag HttpOnly a été extraite dans le module 12-a02-a05-2025, qui lui est entièrement dédié (A02:2025 + A05:2025).


Les 2 vulnerabilites demonstrees

Vulnerabilite 1 : Hachage MD5 sans sel pour les mots de passe

Code vulnerable (vulnerable/) :

// AuthService.java - vulnerable
public String hashPassword(String password) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] hash = md.digest(password.getBytes(StandardCharsets.UTF_8));
        return DatatypeConverter.printHexBinary(hash).toLowerCase();
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}

Problemes :

  • MD5 est un algorithme de hachage rapide, pas concu pour les mots de passe
  • Absence de sel : deux utilisateurs avec le meme mot de passe ont le meme hash
  • Vulnerable aux attaques par rainbow table et dictionnaire
  • MD5 est considere comme cryptographiquement casse depuis 2004

Base de donnees vulnerable :

jdupont  | 7c6a180b36896a65c4c80d592e87e3be  (= MD5("password1"))
mmartin  | [hash MD5 de Assur@nce2024!]
pdurand  | 7c6a180b36896a65c4c80d592e87e3be  (= meme hash que jdupont !)

Vulnerabilite 2 : IBAN stocke en clair dans la base de donnees

Code vulnerable :

// DatabaseInit.java - vulnerable
pstmt.setString(5, "FR7612345678901234567890123"); // IBAN en clair !
// profil.jsp - vulnerable
<p>IBAN : ${assure.iban}</p>  <!-- Affiche directement depuis la BDD -->

Problemes :

  • Une compromission de la base de donnees expose directement toutes les coordonnees bancaires
  • Violation du RGPD (donnees financieres = donnees sensibles)
  • Pas de protection en cas de dump SQL ou acces non autorise a la BDD

Exploitation etape par etape

Exploit 1 : Cassage MD5 par rainbow table

Prerequis : Acces a la table assures (dump BDD, injection SQL, etc.)

  1. Recuperer les hashes MD5 de la BDD :

    SELECT login, password_hash FROM assures;
    -- Resultat :
    -- jdupont | 7c6a180b36896a65c4c80d592e87e3be
    -- pdurand | 7c6a180b36896a65c4c80d592e87e3be
    
  2. Utiliser le script de cassage fourni :

    Linux/Mac :

    chmod +x exploit/crack-md5.sh
    ./exploit/crack-md5.sh 7c6a180b36896a65c4c80d592e87e3be
    # [+] MOT DE PASSE TROUVE !
    #     Hash         : 7c6a180b36896a65c4c80d592e87e3be
    #     Mot de passe : password1
    

    Windows :

    exploit\crack-md5.bat 7c6a180b36896a65c4c80d592e87e3be
    
  3. Constater que jdupont et pdurand ont le meme hash (meme mot de passe), ce qui est visible directement dans la BDD !

  4. Se connecter avec les identifiants recuperes : jdupont / password1

Via la console H2 (accessible sur /h2-console) :

JDBC URL : jdbc:h2:mem:assuriadb
Utilisateur : sa
Mot de passe : (vide)

SELECT login, password_hash, iban FROM assures;

Exploit 2 : Lecture des IBANs en clair

  1. Acceder a la console H2 : https://appsec.cc/h2-console
  2. Se connecter avec jdbc:h2:mem:assuriadb (user: sa, pass: vide)
  3. Executer :
    SELECT login, iban FROM assures;
    
  4. Tous les IBANs sont visibles en clair :
    JDUPONT | FR7612345678901234567890123
    MMARTIN | FR7698765432109876543210987
    PDURAND | FR7611112222333344445555666
    


Les 2 corrections appliquees dans secure/

Correction 1 : BCrypt avec sel pour les mots de passe

// AuthService.java - securise
public String hashPassword(String password) {
    return BCrypt.hashpw(password, BCrypt.gensalt(12));
}

public boolean verifyPassword(String password, String hash) {
    return BCrypt.checkpw(password, hash);
}

Pourquoi BCrypt ?

  • Integre un sel aleatoire automatiquement (elimine les attaques rainbow table)
  • Facteur de cout parametrable (12 = ~300ms de calcul, rend les attaques brute-force tres lentes)
  • Concu specifiquement pour le hachage de mots de passe
  • Chaque hash est unique meme pour des mots de passe identiques

Exemple de hash BCrypt :

$2a$12$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy

Format : $2a$ + cout + $ + sel (22 chars) + hash (31 chars)


Correction 2 : Chiffrement AES/GCM des IBANs

// CryptoService.java - securise
// Algorithme : AES/GCM/NoPadding
// IV : 12 octets aleatoires (SecureRandom)
// Tag GCM : 128 bits
// Cle : 256 bits depuis variable d'environnement ASSURIA_ENCRYPTION_KEY

public String encrypt(String plaintext) throws Exception {
    byte[] iv = new byte[12];
    new SecureRandom().nextBytes(iv);
    // ... chiffrement AES/GCM ...
    // Retourne Base64(IV + ciphertext)
}

Pourquoi AES/GCM ?

  • Chiffrement authentifie : detecte toute modification du ciphertext (integrite)
  • IV aleatoire unique par chiffrement : deux chiffrements du meme texte donnent des resultats differents
  • Cle externe : meme avec un dump BDD, les donnees sont illisibles sans la cle
  • Standard recommande par NIST pour le chiffrement symetrique

Configuration :

# Generer une cle de 32 octets et l'encoder en Base64
export ASSURIA_ENCRYPTION_KEY=$(openssl rand -base64 32)
mvn compile exec:java


Comment lancer les applications

Version vulnerable

cd vulnerable
mvn compile exec:java

Application disponible sur : https://appsec.cc

Console H2 (BDD exposee) : https://appsec.cc/h2-console

  • JDBC URL : jdbc:h2:mem:assuriadb
  • Utilisateur : sa
  • Mot de passe : (laisser vide)

Version securisee

cd secure
# Optionnel : definir une vraie cle de chiffrement
export ASSURIA_ENCRYPTION_KEY=$(openssl rand -base64 32)
# Sur Windows :
# for /f %i in ('powershell -Command "[Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))"') do set ASSURIA_ENCRYPTION_KEY=%i

mvn compile exec:java

Application disponible sur : https://appsec.cc

Note : La console H2 est desactivee dans la version securisee.

Utilisateurs de test

Login Mot de passe IBAN
jdupont password1 FR7612345678901234567890123
mmartin Assur@nce2024! FR7698765432109876543210987
pdurand password1 FR7611112222333344445555666

Lecons de securite cles

1. Ne jamais utiliser MD5/SHA1 pour les mots de passe

Les algorithmes de hachage generiques (MD5, SHA-1, SHA-256) sont trop rapides pour les mots de passe. Utiliser BCrypt, Argon2 ou scrypt.

2. Toujours chiffrer les donnees sensibles au repos

Les donnees personnelles sensibles (IBAN, numero de carte, numero de secu) doivent etre chiffrees en base de donnees. Une compromission de la BDD ne doit pas exposer directement les donnees.

3. Ne pas exposer la console de base de donnees en production

La console H2 (ou pgAdmin, phpMyAdmin, etc.) ne doit jamais etre accessible en production. Elle permet un acces direct et potentiellement dangereux a la BDD.

4. Gerer les cles de chiffrement via des variables d'environnement

Les cles cryptographiques ne doivent jamais etre en dur dans le code source. Utiliser des variables d'environnement, un vault (HashiCorp Vault, AWS KMS), ou un gestionnaire de secrets.

5. Principe de moindre privilege pour les IBANs

En production, afficher les IBANs masques par defaut (FR76 **** **** ****) et ne reveler le numero complet qu'apres une confirmation explicite de l'utilisateur.


Structure du projet

04-cryptographic-failures/
├── README.md                  (ce fichier)
├── exploit/
│   ├── rainbow-table.txt      (hashes MD5 courants)
│   ├── crack-md5.sh           (script de cassage Linux/Mac)
│   └── crack-md5.bat          (script de cassage Windows)
├── vulnerable/                (application Java vulnerable)
│   └── src/main/
│       ├── java/cc/appsec/crypto/
│       │   ├── Main.java
│       │   ├── model/Assure.java
│       │   ├── db/DatabaseInit.java
│       │   ├── service/AuthService.java
│       │   ├── dao/AssureDao.java
│       │   └── servlet/{Login,Profil,Logout}Servlet.java
│       └── webapp/
│           ├── index.jsp
│           └── WEB-INF/
│               ├── web.xml
│               └── jsp/{login,profil}.jsp
└── secure/                    (application Java securisee)
    └── src/main/
        ├── java/cc/appsec/crypto/
        │   ├── Main.java
        │   ├── model/Assure.java
        │   ├── db/DatabaseInit.java
        │   ├── service/{Auth,Crypto}Service.java
        │   ├── dao/AssureDao.java
        │   └── servlet/{Login,Profil,Logout}Servlet.java
        └── webapp/
            ├── index.jsp
            └── WEB-INF/
                ├── web.xml
                └── jsp/{login,profil}.jsp

References