DNS and DHCP Recon using Powershell
I recently had a client pose an interesting problem. They wanted to move all their thin clients to a separate VLAN. In order to do that, I needed to identify which switch port each was on. Since there were several device vendors involved, I couldn't use OUI portion of the MAC. Fortunately, they were using only a few patterns in their thin client hostnames, so that gives me an "in".
Great you say, use "nmap -sn", sweep for the names, get the MAC addresses and map those to switch ports - easy right? Yup, it would be, except that this won't tell me about any devices that are powered off at the time. Which got me to thinking about DNS and DHCP - and how you could use these methods to "mine" Microsoft DHCP and DNS databases for Recon info in a much stealthier (and more complete) way than sweeping the network would be.
DNS Approach
We can get part of what we need out of DNS - first, let's dump DNS for all registered IPs:
$dns = Get-WmiObject -Class MicrosoftDNS_AType -NameSpace Root\MicrosoftDNS -ComputerName DC01 -Filter "DomainName = 'example.com'" -Credential (Get-Credential)
(the "Get-Credential" cmdlet will prompt you for credentials)
Yes, I know that there are get-dns cmdlets in the newest versions of powershell + OS combos (see references), but I haven't gotten to a cmdlet that does as nice a job as the WMI equivalent above ...
Look at what fields we have:
$dns | gm
TypeName: System.Management.ManagementObject#Root\MicrosoftDNS\MicrosoftDNS_AType
Name MemberType Definition
---- ---------- ----------
PSComputerName AliasProperty PSComputerName = __SERVER
CreateInstanceFromTextRepresentation Method System.Management.ManagementBaseObject CreateInstanceFromTextRepresentation(System.String DnsServerName, System.Strin...
GetObjectByTextRepresentation Method System.Management.ManagementBaseObject GetObjectByTextRepresentation(System.String DnsServerName, System.String Conta...
Modify Method System.Management.ManagementBaseObject Modify(System.UInt32 TTL, System.String IPAddress)
Caption Property string Caption {get;set;}
ContainerName Property string ContainerName {get;set;}
Description Property string Description {get;set;}
DnsServerName Property string DnsServerName {get;set;}
DomainName Property string DomainName {get;set;}
InstallDate Property string InstallDate {get;set;}
IPAddress Property string IPAddress {get;set;}
Name Property string Name {get;set;}
OwnerName Property string OwnerName {get;set;}
RecordClass Property uint16 RecordClass {get;set;}
RecordData Property string RecordData {get;set;}
Status Property string Status {get;set;}
TextRepresentation Property string TextRepresentation {get;set;}
Timestamp Property uint32 Timestamp {get;set;}
TTL Property uint32 TTL {get;set;}
__CLASS Property string __CLASS {get;set;}
__DERIVATION Property string[] __DERIVATION {get;set;}
__DYNASTY Property string __DYNASTY {get;set;}
__GENUS Property int __GENUS {get;set;}
__NAMESPACE Property string __NAMESPACE {get;set;}
__PATH Property string __PATH {get;set;}
__PROPERTY_COUNT Property int __PROPERTY_COUNT {get;set;}
__RELPATH Property string __RELPATH {get;set;}
__SERVER Property string __SERVER {get;set;}
__SUPERCLASS Property string __SUPERCLASS {get;set;}
ConvertFromDateTime ScriptMethod System.Object ConvertFromDateTime();
ConvertToDateTime ScriptMethod System.Object ConvertToDateTime();
Let's just pull the system name and IP address:
$dns2 = $dns | Select-Object -property Ownername, ipaddress
or, more elegantly, do these two steps in one:
$dns2 = Get-WmiObject -Class MicrosoftDNS_AType -NameSpace Root\MicrosoftDNS -ComputerName DC01 -Filter "DomainName = 'example.com'" -Credential (Get-Credential) | Select-Object -property Ownername, ipaddress
Next, winnow down to just the systems we want:
$ipsofinterest = $dns | where { ($_.Ownername -like "*TP*") -or ($_.Ownername -like "*THIN*") -or ($_.Ownername -like "*THP*") }
$ipsofinterest
Ownername ipaddress
--------- ---------
THP-01.example.com 10.71.32.5
THP-02.example.com 10.71.32.13
THP-03.example.com 10.71.32.23
THP-05.example.com 10.71.32.21
THP-07.example.com 10.71.4.18
THP-08.example.com 10.71.4.17
....
Finally, what we really want is the MAC addresses and switch ports. Ping the IP's, and while that's happening dump the mac address table on the switch to find which ports are involved:
$ipsofinterest | foreach { ping -n 2 $_.ipaddress }
Pinging 10.71.32.5 with 32 bytes of data:
Reply from 10.71.32.5: bytes=32 time=44ms TTL=123
Request timed out.
Ping statistics for 10.71.32.5:
Packets: Sent = 2, Received = 1, Lost = 1 (50% loss),
Approximate round trip times in milli-seconds:
Minimum = 44ms, Maximum = 44ms, Average = 44ms
This last thing is pretty cludgy though, you still need to get the ARP entry (from whatever subnet you are pinging), and relate that MAC back to the MACs on the switch - this started to sound like more work than I wanted to take on. Plus it's totally counter to the stealthy approach we want to take in a penetration test. Let's look at the DHCP database instead:
DHCP Approach
DHCP is more attractive for hosts that use DHCP - you'll get the hostname, the IP and the MAC address all in one go.
First, dump the scopes from the DHCP Server:
Get-DhcpServerv4Scope
ScopeId SubnetMask Name State StartRange EndRange LeaseDuration
------- ---------- ---- ----- ---------- -------- -------------
10.71.33.0 255.255.255.0 Scope1 Active 10.71.33.17 10.71.33.139 8.00:00:00
10.71.34.0 255.255.255.0 Workstations Active 10.71.34.10 10.71.34.250 01:00:00
10.71.35.0 255.255.255.0 Wireless Active 10.71.35.50 10.71.35.200 8.00:00:00
Dump the leases for each ScopeId on the server:
Get-DhcpServerv4Scope | foreach { get-dhcpserverv4lease $_.ScopeId -allleases }
IPAddress ScopeId ClientId HostName AddressState LeaseExpiryTime
--------- ------- -------- -------- ------------ ---------------
10.71.33.1 10.71.33.0 68-b5-99-e8-22-94 W-HOF-A30.example.com ActiveReservation
10.71.33.2 10.71.33.0 b8-ac-6f-c9-9e-3b W-HOF-A18.example.com ActiveReservation
10.71.33.3 10.71.33.0 68-b5-99-e8-25-d2 w-hof-a12.example.com InactiveReservation
10.71.33.4 10.71.33.0 f0-4d-a2-ab-f2-2a W-HOF-A06.example.com ActiveReservation
10.71.33.5 10.71.33.0 f0-1f-af-66-46-7d W-HOF-A25.example.com ActiveReservation
10.71.33.19 10.71.33.0 f0-4d-a2-ae-30-50 TPC-L19.example.com Active 04 May 2016 4:29:16 PM
10.71.33.20 10.71.33.0 f0-4d-a2-ab-f2-20 W-HOF-L93.example.com Active 04 May 2016 7:50:04 AM
Next, narrow down to just the hostnames of interest:
Get-DhcpServerv4Scope | foreach { get-dhcpserverv4lease $_.ScopeId -allleases } | where { ($_.hostname -like "*TP*") -or ($_.hostname -like "*THIN*") -or ($_.hostname -like "*THP*") }
Or, even better, do that and just pull the fields we want ...
$targethosts = Get-DhcpServerv4Scope | foreach { get-dhcpserverv4lease $_.ScopeId -allleases } | where { ($_.hostname -like "*TP*") -or ($_.hostname -like "*THIN*") -or ($_.hostname -like "*THP*") } | select Hostname, IPAddress, Clientid
Hostname IPAddress Clientid
-------- --------- --------
TPC-L08.example.com 10.71.33.17 00-25-64-79-28-49
W-HOF-THINPC20.example.com 10.71.33.18 64-31-50-41-41-fc
TPC-L19.example.com 10.71.33.19 f0-4d-a2-ae-30-50
Now we have the hostname, the IP and the MAC
For my ops problem, I'd pull the switch ports using some python fun or an SNMP tool
However, in a penetration test, you'd have much different uses for this data:
- umm... the reason that we were moving these thin clients to another vlan is because Thin Clients often have "IOT CLass" operating systems - in other words, linux OS's or embedded Windows OS, with much slower (or nonexistent) patch cycles. So you could use exactly this to target thin clients.
- Or .. if you are perhaps targeting VM's, you could look for MAC addresses starting in 00-50
- If you were looking for something else with a known vulnerability, like say a printer or access point, you could look for the affected OUI(s)
- Maybe target hosts with names like "DC" - maybe look for an older one, maybe win2k3, maybe on a subnet you don't know about yet
- Other fun target strings? "SQL" "COUCHDB" "NOSQL", log or syslog - you really can mine this database and only engage a single host.
- How about hostnames that include the names of system admins, or network admins? Company Execs? Social media is a great place to get this target data, or often you can find an "our executive team" page on the target company website.
How could you go one better? I have found new target subnets using this approach (*everything* is in DNS!). If you have an especially forward-thinking client, the DHCP cmdlets will work on IPv6 scopes by changing the "4" in the cmdlet to a "6".
Have you used an approach like this? If so, did you find anything good? Or do you have a better cmdlet to get the DNS info? Please, use our comment form to share your experiences ..
===========
references:
https://technet.microsoft.com/en-us/library/jj590751%28v=wps.630%29.aspx
https://technet.microsoft.com/en-us/library/jj649850.aspx
===============
Rob VandenBrink
Compugen
Comments