vendredi 15 août 2008

john the ripper pour déchiffrer les MD5

Voila les commande pour installer john avec le patch sous linux:

> mkdir john
> cd john
> wget http://www.openwall.com/john/f/john-1.7.2.tar.bz2
> bunzip2 john-1.7.2.tar.bz2 > tar -xvf john-1.7.2.tar

> cd john-1.7.2
> wget ftp://ftp.openwall.com/pub/projects/john/contrib/john-1.7-rawmd5-ipb2-4.diff.gz

> gzip -d john-1.7-rawmd5-ipb2-4.diff.gz
> patch -p1 < john-1.7-rawmd5-ipb2-4.diff

> cd src
> make
> make clean linux-x86-sse2
> cd ../run/


A partir de la faite le test:

./john -test

et pour la lancer sur un hash:

./john --format=raw-MD5 t_hash

ou t_hash est le fichier avec le hash sous cette forme:

toto:6f3e68a2a11cb9bf3ef40994a59e6b58

Ps: veillez a avoir bien installer patch avant.

Morsegen fallait y penser

En scrutant les bas fond d' internet je viens de tomber sur un petit Tool assez original coder par luigi Auriemma, il prend simplement un fichier texte en argument et vous donne la conversion en morse vous savez le langage pour envoyer des SOS c' est très amusant.
Par exemple je crée un fichier exemple.txt et j' écrit "hello world" à l' interieur:

napoleon@s4t4n:~/Bureau/morsegen$ echo "hello world" > exemple.txt

je lance le petit tool:

napoleon@s4t4n:~/Bureau/morsegen$ ./morsegen exemple.txt
Morse generator 0.2
by Luigi Auriemma
e-mail: aluigi@autistici.org
web: aluigi.org

.... . ._.. ._.. ___ .__ ___ ._. ._.. _..

En cadeaux je vous met l' alphabet morse pour comparer :


Vous le trouverez les sources ici a morsgen dans le zip ya le .exe pour window(pas essayer) et le morsegen.c a compiler.
gcc -c morsegen.c
gcc -o morsegen morsgen.o
Merci monsieur luigi très amusant !!

Au coeur des fonctions C, dissection d' une fonction

Qu' est-ce qui ce passe avant, pendant, et après l' apel d' une fonction C ? C' est ce que je vais décrire pas à pas.Pour pouvoir suivre cette article il est indispensable de connaitre, le fonctionnement d' une stack (pile), et avoir les bases du language assembleur, syntaxe intel, et AT&T pour les sortie avec GDB, une connaissance aussi du debugger GDB ne sera pas de trop, et biensur une bonne maitrise du langage C, bien que ce soit juste les fonctions qui nous intéressent ici.

Avant de commencer je vais quand même rappeler brièvement quelques points fondamentaux.

La mémoire d' un ordinateur est adressée par mot (word) de 4 octets (32bit) et débute à 0x0000000 et fini à 0xfffffff.
Cette espace de mémoire est divisé en deux zones :

1) L 'espace user de 0x00000000 à 0xbfffffff
2) L 'espace kernel de 0xc0000000 à 0xffffffff

Quand un processus est lancer , il est mappé en mémoire et dispose d' un espace de mémoire indépendant de tout les autres processus.(En gros je passe les détails)
Une fois charger en mémoire le processus est divisé en plusieur section:
.text la ou est placer le code du programme
.data la ou sont placer les données initialisées ou non.
.bss la ou sont placer les données globales non initialisées

En plus il y a la stack (pile) qui sert de stockage pour y placer des données temporaire, les variables local d' une fonction seront par exemple placer sur la pile.Maintenant essayons de comprendre le fonctionnement de cette stack.
La stack peut être vue comme une jeux de carte, elle grandit vers les adresses basses, pour revenir au jeux de carte c 'est comme si on ajoutais des cartes par dessous, on appelera %ebp la base de la pile donc le sommet de notre jeux de carte, et on appelera toujour %esp le pointeur vers la dernière valeur(carte) qu' on a ajouter.

adresse haute ------ %ebp ( haut du jeux de carte )
------
------
adresse basse ------ <-- %esp ( dernière carte ajouter )

l' opcode push ajoute une carte, et pop retire une carte, ce qu' il faut bien retenir surtout, c' est que cette pile marche selon le modele LIFO "last in first out" c' est à dire que la dernière donnée(carte) ajouter sera toujour le première à sortir.
Enfaite on ne verra pas ces 2 instructions ici,car gdb utilise la syntax AT&T qui est je l' avoue franchement plus chiante a lire que celle d' intel, mais bon, on a rien sans rien donc on apprend les deux et on s' écrase...

