def __init__(self, tcpPortscans, udpPortscans, policyViolations, suspPolVio): self.tcpPortscans = tcpPortscans self.udpPortscans = udpPortscans self.policyViolations = policyViolations self.portscans = RuleSet() self.doubleIPs = IPsMap() self.portscanIPs = IPsMap() self.violationIPs = IPsMap() self.clearedPolicyViolations = RuleSet() self.suspPolVio = suspPolVio.split(":")
def _packetHandler(self, buf, ts): """Parse a pcap buffer""" SINGLE_IP_SLASHSIZE = 32 try: if (self.p.datalink() == self.PFLOG_DUMP): #pkt = dpkt.pflog.Pflog(buf) pkt = Pflog(buf) self.interface = pkt.interfaceName self.direction = "in" if pkt.direction == 1 else "out" subpkt = pkt.data try: subpkt = dpkt.ip.IP(subpkt) except: #skip non IP packets return else: pkt = dpkt.ethernet.Ethernet(buf) subpkt = pkt.data if not isinstance(subpkt, dpkt.ip.IP): #skip non IP packets return proto = subpkt.p shost = socket.inet_ntoa(subpkt.src) dhost = socket.inet_ntoa(subpkt.dst) shostInner = False dhostInner = False if self.innerNetworks != None: for n in self.innerNetworks: slashSize = str(n).split("/")[1] if IPv4Network(str(shost)+"/"+str(slashSize)) == n: shostInner = True if IPv4Network(dhost+"/"+slashSize) == n: dhostInner = True if shostInner and dhostInner: self.direction = "none-inner" elif shostInner and not dhostInner: self.direction = "out" elif not shostInner and dhostInner: self.direction = "in" else: self.direction = "none-outer" except dpkt.Error: #skip non-ethernet packages return try: if proto == socket.IPPROTO_TCP: try: tcp = subpkt.data flag = tcp.flags if self.connectionChecking: rightFlag = ((flag == dpkt.tcp.TH_SYN) \ or (flag & dpkt.tcp.TH_FIN != 0)) else: rightFlag = (flag == dpkt.tcp.TH_SYN) dport = tcp.dport sport = tcp.sport sIP = IPsMap(self.saveElements) sIP.insert(IPv4Address(shost)) sPort = PortsMap(self.MAX_NUM_PORTS_ANY, self.saveElements) sPort.insert(Port(sport, True)) dIP = IPsMap(self.saveElements) dIP.insert(IPv4Address(dhost)) dPort = PortsMap(self.MAX_NUM_PORTS_ANY, self.saveElements) dPort.insert(Port(dport, False)) if flag == dpkt.tcp.TH_SYN: flag = "SYN" else: flag = "FIN" r = Rule(self.direction, sIP, sPort, dIP, dPort, "tcp", \ self.interface, self.action, self.style, [ts, ], [flag, ]) if self.p.datalink() == self.PFLOG_DUMP or rightFlag: self.tcpRuleSet.insert(r) if self.ddosDetection: self.tcpRuleList.append((IPv4Address(shost), ts)) except AttributeError: #skip broken packages return elif proto == socket.IPPROTO_UDP: udp = subpkt.data dport = udp.dport sport = udp.sport sIP = IPsMap(self.saveElements) sIP.insert(IPv4Address(shost)) sPort = PortsMap(self.MAX_NUM_PORTS_ANY, self.saveElements) sPort.insert(Port(sport, True)) dIP = IPsMap(self.saveElements) dIP.insert(IPv4Address(dhost)) dPort = PortsMap(self.MAX_NUM_PORTS_ANY, self.saveElements) dPort.insert(Port(dport, False)) r = Rule(self.direction, sIP, sPort, dIP, dPort, "udp", \ self.interface, self.action, self.style, [ts, ]) self.udpRuleSet.insert(r) if self.ddosDetection: self.udpRuleList.append((IPv4Address(shost), ts)) elif proto == socket.IPPROTO_ICMP: sIP = IPsMap(self.saveElements) sIP.insert(IPv4Address(shost)) sPort = PortsMap(self.MAX_NUM_PORTS_ANY) sPort.insert(Port(-1, True)) dIP = IPsMap(self.saveElements) dIP.insert(IPv4Address(dhost)) dPort = PortsMap(self.MAX_NUM_PORTS_ANY) dPort.insert(Port(-1, False)) r = Rule(self.direction, sIP, sPort, dIP, dPort, "icmp", \ self.interface, self.action, self.style, [ts, ]) self.icmpRuleSet.insert(r) if self.ddosDetection: self.icmpRuleList.append((IPv4Address(shost), ts)) except dpkt.Error: return
class InfectedHostsDetector: """ InfectedHostsDetector takes found portscans and policy violations and tries to find indected hosts. """ def __init__(self, tcpPortscans, udpPortscans, policyViolations, suspPolVio): self.tcpPortscans = tcpPortscans self.udpPortscans = udpPortscans self.policyViolations = policyViolations self.portscans = RuleSet() self.doubleIPs = IPsMap() self.portscanIPs = IPsMap() self.violationIPs = IPsMap() self.clearedPolicyViolations = RuleSet() self.suspPolVio = suspPolVio.split(":") def detectInfectedHosts(self): for ps in self.tcpPortscans.portscanSet: if ps.direction == "out" or ps.direction == "none-inner": self.portscans.insert(ps) for ps in self.udpPortscans.portscanSet: if ps.direction == "out" or ps.direction == "none-inner": self.portscans.insert(ps) for pv in self.policyViolations: if pv.direction == "out" or pv.direction == "none-inner": if str(pv.dPorts.values()[0].portNumber) in self.suspPolVio: self.clearedPolicyViolations.insert(pv) for portscan in self.portscans: for violation in self.clearedPolicyViolations: if portscan.sIPs == violation.sIPs: self.doubleIPs.insert(portscan.sIPs) for doubleIP in self.doubleIPs: for policyVio in self.clearedPolicyViolations.values(): if policyVio.sIPs == doubleIP: try: self.clearedPolicyViolations.remove(policyVio) except: # already removed pass for doubleIP in self.doubleIPs: for portscan in self.portscans.values(): if portscan.sIPs == doubleIP: try: self.portscans.remove(portscan) except: # already removed pass for violation in self.clearedPolicyViolations: self.violationIPs.insert(violation.sIPs) for portscan in self.portscans: self.portscanIPs.insert(portscan.sIPs) def printInfectedHosts(self): for host in self.doubleIPs: print "%s might be infected! Warning signals include: portscans and policy violations" % str(host) for host in self.portscanIPs: print "%s might be infected! Warning signals include: portscans" % str(host) for host in self.violationIPs: print "%s might be infected! Warning signals include: policy violations" % str(host)
def _ipsVaryIteration(self, ruleSet, sIPvarying): """If sIP=True, the checks are made assuming sIP ist the varying part else, the check are made assuming dIP is the varying part. The checks work like this: 1. The key for a rule are the ports. 2. If the key (ports) is not in sortingDict, the rule is added to sortingDict and to tablesDict. 3. If the key (ports) is already added, it is checked if the new rule is belonging to the rule already added. Belonging to is defined as that: 3.1 If, by putting the rule together, they would have the same IP on both sides (source/destination) they don't belong together. 3.2 If the IPs don't belong into the same size slashSize networks, the rules don't belong together. 4. If the rule can be put together by making the existing IPs into size slashsize networks, the IPs are made into networks. 5. If a rule has its key already in the dict, but can not be matched to the existing rule, it is put into the restSet. sPorts/dPorts exist in key and value, because they could be the same ("any") as the one already in the hashmap and still contain different elements. To provide a correct elements list they needs to be extended. """ self.sortingDict.clear() self.tablesDict.clear() newR = RuleSet() restSet = RuleSet() for r in ruleSet: if sIPvarying: value = [r.sIPs, r.dIPs, r.sPorts, r.dPorts, r.timeStamp, r.flag] else: value = [r.dIPs, r.sIPs, r.sPorts, r.dPorts, r.timeStamp, r.flag] key1 = copy.deepcopy(r.dPorts) key2 = copy.deepcopy(r.sPorts) keys = (r.direction, key1, r.interface, r.action, key2) if keys not in self.sortingDict: self.sortingDict[keys] = value self.tablesDict[keys] = value else: tmpIPs1 = IPsMap() tmpIPs1.extend(value[0]) tmpIPs1.extend(self.tablesDict[keys][0]) tmpIPs2 = IPsMap() tmpIPs2.extend(value[1]) tmpIPs2.extend(self.tablesDict[keys][1]) sPortsRandom = value[2].isRandomized and\ self.tablesDict[keys][2].isRandomized \ or not value[2].isRandomized and not \ self.tablesDict[keys][2].isRandomized if not tmpIPs1.ipInBoth(tmpIPs2) and sPortsRandom \ and self.tablesDict[keys][1].checkForJoinedNetwork(value[1], self.SLASH_SIZE): self.tablesDict[keys][0].extend(value[0]) self.tablesDict[keys][2].extend(value[2]) self.tablesDict[keys][3].extend(value[3]) if self.proto == "tcp": self.tablesDict[keys][5].extend(value[5]) else: if sIPvarying: restSet.insert(Rule(keys[0], value[0], value[2], \ value[1], value[3], self.proto, keys[2], keys[3], self.style, value[4], value[5])) else: restSet.insert(Rule(keys[0], value[1], value[2], \ value[0], value[3], self.proto, keys[2], keys[3], self.style, value[4], value[5])) for key, value in self.tablesDict.iteritems(): if sIPvarying: newR.insert(Rule(key[0], value[0], value[2], value[1], \ value[3], self.proto, key[2], key[3], self.style, value[4], value[5])) else: newR.insert(Rule(key[0], value[1], value[2], value[0], \ value[3], self.proto, key[2], key[3], self.style, value[4], value[5])) return newR, restSet