The NoSuchCon challenge was published in September 2014, for the second edition of the NoSuchCon conference. The last step of this challenge consists in exploiting a remote cryptographic service used to store encrypted messages and keys. To solve this step, a timing attack against the CPU cache was used. The access time for certain memory areas is measured regularly.
The time spent reading those memory areas depends on previous hits, this side-channel information can be used to extract data. This talk will explain the technique commonly called "Cache Attack" based on some existing papers, a demonstration will be conducted showing the extraction of the RSA private key.
3. CHALLENGE NOSUCHCON#2 - SEPTEMBRE 2014
Conférence à Paris 19-21 Novembre
Challenge créé par
Objectif : Trouver email + password
2
4. CHALLENGE EN3 ÉTAPES
1. Rétro ingénierie MIPS
Rétro ingénierie rapide et analyse statistique
2. Escape Python sandbox + XXE
Attaque sur AES-128 avec un padding oracle
(vulnérabilité non souhaitée par les créateurs).
Exfiltration de données par XXE
Evasion de la sandbox Pickle modifiée
3. Timing cache attack sur RSA en remote avec overflow
Exploitation d'un buffer overflow
Réalisation d'une attaque par canaux auxiliaires
3
7. DÉCOUVERTE DE L'ARCHIVE : CLIENT PYTHON
securedrop/client/client.py
[...]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(15)
s.connect(('nsc2014.synacktiv.com', 1337))
s.send('%sn%sn%sn'%(PASSWORD, wk, enc.encode('hex')))
r = ''
while 'n' not in r :
r += s.recv(1024)
try :
r = r.strip('n').decode('hex')
print ocb_decrypt(k, r)
except :
print r
6
13. RÉTROINGÉNIERIE SECDROP: LECTURE DUPASSWORD
Mot de passe fixe hardcodé
if ( read(0, &buf, 0x21uLL) != 33 ||
memcmp(&buf, "UBNtYTbYKWBeo12cHr33GHREdZYyOHMZn", 0x21uLL) )
{
write(1, "WRONG PASSWORD!n", 0x10uLL);
SEC_exit(1LL);
}
sub_400FB0(v7);
SEC_exit(0LL);
12
14. RÉTROINGÉNIERIE SECDROP
LECTUREDELA CLEF AES CHIFFRÉEPAR RSA ET DU MESSAGECHIFFRÉPAR AES
Lecture caractère par caractère
Stockage sur la stack
int __fastcall read_input(__int64 a1, __int64 a2)
{
v2 = 0LL;
while ( 1 )
{
result = SEC_fgetc(a1);
if ( result == -1 || result == 'n' )
break;
v3 = (unsigned int)v2;
v2 = (unsigned int)(v2 + 1);
*(_BYTE *)(a2 + v3) = result;
}
*(_BYTE *)(a2 + v2) = 0;
return result;
}
13
15. RÉTROINGÉNIERIE SECDROP: COMMUNICATIONAVEC STPM
Clef AES chiffrée par RSA envoyée au STPM
Avec la commande : 3n2n0nKEYn
Message chiffré AES transmis au STPM
Avec la commande : 2n2nMESSAGEn
14
18. RÉTROINGÉNIERIE STPM
Écoute via xinetd sur le port 2014 (filtré pour l'extérieur)
Sofware Trusted Platform Module ?
Réalise les opérations de chiffrement et de déchiffrement
Stocke des clefs (16 emplacements pour des clefs
symétriques / asymétriques)
Préchargement des clefs depuis le fichier argv[1]
Absent de l'archive fournie
17
19. RÉTROINGÉNIERIE STPM : PARSING DES COMMANDES
Symboles présents dans le binaire :)
switch ( v2 ) {
case '4':
v3 = export_key();
goto LABEL_6;
case '3':
v3 = import_key();
goto LABEL_6;
case '2':
v3 = message_decrypt();
LABEL_6:
if ( v3 )
goto LABEL_7;
continue;
case '1':
print_keys();
[...]
18
20. RÉTROINGÉNIERIE STPM : COMMANDES DISPONIBLES
1. print_keys()
affiche toutes les clefs stockées
2. decrypt(key_id,message)
déchiffre le message avec la clef key_id
3. import_key(key_id,index,ciphered_AES_key)
Reçoit ciphered_AES_key chiffré en RSA avec la clef key_id
Déchiffre et stocke la clef à l'index spécifié
4. export_key(index,key)
Renvoie la clef AES à l’index spécifié chiffrée en RSA avec
la clef key
5. exit()
19
22. BUFFER OVERFLOWDANS SECDROP
Lecture caractère par caractère sur la socket vers le client
Stockage sur la stack
Arrêt de la lecture si retour à la ligne → overflow
int __fastcall read_input(__int64 a1, __int64 a2)
{
v2 = 0LL;
while ( 1 )
{
result = SEC_fgetc(a1);
if ( result == -1 || result == 'n' )
break;
v3 = (unsigned int)v2;
v2 = (unsigned int)(v2 + 1);
*(_BYTE *)(a2 + v3) = result;
}
*(_BYTE *)(a2 + v2) = 0;
return result;
}
21
28. TIMING CACHE ATTACK
Attaque par canaux auxiliaires utilisant le cache des
processeurs x86
Cible les algorithmes cryptographiques
AES
RSA
FLUSH+RELOAD: a High Resolution,
Low Noise, L3 Cache Side-Channel
Attack
source :
https://eprint.iacr.org/2013/448.pdf
27
29. FLUSH+RELOAD : CONDITIONS D'EXPLOITATION
L'attaquant et la cible doivent être sur le même
processeur
Shellcode dans SecDrop sur la même machine que
STPM
Le code du RSA doit être lisible par l'attaquant
Opérations RSA réalisées dans la librairie partagée
28
30. FLUSH+RELOAD : LE CACHE COMME CANALAUXILIAIRE
Core 0
L1 instr L1 data
L2
Core 1
L1 instr L1 data
L2
L3
STPM SecDrop
Main memorylibsec.so
29
31. FLUSH+RELOAD : LE CACHE COMME CANALAUXILIAIRE
Core 0
L1 instr L1 data
L2
Core 1
L1 instr L1 data
L2
L3
STPM SecDrop
Main memorylibsec.so
30
32. FLUSH+RELOAD : LE CACHE COMME CANALAUXILIAIRE
Core 0
L1 instr L1 data
L2
Core 1
L1 instr L1 data
L2
L3
STPM SecDrop
Main memorylibsec.so
31
33. FLUSH+RELOAD : LE CACHE COMME CANALAUXILIAIRE
Core 0
L1 instr L1 data
L2
Core 1
L1 instr L1 data
L2
L3
STPM SecDrop
Main memorylibsec.so
<X cycles CPU>X cycles CPU
31
34. FLUSH+RELOAD : LE CACHE COMME CANALAUXILIAIRE
Core 0
L1 instr L1 data
L2
Core 1
L1 instr L1 data
L2
L3
STPM SecDrop
Main memorylibsec.so
clflush
32
35. FLUSH+RELOAD : ALGORITHME
while True:
a = get_CPU_cycle()
read_memory(address)
b = get_CPU_cycle()
flush_caches(address)
if b-a < threshold:
# the memory zone was accessed by another process
else:
# the memory zone wasn't accessed
33
38. IDENTIFICATIONDES SEUILS
FLUSH+Reload sur une adresse régulièrement utilisée
Récupération du nombre de cycles CPU pour une lecture
CanvasJS.com
Cache
HITS
< 200
Cache
MISS
> 200
34
39. RSA : EXPONENTIATIONMODULAIRE
RSA_decrypt : bigint(ciphertext) ^ d % n
d => exposant privé
n => modulus
Bignum Exp_mod : square et multiply
/* base = n, exp = d, m = int(ciphertext) */
modpow(base, exp, m) {
result = 1;
while (exp > 0) {
if (exp & 1 > 0) {
result = (result * base) % m; #MULTIPLY
}
exp >>= 1;
base = (base * base) % m; #SQUARE
}
return result;
}
35
40. RSA : EXPONENTIATIONMODULAIRE
RSA_decrypt : bigint(ciphertext) ^ d % n
d => exposant privé
n => modulus
Bignum Exp_mod : square et multiply
/* base = n, exp = d, m = int(ciphertext) */
modpow(base, exp, m) {
result = 1;
while (exp > 0) {
if (exp & 1 > 0) {
result = (result * base) % m; #MULTIPLY
}
exp >>= 1;
base = (base * base) % m; #SQUARE
}
return result;
}
35
55. RECONSTRUCTIONDE L'EXPOSANT PRIVÉ
Bits inversés : consommés par l'exponentiation modulaire
par la fin
Plusieurs tentatives : résultats différents
Un résultat se démarque dans 20% des cas, c'est
l'exposant privé
42
56. RAPPEL: MESSAGE DANS L'ARCHIVE
Ligne 1 : Clef AES chiffrée RSA
Ligne 2 : Message chiffré AES
securedrop/archive/messages
$ cat archive/messages
new message:
0C849AFE0A7C11B2F083C32E7FDB0F8AC03198D84D9990B26D6443B1D185A36A235A561
BB99FE897858371311B2AD6DFE75E199667637EDEA7B9C14A158A5F6FFE15A1C14DAD80
8FDC9F846530EDD4FE3E86F4F98571CD45F11190ED531FC940D62C2C2E05F9977223580
8097763157F140FE4A57DB6AD902D9962F12BDFC1547CED3E282604255B2A5331373CAE
E557CC825DD6A03C3D2D7B106E4AD15347BCB5067BDC60376FF1CC133F2C14
9d41dbb8da10b66cdde844f62e9cc4f96c3a88730b7b8307810cf1906935123f97ac9b6
82dd401512d18775bd7bd9b8b40929f5b4a1871ba44c94038793f0aa639b9d71d72d2ac
cfcc95671c77a5c1c32bc813b048f5dcb1f08b59d6a7afb3b34462ac6abb69cb70accb2
4d78389a1777c5244b8063c542cc1f6c6db8d41d32df2e7132e21db8a1cc711c1a97c51
ba29f1d1ac8fa901a902b2a987f0764734f8b8cd2d476200e7ae62a424e2930d8b02940
9d0e5e13d4e11f4b5f5cc1263f41b500b4340b8641465bbc56c64a575f0ee215d02dea3
d75552328cf5742c
43
57. DÉCHIFFREMENT DE LA CLEF AES
# Inversion des bits, conversion en entier de "d"
d = int(d_binary[::-1],2)
# Conversion en entier de la clef chiffré depuis le message chiffré
encrypted_aes_key = int(encrypted,16)
# Operation de déchiffrement RSA
key_value = pow(encrypted_aes_key, d, n)
# Key : conversion depuis un entier
key = '%0x' % (key_value)
# Suppression du padding PKCS1 v1.5
print key[-32:]
44
58. DÉCHIFFREMENT DUMESSAGE
SIMPLEOPÉRATION AES AVECLA CLEF RETROUVÉE
$ python2 decrypt_msg.py
Good job!
Send the secret 3fcba5e1dbb21b86c31c8ae490819ab6 to
82d6e1a04a8ca30082e81ad27dec7cb4@synacktiv.com.
Also, don't forget to send us your solution within 10 days.
Synacktiv team
45
60. HYPERVISEUR AVEC DÉDUPLICATIONDE MÉMOIRE
KVM : Kernel-based Virtual Machine
KSM : Kernel Samepage Merging
Combinaison par défaut sur certaines distributions
dédiées à la virtualisation
47
68. TEST DE LA PRÉSENCE D'UNUTILISATEUR
Chargement du binaire sshd en mémoire (mmap)
Création d'un thread de monitoring
FLUSH+RELOAD sur l'adresse fakepw (offset dans
sshd)
En parallèle : Connexion à la VM avec libssh2
HIT sur fakepw : utilisateur inexistant
MISS sur fakepw : utilisateur existant
55