Voila c' étais bref mais le but n' est pas de faire un cour sur l' assembleur et la mémoire d' un ordinateur.

Bon pour tout le reste de cette article je me baserais uniquement sur cette exemple de programme C:

#include <stdio.h>

int addition(int parametre1, int parametre2)
{
int res = 0;
res = parametre1 + parametre2;
printf("%d", res);
}

int main()
{
addition(5, 6);
return 0;
}


Donc maintenant on compile et lance avec celui qui va nous permettre d' analyser le programme [ GDB ]:

Afin d' avoir des valeurs qui tombe juste j' ai compiler avec l' option -mpreferred-stack-boundary=2 et -g bien évidement pour le debug.

napoleon@s4t4n:~$ gdb ./exemple
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) disass main
Dump of assembler code for function main:
0x0804839f <main+0>: push %ebp
0x080483a0 <main+1>: mov %esp,%ebp
0x080483a2 <main+3>: sub $0x8,%esp
0x080483a5 <main+6>: movl $0x6,0x4(%esp)
0x080483ad <main+14>: movl $0x5,(%esp)
0x080483b4 <main+21>: call 0x8048374 <addition>
0x080483b9 <main+26>: mov $0x0,%eax
0x080483be <main+31>: leave
0x080483bf <main+32>: ret
End of assembler dump.
(gdb) disass addition
Dump of assembler code for function addition:
0x08048374 <addition+0>: push %ebp
0x08048375 <addition+1>: mov %esp,%ebp
0x08048377 <addition+3>: sub $0xc,%esp
0x0804837a <addition+6>: movl $0x0,-0x4(%ebp)
0x08048381 <addition+13>: mov 0xc(%ebp),%eax
0x08048384 <addition+16>: add 0x8(%ebp),%eax
0x08048387 <addition+19>: mov %eax,-0x4(%ebp)
0x0804838a <addition+22>: mov -0x4(%ebp),%eax
0x0804838d <addition+25>: mov %eax,0x4(%esp)
0x08048391 <addition+29>: movl $0x8048480,(%esp)
0x08048398 <addition+36>: call 0x80482d8 <printf@plt>
0x0804839d <addition+41>: leave
0x0804839e <addition+42>: ret
End of assembler dump.
(gdb)


Commencons par regarder ce qui ce passe en main+6 car c' est ici que débute notre fonction.Enfaite c' est pas le début mais la préparation de la fonction, a ce moment elle n' a pas encore été appelé.
movl $0x6,0x4(%esp)
Cette instruction peut être traduite par : Ajoute la valeur 0x6 (6 en décimal) a +4 de l' adresse pointé par %esp.En syntaxe Intel on pourrais faire push dword 0x6
Et oui ! %esp contient une adresse.
Et cette valeur 6 est bien le deuxième argument de notre fonction addition, enfaite il empile les valeurs en sens inverse ce qui ce vérifie encore en main+14 movl $0x5,(%esp) ou il empile le premier argument.

En main+21 on retrouve un call:
call 0x8048374 <addition>
call est un saut inconditionnel c' est à dire que lorsque qu' il arrive ici il saute sans aucune condition a l' adresse 0x8048374 qui est bien l' adresse de notre fonction addition:
0x08048374 <addition+0>: push %ebp
Pendant cette apel il va ce passer une opération implicite, il va sauvegarder l' adresse de retour de la fonction, donc %eip, puisque je rapel que %eip pointe toujour sur l' adresse de la prochaine instruction à executer.

Une fois nos argument, et l' adresse de retour sauvegarder il va ce passer ce qu' on apel le prologue de la fonction:
0x08048374 <addition+0>: push %ebp
0x08048375 <addition+1>: mov %esp,%ebp

En addition+0 il prepare le nouvel environnement pour la fonction addition,il sauvegarde %ebp sur la pile, puis en addition+1 il met %esp dans %ebp donc a ce moment la %ebp = %esp

Après il va reserver de la place pour les variables locales de la fonction.Il décremente %esp de 12(0xc), en gros il soustrait 12 a %esp:
sub $0xc,%esp
Pourquoi 12 ? Un peu de calcul, nous avons 3 variables de type (int) qui sont des entiers, un entier en général prend 4 octets, donc 3 x 4 = 12 (0xc), par contre si on aurais un char, donc 1 octets il aurais quand même reserver 0x4 puisque il réserve que des multiples de 4, si on on aurais un chaine de 6 octets il aurais réserver 0x8 (a ne pas oublier).

