diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md new file mode 100644 index 0000000000..dcdd5e419b --- /dev/null +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -0,0 +1,132 @@ +The ```auxiliary/client/sms/send_text``` module allows you to send a malicious text/link to a collection +of phone numbers of the same carrier. + +In order to use this module, you must set up your own SMTP server to deliver messages. Popular +mail services such as Gmail, Yahoo, Live should work fine. + +## Module Options + +**CELLNUMBERS** + +The 10-digit phone number (or numbers) you want to send the text to. If you wish to target against +multiple phone numbers, ideally you want to create the list in a text file (one number per line), +and then load the CELLNUMBERS option like this: + +``` +set CELLNUMBERS file:///tmp/att_phone_numbers.txt +``` + +Remember that these phone numbers must be the same carrier. + +**SMSCARRIER** + +The carrier that the targeted numbers use. See **Supported Carrier Gateways** to learn more about +supported carriers. + +**SMSMESSAGE** + +The text message you want to send. For example, this will send a text with a link to google: + +``` +set SMSMESSAGE "Hi, please go: google.com" +``` + +The link should automatically be parsed on the phone and clickable. + +**SMTPADDRESS** + +The mail server address you wish to use to send the text messages. + +**SMTPPORT** + +The mail server port. By default, this is ```25```. + +**SMTPUSERNAME** + +The username you use to log into the SMTP server. + +**SMTPPASSWORD** + +The password you use to log into the SMTP server. + +**SMTPFROM** + +The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. + +## Supported Carrier Gateways + +The module supports the following carriers: + +* AllTel +* AT&T Wireless +* Boost Mobile +* Cricket Wireless +* Google Fi +* T-Mobile +* Verizon +* Virgin Mobile + +**Note:** During development, we could not find a valid gateway for Sprint, therefore it is currently +not supported. + +## Finding the Carrier for a Phone Number + +Since you need to manually choose the carrier gateway for the phone numbers, you need to figure out +how to identify the carrier of a phone number. There are many services that can do this, such as: + +http://freecarrierlookup.com/ + +**Note:** If the phone is using Google Fi, then it may appear as a different carrier. + +## Gmail SMTP Example + +Gmail is a popular mail server, so we will use this as a demonstration. + +Assuming you are already using two-factor authentication, you need to create an [application password](https://support.google.com/accounts/answer/185833?hl=en). + +After creating the application password, configure auxiliary/client/sms/send_text this way: + +* ```set cellnumbers [PHONE NUMBER]``` +* ```set smscarrier [CHOOSE A SUPPORTED CARRIER]``` +* ```set smsmessage "[TEXT MESSAGE]"``` +* ```set smtpaddress smtp.gmail.com``` +* ```set smtpport 587``` +* ```set smtpusername [USERNAME FOR GMAIL]``` (you don't need ```@gmail.com``` at the end) +* ```set smtppassword [APPLICATION PASSWORD]``` + +And you should be ready to go. + +## Yahoo SMTP Example + +Yahoo is also a fairly popular mail server (although much slower to deliver comparing to Gmail), +so we will demonstrate as well. + +Before using the module, you must do this to your Yahoo account: + +1. Sign in to Yahoo Mail. +2. [Go to your "Account security" settings.](https://login.yahoo.com/account/security#less-secure-apps) +3. Turn on Allow apps that use less secure sign in. + +After configuring your Yahoo account, configure auxiliary/client/sms/send_text this way: + +* ```set cellnumbers [PHONE NUMBER]``` +* ```set smscarrier [CHOOSE A SUPPORTED CARRIER]``` +* ```set smsmessage "[TEXT MESSAGE]"``` +* ```set smtpaddress smtp.mail.yahoo.com``` +* ```set smtpport 25``` +* ```set smtpusername [USERNAME FOR YAHOO]@yahoo.com``` +* ```set smtppassword [YAHOO LOGIN PASSWORD]``` + +And you're good to go. + +## Demonstration + +After setting up your mail server and the module, your output should look similar to this: + +``` +msf auxiliary(send_text) > run + +[*] Sending text (16 bytes) to 1 number(s)... +[*] Done. +[*] Auxiliary module execution completed +``` diff --git a/lib/msf/core/auxiliary/mixins.rb b/lib/msf/core/auxiliary/mixins.rb index 46372750ea..ee34547d0c 100644 --- a/lib/msf/core/auxiliary/mixins.rb +++ b/lib/msf/core/auxiliary/mixins.rb @@ -28,3 +28,5 @@ require 'msf/core/auxiliary/iax2' require 'msf/core/auxiliary/ntp' require 'msf/core/auxiliary/pii' require 'msf/core/auxiliary/redis' + +require 'msf/core/auxiliary/sms' diff --git a/lib/msf/core/auxiliary/sms.rb b/lib/msf/core/auxiliary/sms.rb new file mode 100644 index 0000000000..7c15ac319c --- /dev/null +++ b/lib/msf/core/auxiliary/sms.rb @@ -0,0 +1,64 @@ +# -*- coding: binary -*- + +### +# +# The Msf::Auxiliary::Sms mixin allows you to send a text message to +# multiple phones of the same carrier. A valid SMTP server is needed. +# +## + +module Msf + module Auxiliary::Sms + + def initialize(info={}) + super + + register_options( + [ + OptString.new('SMTPFROM', [false, 'The FROM field for SMTP', '']), + OptString.new('SMTPADDRESS', [ true, 'The SMTP server to use to send the text messages']), + OptPort.new('SMTPPORT', [true, 'The SMTP port to use to send the text messages', 25]), + OptString.new('SMTPUSERNAME', [true, 'The SMTP account to use to send the text messages']), + OptString.new('SMTPPASSWORD', [true, 'The SMTP password to use to send the text messages']), + OptEnum.new('SMSCARRIER', [true, 'The targeted SMS service provider', nil,Rex::Proto::Sms::Model::GATEWAYS.keys.collect { |k| k.to_s }]), + OptString.new('CELLNUMBERS', [true, 'The phone numbers to send to']), + OptString.new('SMSMESSAGE', [true, 'The text message to send']) + ], Auxiliary::Sms) + + register_advanced_options( + [ + OptEnum.new('SmtpLoginType', [true, 'The SMTP login type', 'login', ['plain', 'login', 'cram_md5']]), + OptString.new('HeloDdomain', [false, 'The domain to use for HELO', '']) + ], Auxiliary::Sms) + end + + + # Sends a text message to multiple numbers of the same service provider (carrier). + # + # @example This sends a text via Gmail + # smtp = Rex::Proto::Sms::Model::Smtp.new(address: 'smtp.gmail.com', port: 587, username: user, password: pass) + # sms = Rex::Proto::Sms::Client.new(carrier: :verizon, smtp_server: smtp) + # numbers = ['1112223333'] + # sms.send_text_to_phones(numbers, 'Hello from Gmail') + # + # @param phone_numbers [Array] An array of numbers of try (of the same carrier) + # @param message [String] The text to send. + # + # @return [void] + def send_text(phone_numbers, message) + smtp = Rex::Proto::Sms::Model::Smtp.new( + address: datastore['SMTPADDRESS'], + port: datastore['SMTPPORT'], + username: datastore['SMTPUSERNAME'], + password: datastore['SMTPPASSWORD'], + login_type: datastore['SmtpLoginType'].to_sym, + from: datastore['SMTPFROM'] + ) + + carrier = datastore['SMSCARRIER'].to_sym + sms = Rex::Proto::Sms::Client.new(carrier: carrier, smtp_server: smtp) + sms.send_text_to_phones(phone_numbers, message) + end + + end +end diff --git a/lib/rex/proto.rb b/lib/rex/proto.rb index 8696fcd5ea..2f255134aa 100644 --- a/lib/rex/proto.rb +++ b/lib/rex/proto.rb @@ -7,6 +7,7 @@ require 'rex/proto/drda' require 'rex/proto/iax2' require 'rex/proto/kerberos' require 'rex/proto/rmi' +require 'rex/proto/sms' module Rex module Proto diff --git a/lib/rex/proto/sms.rb b/lib/rex/proto/sms.rb new file mode 100644 index 0000000000..bac7a0e9d6 --- /dev/null +++ b/lib/rex/proto/sms.rb @@ -0,0 +1,4 @@ +# -*- coding: binary -*- + +require 'rex/proto/sms/exception' +require 'rex/proto/sms/model' diff --git a/lib/rex/proto/sms/client.rb b/lib/rex/proto/sms/client.rb new file mode 100644 index 0000000000..271dafdec1 --- /dev/null +++ b/lib/rex/proto/sms/client.rb @@ -0,0 +1,81 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Sms + class Client + + # @!attribute carrier + # @return [Symbol] The service provider for the phone numbers. + attr_accessor :carrier + + # @!attribute smtp_server + # @return [Rex::Proto::Sms::Model::Smtp] The Smtp object with the Smtp settings. + attr_accessor :smtp_server + + + # Initializes the Client object. + # + # @param [Hash] opts + # @option opts [Symbol] Service provider name (see Rex::Proto::Sms::Model::GATEWAYS) + # @option opts [Rex::Proto::Sms::Model::Smtp] SMTP object + # + # @return [Rex::Proto::Sms::Client] + def initialize(opts={}) + self.carrier = opts[:carrier] + self.smtp_server = opts[:smtp_server] + + validate_carrier! + end + + + # Sends a text to multiple recipients. + # + # @param phone_numbers [Array] An array of phone numbers. + # @param message [String] The text message to send. + # + # @return [void] + def send_text_to_phones(phone_numbers, message) + carrier = Rex::Proto::Sms::Model::GATEWAYS[self.carrier] + recipients = phone_numbers.collect { |p| "#{p}@#{carrier}" } + address = self.smtp_server.address + port = self.smtp_server.port + username = self.smtp_server.username + password = self.smtp_server.password + helo_domain = self.smtp_server.helo_domain + login_type = self.smtp_server.login_type + from = self.smtp_server.from + + smtp = Net::SMTP.new(address, port) + + begin + smtp.enable_starttls_auto + smtp.start(helo_domain, username, password, login_type) do + recipients.each do |r| + smtp.send_message(message, from, r) + end + end + rescue Net::SMTPAuthenticationError => e + raise Rex::Proto::Sms::Exception, e.message + ensure + smtp.finish if smtp && smtp.started? + end + end + + + private + + + # Validates the carrier parameter. + # + # @raise [Rex::Proto::Sms::Exception] If an invalid service provider is used. + def validate_carrier! + unless Rex::Proto::Sms::Model::GATEWAYS.include?(self.carrier) + raise Rex::Proto::Sms::Exception, 'Invalid carrier.' + end + end + + end + end + end +end diff --git a/lib/rex/proto/sms/exception.rb b/lib/rex/proto/sms/exception.rb new file mode 100644 index 0000000000..241f879f20 --- /dev/null +++ b/lib/rex/proto/sms/exception.rb @@ -0,0 +1,10 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Sms + class Exception < ::RuntimeError + end + end + end +end diff --git a/lib/rex/proto/sms/model.rb b/lib/rex/proto/sms/model.rb new file mode 100644 index 0000000000..c98ecf6dca --- /dev/null +++ b/lib/rex/proto/sms/model.rb @@ -0,0 +1,31 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Sms + module Model + + GATEWAYS = { + :alltel => 'sms.alltelwireless.com', # Alltel + :att => 'txt.att.net', # AT&T Wireless + :boost => 'sms.myboostmobile.com', # Boost Mobile + :cricket => 'sms.mycricket.com', # Cricket Wireless + # Sprint is commented out, because the gateways don't seem to work. + # Gateways tried for Sprint: + # messaging.sprintpcs.com + # pm.sprint.com + #:sprint => 'messaging.sprintpcs.com', # Sprint + :tmobile => 'tmomail.net', # T-Mobile + :verizon => 'vtext.com', # Verizon + :virgin => 'vmobl.com', # Virgin Mobile + :google => 'msg.fi.google.com' # Google Project Fi + } + + end + end + end +end + +require 'net/smtp' +require 'rex/proto/sms/model/smtp' +require 'rex/proto/sms/client' diff --git a/lib/rex/proto/sms/model/smtp.rb b/lib/rex/proto/sms/model/smtp.rb new file mode 100644 index 0000000000..18edc9b4b0 --- /dev/null +++ b/lib/rex/proto/sms/model/smtp.rb @@ -0,0 +1,62 @@ +module Rex + module Proto + module Sms + module Model + class Smtp + + # @!attribute address + # @return [String] SMTP address + attr_accessor :address + + # @!attribute port + # @return [Fixnum] SMTP port + attr_accessor :port + + # @!attribute username + # @return [String] SMTP account/username + attr_accessor :username + + # @!attribute password + # @return [String] SMTP password + attr_accessor :password + + # @!attribute login_type + # @return [Symbol] SMTP login type (:login, :plain, and :cram_md5) + attr_accessor :login_type + + # @!attribute from + # @return [String] Sender + attr_accessor :from + + # @!attribute helo_domain + # @return [String] The domain to use for the HELO SMTP message + attr_accessor :helo_domain + + + # Initializes the SMTP object. + # + # @param [Hash] opts + # @option opts [String] :address + # @option opts [Fixnum] :port + # @option opts [String] :username + # @option opts [String] :password + # @option opts [String] :helo_domain + # @option opts [Symbol] :login_type + # @option opts [String] :from + # + # @return [Rex::Proto::Sms::Model::Smtp] + def initialize(opts={}) + self.address = opts[:address] + self.port = opts[:port] || 25 + self.username = opts[:username] + self.password = opts[:password] + self.helo_domain = opts[:helo_domain] || 'localhost' + self.login_type = opts[:login_type] || :login + self.from = opts[:from] || '' + end + + end + end + end + end +end diff --git a/modules/auxiliary/client/sms/send_text.rb b/modules/auxiliary/client/sms/send_text.rb new file mode 100644 index 0000000000..8bc0382db4 --- /dev/null +++ b/modules/auxiliary/client/sms/send_text.rb @@ -0,0 +1,38 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Sms + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'SMS Client', + 'Description' => %q{ + This module sends a text message to multiple phones of the same carrier. + You can use it to send a malicious link to phones. + + Please note that you do not use this module to send a media file (attachment), + because that is MMS. + }, + 'Author' => [ 'sinn3r' ], + 'License' => MSF_LICENSE + )) + end + + def run + phone_numbers = datastore['CELLNUMBERS'].split + print_status("Sending text (#{datastore['SMSMESSAGE'].length} bytes) to #{phone_numbers.length} number(s)...") + begin + res = send_text(phone_numbers, datastore['SMSMESSAGE']) + print_status("Done.") + rescue Rex::Proto::Sms::Exception => e + print_error(e.message) + end + end + +end diff --git a/spec/lib/rex/proto/sms/client_spec.rb b/spec/lib/rex/proto/sms/client_spec.rb new file mode 100644 index 0000000000..688435497f --- /dev/null +++ b/spec/lib/rex/proto/sms/client_spec.rb @@ -0,0 +1,53 @@ +# -*- coding: binary -*- +require 'spec_helper' +require 'rex/proto/sms/model' + +RSpec.describe Rex::Proto::Sms::Client do + + let(:phone_numbers) { ['1112223333'] } + + let(:message) { 'message' } + + let(:carrier) { :verizon } + + let(:smtp_server) { + Rex::Proto::Sms::Model::Smtp.new( + address: 'example.com', + port: 25, + username: 'username', + password: 'password' + ) + } + + subject do + Rex::Proto::Sms::Client.new( + carrier: carrier, + smtp_server: smtp_server + ) + end + + describe '#initialize' do + it 'sets carrier' do + expect(subject.carrier).to eq(carrier) + end + + it 'sets smtp server' do + expect(subject.smtp_server).to eq(smtp_server) + end + end + + describe '#send_text_to_phones' do + before(:each) do + smtp = Net::SMTP.new(smtp_server.address, smtp_server.port) + allow(smtp).to receive(:start).and_yield + allow(smtp).to receive(:send_message) { |args| @sent_message = args } + allow(Net::SMTP).to receive(:new).and_return(smtp) + end + + it 'sends a text message' do + subject.send_text_to_phones(phone_numbers, message) + expect(@sent_message).to eq(message) + end + end + +end diff --git a/spec/lib/rex/proto/sms/model/smtp_spec.rb b/spec/lib/rex/proto/sms/model/smtp_spec.rb new file mode 100644 index 0000000000..48b7a2b9bb --- /dev/null +++ b/spec/lib/rex/proto/sms/model/smtp_spec.rb @@ -0,0 +1,57 @@ +# -*- coding: binary -*- +require 'spec_helper' +require 'rex/proto/sms/model' + +RSpec.describe Rex::Proto::Sms::Model::Smtp do + + let(:address) { 'example.com' } + let(:port) { 25 } + let(:username) { 'username' } + let(:password) { 'password' } + let(:login_type) { :login } + let(:from) { 'from' } + let(:helo_domain) { 'example.com'} + + subject do + Rex::Proto::Sms::Model::Smtp.new( + address: address, + port: port, + username: username, + password: password, + login_type: login_type, + from: from, + helo_domain: helo_domain + ) + end + + describe '#initialize' do + it 'sets address' do + expect(subject.address).to eq(address) + end + + it 'sets port' do + expect(subject.port).to eq(port) + end + + it 'sets username' do + expect(subject.username).to eq(username) + end + + it 'sets password' do + expect(subject.password).to eq(password) + end + + it 'sets login_type' do + expect(subject.login_type).to eq(login_type) + end + + it 'sets from' do + expect(subject.from).to eq(from) + end + + it 'sets helo domain' do + expect(subject.helo_domain).to eq(helo_domain) + end + end + +end