Metasploit Module: SmarterTools SmarterMail less than build 6985 - .NET Deserialization Remote Code Execution
Type: exploit
Path: modules/exploits/windows/http/smartermail_rce.rb
Platform: win
Disclosure date: 2019-04-17
References: CVE-2019-7214, EDB-49216, URL-https://research.nccgroup.com/2019/04/16/technical-advisory-multiple-vulnerabilities-in-smartermail/
Targets: Windows Command, x86/x64 Windows CmdStager

Description:
This module exploits a vulnerability in the SmarterTools SmarterMail
          software for version numbers <= 16.x or for build numbers < 6985.
          The vulnerable versions and builds expose three .NET remoting endpoints
          on port 17001, namely /Servers, /Mail and /Spool. For example, a
          typical installation of SmarterMail Build 6970 will have the /Servers
          endpoint exposed to the public at tcp://0.0.0.0:17001/Servers, where
          serialized .NET commands can be sent through a TCP socket connection.

          The three endpoints perform deserialization of untrusted data
          (CVE-2019-7214), allowing an attacker to send arbitrary commands
          to be deserialized and executed. This module exploits this vulnerability
          to perform .NET deserialization attacks, allowing remote code execution
          for any unauthenticated user under the context of the SYSTEM account.
          Successful exploitation results in full administrative control of the
          target server under the NT AUTHORITY\SYSTEM account.

          This vulnerability was patched in Build 6985, where the 17001 port is
          no longer publicly accessible, although it can be accessible locally
          at 127.0.0.1:17001. Hence, this would still allow for a privilege
          escalation vector if the server is compromised as a low-privileged user.

Check method (fingerprinting):
print_status('Checking target web server for a response...')
    res = send_request_cgi!({
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path)
    })

    if res
      body = res.body
    else
      return CheckCode::Unknown('Target did not respond to check request.')
    end

    unless res.code == 200 && body.downcase.include?('smartermail')
      return CheckCode::Unknown('Target is not running SmarterMail.')
    end

    print_good('Target is running SmarterMail.')

    print_status('Checking SmarterMail product build...')
    product_build = body.match('stProductBuild.*\s\(')
    build_number = product_build.to_s.scan(/\d+/)[0] if product_build

    if product_build
      print_good("Target is running SmarterMail Build #{build_number}.")
    else
      print_warning('Product build not found. 16.x versions and below do not have a build number.')
    end

    if product_build && Rex::Version.new(build_number) < Rex::Version.new('6985')
      return CheckCode::Appears("Detected vulnerable version: #{build_number}")
    end

    print_status('Checking SmarterMail product version...')
    product_version = body.match('stProductVersion.*')
    version_number = product_version.to_s.split('"')[1] if product_version

    unless product_version
      return CheckCode::Detected('SmarterMail product version cannot be determined.')
    end

    print_good("Target is running SmarterMail Version #{version_number}.")

    if Rex::Version.new(version_number) <= Rex::Ve