Ensuite passons en addition+13 et addition+14
mov 0xc(%ebp),%eax
add 0x8(%ebp),%eax
Il place la valeur qui est en %ebp+12 dans %eax, puis en addition+16 il additione la valeur qui est placer en %ebp+8 avec la valeur de %eax.

Regardond de plus près ce que contient %ebp+12, %ebp+8 à ce moment la:


(gdb) b addition
Breakpoint 1 at 0x804837a: file exemple.c, line 5.
(gdb) r
Starting program: /home/napoleon/exemple

Breakpoint 1, addition (parametre1=5, parametre2=6) at exemple.c:5
5 int res = 0;
(gdb) x/bc $ebp+12
0xbf8535d4: 6 '\006'
(gdb) x/bc $ebp+8
0xbf8535d0: 5 '\005'
(gdb)


La tout devient plus clair !!
mov 0xc(%ebp),%eax place moi la valeur 0x6(6 en déacimal) dans %eax.
add 0x8(%ebp),%eax Additionne moi la valeur placer dans %ebp+8 qui est donc 0x5 (5 en décimal) avec %eax.
ce qui donne bien l' addition qu' on lui a demander de faire 5+6 dans la fonction.

Vérifions maintenant ce que contient %eax à la ligne 7:

Breakpoint 2 at 0x804838a: file exemple.c, line 7.
(gdb) c
Continuing.

Breakpoint 2, addition (parametre1=5, parametre2=6) at exemple.c:7
7 printf("%d", res);
(gdb) p $eax
$1 = 11
(gdb)


Il est donc clair que %eax sers a manipuler des données, beaucoup d' opération passe par lui, entre autre ici il contient le résultat de notre opération soit (11).

En dernier il faut remmettre l' état de la pile comme elle était avant l' apel de la fonction, ce qui ce fait avec ces deux instructions:
leave
ret
Enfaite leave est équivalent à:
mov ebp,esp
pop ebp

Donc %ebp et %esp reviennent ou ils étaient avant l' apel de la fonction.
Puis viens le
ret
Qui a pour effet de dépiler %eip qui contient l' adresse de retour. ainsi le programme reprendra son execution la ou il l' avait interrompu.
On verra dans un autre article qu' il est possible de modifier cette adresse de retour afin que le programme saute ou on lui dit de sauter, c' est le principe des buffer overflow et d' ailleur cette article est je pense une bonne mise en jambe pour ça.
Voilà on a vue en détail avant, pendant, et après l' apel d' une fonction.

mercredi 13 août 2008

comprendre les injections SQL

Qu' est ce qu' une injection SQL?
Tout d' abord on va preparer le terrain et voir ce qu' est une requête normal.
Nous allons tout le long de cette article travailler avec cette table de 3 champs ( id, pseudo, password ).

Et voila les enregistrement de cette table:

| 1 | alain | pofigljfh |
| 2 | admin | tupacritu |
| 3 | moderateur | mfgpgfkg |
| 4 | boby | mdgdggfkg |
| 5 | janine | fofofofofo |

Et nous allons imaginer cette situation, ou le programmeur à oublié, de filtrer les entrer de la base de donnée et que l' option magic_quote_gpc est a Off dans le php.ini.

$connexion = mysql_connect('localhost','user','motDePasse');

mysql_select_db('injection');

