Skip to content

Commit

Permalink
Merge dev into master for v0.2.1 final
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroSteiner committed Jul 14, 2015
2 parents 93643c9 + de2fcec commit ee688db
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 7 deletions.
67 changes: 67 additions & 0 deletions data/msf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# SMS Plugin
The [SMS](sms) plugin uses King Phisher's [REST API](rest-api-docs) to send SMS
messages when a new [Metasploit](metasploit) session is received. King Phisher's
REST API is accessible externally which allows running the SMS plugin within
Metasploit, on a system other than the King Phisher server. The system running
Metasploit only needs to be able to make a HTTP GET request to the King Phisher
server.

## King Phisher Configuration
Edit King Phisher's `server_config.yml` file, under the `rest_api` set the
`enabled` value to `true`.

Change the `token` value from `null` to a secret string that will be used to
access the King Phisher server's REST API remotely. Running this one-liner in
Linux will return a randomly generated 32 character string which can be used.

```cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1```

Save the server configuration file and restart the King Phisher server.

## Metasploit Configuration and Usage
Add the [sms.rb](sms) file to your Metasploit `~/.msf4/plugins` directory.

If this is the first time using the SMS plugin, you will need to set four values
which will be saved in `~/.msf4/sms.yaml`. On future use, these settings will
automatically be loaded and do not need to be set again. Additionally you can
see descriptions of the SMS plugin commands by running `help` in msfconsole.

* Start Metasploit and load the SMS plugin.

`load sms`

* Set the domain name of your King Phisher server.

`sms_set_server king-phisher.com`

* Set the King Phisher server's REST API token.

`sms_set_token 0123456789abcdefABCDEF`

* Set the cellphone number where you would like to receive SMS messages.

`sms_set_number 0123456789`

* Set your cell phone carrier. Currently King Phisher supports AT&T, Boost, Sprint, T-Mobile, Verizon, Virgin Mobile.

`sms_set_carrier Boost`

* Before saving, review your plugin settings.

`sms_show_params`

* If everything looks good, save your settings.

`sms_save`

* Start the SMS plugin, which will wait for incoming sessions.

`sms_start`

* When finished, stop the SMS plugin.

`sms_stop`

[metasploit]: https://github.com/rapid7/metasploit-framework
[rest-api-docs]: https://king-phisher.readthedocs.org/en/latest/server_api/rest_api.html?highlight=sms#get--_-api-sms-send
[sms]: ./sms.rb
196 changes: 196 additions & 0 deletions data/msf/sms.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Copyright (c) 2015, Brandan [coldfusion]
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of the nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


require 'uri'

module Msf
class Plugin::SessionSMS < Msf::Plugin
include Msf::SessionEvent

CARRIERS = ['AT&T', 'Boost', 'Sprint', 'T-Mobile', 'Verizon', 'Virgin Mobile']

def initialize(framework, opts)
super
add_console_dispatcher(SMSCommandDispatcher)
end

def cleanup
self.framework.events.remove_session_subscriber(@inst)
remove_console_dispatcher('sms')
end

def name
"sms"
end

def desc
"Sends a SMS message when recieving a new session through the use of the King Phisher's REST API."
end

def sms_yaml
"#{Msf::Config.get_config_root}/sms.yaml"
end

class SMSCommandDispatcher < Plugin::SessionSMS
include Msf::Ui::Console::CommandDispatcher

@king_phisher_server = nil
@king_phisher_token = nil
@sms_number = nil
@sms_carrier = nil

def on_session_open(session)
print_status('Session received, sending SMS...')
begin
http_client = Rex::Proto::Http::Client.new("#{@king_phisher_server}")
http_client.connect
request = http_client.request_cgi({
'uri' => '/_/api/sms/send',
'query' => "token=#{@king_phisher_token}&message=Shells+On+Deck!!+Session:+#{session.sid}&phone_number=#{@sms_number}&carrier=#{@sms_carrier}"
})
response = http_client.send_recv(request)
rescue Exception => e
print_error('Exception occured, you done goofed!')
ensure
http_client.close
end
end

def name
"sms"
end

def read_settings
return false unless File.exist?(sms_yaml)

ldconfig = YAML.load_file(sms_yaml)
@king_phisher_server = ldconfig['king_phisher_server']
@king_phisher_token = ldconfig['king_phisher_token']
@sms_number = ldconfig['sms_number']
@sms_carrier = ldconfig['sms_carrier']
return true
end

def commands
{
'sms_start' => 'Start SMS alerts for new sessions',
'sms_stop' => 'Stop SMS alerts for new sessions',
'sms_save' => "Save SMS settings to #{sms_yaml}",
'sms_set_server' => 'Set domain name of the King Phisher server',
'sms_set_token' => 'Set King Phisher\'s API token',
'sms_set_number' => 'Set number to send SMS alerts to on new session',
'sms_set_carrier' => 'Set carrier for sending SMS messages',
'sms_show_params' => 'Shows currently set or saved parameters'
}
end

def cmd_sms_start
unless read_settings
print_error('Could not read SMS settings!')
return
end

self.framework.events.add_session_subscriber(self)
print_good('Starting SMS plugin, monitoring sessions...')
end

def cmd_sms_stop
print_good('Stopping SMS alerting!')
self.framework.events.remove_session_subscriber(self)
end

def cmd_sms_save
unless @king_phisher_server && @king_phisher_token && @sms_number && @sms_carrier
print_error('You have not provided all the parameters!')
return
end

