def fetch_sniffer_session(self, session_id): try: debug_output("Fetching session {} from memory".format(session_id)) session = self.sessions.get(ObjectId(session_id)) except Exception as e: debug_output("An {} error occurred when fetching session '{}': {}".format(type(e).__name__, session_id, e), 'error') return # if not found, recreate it from the DB if not session: debug_output("Fetching session {} from DB".format(session_id)) s = self.model.get_sniffer_session(session_id) if not s: return None # TLS interception only possible if PCAP hasn't been generated yet intercept_tls = s['intercept_tls'] and not s['pcap'] if s: session = SnifferSession(s['name'], None, None, self, id=s['_id'], filter_restore=s['filter'], intercept_tls=intercept_tls) session.pcap = s['pcap'] session.public = s['public'] session.date_created = s['date_created'] self.sessions[session.id] = session session_data = bson_loads(s['session_data']) session.nodes = session_data['nodes'] session.edges = session_data['edges'] session.packet_count = s['packet_count'] session.flows = {} for flow in session_data['flows']: f = Flow.load_flow(flow) session.flows[f.fid] = f return session
def handlePacket(self, pkt): IP_layer = IP if IP in pkt else IPv6 # add IPv6 support another night... if IP_layer == IPv6: return self.pkts.append(pkt) self.packet_count += 1 elts = [] edges = [] # FLOW ANALYSIS - reconstruct TCP flow if possible # do flow analysis here, if necessary - this will be replaced by dpkt's magic if TCP in pkt or UDP in pkt: Flow.pkt_handler(pkt, self.flows) flow = self.flows[Flow.flowid(pkt)] self.send_flow_statistics(flow) new_elts, new_edges = self.checkHTTP(flow) if new_elts: elts += new_elts if new_edges: edges += new_edges # end flow analysis # STANDARD PACKET ANALYSIS - extract IP addresses and domain names # the magic for extracting elements from packets happens here new_elts, new_edges = self.checkIP(pkt) # pass decode information if found if new_elts: elts += new_elts if new_edges: edges += new_edges new_elts, new_edges = self.checkDNS(pkt) if new_elts: elts += new_elts if new_edges: edges += new_edges # TLS MITM - intercept TLS communications and send cleartext to malcom # We want to be protocol agnostic (HTTPS, FTPS, ***S). For now, we choose which # connections to intercept based on destination port number # We could also catch ALL connections and MITM only those which start with # a TLS handshake tlsports = [443] if TCP in pkt and pkt[TCP].flags & 0x02 and pkt[TCP].dport in tlsports and not self.pcap and self.intercept_tls: # of course, interception doesn't work with pcaps # mark flow as tls flow.tls = True # add host / flow tuple to the TLS connection list debug_output("TLS SYN: {}:{} -> {}:{}".format(pkt[IP].src, pkt[TCP].sport, pkt[IP].dst, pkt[TCP].dport)) # this could actually be replaced by only flow self.tls_proxy.hosts[(pkt[IP].src, pkt[TCP].sport)] = (pkt[IP].dst, pkt[TCP].dport, flow.fid) self.tls_proxy.factory.flows[flow.fid] = flow if elts != [] or edges != []: self.send_nodes(elts, edges) # send individual packets to modules in case they use them for mod in self.modules.values(): mod.on_packet(pkt)