Summerschool Aachen 2004/Network Reconnaissance Lab
Contents
Notes on Presentations
Fingerprinting
We also worked on our mandatory assignemt. Our idea was basically first to parse the http://cr.yp.to/surveys/dns1.html page with a perl script and load the fingerprints into our datastructure, into which also the fingerprints of the ftp and smtp servers were to be loaded. We planed to use the already implemented functions which computed the fingerprint of a server and pipe their output to our script and compare it with the stored values in our datastructure. When calling our script the user was expected to give it as a parameter a value N and our script was supposed to output for the best N matches of our fingerprint with the fingerprints stored in our datastructure the name of the corresponding server. However, my project partner left the group at 6.30 pm and I was left alone and consequently joined another project group.
Notes on Lab Session
More SNMP Stuff
I decided to go for the suggestion of SNMP fingerprinting. Today I was mainly busy (or better: idle) setting up and using a scanner which would scan the 137.229.0.0/16 network for hosts that speak SNMP. I used perl for that, together with the Net::SNMP-module from CPAN. The scanner would send SNMP-GET-requests to every IP address for the OID system.sysDescr.0 and log the results. I scanned in parallel, sending out about 15 requests per second. In the end, I had files containing a lot of lines saying that the queried host does not answer to SNMP-requests, and 1268 lines of responses from hosts which had an snmpd running, containing the description of the system. There were a lot of HP JetPrint printers, Cisco devices, some Windows 2000 systems and some Linux boxes. I did not get round to much fingerprinting, apart from the trivial thing to do (considering the content of the system.sysDescr-field...). I uploaded the results of my scans, in case anyone wants to have that information. Besides that, I got sidetracked and played a bit with some of the printers. As is not surprising, the somewhat homegrown webservers they were running were not very well implemented...
Some more fingerprinting
After having been one of the guys complaining about the assignment, too, I nevertheless sat down and started coding. After putting some thought into it and maybe also reducing my own expectations, I found a way to get the whole thing going with not too many lines of perl code.
The script right now is still a bit messy, it depends on certain subroutines being available inside the script itself instead of using a modular or oo-based structure. But it is conceptually extendable and is not too hard to clean up. I then implemented the smtp parsing and scanning as proof of concept. It should be possible to add other protocols quite easily.
The only problem I still have left is one of matching two strings. I definitely get the expected status codes from the servers I am fingerprinting, only something inside my script doesn't want me to successfully match against the database :-)
SNMP Reconnaissance
This is a placeholder for the results of the SNMP scanning I've been doing, but here's a list of default passwords that others might find useful
Fingerprinting
So we gave out some mandatory work for today. It was considered boring and frustrating by most and they considered all other possibilities more entertaining. Is that a patter about the grass being greener elsewhere? Alexander seemed to consider the requirement of doing something he doesn't enjoy for a whole afternoon to hard and left without notice. I'm disappointed about that.
To find out if the task was really unbearable I sat down myself and implemented what I asked for. The basic parser was quickly done:
def loadFingerprints(self): # seek list of probes for l in sys.stdin: if 'Here are the DNS packets sent by the surveying program:' in l: break for l in sys.stdin: if l.startswith('<tr><td align=right>'): fields = l.split('<td>') # this IS exploiutable tests.append((eval(fields[1].strip('</>tdtr')), fields[2].strip('</>tdtr</td></tr>\n'))) if '</table>' in l: break # seek list of probes for l in sys.stdin: if not l.startswith('<tr><td>'): continue if l.startswith('<tr><td>Software</td>'): continue probes.append([x.replace('</td>', '').replace('tr>', '').strip(' </\n') for x in l.split('<td>')])
Crude, but works. Mostly. I get entries like
[, 'BIND 9.2', '4q', '5', '5', '1q', '2', '1q', '1q', '1q', '1q', '3AA', '0AA', '3AA', '3AA', '3AA', '3AA', '3AA', '4q', '4q', '4q', '3AA', '3AA', '5', '0AAD, 2, 5']
that is fine, but others are not
[, '1', '1', 't', 't', 't', 't', 't', 't', '1', 't', '0', 't', '0', '15', '0Z0', '0', '0', 't', 't', 't', '0', '0', 't', '4']
I decided to leave that problem for later.
Scaning was easy now:
def scanTargets(self, targetlist, timeout=1): for target in targetlist: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(timeout) s.connect((target, 53)) for test, desc in tests: flags = [] reply = None retries = 5 while 1: print 'sending %r ...' %test, s.send(test) try: reply = s.recv(1500) print repr(reply) break except socket.timeout: print "timeout" retries -= 1 if retries < 0: flags.append('t') break if reply: flags.extend(self.checkFlags(reply)) print "xxx", flags
I did parse the response with pydns:
def checkFlags(self, reply): flags = [] u = DNS.Lib.Munpacker(reply) r = DNS.Lib.DnsResult(u, []) # check RCODE flags.append(r.header['rcode']) if r.header['tc']: flags.append('TC') if r.header['rd']: flags.append('RD') if r.header['aa']: flags.append('AA') if r.answers: flags.append('D') if len(r.questions) == 0: flags.append('q') if len(r.questions) == 0: flags.append('Q2') # X is missing # print vars(r) return flags
But I failed to implement matching against the fingerprints database. I also got far to much timeouts to my DNS queries. I didn't investigate further. :-(
-- MaxDornseif