config = {
'king_phisher_server' => @king_phisher_server,
'king_phisher_token' => @king_phisher_token,
'sms_number' => @sms_number,
'sms_carrier' => @sms_carrier
}
File.open(sms_yaml, 'w') do |out|
YAML.dump(config, out)
end
print_good("All parameters saved to #{sms_yaml}")
end

def cmd_sms_set_server(*args)
if args.length > 0
print_status("Setting the King Phisher server to #{args[0]}")
@king_phisher_server = args[0]
else
print_error('Please provide the domain name of your King Phisher server!')
end
end

def cmd_sms_set_token(*args)
if args.length > 0
print_status("Setting King Phisher's REST API token to #{args[0]}")
@king_phisher_token = args[0]
else
print_error('Please provide the REST API token of your King Phisher server!')
end
end

def cmd_sms_set_number(*args)
if args[0].length == 10
print_status("Setting SMS number to #{args[0]}")
@sms_number = args[0]
else
print_error('Please provide a valid SMS number!')
end
end

def cmd_sms_set_carrier(*args)
if args.length > 0 && CARRIERS.include?(args[0])
print_status("Setting SMS carrier to #{args[0]}")
@sms_carrier = args[0]
else
print_error("Please provide a valid SMS carrier (#{CARRIERS.join(', ')})!")
end
end

def cmd_sms_show_params
unless read_settings
print_error("Could not read settings from #{sms_yaml}!")
return
end

print_status('Parameters:')
print_good(" King Phisher Server: #{@king_phisher_server}")
print_good(" King Phisher Token: #{@king_phisher_token}")
print_good(" SMS Number: #{@sms_number}")
print_good(" SMS Carrier: #{@sms_carrier}")
end
end
end
end
4 changes: 3 additions & 1 deletion docs/source/change_log.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ Version 0.2.x
Version 0.2.1
^^^^^^^^^^^^^

*In Progress*
Released :release:`0.2.1` on July 14th, 2015

* Added syntax highlighting to the message edit tab
* Technical documentation improvements, including documenting the REST API
* Support reloading message templates when they change from an external editor
* Support for pulling the client IP from a cookie set by an upstream proxy
* Support for embedding training videos from YouTube
* Added a Metasploit plugin for using the REST API to send SMS messages
* Support for exporting visit information to GeoJSON

Version 0.2.0
^^^^^^^^^^^^^
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ the `GitHub homepage`_.
server_api/index.rst
environment_vars.rst
change_log.rst
release_steps.rst

Indices and tables
==================
Expand Down
7 changes: 7 additions & 0 deletions docs/source/king_phisher/errors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ Exceptions
----------

.. autoexception:: king_phisher.errors.KingPhisherError
:show-inheritance:

.. autoexception:: king_phisher.errors.KingPhisherAbortRequestError
:show-inheritance:
:members:
:special-members: __init__


.. autoexception:: king_phisher.errors.KingPhisherDatabaseError
:show-inheritance:

.. autoexception:: king_phisher.errors.KingPhisherInputValidationError
:show-inheritance:
35 changes: 35 additions & 0 deletions docs/source/release_steps.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Release Steps
=============

This document contains the steps that are followed for each point version
release of King Phisher.

Pre Release Steps
-----------------

#. Test and fix any issues with the Windows MSI build
#. Ensure unit tests pass with Python 2.7 & Python 3.4
#. Remove the version label
#. Create the final Windows build
#. Update the change log

Release Steps
-------------

#. Create a final signed commit on the dev branch
#. Push the dev branch to GitHub and ensure the Travis-CI build passes
#. Merge dev into master and push master to GitHub
#. Create and push a signed tag of the release commit
#. Create a new release on GitHub

#. Upload the final Windows build
#. Insert the changes from the change log

#. Update the Docker build
#. Publicize the release

Post Release Steps
------------------

#. Increment the version number on the dev branch and re-set the version label
#. Update Python packages with pip
6 changes: 5 additions & 1 deletion king_phisher/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ class KingPhisherAbortRequestError(KingPhisherError):
An exception that can be raised which when caught will cause the handler to
immediately stop processing the current request.
"""
pass
def __init__(self, response_sent=False):
"""
:param bool response_sent: Whether or not a response has already been sent to the client.
"""
self.response_sent = response_sent

class KingPhisherDatabaseError(KingPhisherError):
"""
Expand Down
5 changes: 3 additions & 2 deletions king_phisher/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ def _do_http_method(self, *args, **kwargs):
self.server.throttle_semaphore.acquire()
try:
http_method_handler(*args, **kwargs)
except errors.KingPhisherAbortRequestError:
self.respond_not_found()
except errors.KingPhisherAbortRequestError as error:
if not error.response_sent:
self.respond_not_found()
finally:
self.server.throttle_semaphore.release()
do_GET = _do_http_method
Expand Down
6 changes: 3 additions & 3 deletions king_phisher/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@
version_info = collections.namedtuple('version_info', ['major', 'minor', 'micro'])(0, 2, 1)
"""A tuple representing the version information in the format ('major', 'minor', 'micro')"""

version_label = 'beta'
"""A version lable such as alpha or beta."""
version_label = ''
"""A version label such as alpha or beta."""
version = "{0}.{1}.{2}".format(version_info.major, version_info.minor, version_info.micro)
"""A string representing the full version information."""

# distutils_version is compatible with distutils.version classes
distutils_version = version
"""A string sutiable for being parsed by :py:mod:`distutils.version` classes."""
"""A string suitable for being parsed by :py:mod:`distutils.version` classes."""

if version_label:
version += '-' + version_label
Expand Down

0 comments on commit ee688db

Please sign in to comment.