When conducting an internal penetration test many will start by attempting to run Responder.py in Analyze mode to observe potential victims trying to resolve hostnames via broadcast-based name resolutions services such as NBNS and LLMNR (see references here).
However, during a recent red teaming engagement the VerSprite team began to observe networks where these protocols are not in use anymore and we recommend disabling them whenever possible as part of hardening the AD environment.
In this scenario, where Windows hosts in the target network are not sending broadcast messages to resolve names and we do not have domain user credentials that allows exploiting Active Directory-Integrated DNS, we can still try a MiTM attack between target Windows machines (located in our network segment) and a DNS server they are using to see what they are looking to resolve and for which of those hostnames the DNS server is responding with a No such name message.
With this MiTM attack we want to avoid interrupting any communication to remain as stealthy as possible. Moreover, after obtaining a number of potentially *interesting unresolved hostnames, it would be great to have the chance to respond with a valid DNS message to make the victims think those invalid hostnames they are looking for points to an attacker machine controlled by us.
*Note: I remarked this as ‘interesting’ because our team observed that certain active threat analysis tools are sending fake broadcast name resolution queries for discovering attackers using the technique exploited by Responder.py.
As an example, certain tools send queries for hostnames that look pretty much as MD5 hashes, which make it easier for us to detect them. While not a bulletproof, it is a good idea to always analyze results first and then thoughtfully choose the hostnames to be poisoned before performing the attack.
When performing this attack, we will basically find two different scenarios:
1. The first scenario is in which the attacker machine, the victim, and the DNS server are all in the same network segment (certainly less common). In this case, you will have to perform a MiTM directly between the victim and the DNS server itself.
2. However, the most typical scenario will be when the attacker machine is in the same network segment of the Windows victims and the DNS server is placed in another network segment, meaning the victims will have to go through the default gateway to reach the DNS server. In this case, you will have to perform a MiTM attack (e.g. by using ARP Poisoning) between the victims and their default gateway.
After researching the web thoroughly, I was unable to find a tool that allows performing this attack in a convenient way. Therefore I had to write my own Python script for this, which I called nagar.py.
Nagar.py is a very simple tool that would listen for DNS queries coming to a specified port (e.g. 53)and will forward them to the specified DNS server (you will usually specify the DNS server used by the victims). Once it obtains the response from the actual DNS server, it will deliver it to the client (i.e. the victim) that originally requested it. The most important thing that Nagar.py does is letting the attacker know which are the unresolved hostnames requested by the victims and allowing her/him to decide whether to poison their answers the next time they are requested by adding a line to a continuously monitored target file.
Again, Nagar.py relays entirely in the capacity of the attacker to perform a MiTM attack that allows her/him to redirect DNS traffic coming from the victim(s) to the port on which Nagar.py is listening.
The following section contains a brief description on how to use Nagar.py along with an ARP poisoning to make it work properly.
SCENARIO 1: The DNS server is in the same network segment as the victim host and the attacker machine.
Running the tool:
Iptables and AR Poisoning:
SCENARIO 2: The DNS server is reachable through the default gateway, that is it is located in another network segment.
Running the tool:
Iptables and ARP Poisoning:
Our scenario is as follows:
For this demo and for simplicity, consider the case where the DNS server is located on the same network segment as the victim. However, as already mentioned, it will not usually be the case as the user segment is not in the same segment as the Domain Controller or DNS servers. In any case, doing the attack is practically the same, and the results will not differ.
Before executing the MiTM attack, let’s run Nagar.py to ensure we are not going to interrupt the communication of the victim to avoid suspicions:
Note: Nagar.py was instructed to use the upstream DNS server 10.5.0.190 and to listen on the port 9053.
As we run our Nagar.py on port 9053, then we have to redirect the victim’s DNS traffic to that port by means of Iptables.
Let’s prepare the rules before executing the ARP Poisoning attack:
Now, it is time to perform the MiTM attack to make the victim think the attacker machine’s MAC address is the one of the DNS servers and send the traffic to it:
Once the victim is being ARP-poisoned, let’s use it to attempt resolving an IP address of a valid hostname (e.g. dc1) and an invalid or unknown one (e.g. nosuchname):
In the figure above, it can be observed that the victim received a valid answer for the first DNS query (i.e. dc1.bransh.com points to 10.5.0.190 and 192.168.1.190) and a negative answer for the second query (i.e. nosuchname does not exist on the actual DNS database).
Now, let’s check what Nagar.py has to show around that:
An opportunity for poisoning an unresolved host can be seen in the figure above. So, if you decide that it may be safe to poison that hostname, just add the rule line to the file continuously read by Nagar.py (target.txt) using the following format and command:
Format of the lines on the file target.txt:
Sample command to add new lines to the target.txt file:
After adding the rule, Nagar.py will automatically read it, and the next time the victim queries the specified host, it will answer with a fake response pointing to the attacker machine.
Now that Nagar.py was updated with a rule, let’s run the lookup command again on the victim and see what happens:
As expected, the victim obtained the IP address specified by the attacker on the target.txt file. Let’s check the output of Nagar.py:
What comes next should look familiar to every pentester. You may probably run Responder.py with all its services in case the victim attempts an “interesting” communication against the previously unknown hostnames. For example, a service running on the victim may attempt an SMB authentication:
As a conclusion, this approach may be of help when the network administrators followed the pentester recommendations of disabling any broadcast-based name resolution protocols in the network. Although I tried to make Nagar.py as stealthy as possible by just poisoning the specified targets, we should remember that ARP poisoning attacks are not precisely stealthy per se. However, I have to say that I do not remember the last time I got caught performing this attack.
Finally, I was suggested to add an “aggressive” option to the code that allows the impatient pentester to automatically poison ALL unknown hostnames to the specified target. So, if you are also interested in this feature, you should stay tuned for upcoming updates. 😉