Land #8071, Add API to send an MMS message to mobile devices

bug/bundler_fix
bwatters-r7 2017-03-16 11:57:34 -05:00
commit ab75794cd4
No known key found for this signature in database
GPG Key ID: ECC0F0A52E65F268
16 changed files with 741 additions and 3 deletions

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

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

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.
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),
because that is MMS.
Please note that you do not use this module to send a media file (attachment).
In order to send a media file, please use auxiliary/client/mms/send_mms instead.
},
'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE

View File

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

View File

@ -0,0 +1,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