#! /usr/bin/env python2 # REQUIREMENTS: # libnids (and libnet 1.0.2a, libpcap) # python 2.2 or later # pynids: http://pilcrow.madison.wi.us/pynids/ # shamelessly stolen from the pynids Example code ... # passive HTTP/SSH/MUA client/server snarfer. all hail libnids. # TODO for a more formal release # - append client IP:service tuple # standard imports import os, pwd, string, sys # local imports ... import nids NOTROOT = "nobody" # edit to taste end_states = (nids.NIDS_CLOSE, nids.NIDS_TIMEOUT, nids.NIDS_RESET) seen = [] # hosts we've seen by IP:port def handleTcpStream(tcp): import string mail_from = "" mailer = "" if tcp.nids_state == nids.NIDS_JUST_EST: ((src, sport), (dst, dport)) = tcp.addr if dport in (80, 8000, 8080, 22, 2222, 2022, 25, 587): tcp.client.collect = 1 tcp.server.collect = 1 elif tcp.nids_state == nids.NIDS_DATA: # keep all of the stream's new data tcp.discard(0) elif tcp.nids_state in end_states: headers = string.split(tcp.client.data, "\n") # grab server headers for header in headers: if tcp.addr[1][1] in (80, 8000, 8080): if "Server: " in header: # get Server header servtype = string.replace(header, "Server: ", "") if tcp.addr[1] not in seen: # don't report twice print "%16s:%4d: \t%s" %(tcp.addr[1][0], tcp.addr[1][1], servtype) seen.append(tcp.addr[1]) break if tcp.addr[1][1] in (22, 2222, 2022): if "SSH-" in header: # SSH server string if tcp.addr[1] not in seen: # don't report twice print "%16s:%4d: \t%s" %(tcp.addr[1][0], tcp.addr[1][1], header) seen.append(tcp.addr[1]) break headers = string.split(tcp.server.data, "\n") # grab client data for header in headers: if tcp.addr[1][1] in (80, 8000, 8080): if "User-Agent: " in header: # get client's user-agent header clienttype = string.replace(header, "User-Agent: ", "") if tcp.addr[0][0] not in seen: # don't report twice print "%16s:%4s:\t%s" %(tcp.addr[0][0], "http", clienttype) seen.append(tcp.addr[0][0]) break if tcp.addr[1][1] in (22, 2222, 2022): if "SSH-" in header: # SSH client string if tcp.addr[0][0] not in seen: # don't report twice print "%16s:%4s: \t%s" %(tcp.addr[0][0], "ssh", header) seen.append(tcp.addr[0][0]) break if tcp.addr[1][1] in (25, 587): if "From: " in header: mail_from = string.replace(header, "From: ", "") continue if "X-Mailer: " in header: mailer = string.replace(header, "X-Mailer: ", "") continue if mail_from and mailer: print "%s\n%16s:%4s: \t%s" %(mail_from, "", "smtp", mailer) break def main(): nids.param("scan_num_hosts", 0) # disable portscan detection if not nids.init(): print "error -", nids.errbuf() sys.exit(1) (uid, gid) = pwd.getpwnam(NOTROOT)[2:4] os.setgroups([gid,]) os.setgid(gid) os.setuid(uid) if 0 in [os.getuid(), os.getgid()] + list(os.getgroups()): print "error - drop root, please!" sys.exit(1) nids.register_tcp(handleTcpStream) try: nids.run() # loop forever except KeyboardInterrupt: for ip in seen: print "%s" % (ip[0]) sys.exit(1) if __name__ == '__main__': main()