if(isset($pseudo) AND isset($pass))
{
$req = "SELECT pseudo,password FROM `essai` WHERE pseudo='$pseudo' AND password='$pass'";

$res = mysql_query($req);

while($x = mysql_fetch_array($res))
{
echo $x['pseudo']. ' ' .$x['password'].'
'; } }

Donc le script PHP attend un pseudo et un mot de passe, transmis par le formulaire via la method POST, une fois qu' il a le pseudo et le mot de passe il envoie la requête a la base de donné qui elle cherche si dans la table essai si il ce trouve un pseudo et un mot de passe qui correspond a ce que l' utilisateur à rentrer. si elle trouve une correspondance elle l' affiche sinon elle ne renvoi rien du tout.
Donc si l utilisateur est (alain) et a pour mot de passe (pofigljfh) la requête deviendra (en vert c' est ce que rentre l' utilisateur).

SELECT pseudo,password FROM `essai` WHERE pseudo='alain' AND password='pofigljfh'

Et l utilisateur sera authentifié car il y a bien une correspondance dans la table.
Maintenant en sachant que le script ne filtre pas les caractère spéciaux il est facile de déformer la requête.
Regardons cette exemple (en vert c' est ce que rentre l' utilisateur):


SELECT pseudo,password FROM `essai` WHERE pseudo='alain' OR '1'='1' AND password='chaineAuHazard' OR '1'='1'

Le truc c' est que la condition sera toujour vrai puisque , on demande d afficher les champs ou (1 est égal à 1) donc bête et discipliner le programme renverra tout les enregistrements de la base, avec le pseudo et mot de passe de l' administrateur.Voici quelque autre exemple ou l' egalité est toujours vrai:

WHERE pseudo='alain' OR 'a'='a' AND password='chaineAuHazard' OR 'a'='a'
WHERE pseudo='alain' OR 'a'='a' AND password='bloup' OR 'b' between 'a' AND 'c'

Le dernier exemple est aussi valide et oui car on demande les champs ou b est entre a et c.
Aller pour la forme un dernier, on sais que les commentaires en SQL commencent par un # c' est a dire que tout ce qui ce trouve après sera ignorer.Ici on va imaginer que l on connais juste le pseudo de l administrateur du site.
Mise en pratique:


SELECT pseudo,password FROM `essai` WHERE pseudo='admin'#' AND password='bloup'
Donc ici pas besoin du mot de passe puisque le password est mis en commentaire.Donc voila quelque exemple parmis tant d' autre, mais comment sécurisé tous ca?
Avec la fonction mysql_escape_string() ou mysql_real_escape_string() par exemple.
Donc notre script securisé devient:
SELECT pseudo,password FROM `essai` WHERE pseudo='mysql_escape_string($pseudo)' AND password='mysql_escape_string($pass)'
Je ne vais pas passer en revue tout les types d' injection car chaque cas est différent mais les base sont là.

::: conseil

Je ne peut que vous conseiller de mettre séverement à l' épreuve votre site avant de le publier, il ne faut pas oublier que le but premier d' un hacker est de faire planter votre script afin qu' il génère une erreur, vous allez me dire pourquoi ?
C' est tout simplement pour obtenir des informations sur vos bases,vos tables, les noms des champs, la version de mysql etc ...
Protèger chaque variable quand vous le pouvez avec une fonction adapté, vous avez le choix, mysql et PHP disposent de beaucoup de fonctions pour vérifier les types des donnés, échappé les caractère spéciaux etc ...
Rentrer des caractères dans l' url comme %22 %23 %27 %25 %24 %5E %3B %2C %3A %21 %3C %3E et analyser le comportement du script, il ne doit y avoir aucun message d' erreur qui s' affiche, n' oublier pas qu' il est possible de cacher les messages d' erreur avec un @ placer devant le nom d' une fonction ou d' une instruction.D' autre par ne laisser pas trainer des fichiers inutile.
Faite tout ce qui est possible et imaginable pour faire planter votre script !! et corriger les erreurs.

dimanche 10 août 2008

Le padding de GCC qui énerve ..

Je suis assez enerver de voir que gcc n' en fait qu' a sa tête,a partir de la version 3.x il rajoute un padding a chaque fois, un exemple :

napoleon@s4t4n:~$cat exemple.c
int adi()
{
int a = 5;
}
int main()
{
return 0;
}

napoleon@s4t4n:~$ gcc -c -g exemple.c
napoleon@s4t4n:~$ gcc -o exemple exemple.o
napoleon@s4t4n:~$ gcc -S exemple.c
napoleon@s4t4n:~$ gdb ./exemple
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) disass adi
Dump of assembler code for function adi:
0x08048344 : push %ebp
0x08048345 : mov %esp,%ebp
0x08048347 : sub $0x10,%esp
0x0804834a : movl $0x5,-0x4(%ebp)
0x08048351 : leave
0x08048352 : ret
End of assembler dump.
(gdb)

Comme on le voit a l' adresse 0x08048347 il soustrait 0x10 (16 en decimal) octets a esp, alors qu' il ne devrait en soustraire que 0x4 (4 en decimal) puisque chez moi un int prend 4 octets en mémoire.

Donc après une petite recherche sur google j' ai trouver comment éviter cela, la solution est de compiler avec -mpreferred-stack-boundary=2



napoleon@s4t4n:~$ gcc -c -g -mpreferred-stack-boundary=2 exemple.c
napoleon@s4t4n:~$ gcc -o exemple exemple.o
napoleon@s4t4n:~$ gcc -S exemple.c
napoleon@s4t4n:~$ gdb ./exemple
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) disass adi
Dump of assembler code for function adi:
0x08048344 : push %ebp
0x08048345 : mov %esp,%ebp
0x08048347 : sub $0x4,%esp
0x0804834a : movl $0x5,-0x4(%ebp)
0x08048351 : leave
0x08048352 : ret
End of assembler dump.

