def create_socket_address(self,hostname,port,ip_address,ip_cat=Address.CAT_IPV4,layer4_protocol='TCP',is_domain_name=True,hostname_value=None,naming_system=None): socket = SocketAddress() socket.ip_address = Address(address_value=ip_address,category=ip_cat) socket.port = Port() socket.port.port_value=port socket.port.layer4_protocol =layer4_protocol socket.hostname = Hostname() socket.hostname.is_domain_name=is_domain_name socket.hostname.hostname_value = hostname_value socket.hostname.naming_system = naming_system return socket
def create_network_connection_closed_observable(ct): obj = NetworkConnection() obj.creation_time = d[ct]['timestamp'] sock = SocketAddress() sock.ip_address = d[ct]['src_ip'] obj.source_socket_address = sock obj.custom_properties = CustomProperties() create_custom_properties(obj, "Event_Name", d[ct]['eventid']) create_custom_properties(obj, "Message", d[ct]['message']) create_custom_properties(obj, "Service", d[ct]['system']) create_custom_properties(obj, "Host", d[ct]['sensor']) create_custom_properties(obj, "session_Duration", d[ct]['duration']) return obj
def TCPConnectionEstablishedObj(tcpinfo): networkconnection = NetworkConnection() networkconnection.layer3_protocol = "IPv4" networkconnection.layer4_protocol = "TCP" if tcpinfo[0] != VMIP: # incoming connection networkconnection.destination_tcp_state = "ESTABLISHED" ssocketaddress = SocketAddress() ssocketaddress.ip_address = tcpinfo[0] sport = Port() sport.port_value = tcpinfo[2] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif tcpinfo[1] != VMIP: # outgoing connection networkconnection.source_tcp_state = "ESTABLISHED" dsocketaddress = SocketAddress() dsocketaddress.ip_address = tcpinfo[1] dport = Port() dport.port_value = tcpinfo[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator = Indicator() indicator.title = "TCP Connection Established" indicator.description = ( "An indicator containing information about a successful TCP hand shake" ) indicator.set_produced_time(utils.dates.now()) indicator.add_object(networkconnection) return indicator
def UDPRequestObj(udpinfo): u = NetworkConnection() u.layer3_protocol = "IPv4" u.layer4_protocol = "UDP" ssocketaddress = SocketAddress() if udpinfo[3] != VMIP: ssocketaddress.ip_address = udpinfo[3] sport = Port() sport.port_value = udpinfo[0] sport.layer4_protocol = "UDP" ssocketaddress.port = sport u.source_socket_address = ssocketaddress dsocketaddress = SocketAddress() if udpinfo[2] != VMIP: dsocketaddress.ip_address = udpinfo[2] dport = Port() dport.port_value = udpinfo[1] dport.layer4_protocol = "UDP" dsocketaddress.port = dport u.destination_socket_address = dsocketaddress indicator = Indicator() indicator.title = "UDP connection" indicator.description = ( "An indicator containing information about a UDP connection") indicator.set_produced_time(utils.dates.now()) indicator.add_object(u) return indicator
def SSHObj(SSH): networkconnection = NetworkConnection() networkconnection.layer3_protocol = "IPv4" networkconnection.layer4_protocol = "TCP" networkconnection.layer7_protocol = "SSH" if SSH[0] != VMIP and SSH[4] == 1 and SSH[5] == 0: # incoming connection ssocketaddress = SocketAddress() ssocketaddress.ip_address = SSH[0] sport = Port() sport.port_value = SSH[1] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif SSH[2] != VMIP and SSH[4] == 1 and SSH[5] == 0: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = SSH[2] dport = Port() dport.port_value = SSH[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator = Indicator() if SSH[6] != '': indicator.title = "SSH Request with pulic key" indicator.description = ("SSH public key: " + SSH[6]) else: indicator.title = "SSH Request" indicator.description = ( "An indicator containing information about a SSH request") indicator.set_produced_time(utils.dates.now()) indicator.add_object(networkconnection) return indicator
def from_dict(network_connection_dict): if not network_connection_dict: return None network_connection_ = NetworkConnection() network_connection_.tls_used = network_connection_dict.get('tls_used') network_connection_.creation_time = DateTime.from_dict(network_connection_dict.get('creation_time')) network_connection_.layer3_protocol = String.from_dict(network_connection_dict.get('layer3_protocol')) network_connection_.layer4_protocol = String.from_dict(network_connection_dict.get('layer4_protocol')) network_connection_.layer7_protocol = String.from_dict(network_connection_dict.get('layer7_protocol')) network_connection_.source_socket_address = SocketAddress.from_dict(network_connection_dict.get('source_socket_address')) network_connection_.source_tcp_state = network_connection_dict.get('source_tcp_state') network_connection_.destination_socket_address = SocketAddress.from_dict(network_connection_dict.get('destination_socket_address')) network_connection_.destination_tcp_state = network_connection_dict.get('destination_tcp_state') network_connection_.layer7_connections = Layer7Connections.from_dict(network_connection_dict.get('layer7_connections')) return network_connection_
def from_obj(network_connection_obj): if not network_connection_obj: return None network_connection_ = NetworkConnection() network_connection_.tls_used = network_connection_obj.get_tls_used() network_connection_.creation_time = DateTime.from_obj(network_connection_obj.get_Creation_Time()) network_connection_.layer3_protocol = String.from_obj(network_connection_obj.get_Layer3_Protocol()) network_connection_.layer4_protocol = String.from_obj(network_connection_obj.get_Layer4_Protocol()) network_connection_.layer7_protocol = String.from_obj(network_connection_obj.get_Layer7_Protocol()) network_connection_.source_socket_address = SocketAddress.from_obj(network_connection_obj.get_Source_Socket_Address()) network_connection_.source_tcp_state = network_connection_obj.get_Source_TCP_State() network_connection_.destination_socket_address = SocketAddress.from_obj(network_connection_obj.get_Destination_Socket_Address()) network_connection_.destination_tcp_state = network_connection_obj.get_Destination_TCP_State() network_connection_.layer7_connections = Layer7Connections.from_obj(network_connection_obj.get_Layer7_Connections()) return network_connection_
def DNSRequestObj(dnsinfo): networkconnection = NetworkConnection() networkconnection.layer3_protocol = "IPv4" networkconnection.layer4_protocol = "UDP" networkconnection.layer7_protocol = "DNS" ssocketaddress = SocketAddress() sport = Port() sport.port_value = dnsinfo[1] sport.layer4_protocol = "UDP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress dsocketaddress = SocketAddress() dsocketaddress.ip_address = dnsinfo[2] dport = Port() dport.port_value = dnsinfo[3] dport.layer4_protocol = "UDP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress layer7connections = Layer7Connections() dqr = DNSQuery() indicator = Indicator() dnsques = DNSQuestion() dnsques.qname = dnsinfo[4] dnsques.qtype = translateType(dnsinfo[5]) dqr.question = dnsques indicator.title = "DNS Request" indicator.description = ( "An indicator containing information about a DNS Request") layer7connections.dns_query = dqr networkconnection.layer7_connections = layer7connections indicator.set_produced_time(utils.dates.now()) indicator.add_object(networkconnection) return indicator
def createDynamicIndicators(stix_package, dynamicindicators): filescreated = False processesstarted = False regkeyscreated = False mutexescreated = False hostscontacted = False hasdynamicindicators = False # Here we are just testing to see if the report had any # of the various dynamic indicator types so we know whether # or not to process them at all if len(dynamicindicators['droppedfiles']) > 0: filescreated = True hasdynamicindicators = True if len(dynamicindicators['processes']) > 0: processesstarted = True hasdynamicindicators = True if len(dynamicindicators['regkeys']) > 0: regkeyscreated = True hasdynamicindicators = True if len(dynamicindicators['mutexes']) > 0: mutexescreated = True hasdynamicindicators = True if len(dynamicindicators['hosts']) > 0: hostscontacted = True hasdynamicindicators = True if not hasdynamicindicators: return if filescreated: createdfilesind = Indicator() for createdfile in dynamicindicators['droppedfiles']: createdfilename = File() createdfilename.file_name = createdfile[0] createdfilename.size_in_bytes = createdfile[1] createdfilename.md5 = createdfile[2] createdfilename.sha1 = createdfile[3] createdfilename.sha256 = createdfile[4] createdfilesind.add_observable(Observable(createdfilename)) stix_package.add_indicator(createdfilesind) if processesstarted: procindicator = Indicator() for process in dynamicindicators['processes']: # Process name processname = process[0] # Process pid processpid = process[1] # Process parent pid processparentpid = process[2] proc = Process() proc.name = processname proc.pid = processpid proc.parent_pid = processparentpid procindicator.add_observable(Observable(proc)) stix_package.add_indicator(procindicator) if regkeyscreated: regindicator = Indicator() keypath = WinRegistryKey() for regkey in dynamicindicators['regkeys']: keypath = WinRegistryKey() keypath.key = regkey regindicator.add_observable(Observable(keypath)) stix_package.add_indicator(regindicator) if not mutexescreated: mutexind = Indicator() for mutex in dynamicindicators['mutexes']: winhandle = WinHandle() winhandle.name = mutex winmutex = WinMutex() winmutex.handle = winhandle mutexind.add_observable(Observable(winmutex)) stix_package.add_indicator(mutexind) if hostscontacted: networkconnectionind = Indicator() for host in dynamicindicators['hosts']: networkconnection = NetworkConnection() socketaddress = SocketAddress() socketaddress.ip_address = host networkconnection.destination_socket_address = socketaddress networkconnectionind.add_observable(Observable(networkconnection)) stix_package.add_indicator(networkconnectionind) return
def transform(self, event): self._set_namespace(self.config['contact_domain'], self.config['contact_name']) stix_package = STIXPackage() self._add_header(stix_package, "Unauthorized traffic to honeypot", "Describes one or more honeypot incidents") incident = Incident(id_="%s:%s-%s" % (self.config['contact_name'], 'incident', event['session_id'])) initial_time = StixTime() initial_time.initial_compromise = event['timestamp'].isoformat() incident.time = initial_time incident.title = "Conpot Event" incident.short_description = "Traffic to Conpot ICS honeypot" incident.add_category(VocabString(value='Scans/Probes/Attempted Access')) tool_list = ToolInformationList() tool_list.append(ToolInformation.from_dict({ 'name': "Conpot", 'vendor': "Conpot Team", 'version': conpot.__version__, 'description': textwrap.dedent('Conpot is a low interactive server side Industrial Control Systems ' 'honeypot designed to be easy to deploy, modify and extend.') })) incident.reporter = InformationSource(tools=tool_list) incident.add_discovery_method("Monitoring Service") incident.confidence = "High" # Victim Targeting by Sector ciq_identity = CIQIdentity3_0Instance() #identity_spec = STIXCIQIdentity3_0() #identity_spec.organisation_info = OrganisationInfo(industry_type="Electricity, Industrial Control Systems") #ciq_identity.specification = identity_spec ttp = TTP(title="Victim Targeting: Electricity Sector and Industrial Control System Sector") ttp.victim_targeting = VictimTargeting() ttp.victim_targeting.identity = ciq_identity incident.leveraged_ttps.append(ttp) indicator = Indicator(title="Conpot Event") indicator.description = "Conpot network event" indicator.confidence = "High" source_port = Port.from_dict({'port_value': event['remote'][1], 'layer4_protocol': 'tcp'}) dest_port = Port.from_dict({'port_value': self.protocol_to_port_mapping[event['data_type']], 'layer4_protocol': 'tcp'}) source_ip = Address.from_dict({'address_value': event['remote'][0], 'category': Address.CAT_IPV4}) dest_ip = Address.from_dict({'address_value': event['public_ip'], 'category': Address.CAT_IPV4}) source_address = SocketAddress.from_dict({'ip_address': source_ip.to_dict(), 'port': source_port.to_dict()}) dest_address = SocketAddress.from_dict({'ip_address': dest_ip.to_dict(), 'port': dest_port.to_dict()}) network_connection = NetworkConnection.from_dict( {'source_socket_address': source_address.to_dict(), 'destination_socket_address': dest_address.to_dict(), 'layer3_protocol': u"IPv4", 'layer4_protocol': u"TCP", 'layer7_protocol': event['data_type'], 'source_tcp_state': u"ESTABLISHED", 'destination_tcp_state': u"ESTABLISHED", } ) indicator.add_observable(Observable(network_connection)) artifact = Artifact() artifact.data = json.dumps(event['data']) artifact.packaging.append(ZlibCompression()) artifact.packaging.append(Base64Encoding()) indicator.add_observable(Observable(artifact)) incident.related_indicators.append(indicator) stix_package.add_incident(incident) stix_package_xml = stix_package.to_xml() return stix_package_xml
def main(): # NOTE: ID values will differ due to being regenerated on each script execution pkg = STIXPackage() pkg.title = "Examples of Observable Composition" # USE CASE: single obj with single condition obs = File() obs.file_name = "foo.exe" obs.file_name.condition = "Contains" pkg.add_observable(obs) # USE CASE: single obj with multiple conditions obs = File() obs.file_name = "foo" obs.file_name.condition = "Contains" obs.size_in_bytes = '1896000' obs.size_in_bytes.condition = "Equals" pkg.add_observable(obs) # USE CASE: multiple obj with individual conditions obs = EmailMessage() obs.subject = "Syria strategic plans leaked" obs.subject.condition = "Equals" file_obj = File() file_obj.file_name = "bombISIS.pdf" file_obj.file_name.condition = "Equals" obs.add_related(file_obj, "Contains") pkg.add_observable(obs) # USE CASE: multiple objects with complex condition like (A OR B) AND C # orcomp = either of a mutex or file are present orcomp = ObservableComposition() orcomp.operator = "OR" obs = Mutex() obs.name = 'foo' obs.name.condition = "Contains" orcomp.add(obs) obs = File() obs.file_name = "barfoobar" obs.file_name.condition = "Equals" orcomp.add(obs) # andcomp = the above is true AND a network connection is present andcomp = ObservableComposition() andcomp.operator = "AND" andcomp.add(orcomp) obs = NetworkConnection() sock = SocketAddress() sock.ip_address = "46.123.99.25" sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" obs.destination_socket_address = sock andcomp.add(obs) pkg.add_observable(andcomp) # USE CASE: single object, one property with multiple values obs = SocketAddress() obs.ip_address = ['10.0.0.0', '10.0.0.1', '10.0.0.2'] # comma delimiter automagically added obs.ip_address.condition = "Equals" obs.ip_address.apply_condition = "ANY" pkg.add_observable(obs) print pkg.to_xml()
def main(): # NOTE: ID values will differ due to being regenerated on each script execution pkg1 = STIXPackage() pkg1.title = "Example of Indicator Composition for an aggregate indicator composition" # USE CASE: Indicator with aggregate pattern # Add TTP for malware usage malware_ttp = TTP() malware_ttp.behavior = Behavior() malware = MalwareInstance() malware.title = "foobar malware" malware.add_type("Remote Access Trojan") malware_ttp.behavior.add_malware_instance(malware) c2_ttp = TTP() c2_ttp.resources = Resource() c2_ttp.resources.infrastructure = Infrastructure() c2_ttp.resources.infrastructure.add_type(VocabString("Malware C2")) pkg1.add_ttp(c2_ttp) pkg1.add_ttp(malware_ttp) nw_ind = Indicator() nw_ind.description = "Indicator for a particular C2 infstructure IP address." # add network network connection to this indicator obs = NetworkConnection() sock = SocketAddress() sock.ip_address = "46.123.99.25" sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" obs.destination_socket_address = sock nw_ind.add_observable(obs) nw_ind.add_indicated_ttp(TTP(idref=c2_ttp.id_)) # create File Hash indicator w/ embedded Observable file_ind = Indicator() file_ind.description = "Indicator for the hash of the foobar malware." file_ind.add_indicator_type("File Hash Watchlist") file_obs = File() file_obs.add_hash("01234567890abcdef01234567890abcdef") file_obs.hashes[0].type_ = "MD5" file_obs.hashes[0].type_.condition = "Equals" file_ind.add_observable(file_obs) # create references file_ind.add_indicated_ttp(TTP(idref=malware_ttp.id_)) # create container indicator ind = Indicator() ind.add_indicator_type(VocabString("Campaign Characteristics")) ind.description = "Indicator for a composite of characteristics for the use of specific malware and C2 infrastructure within a Campaign." # Add campaign with related camp = Campaign() camp.title = "holy grail" pkg1.add_campaign(camp) camp.related_ttps.append(TTP(idref=c2_ttp.id_)) camp.related_ttps.append(TTP(idref=malware_ttp.id_)) # Add threat actor ta = ThreatActor() ta.identity = Identity() ta.identity.name = "boobear" ta.observed_ttps.append(TTP(idref=malware_ttp.id_)) pkg1.add_threat_actor(ta) # Create composite expression ind.composite_indicator_expression = CompositeIndicatorExpression() ind.composite_indicator_expression.operator = "AND" ind.composite_indicator_expression.append(file_ind) ind.composite_indicator_expression.append(nw_ind) pkg1.add_indicator(ind) print pkg1.to_xml() # USE CASE: Indicator with partial matching pkg2 = STIXPackage() pkg2.title = "Example of Indicator Composition for a one of many indicator composition" # create container indicator watchlistind = Indicator() watchlistind.add_indicator_type("IP Watchlist") watchlistind.description = "This Indicator specifies a pattern where any one or more of a set of three IP addresses are observed." watchlistind.add_indicated_ttp(TTP(idref=c2_ttp.id_)) # Create composite expression watchlistind.composite_indicator_expression = CompositeIndicatorExpression() watchlistind.composite_indicator_expression.operator = "OR" ips = ['23.5.111.68', '23.5.111.99', '46.123.99.25'] for ip in ips: new_ind = Indicator() new_ind.description = "This Indicator specifies a pattern where one specific IP address is observed" # add network network connection to this indicator obs = Address() obs.address_value = ip obs.address_value.condition = "Equals" new_ind.add_observable(obs) new_ind.add_indicated_ttp(TTP(idref=c2_ttp.id_)) watchlistind.composite_indicator_expression.append(new_ind) pkg2.add_indicator(watchlistind) print pkg2.to_xml() # USE CASE: Indicator with compound detection pkg3 = STIXPackage() pkg3.title = "Example of Indicator Composition for compound detection" # create container indicator watchlistind2 = Indicator() watchlistind2.add_indicator_type("IP Watchlist") watchlistind2.description = "This Indicator specifies a composite condition of two preexisting Indicators (each identifying a particular TTP with low confidence) that in aggregate identify the particular TTP with high confidence." # Create composite expression watchlistind2.composite_indicator_expression = CompositeIndicatorExpression() watchlistind2.composite_indicator_expression.operator = "OR" watchlistind2.add_indicated_ttp(TTP(idref=c2_ttp.id_)) watchlistind2.confidence = "High" nw_ind.description = "Indicator for a particular C2 IP address used by a malware variant." nw_ind.confidence = "Low" nw_ind.indicator_types = ["C2"] file_ind.description = "Indicator that contains malicious file hashes for a particular malware variant." file_ind.confidence = "Low" watchlistind2.composite_indicator_expression.append(nw_ind) watchlistind2.composite_indicator_expression.append(file_ind) pkg3.add_indicator(watchlistind2) print pkg3.to_xml()
def FTPObj(ftp): networkconnection = NetworkConnection() networkconnection.layer3_protocol = "IPv4" networkconnection.layer4_protocol = "TCP" networkconnection.layer7_protocol = "FTP" indicator = Indicator() if ftp[4] == '220': if ftp[0] != VMIP: # incoming connection ssocketaddress = SocketAddress() ssocketaddress.ip_address = ftp[0] sport = Port() sport.port_value = ftp[1] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif ftp[2] != VMIP: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = ftp[2] dport = Port() dport.port_value = ftp[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator.title = "FTP" indicator.description = ("Service ready for new user: "******"TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif ftp[2] != VMIP: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = ftp[2] dport = Port() dport.port_value = ftp[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator.title = "FTP" indicator.description = ("User logged in") indicator.set_produced_time(utils.dates.now()) indicator.add_object(networkconnection) return indicator elif ftp[4] == '250': if ftp[0] != VMIP: # incoming connection ssocketaddress = SocketAddress() ssocketaddress.ip_address = ftp[0] sport = Port() sport.port_value = ftp[1] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif ftp[2] != VMIP: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = ftp[2] dport = Port() dport.port_value = ftp[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator.title = "FTP" indicator.description = ("Requested file action okay, completed.") indicator.set_produced_time(utils.dates.now()) indicator.add_object(networkconnection) return indicator elif ftp[5] == "USER": if ftp[0] != VMIP: # incoming connection ssocketaddress = SocketAddress() ssocketaddress.ip_address = ftp[0] sport = Port() sport.port_value = ftp[1] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif ftp[2] != VMIP: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = ftp[2] dport = Port() dport.port_value = ftp[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator.title = "FTP" indicator.description = ("Requested username: "******"PASS": if ftp[0] != VMIP: # incoming connection ssocketaddress = SocketAddress() ssocketaddress.ip_address = ftp[0] sport = Port() sport.port_value = ftp[1] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif ftp[2] != VMIP: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = ftp[2] dport = Port() dport.port_value = ftp[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator.title = "FTP" indicator.description = ("Requested Password: "******"STOR": if ftp[0] != VMIP: # incoming connection ssocketaddress = SocketAddress() ssocketaddress.ip_address = ftp[0] sport = Port() sport.port_value = ftp[1] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif ftp[2] != VMIP: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = ftp[2] dport = Port() dport.port_value = ftp[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator.title = "FTP" indicator.description = ("Upload file to server: " + ftp[6]) indicator.set_produced_time(utils.dates.now()) indicator.add_object(networkconnection) return indicator elif ftp[5] == "RETR": if ftp[0] != VMIP: # incoming connection ssocketaddress = SocketAddress() ssocketaddress.ip_address = ftp[0] sport = Port() sport.port_value = ftp[1] sport.layer4_protocol = "TCP" ssocketaddress.port = sport networkconnection.source_socket_address = ssocketaddress elif ftp[2] != VMIP: # outgoing connection dsocketaddress = SocketAddress() dsocketaddress.ip_address = ftp[2] dport = Port() dport.port_value = ftp[3] dport.layer4_protocol = "TCP" dsocketaddress.port = dport networkconnection.destination_socket_address = dsocketaddress indicator.title = "FTP" indicator.description = ("Retrieve a copy of the file: " + ftp[6]) indicator.set_produced_time(utils.dates.now()) indicator.add_object(networkconnection) return indicator
def ICMPObj(icmp): # block types 0 (ping response), 8 (ping request) nc = NetworkConnection() indicator = Indicator() nc.layer3_protocol = "ICMP" if icmp[0] == 0: # echo-reply if icmp[1] != VMIP: # incoming reply from a server VM pinged ssocketaddress = SocketAddress() ssocketaddress.ip_address = icmp[1] nc.source_socket_address = ssocketaddress indicator.title = "ICMP echo-reply" indicator.description = ("0") else: # outgoing reply to a server that pinged you dsocketaddress = SocketAddress() dsocketaddress.ip_address = icmp[2] nc.destination_socket_address = dsocketaddress indicator.title = "ICMP echo-reply" indicator.description = ("0") elif icmp[0] == 8: # echo-request if icmp[1] != VMIP: # incoming ping request from a server ssocketaddress = SocketAddress() ssocketaddress.ip_address = icmp[1] nc.source_socket_address = ssocketaddress indicator.title = "ICMP echo-request" indicator.description = ("8") else: # VM is sending a ping request dsocketaddress = SocketAddress() dsocketaddress.ip_address = icmp[2] nc.destination_socket_address = dsocketaddress indicator.title = "ICMP echo-request" indicator.description = ("8") indicator.set_produced_time(utils.dates.now()) indicator.add_object(nc) return indicator
def create_socket_address(ip, prt): sock = SocketAddress() sock.ip_address = ip sock.port = create_port(prt) return sock
def transform(self, event): stix_package = STIXPackage() self._add_header(stix_package, "Unauthorized traffic to honeypot", "Describes one or more honeypot incidents") incident = Incident( id_="%s:%s-%s" % (CONPOT_NAMESPACE, 'incident', event['session_id'])) initial_time = StixTime() initial_time.initial_compromise = event['timestamp'].isoformat() incident.time = initial_time incident.title = "Conpot Event" incident.short_description = "Traffic to Conpot ICS honeypot" incident.add_category( VocabString(value='Scans/Probes/Attempted Access')) tool_list = ToolInformationList() tool_list.append( ToolInformation.from_dict({ 'name': "Conpot", 'vendor': "Conpot Team", 'version': conpot.__version__, 'description': textwrap.dedent( 'Conpot is a low interactive server side Industrial Control Systems ' 'honeypot designed to be easy to deploy, modify and extend.' ) })) incident.reporter = InformationSource(tools=tool_list) incident.add_discovery_method("Monitoring Service") incident.confidence = "High" # Victim Targeting by Sector ciq_identity = CIQIdentity3_0Instance() #identity_spec = STIXCIQIdentity3_0() #identity_spec.organisation_info = OrganisationInfo(industry_type="Electricity, Industrial Control Systems") #ciq_identity.specification = identity_spec ttp = TTP( title= "Victim Targeting: Electricity Sector and Industrial Control System Sector" ) ttp.victim_targeting = VictimTargeting() ttp.victim_targeting.identity = ciq_identity incident.leveraged_ttps.append(ttp) indicator = Indicator(title="Conpot Event") indicator.description = "Conpot network event" indicator.confidence = "High" source_port = Port.from_dict({ 'port_value': event['remote'][1], 'layer4_protocol': 'tcp' }) dest_port = Port.from_dict({ 'port_value': self.protocol_to_port_mapping[event['data_type']], 'layer4_protocol': 'tcp' }) source_ip = Address.from_dict({ 'address_value': event['remote'][0], 'category': Address.CAT_IPV4 }) dest_ip = Address.from_dict({ 'address_value': event['public_ip'], 'category': Address.CAT_IPV4 }) source_address = SocketAddress.from_dict({ 'ip_address': source_ip.to_dict(), 'port': source_port.to_dict() }) dest_address = SocketAddress.from_dict({ 'ip_address': dest_ip.to_dict(), 'port': dest_port.to_dict() }) network_connection = NetworkConnection.from_dict({ 'source_socket_address': source_address.to_dict(), 'destination_socket_address': dest_address.to_dict(), 'layer3_protocol': "IPv4", 'layer4_protocol': "TCP", 'layer7_protocol': event['data_type'], 'source_tcp_state': "ESTABLISHED", 'destination_tcp_state': "ESTABLISHED", }) indicator.add_observable(Observable(network_connection)) artifact = Artifact() artifact.data = json.dumps(event['data']) artifact.packaging.append(ZlibCompression()) artifact.packaging.append(Base64Encoding()) indicator.add_observable(Observable(artifact)) incident.related_indicators.append(indicator) stix_package.add_incident(incident) stix_package_xml = stix_package.to_xml() return stix_package_xml
def main(): # NOTE: ID values will differ due to being regenerated on each script execution pkg1 = STIXPackage() pkg1.title = "Example of Indicator Composition for an aggregate indicator composition" # USE CASE: Indicator with aggregate pattern # Add TTP for malware usage malware_ttp = TTP() malware_ttp.behavior = Behavior() malware = MalwareInstance() malware.title = "foobar malware" malware.add_type("Remote Access Trojan") malware_ttp.behavior.add_malware_instance(malware) c2_ttp = TTP() c2_ttp.resources = Resource() c2_ttp.resources.infrastructure = Infrastructure() c2_ttp.resources.infrastructure.add_type(VocabString("Malware C2")) pkg1.add_ttp(c2_ttp) pkg1.add_ttp(malware_ttp) nw_ind = Indicator() nw_ind.description = "Indicator for a particular C2 infstructure IP address." # add network network connection to this indicator obs = NetworkConnection() sock = SocketAddress() sock.ip_address = "46.123.99.25" sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" obs.destination_socket_address = sock nw_ind.add_observable(obs) nw_ind.add_indicated_ttp(TTP(idref=c2_ttp.id_)) # create File Hash indicator w/ embedded Observable file_ind = Indicator() file_ind.description = "Indicator for the hash of the foobar malware." file_ind.add_indicator_type("File Hash Watchlist") file_obs = File() file_obs.add_hash("01234567890abcdef01234567890abcdef") file_obs.hashes[0].type_ = "MD5" file_obs.hashes[0].type_.condition = "Equals" file_ind.add_observable(file_obs) # create references file_ind.add_indicated_ttp(TTP(idref=malware_ttp.id_)) # create container indicator ind = Indicator() ind.add_indicator_type(VocabString("Campaign Characteristics")) ind.description = "Indicator for a composite of characteristics for the use of specific malware and C2 infrastructure within a Campaign." # Add campaign with related camp = Campaign() camp.title = "holy grail" pkg1.add_campaign(camp) camp.related_ttps.append(TTP(idref=c2_ttp.id_)) camp.related_ttps.append(TTP(idref=malware_ttp.id_)) # Add threat actor ta = ThreatActor() ta.identity = Identity() ta.identity.name = "boobear" ta.observed_ttps.append(TTP(idref=malware_ttp.id_)) pkg1.add_threat_actor(ta) # Create composite expression ind.composite_indicator_expression = CompositeIndicatorExpression() ind.composite_indicator_expression.operator = "AND" ind.composite_indicator_expression.append(file_ind) ind.composite_indicator_expression.append(nw_ind) pkg1.add_indicator(ind) print pkg1.to_xml() # USE CASE: Indicator with partial matching pkg2 = STIXPackage() pkg2.title = "Example of Indicator Composition for a one of many indicator composition" # create container indicator watchlistind = Indicator() watchlistind.add_indicator_type("IP Watchlist") watchlistind.description = "This Indicator specifies a pattern where any one or more of a set of three IP addresses are observed." watchlistind.add_indicated_ttp(TTP(idref=c2_ttp.id_)) # Create composite expression watchlistind.composite_indicator_expression = CompositeIndicatorExpression( ) watchlistind.composite_indicator_expression.operator = "OR" ips = ['23.5.111.68', '23.5.111.99', '46.123.99.25'] for ip in ips: new_ind = Indicator() new_ind.description = "This Indicator specifies a pattern where one specific IP address is observed" # add network network connection to this indicator obs = Address() obs.address_value = ip obs.address_value.condition = "Equals" new_ind.add_observable(obs) new_ind.add_indicated_ttp(TTP(idref=c2_ttp.id_)) watchlistind.composite_indicator_expression.append(new_ind) pkg2.add_indicator(watchlistind) print pkg2.to_xml() # USE CASE: Indicator with compound detection pkg3 = STIXPackage() pkg3.title = "Example of Indicator Composition for compound detection" # create container indicator watchlistind2 = Indicator() watchlistind2.add_indicator_type("IP Watchlist") watchlistind2.description = "This Indicator specifies a composite condition of two preexisting Indicators (each identifying a particular TTP with low confidence) that in aggregate identify the particular TTP with high confidence." # Create composite expression watchlistind2.composite_indicator_expression = CompositeIndicatorExpression( ) watchlistind2.composite_indicator_expression.operator = "OR" watchlistind2.add_indicated_ttp(TTP(idref=c2_ttp.id_)) watchlistind2.confidence = "High" nw_ind.description = "Indicator for a particular C2 IP address used by a malware variant." nw_ind.confidence = "Low" nw_ind.indicator_types = ["C2"] file_ind.description = "Indicator that contains malicious file hashes for a particular malware variant." file_ind.confidence = "Low" watchlistind2.composite_indicator_expression.append(nw_ind) watchlistind2.composite_indicator_expression.append(file_ind) pkg3.add_indicator(watchlistind2) print pkg3.to_xml()
def main(): # get args parser = argparse.ArgumentParser ( description = "Parse a given CSV and output STIX XML" , formatter_class=argparse.ArgumentDefaultsHelpFormatter ) parser.add_argument("--infile","-f", help="input CSV", default = "in.csv") args = parser.parse_args() # setup header contain_pkg = STIXPackage() stix_header = STIXHeader() stix_header.title = "Indicators" stix_header.add_package_intent ("Indicators") # XXX add Information_Source and Handling contain_pkg.stix_header = stix_header # create kill chain with three options (pre, post, unknown), relate as needed pre = KillChainPhase(phase_id="stix:KillChainPhase-1a3c67f7-5623-4621-8d67-74963d1c5fee", name="Pre-infection indicator", ordinality=1) post = KillChainPhase(phase_id="stix:KillChainPhase-d5459305-1a27-4f50-9875-23793d75e4fe", name="Post-infection indicator", ordinality=2) chain = KillChain(id_="stix:KillChain-3fbfebf2-25a7-47b9-ad8b-3f65e56e402d", name="Degenerate Cyber Kill Chain" ) chain.definer = "U5" chain.kill_chain_phases = [pre, post] contain_pkg.ttps.kill_chains.append(chain) # read input data fd = open (args.infile, "rb") infile = csv.DictReader(fd) for row in infile: # create indicator for each row error = False ind = Indicator() ind.add_alternative_id(row['ControlGroupID']) ind.title = "Indicator with ID " + row['IndicatorID'] ind.description = row['Notes'] ind.producer = InformationSource() ind.producer.description = row['Reference'] # XXX unknown purpose for 'Malware' field - omitted # if the field denotes a specific malware family, we might relate as 'Malware TTP' to the indicator # set chain phase if 'Pre' in row['Infection Type']: ind.kill_chain_phases.append(KillChainPhaseReference(phase_id="stix:KillChainPhase-1a3c67f7-5623-4621-8d67-74963d1c5fee",kill_chain_id="stix:KillChain-3fbfebf2-25a7-47b9-ad8b-3f65e56e402d")) elif 'Post' in row['Infection Type']: ind.kill_chain_phases.append(KillChainPhaseReference(phase_id="stix:KillChainPhase-1a3c67f7-5623-4621-8d67-74963d1c5fee",kill_chain_id="stix:KillChain-3fbfebf2-25a7-47b9-ad8b-3f65e56e402d")) ind_type = row['Indicator Type'] if 'IP' in ind_type: ind.add_indicator_type( "IP Watchlist") ind_obj = SocketAddress() ind_obj.ip_address = row['Indicator'] ind_obj.ip_address.condition= "Equals" if row['indValue']: port = Port() # pull port out, since it's in form "TCP Port 42" port.port_value = row['indValue'].split()[-1] port.layer4_protocol = row['indValue'].split()[0] port.port_value.condition= "Equals" ind_obj.port = port elif 'Domain' in ind_type: ind.add_indicator_type ("Domain Watchlist") ind_obj = DomainName() ind_obj.value = row['Indicator'] ind_obj.value.condition= "Equals" elif 'Email' in ind_type: # parse out which part of the email is being # i.e. "Sender: attach | Subject: whatever" tag = row['Indicator'].split(':')[0] val = row['Indicator'].split(':')[1] ind.add_indicator_type ("Malicious E-mail") ind_obj = EmailMessage() if "Subject" in tag: ind_obj.subject = val ind_obj.subject.condition= "Equals" elif "Sender" in tag: ind_obj.sender = val ind_obj.sender.condition= "Equals" elif "Attachment" in tag: # make inline File to store filename file_obj = File() file_obj.id_ = cybox.utils.create_id(prefix="File") file_obj.file_name = val file_obj.file_name.condition = "Equals" ind_obj.add_related(file_obj, "Contains") attach = Attachments() attach.append(file_obj.id_) ind_obj.attachments = attach elif 'User Agent' in ind_type: ind.add_indicator_type( VocabString(row['Indicator Type'])) fields = HTTPRequestHeaderFields() fields.user_agent = row['Indicator'] fields.user_agent.condition = "Equals" header = HTTPRequestHeader() header.parsed_header = fields thing = HTTPRequestResponse() thing.http_client_request = HTTPClientRequest() thing.http_client_request.http_request_header = header ind_obj = HTTPSession() ind_obj.http_request_response = [thing] elif 'URI' in ind_type: ind.add_indicator_type( VocabString(row['Indicator Type'])) thing = HTTPRequestResponse() thing.http_client_request = HTTPClientRequest() thing.http_client_request.http_request_line = HTTPRequestLine() thing.http_client_request.http_request_line.http_method = row['Indicator'].split()[0] thing.http_client_request.http_request_line.http_method.condition = "Equals" thing.http_client_request.http_request_line.value = row['Indicator'].split()[1] thing.http_client_request.http_request_line.value.condition = "Equals" ind_obj = HTTPSession() ind_obj.http_request_response = [thing] elif 'File' in ind_type: ind.add_indicator_type( VocabString(row['Indicator Type'])) ind_obj = File() ind_obj.file_name = row['Indicator'] ind_obj.file_name.condition = "Equals" digest = Hash() # XXX assumes that hash digests are stored in this field in real data digest.simple_hash_value = row['indValue'].strip() digest.simple_hash_value.condition = "Equals" digest.type_.condition = "Equals" ind_obj.add_hash(digest) elif 'Registry' in ind_type: ind.add_indicator_type( VocabString(row['Indicator Type'])) ind_obj = WinRegistryKey() keys = RegistryValues() key = RegistryValue() key.name = row['Indicator'] key.name.condition = "Equals" key.data = row['indValue'] key.data.condition = "Equals" keys.append(key) ind_obj.values = keys elif 'Mutex' in ind_type: ind.add_indicator_type (VocabString(row['Indicator Type'])) ind_obj = Mutex() ind_obj.name = row['Indicator'] ind_obj.name.condition= "Equals" else: print "ERR type not supported: " + ind_type + " <- will be omitted from output" error = True # finalize indicator if not error: ind.add_object(ind_obj) contain_pkg.add_indicator(ind) # DONE looping print contain_pkg.to_xml()
def home(request): """ Name: home Desc: Main GUI view """ # Forms:Job,target and relay creation create_job_form = CreateJob(request=request, prefix="create_job") create_target_form = CreateTarget(request=request, prefix="create_target") create_relay_form = CreateRelay(request=request, prefix="create_relay") if request.method == "POST": # Remove a relay if "delete_relay_id" in request.POST: try: Relay.objects.get(pk=request.POST["delete_relay_id"]).delete() except ObjectDoesNotExist, e: pass # Create new relay if "create_relay-name" in request.POST: # Actuator creation create_relay_form = CreateRelay(request.POST, request=request, prefix="create_relay") if create_relay_form.is_valid(): host = create_relay_form.save() host.save() # TODO - Call a sync here # Job Creations if "create_job-raw_message" in request.POST: new_job = Job(capability=Capability.objects.get( pk=request.POST["create_job-capability"]), target=Target.objects.get( pk=request.POST["create_job-target"]), raw_message="Pending", status=JobStatus.objects.get(status="Pending"), created_by=request.user) new_job.save() # Now we have a pk - update the id command = json.loads(request.POST["create_job-raw_message"]) command["modifiers"]["command-ref"] = new_job.id logger.info("Job Created\n%s" % json.dumps(command)) new_job.raw_message = json.dumps(command, sort_keys=True, indent=4).replace( "\t", u'\xa0\xa0\xa0\xa0\xa0') new_job.save() # Target Creations namespace_url = getattr(settings, "NAMESPACE_URL", None) namespace_id = getattr(settings, "NAMESPACE_ID", None) set_id_namespace(Namespace(namespace_url, namespace_id)) if "create_target-cybox_type" in request.POST: cybox_type = CybOXType.objects.get( pk=request.POST["create_target-cybox_type"]) if cybox_type.identifier == "cybox:NetworkConnectionObjectType": obs = NetworkConnection() # Source sock = SocketAddress() sock.ip_address = request.POST["create_target-source_address"] sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" sport = Port() sport.port_value = int( request.POST["create_target-source_port"]) sock.port = sport obs.source_socket_address = sock # Dest sock = SocketAddress() sock.ip_address = request.POST[ "create_target-destination_address"] sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" dport = Port() dport.port_value = int( request.POST["create_target-destination_port"]) sock.port = dport obs.destination_socket_address = sock name = "Network Connection %s:%s -> %s:%s (%s)" % ( request.POST["create_target-source_address"], request.POST["create_target-source_port"], request.POST["create_target-destination_address"], request.POST["create_target-destination_port"], request.POST["create_target-protocol"]) raw_message = Observable(item=obs, title=name).to_json() elif cybox_type.identifier == "cybox:AddressObjectType": name = "Address %s " % (request.POST["create_target-address"]) raw_message = Observable(item=Address( address_value=request.POST["create_target-address"], category=Address.CAT_IPV4), title=name).to_json() elif cybox_type.identifier == "cybox:URIObjectType": name = "URI %s " % (request.POST["create_target-uri"]) obs = URI() obs.value = request.POST["create_target-uri"] obs.type_ = URI.TYPE_URL obs.condition = "Equals" raw_message = Observable(item=obs, title=name).to_json() elif cybox_type.identifier == "cybox:EmailMessageObjectType": name = "Email %s " % ( request.POST["create_target-email_subject"]) obs = EmailMessage() obs.raw_body = request.POST["create_target-email_message"] obs.header = EmailHeader() obs.header.subject = request.POST[ "create_target-email_subject"] obs.header.subject.condition = "StartsWith" obs.header.to = request.POST["create_target-email_to"] obs.header.from_ = request.POST["create_target-email_from"] raw_message = Observable(item=obs, title=name).to_json() else: # Should never reach here raw_message = {} name = "Undefined Object" create_target_form = CreateTarget(request.POST, request=request, prefix="create_target") if create_target_form.is_valid(): target = create_target_form.save(commit=False) target.name = name target.raw_message = raw_message target.save()
def main(): # NOTE: ID values will differ due to being regenerated on each script execution pkg = STIXPackage() pkg.title="Examples of Observable Composition" # USE CASE: single obj with single condition obs = File() obs.file_name = "foo.exe" obs.file_name.condition = "Contains" pkg.add_observable(obs) # USE CASE: single obj with multiple conditions obs = File() obs.file_name = "foo" obs.file_name.condition = "Contains" obs.size_in_bytes = '1896000' obs.size_in_bytes.condition = "Equals" pkg.add_observable(obs) # USE CASE: multiple obj with individual conditions obs = EmailMessage() obs.subject = "Syria strategic plans leaked" obs.subject.condition= "Equals" file_obj = File() file_obj.file_name = "bombISIS.pdf" file_obj.file_name.condition = "Equals" obs.add_related(file_obj, "Contains") pkg.add_observable(obs) # USE CASE: multiple objects with complex condition like (A OR B) AND C # orcomp = either of a mutex or file are present orcomp = ObservableComposition() orcomp.operator = "OR" obs = Mutex() obs.name = 'foo' obs.name.condition= "Contains" orcomp.add(obs) obs = File() obs.file_name = "barfoobar" obs.file_name.condition = "Equals" orcomp.add(obs) # andcomp = the above is true AND a network connection is present andcomp = ObservableComposition() andcomp.operator = "AND" andcomp.add(orcomp) obs = NetworkConnection() sock = SocketAddress() sock.ip_address = "46.123.99.25" sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" obs.destination_socket_address = sock andcomp.add (obs) pkg.add_observable(andcomp) # USE CASE: single object, one property with multiple values obs = SocketAddress() obs.ip_address = ['10.0.0.0','10.0.0.1','10.0.0.2'] # comma delimiter automagically added obs.ip_address.condition = "Equals" obs.ip_address.apply_condition = "ANY" pkg.add_observable(obs) print pkg.to_xml()
def main(): # get args parser = argparse.ArgumentParser ( description = "Parse a given CSV from Shadowserver and output STIX XML to stdout" , formatter_class=argparse.ArgumentDefaultsHelpFormatter ) parser.add_argument("--infile","-f", help="input CSV with bot data", default = "bots.csv") args = parser.parse_args() # setup stix document stix_package = STIXPackage() stix_header = STIXHeader() stix_header.title = "Bot Server IP addresses" stix_header.description = "IP addresses connecting to bot control servers at a given port" stix_header.add_package_intent ("Indicators - Watchlist") # add marking mark = Marking() markspec = MarkingSpecification() markstruct = SimpleMarkingStructure() markstruct.statement = "Usage of this information, including integration into security mechanisms implies agreement with the Shadowserver Terms of Service available at https://www.shadowserver.org/wiki/pmwiki.php/Shadowserver/TermsOfService" markspec.marking_structures.append(markstruct) mark.add_marking(markspec) stix_header.handling = mark # include author info stix_header.information_source = InformationSource() stix_header.information_source.time = Time() stix_header.information_source.time.produced_time =datetime.now(tzutc()) stix_header.information_source.tools = ToolInformationList() stix_header.information_source.tools.append("ShadowBotnetIP-STIXParser") stix_header.information_source.identity = Identity() stix_header.information_source.identity.name = "MITRE STIX Team" stix_header.information_source.add_role(VocabString("Format Transformer")) src = InformationSource() src.description = "https://www.shadowserver.org/wiki/pmwiki.php/Services/Botnet-CCIP" srcident = Identity() srcident.name = "shadowserver.org" src.identity = srcident src.add_role(VocabString("Originating Publisher")) stix_header.information_source.add_contributing_source(src) stix_package.stix_header = stix_header # add TTP for overall indicators bot_ttp = TTP() bot_ttp.title = 'Botnet C2' bot_ttp.resources = Resource() bot_ttp.resources.infrastructure = Infrastructure() bot_ttp.resources.infrastructure.title = 'Botnet C2' stix_package.add_ttp(bot_ttp) # read input data fd = open (args.infile, "rb") infile = csv.DictReader(fd) for row in infile: # split indicators out, may be 1..n with positional storage, same port and channel, inconsistent delims domain = row['Domain'].split() country = row['Country'].split() region = row['Region'].split('|') state = row['State'].split('|') asn = row['ASN'].split() asname = row['AS Name'].split() asdesc = row['AS Description'].split('|') index = 0 for ip in row['IP Address'].split(): indicator = Indicator() indicator.title = "IP indicator for " + row['Channel'] indicator.description = "Bot connecting to control server" # point to overall TTP indicator.add_indicated_ttp(TTP(idref=bot_ttp.id_)) # add our IP and port sock = SocketAddress() sock.ip_address = ip # add sighting sight = Sighting() sight.timestamp = "" obs = Observable(item=sock.ip_address) obsref = Observable(idref=obs.id_) sight.related_observables.append(obsref) indicator.sightings.append(sight) stix_package.add_observable(obs) # add pattern for indicator sock_pattern = SocketAddress() sock_pattern.ip_address = ip port = Port() port.port_value = row['Port'] sock_pattern.port = port sock_pattern.ip_address.condition= "Equals" sock_pattern.port.port_value.condition= "Equals" indicator.add_object(sock_pattern) stix_package.add_indicator(indicator) # add domain domain_obj = DomainName() domain_obj.value = domain[index] domain_obj.add_related(sock.ip_address,"Resolved_To", inline=False) stix_package.add_observable(domain_obj) # add whois obs whois_obj = WhoisEntry() registrar = WhoisRegistrar() registrar.name = asname[index] registrar.address = state[index] + region[index] + country[index] whois_obj.registrar_info = registrar whois_obj.add_related(sock.ip_address,"Characterizes", inline=False) stix_package.add_observable(whois_obj) # add ASN obj asn_obj = AutonomousSystem() asn_obj.name = asname[index] asn_obj.number = asn[index] asn_obj.handle = "AS" + str(asn[index]) asn_obj.add_related(sock.ip_address,"Contains", inline=False) stix_package.add_observable(asn_obj) # iterate index = index + 1 print stix_package.to_xml()