def sendGeoIPTweet(tweet_raw): try: latitude = None longitude = None tweet = tweet_raw metaData = None pat = r'\d+\.\d+\.\d+\.\d+' # locate a number of IP addresses ips = re.findall(pat, tweet) if len(ips) != 0: ip = ips[0] # GeoIP information - faster than WHOIS for looking up Country Code information geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP['longitude'] # Used to calc approx. localtime latitude = geoIP['latitude'] metaData = "city=" + city + " cc=" + countryCode if countryCode == 'None': tweet = "??" + "," + tweet_raw else: tweet = countryCode + "," + tweet_raw else: # Did not find an IP address tweet = "--" + "," + tweet_raw sendTweet(tweet, lat=latitude, long=longitude, meta=metaData) except Exception, e: syslog.syslog( "twitter_funcs.py : sendGeoIPTweet() exception caught = " + ` e ` + " tweet_raw=" + tweet_raw)
def traceroute(sensorId,ip,hops,fpDebug=None): asn = [] asnUnique = [] print "----------------------" if fpDebug != None: print >> fpDebug,"-------------" if hops != 0: #cmdLine = "/usr/local/bin/traceroute -p 53 -A -m " + hops.__str__() + " " + ip cmdLine = "/usr/local/bin/paris-traceroute -n -m " + hops.__str__() + " " + ip else: #cmdLine = "/usr/local/bin/traceroute -p 53 -A " + ip cmdLine = "/usr/local/bin/traceroute -n " + ip print cmdLine pipe = os.popen(cmdLine,'r') if pipe == None : syslog.syslog("getP0fInfo() os.popen() returned None for " + cmdLine) raw = pipe.read().strip() if fpDebug != None: print >> fpDebug,raw print "raw = " + raw.__str__() #asn = re.findall("AS(\d+)",raw) ipList = re.findall("(\d+\.\d+\.\d+\.\d+)",raw) print "traceroute() : list of IPs = " + ipList.__str__() for ip in ipList[3:] : a = ipintellib.ip2asn(ip) #asn.append(a['as'] + ":" + a['registeredCode']) asn.append(a['registeredCode']) print "asn = " + asn.__str__() #sys.exit() # Pre-pend sensorId to start of AS Path asnUnique.append(sensorId) asnUnique = asnUnique + asn # Create list of unique AS numbers by filtering out duplicates # asnUnique.append("AS" + asn[0]) #for i in range(0,len(asn)-1): # if asn[i+1] != asn[i] : # if asn[i+1] != "28513" and asn[i+1] != "8151": # IP is private IP ? # asnUnique.append("AS" + asn[i+1]) # Append the countryCode to the target IP geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] #asnUnique.append(countryCode.__str__() + ":" + ip + ":" + city.__str__()) asnUnique.append(countryCode.__str__() + ":" + ip) # Eliminate duplicates asnUnique = eliminateASpathDuplicates(asnUnique) print asnUnique if fpDebug != None: print >> fpDebug,"traceroute(out) : " + asnUnique.__str__() return asnUnique
def vizNmap(ip, portsList): vizFile = "/home/var/secviz/nmap.csv" try: geoIP = ipintellib.geo_ip(ip) cc = geoIP['countryCode'] print cc # Too many open ports - maybe a honeypot ? # bug : move it out of here since honeypot detection shoudl not be linked to visualisation if len(portsList) > 20: msg = "vizNmap() : " + ip + " has too many open ports associated : suspected honeypot" print msg #syslog.syslog(msg) fp = open(vizFile, 'a') msg = ip + ":" + cc + "," + "SUSPECTED HONEYPOT" print >> fp, msg fp.close() return fp = open(vizFile, 'a') for port in portsList: msg = ip + ":" + cc + "," + port.__str__() print "vizNmap() : " + msg print >> fp, msg fp.close() except Exception, e: msg = "kojoney_anubis.py : vizNmap() : exception : " + e.__str__() print msg syslog.syslog(msg) return
def test_geo_ip_random(): for i in range(0, 9889): first = int(255 * random.random()) second = int(255 * random.random()) third = int(255 * random.random()) fourth = int(255 * random.random()) random_ip = first.__str__() + '.' + second.__str__( ) + '.' + third.__str__() + '.' + fourth.__str__() ip_info = ipintellib.geo_ip(random_ip)
def alert(subject, ip, username, content): smtpServer = 'smtp.btconnect.com' sender = '*****@*****.**' destination = ['*****@*****.**'] debugLevel = False try: # Get DNS info dnsInfo = ipintellib.ip2name(ip) dnsName = dnsInfo['name'] # WHOIS information asInfo = ipintellib.ip2asn(ip) asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo['registeredCode'] # Short-form e.g.ARCOR # GeoIP information geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP['longitude'] # Calc approx. localtime latitude = geoIP['latitude'] info = "haxx0r IP : " + ip + "\nuser : "******"\nDNS : " + dnsName + "\n\nAS Number : " + asNum + "\nAS Name : " + asRegisteredCode + "\n\nGeoIP Country : " + countryCode + "\nGeoIP City : " + "\nGeoIP Longitude : " + "%.2f" % longitude + "\nGeoIP Latitude : " + "%.2f" % latitude # Haxx0r's client stack information p0fInfo = p0fcmd.getP0fInfo(ip, "0", "172.31.0.67", "22") if p0fInfo['result'] == True: p0fStr = "os=" + p0fInfo['genre'] + " hops=" + p0fInfo[ 'hops'] + " linktype=" + p0fInfo[ 'linktype'] + " up_secs=" + p0fInfo[ 'uptime'] + " tos=" + p0fInfo[ 'tos'] + " masq=" + p0fInfo[ 'masq'] + " fw=" + p0fInfo[ 'firewall'] + " NAT=" + p0fInfo[ 'nat'] + " realOS=" + p0fInfo['realos'] else: p0fStr = p0fInfo['errormsg'] # Notify ! alertSubject = "honeypot intrusion! : " + subject alertContent = info + "\n\np0f : " + p0fStr + "\n\n" + content + "\n\nSent by Kojoney Honeypot\n\n" print "alert():\nsubject:" + alertSubject + "\ncontent:\n" + alertContent + "\n" status = mailalert.mailalert(sender, destination, smtpServer, alertSubject, alertContent, debugLevel) # Add a record to syslog a = "Sent alert e-mail, Subject=" + alertSubject + " to " + destination[ 0] syslog.syslog(a) except Exception, e: syslog.syslog("kojoney_tail.py : alert() : " + ` e ` + " ip=" + ip)
def isSafeToScan(ip): #UNSAFE_COUNTRIES = ['?','GB','US','DE'] # if testing using ShieldsUp (US) #UNSAFE_COUNTRIES = ['GB'] # Normal SAFE_COUNTRIES = [ 'CN', 'RU', 'TW', 'UA', 'BR', 'NL', 'PL', 'KZ', 'JP', 'FR', 'VN', 'JP', 'TR', 'BG', 'AR', 'MX', 'TH', 'IN', 'HK', 'KR', 'NG', 'JO', 'IR', 'IQ', 'PK', 'KE', 'ID', 'CL', 'HN', 'AE', 'LV', 'EG', 'RO', 'MA', 'VE', 'PH' ] geoIP = {} try: print "*** kojoney_anubis.py : calling hiddenIP() ***" # Do not scan Google / Local LAN etc if kojoney_hiddenip.hiddenIP(ip) == True: msg = "kojoney_anubis.py : isSafeToScan() : " + ip + " is **not** OK to scan according to hiddenIP()" print msg #syslog.syslog(msg) return False else: msg = "kojoney_anubis.py : isSafeToScan() : " + ip + " is OK to scan according to hiddenIP()" print msg #syslog.syslog(msg) # Check the country of the attacker geoIP = ipintellib.geo_ip(ip) cc = geoIP['countryCode'] #print cc if cc not in SAFE_COUNTRIES: msg = ip + " is in " + cc.__str__( ) + " jurisdiction and so considered UNSAFE to scan" #syslog.syslog(msg) print msg return False else: msg = ip + " is in " + cc.__str__( ) + " jurisdiction and so considered safe to scan" #syslog.syslog(msg) print msg return True except Exception, e: msg = "kojoney_anubis.py : isSafeToScan() : exception : " + e.__str__() print msg syslog.syslog(msg) return False
def afterglowPorts(ip,openPorts,fpOut,fpDebug): a = "afterglowPorts() : openPorts = " + openPorts.__str__() print a print >> fpDebug,a geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] #attacker = countryCode.__str__() + ":" + ip + ":" + city.__str__() attacker = countryCode.__str__() + ":" + ip # Write open ports info to afterglow file for i in openPorts: a = i.__str__() + "," + attacker print >> fpOut,a print >> fpDebug,a print a return None
def checkDoStweet(text, group, victim): try: global VERSION if ("IP" in text.upper() or "TARGET" in text.upper() or "FIRE" in text.upper()) and ("#ANON" in text.upper() or "#OP" in text.upper()): asInfo = ipintellib.ip2asn(victim) asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo[ 'registeredCode'] # Short-form e.g. ARCOR dnsInfo = ipintellib.ip2name(victim) dnsName = dnsInfo['name'] geoIP = ipintellib.geo_ip(victim) countryCode = geoIP['countryCode'].__str__() subject = "Anonymous DDoS Request" body = "The text in the Tweet below *MAY* indicate that a hactivist-based DDoS attack is being requested against IP " + victim.__str__() + " DNS=" + dnsName.__str__() \ + " located in BGP AS" + asNum.__str__() + " ISP=" + asRegisteredCode.__str__() + " CC=" + countryCode.__str__() body = body + " => Tweet=" body = body + '[' + text.replace('\t', " ") + ']' body = body + " : " body = body + "This e-mail notification was generated by soclscrpr v" + VERSION + " at " + time.ctime( ) body = body + " : " body = body + "For support, contact [email protected]" kojoney_alert_client.sendAlert(subject, body, True, True) except Exception, e: msg = "twitter_streamer.py : checkDoStweet() : exception : " + e.__str__( ) + " : " + text.__str__() print msg syslog.syslog(msg)
def printAttackerOIDs(): # need to add logic to fail if the shelf file does not exist database = shelve.open('/home/var/log/attacker_shelf.dat') if len(database) == 0: # contains no entries sys.exit("Failed to locate shelf file") print " " print "Attackers" print "---------" print "NUM_IP : " + database['NUM_IP'].__str__() print "NUM_SLASH_24 : " + database['NUM_SLASH_24'].__str__() print "NUM_CC : " + database['NUM_CC'].__str__() print "NUM_CITY : " + database['NUM_CITY'].__str__() print "NUM_ASN : " + database['NUM_ASN'].__str__() print " " print "Malware Captured" print "----------------" print "AMUN_FILES_BIN : " + database['AMUN_FILES_BIN'].__str__() print "AMUN_FILES_HEX : " + database['AMUN_FILES_HEX'].__str__() print "NEPENTHES_FILES : " + database['NEPENTHES_FILES'].__str__() print "KIPPO_FILES : " + database['KIPPO_FILES'].__str__() print "GLASTOPF_FILES_GET : " + database['GLASTOPF_FILES_GET'].__str__() print "GLASTOPF_FILES_POST : " + database['GLASTOPF_FILES_POST'].__str__() print "ANALYST_FILES_ALL : " + database['ANALYST_FILES_ALL'].__str__() print "ANALYST_FILES_EXE : " + database['ANALYST_FILES_EXE'].__str__() print "ANALYST_FILES_PHP : " + database['ANALYST_FILES_PHP'].__str__() print "ANALYST_FILES_TXT : " + database['ANALYST_FILES_TXT'].__str__() print "ANALYST_FILES_GIF : " + database['ANALYST_FILES_GIF'].__str__() print "ANALYST_FILES_JPG : " + database['ANALYST_FILES_JPG'].__str__() print "ANALYST_FILES_PNG : " + database['ANALYST_FILES_PNG'].__str__() print "ANALYST_FILES_TGZ : " + database['ANALYST_FILES_TGZ'].__str__() print " " print "Attackers" outfile = "blackrain_attackers-report.csv" fp = open(outfile, 'w') for ip in database['IP']: asInfo = ipintellib.ip2asn(ip) # asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo['registeredCode'] # Short-form e.g.ARCOR geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP['longitude'] # Used to calc approx. localtime latitude = geoIP['latitude'] dnsInfo = ipintellib.ip2name(ip) dnsName = dnsInfo['name'].rstrip('.') msg = ip + "," + "AS" + asNum.__str__( ) + "," + countryCode + "," + dnsName.__str__( ) + "," + asRegisteredCode.__str__() + "," + countryCode.__str__( ) + "," + city.__str__() print msg print >> fp, msg fp.close()
def processSSH(line): global PreviousIPs global CLInum global SessionId global Username if Username == None: Username = "******" try: #print "line read from file\n:" + line # haxx0r guessed password OK # Use this one to perform the ipintellib() functions if line.find("authenticated with password") != -1: SessionId = SessionId + 1 fields = line.split(',') #print fields a = fields[2].split() ip = a[0].rstrip(']') Username = a[1] #print "a is " + `a` # Get DNS info dnsInfo = ipintellib.ip2name(ip) dnsName = dnsInfo['name'] # WHOIS information asInfo = ipintellib.ip2asn(ip) asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo['registeredCode'] # Short-form e.g.ARCOR # GeoIP information geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP['longitude'] # Used to calc approx. localtime msg = "------------------------------------------------------------------------------------------" makeMsg(0, ip, msg) msg = "EXPL:authOK," + Username + "," + countryCode + "," + asNum + "," + asRegisteredCode + "," + city + "," + dnsName + ",long=" + "%.2f" % float( longitude) makeMsg(0, ip, msg) # Write Security Visualisation Data to secViz file print "Calling writeSecViz3()" writeSecViz3(ip, Username) # Compute localtime based on longitude locTime = calcLocalTime(longitude) msg = "INTEL:haxx0r localTime(est) is " + locTime makeMsg(0, ip, msg) # Haxx0r's client stack information - using p0f 3.0.0, uptime is in seconds not hours try: p0fInfo = p0fcmd.getP0fInfo(ip, "0", "172.31.0.67", "22") if p0fInfo['result'] == True: # p0f data is available hops = p0fInfo['hops'] os = p0fInfo['genre'] fw = p0fInfo['firewall'] nat = p0fInfo['nat'] if p0fInfo['genre'] == "Linux": uptime = p0fInfo['uptime'] # measured in secs else: uptime = 0 else: # p0f data is not available hops = 0 os = "?" fw = "?" nat = "?" uptime = 0 #p0fStr = "os=" + os + " hops=" + hops + " lt=" + p0fInfo['linktype'] + " up=" + uptime + " tos=" + p0fInfo['tos'] + " masq=" + p0fInfo['masq'] + " fw=" + p0fInfo['firewall'] + " NAT=" + p0fInfo['nat'] + " realOS=" + p0fInfo['realos'] p0fStr = "os=" + os + " hops=" + hops + " up=" + uptime + " fw=" + fw + " NAT=" + nat # Compute haxx0r's PC bootTime based on p0f uptime (seconds) bootTime = calcBootTime(uptime) bootmsg = "haxx0r PC bootTime(est,UTC) is " + bootTime[ 'timeStr'] # p0f info msg = "p0f,INTEL:" + p0fStr # INT = Intelligence makeMsg(0, ip, msg) # haxx0r boot time msg = "INTEL:bootTime," + bootmsg makeMsg(0, ip, msg) # Has this IP been seen before ? if PreviousIPs.has_key(ip): # IP has been seen before msg = "INTEL:IP was last seen " + PreviousIPs[ip][ 'lastVisitStr'] + " with a bootTime of " + PreviousIPs[ ip]['timeStr'] makeMsg(0, ip, msg) # Has this PC stack been seen before ? # i.e. are bootTimes within 30 minutes of each other ? if abs( float(PreviousIPs[ip]['epoch']) - float(bootTime['epoch'])) < 1800.0: msg = "INTEL:p0f uptime (secs) indicates repeat visit from haxx0r's PC from this ip" makeMsg(0, ip, msg) else: PreviousIPs[ ip] = bootTime # set info to be haxx0r boottime msg = "INTEL:first time visit from " + ip + ", user " + Username makeMsg(0, ip, msg) except Exception, e: syslog.syslog( "Exception in processSSH() p0f for authOK section of code " + ` e ` + " ip=" + ip) # Extract haxxor's SSH client elif line.find("pty request") != -1: fields = line.split(',') #print fields a = fields[2].split() #print "a is " + `a` ip = a[0].rstrip(']') pty = a[3] #print "pty is " + `pty` msg = "INTEL:client=" + pty makeMsg(0, ip, msg)
def sendToLoggly(sensorId, line): try: global txnId print "sendToLoggly() : line=" + line # honeytweeter #shakey = "e25e6042-e490-4910-a246-94cefbdd11b9" # honeytweeter-json shakey = "fe39eb54-7c8f-417c-afc8-5b8db98961d3" sdata = {} cifdata = {} # Event Type fields = line.split(",") eventType = fields[0] sdata['eventType'] = fields[0] # Do not process obsolete eventTypes if sdata['eventType'] == 'FW_SNORT' or sdata['eventType'] == 'NIDS_SH': return None if sdata['eventType'] == "ANALYST" and "TRACEROUTE" in line: # ANALYST traceroutes don't visualise well return None if sdata['eventType'] == "ANALYST" and "NMAP" in line: # ANALYST nmaps don't visualise well return None #print sdata['eventType'] # Sensor Name sdata['sensorId'] = sensorId # IP address ips = re.findall("\d+\.\d+\.\d+\.\d+", line) if len(ips) > 0: sdata['ip'] = ips[0] # GeoIP geoIP = ipintellib.geo_ip(sdata['ip']) cc = geoIP['countryCode'] if cc != "?": sdata['cc'] = cc.__str__() sdata['ipcc'] = sdata['ip'].__str__( ) + " - " + sdata['cc'].__str__() # Reverse DNS : fixme Extract the TLD and create a sdata field for it dnsInfo = ipintellib.ip2name(sdata['ip']) dnsName = dnsInfo['name'] if dnsName != "NoDNS": sdata['rdns'] = dnsName.rstrip('.').lower() sdata['tld'] = crudeTld.getTLD(sdata['rdns']) if "baiduspider" in sdata['rdns']: return None # this is not an interesting event if sdata['rdns'] == "pointer": return None # ASN info asInfo = ipintellib.ip2asn(sdata['ip']) asNum = asInfo['as'] # AS123 if asNum == "AS-none": asNum = "NO_INFO" else: asNum = "AS" + asNum asRegisteredCode = asInfo['registeredCode'].upper() # e.g. GOOGLE sdata['asn'] = asNum sdata['isp'] = asRegisteredCode # Snort SID if sdata['eventType'] == "SNORT_NIDS" or sdata[ 'eventType'] == "NIDS_SH": sids = re.findall("SID=(\d+)", line) if len(sids) > 0: sdata['sid'] = sids[0] a = re.findall("P(\d+) SID", line) if len(a) > 0: sdata['priority'] = a[0] # removed the P from the priority - due to ELK issues - fixme : make a Blackrain-wide PRIORITY ? for all events ? # Clamd malware name - e.g. Exploit.Shellcode.X86-Gen-1 # Jun 27 04:47:39 mars kojoney_tweet_engine[3173]: SENDTWEET = <0>CLAMD,Malware Exploit.Shellcode.X86-Gen-1 in flow from 79.5.203.86 ports={s=4592 d=135} if sdata['eventType'] == "CLAMD": a = line.split(",Malware ")[1] a = a.split(" ")[0] sdata['malware'] = a sdata['avendor'] = "ClamAV" # Threat Report # submitted=Wed Jun 26 02:54:18 2013 cmd=GEO_IP tweet=REPORT,Threat Level for 203.250.135.20 is 41.1, flags={PR SC PS BH AT GA} if "flags={" in line and sdata['eventType'] == "REPORT": a = line.split("flags=")[1] #a = a.rstrip("}") sdata['flags'] = a # VirusTotal # submitted=Fri May 17 07:48:03 2013 cmd=BASIC tweet=ANALYST,AV eb7656dd256eb414abe092eb0f41ea1f.php => Norman=PhpShell.BL 17/46 VT=http://bit.ly/14vyont # line=ANALYST,AV 06a940dd7824d6a3a6d5b484bb7ef9d5.php => Unseen by VirusTotal if sdata[ 'eventType'] == "ANALYST" and "AV" in line and "Unseen by" not in line: a = line.split(" => ")[1] b = a.split(" ")[0] # Symantec=Trojan.Usuge!gen3 sdata['avendor'] = b.split("=")[0] sdata['malware'] = b.split("=")[1] b = a.split("VT=")[1] sdata['virustotal'] = b # filename = MD5 name + extension (optional) c = line.split("AV ")[1] c = c.split(" ")[0] #print c if "." in c: c = c.split(".")[0] # lose filename extension sdata['md5'] = c.lower() # Destination port - make this a string so it is not displayed with commas in Kibana # ---------------------------------------------------------------------------------- # Snort messages flow = re.findall("\w+\:(\d+) ", line) if len(flow) > 0: sdata['port'] = str(flow[0]) # IPLOG - make a string so it is displayed with commas in Kibana # -------------------------------------------------------------- if sdata['eventType'] == "IPLOG": ports = re.findall("port (\d+)", line) if len(ports) > 0: sdata['port'] = str(ports[0]) # CLAMD - clsniffer if sdata['eventType'] == "CLAMD": ports = re.findall("d=(\d+)", line) if len(ports) > 0: sdata['port'] = str(ports[0]) # KIPPO if sdata['eventType'] == "KIPPO": #sdata['port'] = 2222 sdata['port'] = "22" sdata['protocol'] = "tcp" ############ # Glastopf # ############ if "WEB_" in sdata['eventType']: #sdata['port'] = 18080 sdata['port'] = "80" sdata['protocol'] = "tcp" line = line.replace( '|', '/' ) # pipe character is used in Tweets to avoid Twitter generating shortened URLs url = line.split('req=')[1] sdata['url'] = url.lower() #if sdata['url'] == '/' or sdata['url'] == '//' : # return None # Botjuicer cracked scripts if sdata['eventType'] == "ANALYST" and "BOTJUICER" in line: #if "UNDETERMINED" in line.upper(): # return None #print "BOTJUICER log found : " + line a = re.findall("p=(\d+)", line) if len(a) > 0: sdata['port'] = str(a[0]) a = re.findall("ch=(#\w+)", line) if len(a) > 0: sdata['irc'] = a[0] # Protocol - generic if "TCP" in line.upper(): sdata['protocol'] = "tcp" if "UDP" in line.upper(): sdata['protocol'] = "udp" if "ICMP" in line.upper(): sdata['protocol'] = "icmp" # Timestamp sdata['datetime'] = time.ctime() # Message sdata['msg'] = line.split(",")[1:][0] # Txnid - increment this last, just before submission to Loggly txnId = txnId + 1 sdata['txnId'] = txnId # Splunk #print "\nkey-value pairs for Splunk :-" #splunkMsg = "'" + time.ctime() + ' ' + sensorId + ' ' #for i in sdata: # if i == 'datetime' : # ignore # continue # if i == 'msg' and "SNORT" in eventType: # print "Snort event found" # # sdata[i] = '"' + sdata[i] + '"' # # sdata[i] = sdata[i].replace('"','') # splunkMsg = splunkMsg + ' ' + i.__str__() + '=' + '"' + sdata[i].__str__() + '"' # #print i,sdata[i] #splunkMsg = splunkMsg + "'" # Abandoned - has my API key run out ? #print "Send to SplunkStorm Cloud SIEM => " + splunkMsg #log.send(splunkMsg , sourcetype='syslog',host=sensorId) # Loggly - abandoned in favour of splunk #body = json.dumps(sdata) #print "\nsendToLoggly() : JSON body = " + body # Send to Loggly #insert_url = "http://logs.loggly.com/inputs/" + shakey #insert_http = httplib2.Http(timeout=10) ##body = line #resp, content = insert_http.request(insert_url, "POST", body=body, headers={'content-type':'text/plain'}) ##print "Loggly : resp : " + resp.__str__() ##print "Loggly : content : " + content.__str__() ##{'status': '200', 'content-length': '18', 'vary': 'Accept-Encoding', 'server': 'TwistedWeb/12.0.0', 'date': 'Tue, 25 Jun 2013 05:55:58 GMT', 'content-type': 'text/html'} ##{"response": "ok"} #if "ok" in content.__str__() : # bug -> why can't I look at the "response" field in a structured way # msg = "Sent to Loggly OK : " + body.__str__() # print msg #else: # msg = "Sent to Loggly FAIL : " + body.__str__() + " error = " + content.__str__() # print msg # syslog.syslog(msg) # crude form of rate-limiter #time.sleep(0.2) # Return the JSON structure so it can be used by NoSQL type databases sdata = json.dumps(sdata) pprint(sdata) #writeToSyslogFake(sdata) return sdata except Exception, e: msg = "kojoney_loggly.py : sendToLoggly() : exception : " + e.__str__( ) + " line=" + line print msg syslog.syslog(msg) return None
def setIDMEFcommon(idmef, analyserClass, sensorId, srcIP, dstIP, dstPort, attackerIP, logEntry): try: print "kojoney_idmef_common.py : setIDMEFcommon() : srcIP = " + srcIP.__str__( ) print "kojoney_idmef_common.py : setIDMEFcommon() : dstIP = " + dstIP.__str__( ) #print "kojoney_idmef_common.py : setIDMEFcommon() : attackerIP = " + attackerIP.__str__() idmef.Set("alert.analyzer(0).model", "Blackrain") idmef.Set("alert.analyzer(0).name", "blackrain-" + sensorId.upper()) idmef.Set("alert.analyzer(0).manufacturer", "Blackrain Technologies") idmef.Set("alert.analyzer(0).class", analyserClass) idmef.Set("alert.analyzer(0).version", "1.0rc1") idmef.Set("alert.analyzer(0).ostype", "Linux") idmef.Set("alert.analyzer(0).osversion", "2.6.21.5") if logEntry != None: logEntry = logEntry.rstrip() else: logEntry = "None" idmef.Set("alert.additional_data(0).type", "string") idmef.Set("alert.additional_data(0).meaning", "Original log entry") idmef.Set("alert.additional_data(0).data", logEntry) print "kojoney_idmef_common.py : setIDMEFcommon() : logEntry = " + logEntry.__str__( ) fieldsSet = 1 if attackerIP != None: # GeoIP enhancement geoIP = ipintellib.geo_ip(attackerIP) #print geoIP.__str__() countryCode = geoIP['countryCode'].__str__() city = geoIP['city'].__str__() # Prewikka has a "spare" pie-chart used for source users - so abuse it for Country Code pie-chart idmef.Set("alert.source(0).user.user_id(0).name", "haxx0r-" + countryCode) idmef.Set("alert.source(0).user.user_id(0).tty", "UserId Name is faked") if attackerIP == srcIP: idmef.Set("alert.source(0).node.location", countryCode) addInfoLabel = "Source(0) " elif attackerIP == dstIP: idmef.Set("alert.target(0).node.location", countryCode) addInfoLabel = "Target(0) " latitude = "%.2f" % geoIP['latitude'] + " N" longitude = "%.2f" % geoIP['longitude'] + " E" # AS enhancement asInfo = ipintellib.ip2asn(attackerIP) #print asInfo.__str__() asNum = asInfo['as'].__str__() asRegisteredCode = asInfo['registeredCode'].__str__() asRegisteredName = asInfo['registeredName'].__str__() asNetblock = asInfo['netblock'].__str__() asRegistry = asInfo['registry'].__str__() idmef.Set("alert.additional_data(1).type", "string") idmef.Set("alert.additional_data(1).meaning", addInfoLabel + "MaxMind GeoIP City") idmef.Set("alert.additional_data(1).data", city) idmef.Set("alert.additional_data(2).type", "string") idmef.Set("alert.additional_data(2).meaning", addInfoLabel + "MaxMind GeoIP Latitude") idmef.Set("alert.additional_data(2).data", latitude) idmef.Set("alert.additional_data(3).type", "string") idmef.Set("alert.additional_data(3).meaning", addInfoLabel + "MaxMind GeoIP Longitude") idmef.Set("alert.additional_data(3).data", longitude) idmef.Set("alert.additional_data(4).type", "string") idmef.Set("alert.additional_data(4).meaning", addInfoLabel + "BGP ASN") idmef.Set("alert.additional_data(4).data", "AS" + asNum) idmef.Set("alert.additional_data(5).type", "string") idmef.Set("alert.additional_data(5).meaning", addInfoLabel + "ISP Code") idmef.Set("alert.additional_data(5).data", asRegisteredCode) idmef.Set("alert.additional_data(6).type", "string") idmef.Set("alert.additional_data(6).meaning", addInfoLabel + "ISP Name") idmef.Set("alert.additional_data(6).data", asRegisteredName) idmef.Set("alert.additional_data(7).type", "string") idmef.Set("alert.additional_data(7).meaning", addInfoLabel + "Internet prefix/route") idmef.Set("alert.additional_data(7).data", asNetblock) idmef.Set("alert.additional_data(8).type", "string") idmef.Set("alert.additional_data(8).meaning", addInfoLabel + "Internet Registry") idmef.Set("alert.additional_data(8).data", asRegistry) fieldsSet = fieldsSet + 8 # p0f enhancement - optional if srcIP != None and dstIP != None and dstPort != None: p0fInfo = p0fcmd.getP0fInfo(srcIP, "0", dstIP, dstPort) # 0 = wildcard the srcPort if p0fInfo['result'] == True: # p0f data is available os = p0fInfo['genre'] nat = p0fInfo['nat'][0] hops = p0fInfo['hops'] idmef.Set("alert.additional_data(9).type", "string") idmef.Set("alert.additional_data(9).meaning", "p0f : OS") idmef.Set("alert.additional_data(9).data", os.__str__()) idmef.Set("alert.additional_data(10).type", "string") idmef.Set("alert.additional_data(10).meaning", "p0f : NAT detected") idmef.Set("alert.additional_data(10).data", nat.__str__()) idmef.Set("alert.additional_data(11).type", "string") idmef.Set("alert.additional_data(11).meaning", "p0f : IP hops") idmef.Set("alert.additional_data(11).data", hops.__str__()) fieldsSet = fieldsSet + 3 #print "fieldsSet = " + fieldsSet.__str__() return fieldsSet except Exception, e: msg = "kojoney_idmef_common.py : setIDMEFcommon() : exception : " + e.__str__( ) print msg syslog.syslog(msg) return None
def processKippo(txnId,sensorId,line): try : line=line.strip("\n") print "############################################" print "processKippo() : line received from Honeypot : " + line addInfo1 = None addInfo2 = None # log succeeded attempted passwords to a file if line.find("login attempt") != -1 and line.find("succeeded") != -1 : pat = '\d+\.\d+\.\d+\.\d+' attacker = re.findall(pat,line) if len(attacker) == 1 : srcIP = attacker[0] else : srcIP = "0.0.0.0" geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'].__str__() fields = line.split(" ") #print fields a = fields[8] # e.g. [root/123456] a = a.lstrip("[") a = a.rstrip("]") username = a.split('/')[0] password = a.split('/')[1] #print "login OK : credentials = " + username + " " + password msg = srcIP + ":" + countryCode + "," + username + ":" + password + ",succeeded" + ",kippo" print msg # Fake auth.log entry for use by OSSEC :- # Accepted password for crouchr from 192.168.1.73 port 46366 ssh2 tstamp = time.ctime() fields = tstamp.split(" ") print "kojoney_kippo_parse.py : fields=" + fields.__str__() tstamp = fields[1] + " " + fields[2] + " " + fields[3] fakeAuthLogMsg = tstamp + " mars sshd[12345]: Accepted password for " + username + " from " + srcIP + " port 12345 ssh2" print "kojoney_kippo_parse.py : fakeAuthLogMsg : " + fakeAuthLogMsg fp = open("/home/var/log/kippo_auth.log",'a') print >> fp, fakeAuthLogMsg fp.close() # Send event to SIEM kojoney_kippo_idmef.sendSshIDMEF(srcIP,"192.168.1.64","2222",username,password,True,line) # Send to syslog to be picked up by logstash #sdata = {} #sdata['username'] = username #sdata['password'] = password #sdata['ip'] = srcIP.__str__() #sdata['phase'] = "GAINED_ACCESS" #syslog.openlog("kojoney_kippo") #syslog.syslog(json.dumps(sdata)) # Update attacker database addInfo1 = username addInfo2 = password kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"GAINED_ACCESS","KIPPO",None,"Successful login",None,None,None,addInfo1,addInfo2) fp = open("/home/var/secviz/failedCredentialsViz.csv",'a') print >> fp, msg fp.close() # log failed attempted passwords to a file if line.find("login attempt") != -1 and line.find("failed") != -1 : pat = '\d+\.\d+\.\d+\.\d+' attacker = re.findall(pat,line) if len(attacker) == 1 : srcIP = attacker[0] else : srcIP = "0.0.0.0" geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'] fields = line.split(" ") #print fields a = fields[8] # e.g. [root/123456] a = a.lstrip("[") a = a.rstrip("]") username = a.split('/')[0] password = a.split('/')[1] if len(password) == 0 : password = "******" #print "login FAIL : credentials = " + username + " " + password msg = srcIP + ":" + countryCode + "," + username + ":" + password + ",failed" + ",kippo" + "," + time.ctime() print msg # Fake FAILED auth.log entry for use by Ossec :- # Failed password for user crouchr from 192.168.1.73 port 46366 ssh2 tstamp = time.ctime() fields = tstamp.split(" ") tstamp = fields[1] + " " + fields[2] + " " + fields[3] fakeAuthLogMsg = tstamp + " mars sshd[12345]: Failed password for user " + username + " from " + srcIP + " port 12345 ssh2" fakeAuthLogMsg = fakeAuthLogMsg.replace("2013 ","") print "fakeAuthLogMsg : " + fakeAuthLogMsg # Update clone of auth.log so OSSEC standard SSH rules can be used fp = open("/home/var/log/kippo_auth.log",'a') print >> fp, fakeAuthLogMsg fp.close() # Send event to SIEM kojoney_kippo_idmef.sendSshIDMEF(srcIP,"192.168.1.64","2222",username,password,False,line) # Send to syslog to be picked up by logstash #sdata = {} #sdata['username'] = username #sdata['password'] = password #sdata['ip'] = srcIP.__str__() #sdata['phase'] = "ATTACKING" #syslog.openlog("kojoney_kippo") #syslog.syslog(json.dumps(sdata)) # Update attacker database addInfo1 = username addInfo2 = password kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"ATTACKING","KIPPO",None,"Failed login attempt",None,None,None,addInfo1,addInfo2) fp = open("/home/var/secviz/failedCredentialsViz.csv",'a') print >> fp, msg fp.close() # Also add INPUT - i.e. if user performs a passwd # Received unhandled keyID => attacker is a human if (line.find("Opening TTY log") == -1 and line.find("CMD:") == -1 and line.find("Received unhandled keyID") == -1) : # can't find the interesting entries so return return None # Human keystrokes (backspace etc.) detected ? if "Received unhandled keyID" in line : ip = re.findall("(\d+\.\d+\.\d+\.\d+)",line) if len(ip) > 0 : srcIP = ip[0] else: srcIP = "0.0.0.0" kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"HUMAN_ACTIVITY","KIPPO",None,"Attacker is a human",None,None,None,addInfo1,addInfo2) return None #print "processKippo() : candidate syslog read from Honeypot : " + line fields = line.split() #print fields uid = "0" # Kippo only supports a root account a = fields[9].rstrip(']') srcip = a.split(',')[2] #print "Attacker IP : " + srcip # INT = intrusion if line.find("Opening TTY log") != -1: tweet = "KIPPO_INT," + "login from " + srcip + " to be logged in " + fields[13] else: cmd = ' '.join(fields[11:]) #cmd = 'rch testing - ignore' print "kojoney_kippo_parse.py : cmd=[" + cmd.__str__() + "]" ip = re.findall("(\d+\.\d+\.\d+\.\d+)",line) if len(ip) > 0 : srcIP = ip[0] else: srcIP = "0.0.0.0" geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'].__str__() #print "kojoney_kippo_parse.py : Attacker " + srcIP + " from " + countryCode + " typed : " + cmd # fake the correct shell prompt if uid == "0" : prompt = "#" else: prompt = "$" #tweet = "--,KIPPO,UID:" + uid + " {sshd} " + prompt + " " + cmd # fake the GeoIP of src (unknown) tweet = "KIPPO,UID:" + uid + " {sshd} " + prompt + " " + cmd # fake the GeoIP of src (unknown) kojoney_kippo_idmef.sendSshCmdIDMEF(srcIP,"192.168.1.64","2222",uid,prompt + " " + cmd,line) # Log all commands to a file msg = time.ctime() + "," + srcIP + "," + countryCode.__str__() + "," + cmd fpCmds = open("/home/var/log/kippo-all-cmds.csv","a") print >> fpCmds,msg fpCmds.close() # Update Attacker Database addInfo1 = cmd addInfo2 = None if "wget " in cmd.lower() : # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"MAINTAIN_ACCESS","KIPPO",None,"Attacker attempted to retrieve malware",None,None,None,addInfo1,addInfo2) elif "apt-get install " in cmd.lower(): # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"MAINTAIN_ACCESS","KIPPO",None,"Attacker attempted to install software",None,None,None,addInfo1,addInfo2) elif "chmod " in cmd.lower() or "tar " in cmd.lower(): # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"MAINTAIN_ACCESS","KIPPO",None,"Attacker attempted to install software",None,None,None,addInfo1,addInfo2) elif "perl " in cmd.lower() or "sh " in cmd.lower() or "python " in cmd.lower() or "./" in cmd.lower(): # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"MAINTAIN_ACCESS","KIPPO",None,"Attacker attempted to execute software",None,None,None,addInfo1,addInfo2) elif "rm " in cmd.lower() : # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"COVER_TRACKS","KIPPO",None,"Attacker attempted to delete file",None,None,None,addInfo1,addInfo2) elif "passwd" in cmd.lower() : kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"COVER_TRACKS","KIPPO",None,"Attacker attempted to modify password",None,None,None,addInfo1,addInfo2) elif "adduser" in cmd.lower() : kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"COVER_TRACKS","KIPPO",None,"Attacker attempted to add user",None,None,None,addInfo1,addInfo2) elif "apt-get remove " in cmd.lower(): # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"COVER_TRACKS","KIPPO",None,"Attacker attempted to uninstall software",None,None,None,addInfo1,addInfo2) elif "reboot" in cmd.lower(): # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"COVER_TRACKS","KIPPO",None,"Attacker attempted to reboot node",None,None,None,addInfo1,addInfo2) elif "shutdown " in cmd.lower(): # Use trailing space to force an argument to have been supplied for wget etc. kojoney_attacker_event.generateAttackerEvent(txnId,srcIP,None,sensorId,"COVER_TRACKS","KIPPO",None,"Attacker attempted to shutdown node",None,None,None,addInfo1,addInfo2) print "processKippo() : tweet=" + tweet return tweet except Exception,e: syslog.syslog("kojoney_tweet.py : processKippo() exception caught = " + `e` + " line=" + line)
# ***************************************************************************** ipUrl = processURLfoundWget(tweet,test) # Case 1 : Generate Tweets for raw IPs found # TODO : Need a safety feature to ensure that IPs in range 192.168.1.0/24 are never added to TweetQueue if len(ips) != 0 : # Case #1 : Generate Tweets for raw IPs found for ip in ips: if ipList.has_key(ip) == False : # not seen this IP before # Get DNS name dnsInfo = ipintellib.ip2name(ip) dnsName = dnsInfo['name'].rstrip('.') + " " asMsg = ipintellib.prettyAS(ip) geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] if city == "?" : geoInfo = "" else: geoInfo = "," + "city=" + city gid = gid + 1 #tweet = "GURU," + countryCode + "," + "ip=" + ip + " " + dnsName + asMsg + geoInfo tweet = "GURU,IP " + ip + " => " + dnsName + asMsg + geoInfo if tweet.find("192.168.1.") == -1 : twitter_funcs.addTweetToQueue(tweet,geoip=True) # ****************************************************************
def processHoneyd(line): flowEvent = {} try: #print "\nEntered blackrain_honeyd.processHoneyd()" #print line flowEvent['flowType'] = "FLOW_HONEYD_FLOW" ip = re.findall("\d+\.\d+\.\d+\.\d+", line) if len(ip) == 0: #print "No IP addresses found" return None #else : # print "Found IP addresses..." if not "END" in line: #print "No END honeyd flow found, so return None" return None sIP = re.findall("(\d+\.\d+\.\d+\.\d+)", line)[0] #print sIP sP = re.findall("\d+\.\d+\.\d+\.\d+ (\d+) \d+\.\d+\.\d+\.\d+ \d+", line)[0] #print sP dP = re.findall("\d+\.\d+\.\d+\.\d+ \d+ \d+\.\d+\.\d+\.\d+ (\d+)", line)[0] #print dP flowEvent['flowDirection'] = "in" flowEvent['flowRemoteIP'] = sIP flowEvent['flowRemotePort'] = sP flowEvent['flowHpotPort'] = dP if "icmp" in line: flowEvent['flowProto'] = "I" elif "tcp" in line: flowEvent['flowProto'] = "T" elif "udp" in line: flowEvent['flowProto'] = "UDP" else: flowEvent[ 'flowProto'] = "unknown" # attention : need to test other protocols #flowEvent['flowOS'] = "none" # Optional parameters # =================== #flowEvent['flowDuration'] #flowEvent['flowPkts'] #flowEvent['flowTflags'] = re.findall("fl=(\d+)",line)[0] # Number of bytes received by the honeypot # This does not include the data part of the TCP handshake flowEvent['flowBytes'] = re.findall("rx=(\d+)", line)[0] #print flowEvent # Data enrichment # =============== # DNS info dnsInfo = ipintellib.ip2name(flowEvent['flowRemoteIP']) flowEvent['flowDNS'] = dnsInfo['name'].rstrip('.') #print flowEvent['flowDNS'] # GeoIP info geoIP = ipintellib.geo_ip(flowEvent['flowRemoteIP']) flowEvent['flowCC'] = geoIP['countryCode'] flowEvent['flowCountry'] = geoIP['countryName'] flowEvent['flowCity'] = geoIP['city'] flowEvent['flowLat'] = "%.3f" % float(geoIP['latitude']) flowEvent['flowLong'] = "%.3f" % float(geoIP['longitude']) #print flowEvent['flowCC'] # WHOIS info asInfo = ipintellib.ip2asn(flowEvent['flowRemoteIP']) flowEvent['flowASN'] = asInfo['as'] # AS123 flowEvent['flowISP'] = asInfo[ 'registeredCode'] # Short-form e.g. LEVEL3 flowEvent['flowRoute'] = asInfo['netblock'] flowEvent['flowRIR'] = asInfo['registry'] #print flowEvent['flowASN'] #print flowEvent return flowEvent except Exception, e: msg = "Exception : " + e.__str__() + " in line=" + line print msg syslog.syslog(msg) return None
def processTelnetd(txnId, sensorId, line): try: addInfo1 = None addInfo2 = None line = line.rstrip('\n') #print line.rstrip('\n') if "echo Failed login from" not in line and "echo Successful login from" not in line and "echo Command ran from" not in line: return None #print "--------------------" print "processTelnetd() : " + line username = "" if "Failed" in line: success = False else: success = True ips = re.findall("(\d+\.\d+\.\d+\.\d+)", line) if len(ips) > 0: srcIP = ips[0] else: srcIP = "0.0.0.0" #print "srcIP = " + srcIP geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'].__str__() c = re.findall("with (\S+)\:(\S+) ", line) if len(c) > 0: username = c[0][0] password = c[0][1] #print c.__str__() #print "username : "******"password : "******"login" in line: kojoney_telnetd_idmef.sendTelnetIDMEF(srcIP, "192.168.1.69", "10023", username, password, success, line) # Update attacker database addInfo1 = username addInfo2 = password if success == True: kojoney_attacker_event.generateAttackerEvent( txnId, srcIP, None, sensorId, "GAINED_ACCESS", "TELNETD", None, "Successful login", None, None, None, addInfo1, addInfo2) else: kojoney_attacker_event.generateAttackerEvent( txnId, srcIP, None, sensorId, "ATTACKING", "TELNETD", None, "Failed login attempt", None, None, None, addInfo1, addInfo2) elif "Command" in line: # attacker entered a command c = re.findall("with (\S+)\:(\S+)\: (\S+)", line) if len(c) > 0: #username = c[0][0] #password = c[0][1] cmd = c[0][2] print "telnet command : [" + cmd + "]" addInfo1 = cmd addInfo2 = None kojoney_attacker_event.generateAttackerEvent( txnId, srcIP, None, sensorId, "MAINTAIN_ACCESS", "TELNETD", None, "Attacker entered command", None, None, None, addInfo1, addInfo2) return None except Exception, e: msg = "processTelnetd() : exception : " + e.__str__() print msg syslog.syslog(msg)
def processSpamholed(line): try: line = line.rstrip('\n') #if "MAIL FROM:" not in line and "Receved: from " not in line : if "connection count " in line: a = re.findall( "(\d+\.\d+\.\d+\.\d+) hole=(\d+) connection count (\d+)", line) if len(a) > 0: #print a.__str__() srcIP = a[0][0] hole = a[0][1] count = a[0][2] else: srcIP = "0.0.0.0" hole = -1 count = -1 geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'].__str__() print "spammer IP : " + srcIP print "spammer country code : " + countryCode print "hole flag : " + hole print "spammer connection count : " + count if "allowing e-mail passthrough" in line: passthrough = True else: passthrough = False kojoney_spamholed_idmef.sendSpamholedIDMEF(srcIP, "192.168.1.61", "10025", "Spammer connected", count, passthrough, line) elif "HELO" in line.upper() or "EHLO" in line.upper(): a = re.findall("(\d+\.\d+\.\d+\.\d+) HOLETAG5:(.*)", line) if len(a) > 0: #print a.__str__() srcIP = a[0][0] ehloStr = a[0][1] geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'].__str__() #print "********************" print "spammer IP : " + srcIP print "spammer country code : " + countryCode print "EHLO message : " + ehloStr kojoney_spamholed_idmef.sendSpamholedEhloIDMEF( srcIP, "192.168.1.61", "10025", "Spammer said EHLO", ehloStr, line) elif "HOLETAG5:MAIL FROM:" in line.upper(): a = re.findall("(\d+\.\d+\.\d+\.\d+) holetag5:mail from:(.*)", line.lower()) if len(a) > 0: #print a.__str__() srcIP = a[0][0] spammerEmail = a[0][1] geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'].__str__() print "*****************************" print "spammer IP : " + srcIP print "spammer country code : " + countryCode print "spammer email : " + spammerEmail kojoney_spamholed_idmef.sendSpamholedMailfromIDMEF( srcIP, "192.168.1.61", "10025", "Spammer said MAIL:FROM", spammerEmail, line) return None except Exception, e: msg = "exception : " + e.__str__() print msg syslog.syslog("kojoney_spamhole_parse.py : processSpamholed() : " + ` e ` + " line=" + line)
def processSebekTweet(line): ftpInfo = {} line = line.strip("\n") print "entered processSebekTweet() with line=" + line try: filtered = filter_sebek.filterSebek(line) print "processSebekTweet() : filtered = " + filtered # missing step is to normalise the sebek line i.e. to remove [BS] etc. if len(filtered) > 0: #msg = "Honeypot access:" + filtered msg = filtered #print "tweet before compression : " + msg sendTweet(msg) # file needs to be touched - is this the daily file ? fpOut = open(r'/home/var/log/kojoney_tail_tweets.csv', 'a') print >> fpOut, msg fpOut.close() # for sebek lines containing "wget", perform additional analysis on destination URL if filtered.find("wget") != -1: print "kojoney_tweet.py : processSebekTweet() : wget found" url = extract_url.extractURL(filtered) # Normalise URL o = urlparse(url) domain = "127.0.0.1" path = "" if o.scheme == 'ftp': ftpInfo = extract_url.extractDomainFTP(url) domain = ftpInfo['domain'] path = ftpInfo['path'] elif len(url) != 0: domain = o.netloc path = o.path # Tweet additional info if a valid URL was found if len(url) != 0: # Get IP from DNS info dnsInfo = ipintellib.ip2name(domain) srcIP = dnsInfo['name'].rstrip( '.') # right-strip the trailing . # WHOIS asInfo = ipintellib.ip2asn(srcIP) # asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo[ 'registeredCode'] # Short-form e.g.ARCOR # GeoIP information - faster than WHOIS for looking up Country Code information geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP[ 'longitude'] # Used to calc approx. localtime #latitude = geoIP['latitude'] msg = "URL_FOUND," + url + "->" + \ "IP=" + srcIP + \ ",WHOIS=" + asNum + " (" + asRegisteredCode + ")" + \ ",GeoIP=" + countryCode + " " + city + " " + "%.2f" % longitude + "E" print msg sendTweet(msg) # file needs to be touched - see above fpOut = open(r'/home/var/log/kojoney_tail_tweets.csv', 'a') print >> fpOut, msg fpOut.close() # for sebek lines containing an IP address, perform additional analysis # only searches for 1 IP address pat = r'\d+\.\d+\.\d+\.\d+' # locate a number of IP addresses ips = re.findall(pat, filtered) print "first IP address found = " + ` ips[0] ` if len(ips) != 0: ip = ips[0] # Get DNS name dnsInfo = ipintellib.ip2name(ip) dnsName = dnsInfo['name'].rstrip( '.') # right-strip the trailing . # WHOIS asInfo = ipintellib.ip2asn(ip) # asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo[ 'registeredCode'] # Short-form e.g.ARCOR # GeoIP information - faster than WHOIS for looking up Country Code information geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP[ 'longitude'] # Used to calc approx. localtime #latitude = geoIP['latitude'] msg = "IP_ADDR_FOUND," + ip + "->" + \ "DNS=" + dnsName + \ ",WHOIS=" + asNum + " (" + asRegisteredCode + ")" + \ ",GeoIP=" + countryCode + " " + city + " " + "%.2f" % longitude + "E" print msg sendTweet(msg) # file needs to be touched - see above fpOut = open(r'/home/var/log/kojoney_tail_tweets.csv', 'a') print >> fpOut, msg fpOut.close() else: #print "tweet filtered out : " + line pass except Exception, e: syslog.syslog( "kojoney_tweet.py : processSebekTweet() exception caught = " + ` e ` + " line=" + line)
def updateAttackerOIDsNetflow(attacker,line) : try : #print "attacker['IP'] is " + attacker['IP'].__str__() if line.find("dir=in") == -1 : return print "----" #print "attacker_statd.py : updateAttackerOIDsNetflow() : INCOMING : line=" + line[0:120] + "..." pat1 = 'dIP=(\d+\.\d+\.\d+\.\d+)' pat2 = 'sIP=(\d+\.\d+\.\d+\.\d+)' dip = re.findall(pat1,line) sip = re.findall(pat2,line) if len(dip) < 1 or len(sip) < 1 : # could not find both a source IP and a dest IP return #print "attacker_statd.py : sip = " + sip.__str__() #print "attacker_statd.py : dip = " + dip.__str__() if dip[0] in honeypotIPs : #print "destination IP : " + dip[0] + " is a honeynet IP" #print "source IP : found attacker sIP : " + sip[0] # case 1 : update list of unique source IPs srcIP = sip[0] #print srcIP # Weed out comms with Twitter, Google etc. print "attacker_statd.py : called hiddenIP() with IP = " + srcIP if kojoney_hiddenip.hiddenIP(srcIP) == True : print "attacker_statd.py : srcIP " + srcIP + " is not a real attacker since hiddenIP()=True, so ignore" return else: print "attacker_statd.py : srcIP " + srcIP + " is an attacker since hiddenIP()=False, so update SNMP stats" if srcIP not in attacker['IP'] : #print srcIP + " not seen before" temp = attacker['IP'] temp.append(srcIP) attacker['IP'] = temp #print "attacker['IP'] updated to : " + attacker['IP'].__str__() # increment number of unique IPs found num = len(attacker['IP']) attacker['NUM_IP'] = num msg = "attacker['NUM_IP'] updated to " + attacker['NUM_IP'].__str__() + " by adding " + srcIP #print msg #syslog.syslog(msg) # case 2 : update list of unique country codes and cities geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'] city = geoIP['city'] if countryCode not in attacker['CC'] : #print "attacker countryCode " + countryCode + " not seen before" temp = attacker['CC'] temp.append(countryCode) attacker['CC'] = temp msg = "attacker['CC'] updated to : " + attacker['CC'].__str__() #print msg # increment number of unique CCs found num = len(attacker['CC']) attacker['NUM_CC'] = num msg = "attacker['NUM_CC'] updated to " + attacker['NUM_CC'].__str__() + " by adding " + countryCode #print msg #syslog.syslog(msg) if city not in attacker['CITY'] : #print "attacker city " + city + " not seen before" temp = attacker['CITY'] temp.append(city) attacker['CITY'] = temp msg = "attacker['CITY'] updated to : " + attacker['CITY'].__str__() #print msg # increment number of unique cities found num = len(attacker['CITY']) attacker['NUM_CITY'] = num msg = "attacker['NUM_CITY'] updated to " + attacker['NUM_CITY'].__str__() + " by adding " + city #print msg #syslog.syslog(msg) # case 3 : update list of unique AS numbers asInfo = ipintellib.ip2asn(srcIP) asn = asInfo['as'] if asn not in attacker['ASN'] : #print "attacker ASN " + asn + " not seen before" temp = attacker['ASN'] temp.append(asn) attacker['ASN'] = temp msg = "attacker['ASN'] updated to : " + attacker['ASN'].__str__() #print msg # increment number of unique AS numbers num = len(attacker['ASN']) attacker['NUM_ASN'] = num msg = "attacker['NUM_ASN'] updated to " + attacker['NUM_ASN'].__str__() #print msg #syslog.syslog(msg) # case 4 : update list of unique /24 slash24 = ipintellib.getSlash24(srcIP) if slash24 not in attacker['SLASH_24'] : #print "attacker /24 " + slash24 + " not seen before" temp = attacker['SLASH_24'] temp.append(slash24) attacker['SLASH_24'] = temp msg = "attacker['SLASH_24'] updated to : " + attacker['SLASH_24'].__str__() #print msg # increment number of unique AS numbers num = len(attacker['SLASH_24']) attacker['NUM_SLASH_24'] = num msg = "attacker['NUM_SLASH_24'] updated to " + attacker['NUM_SLASH_24'].__str__() + " by adding " + slash24 #print msg #syslog.syslog(msg) else: print "attacker_statd.py : dstIP " + dip[0] + " not found in honeypotList=" + honeypotIPs.__str__() + ", so no need to update attacker SNMP stats" # All done so return return except Exception,e: msg = "attacker_statd.py : updateAttackerOIDsNetflow() : exception caught = " + `e` + " line=" + line print msg syslog.syslog(msg)
def test(): print "\n\n\n\n" print "==========================" print "p0f logfile to Reputation " print "==========================" print "Library version : " + ipintellib.getVersion() print "Hard-coded tests" print "----------------" # IP to DNS name ipStr = "217.41.27.169" # My IP dnsInfo = ipintellib.ip2name(ipStr) # resolve get DNS name print ipStr + " resolves to " + dnsInfo['name'] # DNS name to IP ipStr = "www.openbsd.org" dnsInfo = ipintellib.ip2name(ipStr) # resolve get DNS name print ipStr + " resolves to " + dnsInfo['name'] # input file : file of IPs (hand-crafted) fpIn = open(r'/home/var/log/p0f.log', 'r') # output file fpOut0 = open(r'/home/var/log/p0f2reputation.out.csv', 'w') # Main loop #logs = {} asInfo = {} dnsInfo = {} # Logging file #logging.basicConfig(level=logging.INFO,filename='botclientsyslog.py.log') #logging.info('SYSLOG log file analysis started') lineCounter = -1 while True: lineCounter = lineCounter + 1 ############################### # if lineCounter >= 3000: # sys.exit(0) ############################### line1 = fpIn.readline() if not line1: break if line1[0] == '#': # ignore leading # comment #print "Ignore # comment" continue if line1.find( "distance") == -1: # all valid lines have 'distance' in them" continue print "----------------------------------------------" fields = line1.split(' ') print fields numb = len(fields) print "numb fields is " + ` numb ` os = fields[8] # re-write this using regular expressions and make a function so that it can be reused # !!!!!!!!!!!!!!!!!!!!!!! if line1.find("Linux") != -1: if numb == 17: ipStr, port = fields[12].split( ':') # dest IP and dest TCP port number elif numb == 24: ipStr, port = fields[17].split( ':') # dest IP and dest TCP port number elif line1.find("Windows") != -1: if numb == 19: ipStr, port = fields[14].split( ':') # dest IP and dest TCP port number elif line1.find("Novell") != -1: continue # ignore Novell for moment #if numb == 19: # ipStr,port = fields[13].split(':') # dest IP and dest TCP port number else: sys.exit("Failed to parse") print "line=" + ` lineCounter ` + ": *** haxx0r : ip=" + ipStr + " port=" + port + " os=" + os dnsInfo = ipintellib.ip2name(ipStr) # resolve get DNS name asInfo = ipintellib.ip2asn(ipStr) # get AS information from WHOIS whob reputation = ipintellib.ip2reputation( ipStr) # does slow things down... geoIP = ipintellib.geo_ip(ipStr) result = ipStr + "," + dnsInfo['name'].strip('.') + \ "," + asInfo['as'] + ",ASowner=" + asInfo['registeredCode'] + ",ASnetblock=" + asInfo['netblock'] + ",ASregistry=" + asInfo['registry'] + \ ",geoIPcountry=" + geoIP['countryCode'] + ",geoIPcity=" + geoIP['city'] + ",geoIPlat=" + "%.2f" % geoIP['latitude'] + ",geoIPlong=" + "%.2f" % geoIP['longitude'] + \ ",zen.spamhaus=" + reputation['zen.spamhaus.org'] + \ ",dnsbl.ahbl.org=" + reputation['dnsbl.ahbl.org'] + \ ",bl.deadbeef.com=" + reputation['bl.deadbeef.com'] + \ ",bogons.cymru.com=" + reputation['bogons.cymru.com'] + \ ",zombie.dnsbl.sorbs.net=" + reputation['zombie.dnsbl.sorbs.net'] + \ ",bl.spamcop.net=" + reputation['bl.spamcop.net'] + \ ",dul.dnsbl.sorbs.net=" + reputation['dul.dnsbl.sorbs.net'] + \ ",l2.apews.org=" + reputation['l2.apews.org'] + \ ",virus.rbl.msrbl.net=" + reputation['virus.rbl.msrbl.net'] + \ ",phishing.rbl.msrbl.net=" + reputation['phishing.rbl.msrbl.net'] + \ ",images.rbl.msrbl.net=" + reputation['images.rbl.msrbl.net'] + \ ",spam.rbl.msrbl.net=" + reputation['spam.rbl.msrbl.net'] print result print >> fpOut0, ipStr + "," + "os" + reputation['zen.spamhaus.org']
def sendToLoggly(sensorId,line): try : global txnId print "sendToLoggly() : line=" + line # honeytweeter #shakey = "e25e6042-e490-4910-a246-94cefbdd11b9" # honeytweeter-json shakey = "fe39eb54-7c8f-417c-afc8-5b8db98961d3" sdata = {} # Event Type fields = line.split(",") eventType = fields[0] sdata['eventType'] = fields[0] #print sdata['eventType'] # Sensor Name sdata['sensorId'] = sensorId # IP address ips = re.findall("\d+\.\d+\.\d+\.\d+",line) if len(ips) > 0 : sdata['ip'] = ips[0] # GeoIP geoIP = ipintellib.geo_ip(sdata['ip']) cc = geoIP['countryCode'] if cc != "?" : sdata['cc'] = cc.__str__() # Reverse DNS dnsInfo = ipintellib.ip2name(sdata['ip']) dnsName = dnsInfo['name'] if dnsName != "NoDNS": sdata['rdns'] = dnsName.rstrip('.') # ASN info asInfo = ipintellib.ip2asn(sdata['ip']) asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo['registeredCode'].upper() # e.g. GOOGLE sdata['asn'] = "AS" + asNum sdata['isp'] = asRegisteredCode # Snort SID if sdata['eventType'] == "SNORT_NIDS" : sids = re.findall("SID=(\d+)",line) if len(sids) > 0: sdata['sid'] = sids[0] a = re.findall("P(\d+) SID",line) if len(a) > 0 : sdata['priority'] = "P" + a[0] # Clamd malware name - e.g. Exploit.Shellcode.X86-Gen-1 # Jun 27 04:47:39 mars kojoney_tweet_engine[3173]: SENDTWEET = <0>CLAMD,Malware Exploit.Shellcode.X86-Gen-1 in flow from 79.5.203.86 ports={s=4592 d=135} if sdata['eventType'] == "CLAMD" : a = line.split(",Malware ")[1] a = a.split(" ")[0] sdata['malware'] = a sdata['avendor'] = "ClamAV" # Threat Report # submitted=Wed Jun 26 02:54:18 2013 cmd=GEO_IP tweet=REPORT,Threat Level for 203.250.135.20 is 41.1, flags={PR SC PS BH AT GA} if "flags={" in line and sdata['eventType'] == "REPORT" : a = line.split("flags=")[1] #a = a.rstrip("}") sdata['flags'] = a # VirusTotal # submitted=Fri May 17 07:48:03 2013 cmd=BASIC tweet=ANALYST,AV eb7656dd256eb414abe092eb0f41ea1f.php => Norman=PhpShell.BL 17/46 VT=http://bit.ly/14vyont # line=ANALYST,AV 06a940dd7824d6a3a6d5b484bb7ef9d5.php => Unseen by VirusTotal if sdata['eventType'] == "ANALYST" and "AV" in line and "Unseen by" not in line : a = line.split(" => ")[1] b = a.split(" ")[0] # Symantec=Trojan.Usuge!gen3 sdata['avendor'] = b.split("=")[0] sdata['malware'] = b.split("=")[1] b = a.split("VT=")[1] sdata['virustotal'] = b # filename = MD5 name + extension (optional) c = line.split("AV ")[1] c = c.split(" ")[0] #print c if "." in c: c = c.split(".")[0] # lose filename extension sdata['md5'] = c.lower() # Destination port # ---------------- # Snort messages flow = re.findall("\w+\:(\d+) ",line) if len(flow) > 0 : sdata['port'] = int(flow[0]) # IPLOG if sdata['eventType'] == "IPLOG" : ports = re.findall("port (\d+)",line) if len(ports) > 0 : sdata['port'] = int(ports[0]) # CLAMD - clsniffer if sdata['eventType'] == "CLAMD" : ports = re.findall("d=(\d+)",line) if len(ports) > 0 : sdata['port'] = int(ports[0]) # KIPPO if sdata['eventType'] == "KIPPO" : sdata['port'] = 2222 sdata['protocol'] = "tcp" # Glastopf if "WEB" in sdata['eventType'] : sdata['port'] = 18080 sdata['protocol'] = "tcp" # Botjuicer cracked scripts if sdata['eventType'] == "ANALYST" and "BOTJUICER" in line : #if "UNDETERMINED" in line.upper(): # return None #print "BOTJUICER log found : " + line a = re.findall("p=(\d+)",line) if len(a) > 0 : sdata['port'] = int(a[0]) a = re.findall("ch=(#\w+)",line) if len(a) > 0 : sdata['irc'] = a[0] # Protocol - generic if "TCP" in line.upper(): sdata['protocol'] = "tcp" if "UDP" in line.upper(): sdata['protocol'] = "udp" if "ICMP" in line.upper(): sdata['protocol'] = "icmp" # Timestamp sdata['datetime'] = time.ctime() # Message sdata['msg'] = line # Txnid - increment this last, just before submission to Loggly txnId = txnId + 1 sdata['txnId'] = txnId body = json.dumps(sdata) print "sendToLoggly() : JSON body = " + body # Send to Loggly insert_url = "http://logs.loggly.com/inputs/" + shakey insert_http = httplib2.Http(timeout=10) #body = line resp, content = insert_http.request(insert_url, "POST", body=body, headers={'content-type':'text/plain'}) #print "Loggly : resp : " + resp.__str__() #print "Loggly : content : " + content.__str__() #{'status': '200', 'content-length': '18', 'vary': 'Accept-Encoding', 'server': 'TwistedWeb/12.0.0', 'date': 'Tue, 25 Jun 2013 05:55:58 GMT', 'content-type': 'text/html'} #{"response": "ok"} if "ok" in content.__str__() : # bug -> why can't I look at the "response" field in a structured way msg = "Sent to Loggly OK : " + body.__str__() print msg else: msg = "Sent to Loggly FAIL : " + body.__str__() + " error = " + content.__str__() print msg syslog.syslog(msg) # crude form of rate-limiter time.sleep(0.5) except Exception,e: msg = "kojoney_loggly.py : sendToLoggly() : exception : " + e.__str__() + " line=" + line print msg syslog.syslog(msg)
def sendTweetCLI(sessionid, username, ip, cli): global TweetClient global TweetVersion # bump version of format of Tweet changes print "Entered sendTweetCLI()" now = time.time() try: # sessionid of -1 indicates that we have no AUTH_OK event and so no username - so don't tweet it if (int(sessionid) < 0): print "sessionId < 0 -> no previous AUTH_OK event to get username" return p0fInfo = p0fcmd.getP0fInfo(ip, "0", "172.31.0.67", "22") if p0fInfo['result'] == True: # p0f data is available hops = p0fInfo['hops'] os = p0fInfo['genre'] fw = p0fInfo['firewall'] nat = p0fInfo['nat'] if p0fInfo['genre'] == "Linux": uptime = p0fInfo['uptime'] bte = now - int(uptime) # boot time (epoch secs) hops = p0fInfo['hops'] else: uptimeHours = 0 bte = 0 else: # p0f data not read OK hops = 0 os = "?" fw = "?" nat = "?" bte = 0 # get current time timeTuple = time.localtime(now) nowStr = time.asctime(timeTuple) # calc haxx0r bootTime #timeTuple = time.localtime(bte) #bootTimeStr = time.asctime(timeTuple) bteh = int(bte / 3600) # bteh = boot time epoch (hours) # Get DNS info dnsInfo = ipintellib.ip2name(ip) dnsName = dnsInfo['name'] # WHOIS information asInfo = ipintellib.ip2asn(ip) asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo['registeredCode'] # Short-form e.g.ARCOR # GeoIP information geoIP = ipintellib.geo_ip(ip) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP['longitude'] # Used to calc approx. localtime # Compact usual returns if asNum.find("AS-none") != -1: asNum = "?" if asRegisteredCode.find("failed") != -1: asRegisteredCode = "?" if countryCode.find("None") != -1: countryCode = "?" if city.find("None") != -1: city = "?" # Construct Tweet # todo - if os = windoes, do not add bteh msg = "sid=" + `sessionid` + ":IP=" + ip + ":" + asNum + "(" + asRegisteredCode + ")" + ":"\ + countryCode + ":" + city + ":" + "%.2f" % longitude + ":" + os + ":" + hops\ + ":fw=" + fw + ":nat=" + nat + ":bteh=" + `bteh`\ + ":" + username + "@hpot $ " + cli # Send the Tweet - max = 147 ? syslog.syslog("sendTweetCLI(): msg length=" + ` len(msg) ` + " chars") print "Tweet=" + msg # syslog every Tweet attempted to be sent syslog.syslog("sendTweetCLI(): " + msg) # *** Disable during testing *** status = TweetClient.PostUpdate(msg) time.sleep(5) # crude rate-limit ? except Exception, e: syslog.syslog("kojoney_tail.py : sendTweetCLI() exception caught = " + ` e ` + " ip=" + ip)
def processHoneytrap(txnId, sensorId, line): try: line = line.rstrip("\n") print "processHoneytrap() : line read is " + line # Only interested in certain events #if line.find("Connection from ") == -1 and line.find(" attack string from ") == -1 : if line.find(" attack string from " ) == -1: # only interested if attacker sends data return None # Where is the attack coming from ? fields = re.findall("(\d+\.\d+\.\d+\.\d+)\:(\d+)", line) if len(fields) > 0: srcip = fields[0][0] srcPort = fields[0][1] else: srcip = "None" srcPort = "None" #print "srcIP = " + srcip #print "srcPort = " + srcPort fields = re.findall("(\d+) bytes attack string from", line) if len(fields) > 0: bytes = fields[0] else: bytes = "0" #print "bytes = " + bytes fields = re.findall("(\d+)\/tcp", line) if len(fields) > 0: dport = fields[0] else: dport = "None" #print "dport = " + dport dstip = "192.168.1.60" # bug -> hard-coded dst IP # Not interested in events originating from LAN print "*** kojoney_honeytrap_parse.py : calling hiddenIP() ***" if kojoney_hiddenip.hiddenIP(srcip) == True: return None p0fDict = kojoney_p0f_lib.getp0f(srcip, dstip, dport) if p0fDict != None: p0f = " p0f=" + p0fDict['genre_short'] + " hops=" + p0fDict[ 'hops'] + " up=" + p0fDict['uptime'] else: p0f = "" tweet = "HTRAP," + srcip + ":" + srcPort + " -> " + dstip + ":" + dport + " [bytes=" + bytes + p0f + "]" # bug -> hard-coded dest IP !!! print tweet geoIP = ipintellib.geo_ip(srcip) countryCode = geoIP['countryCode'].__str__() kojoney_honeytrap_idmef.sendHoneytrapIDMEF(srcip, dstip, dport, p0f, line) # Update Attacker Database addInfo1 = "proto=TCP:dPort=" + dport.__str__( ) + ":" + "bytes=" + bytes.__str__() addInfo2 = None attackerIP = srcip kojoney_attacker_event.generateAttackerEvent( txnId, attackerIP, p0fDict, sensorId, "SCANNING", "HONEYTRAP", None, "Established incoming connection", None, None, None, addInfo1, addInfo2) # Replace destination IP with text tweet = kojoney_snort_funcs.snortTwittifyLite(tweet) return None # no need to Tweet now we have SIEM #return tweet except Exception, e: msg = "kojoney_honeytrap_parse.py : processHoneytrap() : " + ` e ` + " line=" + line print msg syslog.syslog(msg) return None
def test_geo_ip(ip, countryCode, countryName, city): ip_info = ipintellib.geo_ip(ip) assert ip_info['countryCode'] == countryCode assert ip_info['countryName'] == countryName assert ip_info['city'] == city
def processMessages(line): try: line = line.strip("\n") #print "processMessages() : line read from /var/log/messages : " + line if line.find("from 192.168.1." ) != -1: # do not log legitimate local LAN access return if line.find("mars sshd") == -1: return if line.find("Accepted password for") == -1: return print "processMessages() : candidate line read from /var/log/messages : " + line # Parse # ----- pat = r'\d+\.\d+\.\d+\.\d+' # locate a number of IP addresses ips = re.findall(pat, line) #fields=line.split(" ") #print fields # locate username #username = fields[9] pat = r'password for (\w+)' # locate a number of IP addresses username = re.findall(pat, line)[0] print "kojoney_tweet.py : processMessages() : username is " + username srcIP = ips[0] #dstIP = "HPOT" dstIP = "172.31.0.67" dstPort = "22" proto = "6" # Tevent = "user="******"kojoney_tweet.py : processMessages() : p0f input is srcIP=" + srcIP + " dstIP=" + dstIP + " dstPort=" + dstPort p0fInfo = p0fcmd.getP0fInfo(srcIP, "0", dstIP, dstPort) # 0 = wildcard the srcPort if p0fInfo['result'] == True: # p0f data is available os = p0fInfo['genre'] nat = p0fInfo['nat'][0] hops = p0fInfo['hops'] else: os = "?" nat = "?" hops = "?" # Get DNS info dnsInfo = ipintellib.ip2name(srcIP) dnsName = dnsInfo['name'].rstrip('.') # right-strip the trailing . # WHOIS asInfo = ipintellib.ip2asn(srcIP) # asNum = asInfo['as'] # AS123 asRegisteredCode = asInfo['registeredCode'] # Short-form e.g.ARCOR # GeoIP information - faster than WHOIS for looking up Country Code information geoIP = ipintellib.geo_ip(srcIP) countryCode = geoIP['countryCode'] city = geoIP['city'] longitude = geoIP['longitude'] # Used to calc approx. localtime latitude = geoIP['latitude'] msg = "INTRUSION" + \ ",user="******",IP=" + srcIP + \ ",p0f=" + os + " NAT=" + nat + " hops=" + hops + \ ",DNS=" + dnsName + \ ",WHOIS=" + asNum + " (" + asRegisteredCode + ")" + \ ",GeoIP=" + countryCode + " " + city + " " + "%.2f" % longitude + "E" print "tweet before compression : " + msg sendTweet(msg) except Exception, e: syslog.syslog( "kojoney_tweet.py : processMessages() exception caught = " + ` e ` + " line=" + line)
def test_geo_ip_bad_1(): ip_info = ipintellib.geo_ip("0.0.0.0.0.0.0") assert ip_info['city'] == 'None'
def passerViz(line): try: print "---" version = "?" os = "?" #print "Entered passerViz() : " + line line = line.rstrip("\n") fields = line.split(",") print fields ip = fields[1] port = fields[2] info = fields[4] geoIP = ipintellib.geo_ip(ip) cc = geoIP['countryCode'] print cc print "info(raw) = " + info infoRaw = info info = info.replace("/",":") print "ip = " + ip print "port = " + port info = info.replace("protocol ","protocol_") info = info.replace(":::",":") info = info.replace(" beta","beta") info = info.replace("Microsoft IIS SSL","MS_IIS_SSL") info = info.replace("Microsoft IIS","MS_IIS") info = info.replace("Microsoft Windows RPC","MS_RPC") info = info.replace("Microsoft Windows daytime","MS_TIME") info = info.replace("Microsoft SQL Server","MS_SQL") info = info.replace("Microsoft Terminal Service","MS_TS") info = info.replace("Microsoft DNS","MS_DNS") info = info.replace("Microsoft ftpd","MS_FTPD") info = info.replace("Apache Jserv","JSERV") info = info.replace("Internet Rex","REX") info = info.replace("Courier pop3d","COURIER_POP3D") info = info.replace("Postfix smtpd","POSTFIX_SMTPD") info = info.replace("Linux telnetd","LINUX_TELNETD") info = info.replace("Linux SNMP multiplexer","LINUX_SMUX") info = info.replace("Cisco SSH","CISCO_SSH") info = info.replace("Cisco IOS http","CISCO_HTTPD") info = info.replace("Cisco SIP Gateway","CISCO_SIP") info = info.replace("Oracle HTTP Server","ORACLE_HTTPD") info = info.replace("Oracle XML DB Enterprise","ORACLE_XML_DB") info = info.replace("ISC BIND","BIND") info = info.replace("SCS sshd","SCS_SSHD") info = info.replace("osiris host IDS agent","OSIRIS_AGENT") print "info(post) = " + info infofields = info.split(" ") print "infofields = " + infofields.__str__() for i in infofields : #print "i = " + i.__str__() if i.find(":p:") >= 0 : program = i.rstrip(":") program = i.lstrip(":") # program = program.replace("http:p:","") program = program.replace("ssl:p:","") program = program.replace("mysql:p:","") program = program.replace("msrpc:p:","") program = program.replace("http-proxy:p:","") program = program.replace("proxy:p:","") program = program.replace("openSSH:p:","") program = program.replace("imap:p:","") program = program.replace("ajp13:p:","JSERV") program = program.replace("ms-sql-s:p:","SQL") program = program.replace("pop3:p:","POP3") program = program.replace("telnet:p:","TELNETD") program = program.replace("ident:p:","") program = program.replace("smtp:p:","") program = program.replace("ftp:p:","") program = program.replace("dominoconsole:p:","-") #program = program.replace("domain:p:","DNS") program = program.replace("microsoft-ds:p:","") #program = program.replace("ssh:p:","SSH") program = program.replace("nagios-nsca:p:","") print "program found in " + i.__str__() + " is " + program.__str__() if i.find("v:") >= 0 : version = i.rstrip(":") version = version.lstrip(":") version = version.replace("v:","") print "version found in " + i.__str__() + " is " + version.__str__() if i.find("i:") >= 0 : info = i.rstrip(":") info = info.lstrip(":") info = info.replace("protocol_","") print "info found in " + i.__str__() + " is " + info.__str__() if i.find("o:") >= 0 : os = i.rstrip(":") os = os.lstrip(":") os = os.replace("Windows","W") os = os.replace("Linux","L") os = os.replace("Unix","U") os = os.replace("IOS","I") os = os.replace("o:","") os = os.rstrip("\n") print "os found in " + i.__str__() + " is " + os.__str__() now = time.time() nowLocal = time.gmtime(now) tstamp = time.asctime(nowLocal) msg = "passerViz() : ip=" + ip.__str__() + " port=" + port.__str__() + " program=" + program.__str__() + " os=" + os.__str__() syslog.syslog(msg) fp = open("/home/var/secviz/passer.csv","a") msg1 = port + "," + program + "," + tstamp + "," + infoRaw print msg1 print >> fp, msg1 msg2 = program + version + "," + program + "," + tstamp + "," + infoRaw print msg2 print >> fp, msg2 msg3 = ip + ":" + cc + ":" + os + "," + program + version + "," + tstamp + "," + infoRaw print msg3 print >> fp, msg3 fp.close() except Exception,e: msg = "kojoney_passer_parse.py : passerViz() : " + `e` + " line=" + line syslog.syslog(msg) return None