Et la miracle il nous a bien reservé les 4 octets normalement ! Que demande le peuple ? hien ??

vendredi 8 août 2008

Obfuscation de code en javascript

Pour la petite hisoire :

Napol3on ce balladait dans le rayon presse du centre commercial Auchan près de chez lui, soudain il tombe sur le dernier numéro du mag haking, un chapitre parle justement de l' obfuscation de code en javascript, après avoir rapidement jetter un coup d' oeil dessus, je me suis dit,tiens je vais me coder un petit truc équivalent en rentrant !....Et voila le resultat :


Technique de chiffrement simple :


<script type="text/javascript">
var i, key;
/* Ici est placer la chaine chiffrer */
var src_enc = 'bmfsu)((*';

key = 1;
src_dec = '';
for(i = 0; i < 9;i++){
as = src_enc.charCodeAt(i) - key;
src_dec = src_dec+String.fromCharCode(as);
}
eval(src_dec);
</script>

Ce script est très simple, on lui donne le script malicieux dans src_enc avec a chaque fois la prochaine lettre dans l alphabet, ce qui donne simplement : alert(''); pour l ' exemple, après on parcourt la chaine avec charCodeAt() qui renvoi le code ascii de chaque caractere de la chaine - 1 et le stock dans 'as', il reste simplement a faire l' inverse avec String.fromCharCode() qui renvoie la valeur du code ascii de chaque caractère, et en dernier avec la fonction eval() on fait executer le code.

Rats : Rough Auditing Tool Sécurity

RATS est un logiciel d' audit de code, a tester :


Explication des options :
# -d : spécifier une base de donnée de vulnérabilité alternative
# -h : affiche l'aide d'utilisation
# -i : rapporte les fonctions qui autorise des entrées externes
# -l : force le langage à auditer
# -r : inclus les références qui ne sont pas des appels de fonctions
# -w <1,2,3> : niveau d'alerte (par défault 2)
# -x : ne charge pas la base de donnée des vulnérabilités par défaul
# -R : n'autorise pas l'analyse récursive des fichiers audités
# --xml : rapport d'audit au format XML
# --html : rapport d'audit au format HTML
# --follow-symlinks : suit les liens symboliques
# --columns : Affiche la colonne dans laquelle RATS a trouver un problème de sécurité
# --context : Affiche la ligne dans laquelle RATS a trouver un problème de sécurité

Exemple:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void copier(char *chaine)
{
char buffer[100];
strcpy(buffer, chaine);
}

int main(int argc,char *argv[])
{
if(argc < 2)
{
fprintf(stderr,"oups! et la chaine de caractere elle est ou ?\n\n");
exit(EXIT_FAILURE);
}
copier(argv[1]);
return 0;
}


Au dessus le programme C vulnérable, dans ce programme j' ai volontairement laisser trainer un buffer de taille fixe de 100 octets, le programme prend en argument une chaine de caractere qui sera transmis a la fonction copier() et placer dans le buffer .ça sens le BOF a 3km ! Bon si il affiche pas d 'alerte c' est qu' il est a mettre dans la corbeille :-)

n4pol3on@debian:~/prog_C$ rats -l c --columns --context --html vuln.c

RATS results.

Issue: fixed size global buffer

Extra care should be taken to ensure that character arrays that are
allocated on the stack are used safely. They are prime targets for
buffer overflow attacks. <------ Bien vue l amis rats !
File: vuln.c Line:7 char buffer[100]; <------- Le buffer que je parlais


Issue: strcpy <-------- La fonction strcpy()
Severity: High
Check to be sure that argument 2 passed to this function call will no copy more data than can be handled, resulting in a buffer overflow. <--------- Bien vue l' araignée
File: vuln.c Line:8 strcpy(buffer, chaine); <--------- aie aie aie !!!


Inputs detected at the following points
Total lines analyzed: 38
Total time 0.032423 seconds
1172 lines per second


Voila un exemple affreusement exagerer mais c ' est simplement histoire de montrer son utilisation, qui est extremement simple, ceci dit il vaut mieu jetter quand même un coup d' oeil soit même au code ..