---
title: Attaques crypto
description: "Reconnaître un schéma faible et l'attaquer : XOR, RSA, ECB, padding oracle et JWT."
category: crypto
kind: technique
tags: [rsa, xor, ecb, padding-oracle, jwt]
level: advanced
updated: 2026-10-30
order: 2
aliases: ["cryptography attacks", "rsa attacks"]
---

## Identifier le schéma

```bash
# Taille et fingerprints
openssl x509 -in cert.pem -noout -text
python3 -c "import sys; print(len(open(sys.argv[1],'rb').read()))" cipher.bin

# Entropie (CyberChef : Entropy)
binwalk -E suspicious.bin
```

| Indice | Piste |
| --- | --- |
| Blocs de 8/16 octets répétés | ECB |
| Clé courte / répétée | XOR repeating-key |
| `n` petit ou facteurs proches | RSA faible |
| Message identique + IV réutilisé | CBC IV reuse |
| Erreur de padding différente | Padding oracle |
| JWT `alg:none` / clé publique | JWT confusion |

## XOR

```python
from pwn import xor

cipher = bytes.fromhex('...')
key = b'KEY'
print(xor(cipher, key))

# Clé de 1 octet : tester toutes les valeurs
for k in range(256):
    out = xor(cipher, bytes([k]))
    if b'flag' in out or b'CTF' in out:
        print(k, out)
```

```python
from pwn import xor
from string import printable

def score(data):
    return sum(chr(c) in printable or chr(c) in '\n\t' for c in data)

# Retrouver la clé répétée octet par octet, pour chaque longueur candidate
best = None
for size in range(1, 33):
    key = bytes(
        max(range(256), key=lambda k: score(xor(cipher[i::size], bytes([k]))))
        for i in range(size)
    )
    plain = xor(cipher, key)
    if best is None or score(plain) > best[0]:
        best = (score(plain), key, plain)

print(best[1], best[2])
```

## RSA

```bash
# Factoriser un n faible
python3 -m pip install pycryptodome gmpy2
# RsaCtfTool automatise les attaques classiques
RsaCtfTool --publickey pub.pem --uncipher cipher.bin
```

```python
# n factorisable (petit ou facteurs proches)
from sympy import factorint
factors = factorint(n)
p, q = list(factors)
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
m = pow(c, d, n)

# e = 3 et message petit sans padding
import gmpy2
m, exact = gmpy2.iroot(c, 3)
if exact:
    print(bytes.fromhex(hex(int(m))[2:]))
```

| Attaque | Condition |
| --- | --- |
| Small `n` | Factorisation facile |
| Small `e` | `m^e < n`, racine entière |
| Common modulus | Même `n`, deux exposants |
| Wiener | `d` petit |
| Hastad | Même message, plusieurs `n` |
| Fermat | `p` et `q` proches |

## ECB

```python
# Détecter ECB : blocs identiques
blocks = [cipher[i:i+16] for i in range(0, len(cipher), 16)]
print(len(blocks), len(set(blocks)), 'blocs uniques')

# Byte-at-a-time : envoyer des préfixes choisis
for pad in range(16):
    payload = b'A' * pad
    # comparer les blocs avec un oracle d'encryption
```

> [!TIP]
> Un oracle qui chiffre `prefix + secret` avec AES-ECB permet de retrouver le secret octet par octet. C'est l'attaque ECB byte-at-a-time : fais varier le préfixe pour aligner l'octet inconnu en fin de bloc.

## CBC et padding oracle

```python
# Padding oracle : modifier le bloc précédent pour contrôler le padding
# P_i = D(C_i) XOR C_{i-1}
# Pour obtenir un octet, brute force C_{i-1}[j] jusqu'à un padding valide
```

```bash
# Outils
pip install paddingoracle
# Ou implémentation maison : 256 essais par octet, détecter "invalid padding"
```

## JWT

```bash
# Décoder sans vérifier
cut -d. -f1,2 token | tr '.' '\n' | base64 -d 2>/dev/null

# alg:none
python3 - <<'PY'
import base64, json
enc = lambda d: base64.urlsafe_b64encode(json.dumps(d, separators=(',',':')).encode()).rstrip(b'=').decode()
print(enc({"alg":"none","typ":"JWT"}) + '.' + enc({"sub":"admin","role":"admin"}) + '.')
PY

# HS256 avec clé publique connue
# Récupérer la clé publique, l'utiliser comme secret HMAC
```

```bash
# Crack du secret HS256
hashcat -m 16500 jwt.txt rockyou.txt
```

## PRNG et IV

- Vérifie la réutilisation d'IV en CBC : deux messages avec le même IV révèlent `P1 XOR P2`.
- Un PRNG basé sur le temps (`time()`, `rand()`) se prédit avec une seed proche.
- Les tokens de reset générés avec `random` Python ne sont pas cryptographiques.

## Outils

```bash
# RsaCtfTool
RsaCtfTool --publickey key.pub --attack all

# FeatherDuster
python3 featherduster.py --input cipher.bin

# CyberChef : XOR, RSA, AES, JWT
# hashcat : modes 16500 (JWT), 13100/18200 (Kerberos)
```

> [!WARNING]
> Les attaques crypto sont souvent détectables (nombre de requêtes, timing). Sur un oracle en ligne, limite le bruteforce, mets en cache les résultats et documente la faisabilité plutôt que d'extraire des données réelles.
