Beispiel #1
0
def main():
    # get args
    parser = argparse.ArgumentParser(
        description="Parse an input JSON file and output STIX XML ",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("infile",help="input file")
    parser.add_argument("--outfile","-o", help="output file")

    args = parser.parse_args()
    
    # We assume the input file is a flat JSON file
    # format 'bot_name':[list,of,ips]
    content = json.load(open(args.infile))
        
    # Set up STIX document
    stix_package = STIXPackage()
    stix_header = STIXHeader()
    stix_header.title = "C2 Server IP Addresses"
    stix_header.add_package_intent (PackageIntent.TERM_INDICATORS_WATCHLIST)
    stix_package.stix_header = stix_header

    # Create Indicator and TTP for each item in JSON document
    for item in content:

        # Create TTP for C2 server
        ttp = TTP()
        ttp.title = item
        stix_package.add_ttp(ttp)

        # Create Indicator for C2 IP addresses
        indicator = Indicator()
        indicator.title = "IP addresses for known C2 channel"
        indicator.description = "Bot connecting to control server"

        # Add IPs for C2 node
        addr = Address(address_value=content[item], category=Address.CAT_IPV4)
        addr.address_value.condition= "Equals"
        indicator.add_object(addr)

        # Relate Indicator and TTP
        indicator.add_indicated_ttp(TTP(idref=ttp.id_))

        # Add Indicator to STIX PAckage
        stix_package.add_indicator(indicator)

    # Output to given file
    # The context manager is just to make the output look nicer by ignoring
    # warnings from to_xml()
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        stix_out = stix_package.to_xml()

        if args.outfile:
            fd = open(args.outfile,'w')
            fd.write(stix_out)
        else:
            print stix_out
def build_stix( input_dict ):
    # setup stix document
    stix_package = STIXPackage()
    stix_header = STIXHeader()

    stix_header.description = "Incident report for " + input_dict['organization']
    stix_header.add_package_intent ("Incident")

    # Add handling requirements if needed
    if input_dict['sensitive'] == "True":
        mark = SimpleMarkingStructure()
        mark.statement = "Sensitive"
        mark_spec = MarkingSpecification()
        mark_spec.marking_structures.append(mark)
        stix_header.handling = Marking(mark_spec)


    stix_package.stix_header = stix_header

    # add incident and confidence
    incident = Incident()
    incident.description = input_dict['description']
    incident.confidence = input_dict['confidence']

    # add incident reporter
    incident.reporter = InformationSource()
    incident.reporter.description = "Person who reported the incident"

    incident.reporter.time = Time()
    incident.reporter.time.produced_time = datetime.strptime(input_dict['timestamp'], "%Y-%m-%d") # when they submitted it

    incident.reporter.identity = Identity()
    incident.reporter.identity.name = input_dict['submitter']

    # incident time is a complex object with support for a bunch of different "when stuff happened" items
    incident.time = incidentTime()
    incident.title = "Breach of " + input_dict['organization']
    incident.time.incident_discovery = datetime.strptime(input_dict['timestamp'], "%Y-%m-%d") # when they submitted it

    # add the impact
    impact = ImpactAssessment()
    impact.add_effect(input_dict['damage'])
    incident.impact_assessment = impact

    #Add the thing that was stolen
    jewels = AffectedAsset()
    jewels.type_ = input_dict['asset']
    incident.add_affected_asset (jewels)

    # add the victim
    incident.add_victim (input_dict['organization'])

    stix_package.add_incident(incident)

    return stix_package
def build_stix( ):
    # setup stix document
    stix_package = STIXPackage()
    stix_header = STIXHeader()

    stix_header.description = "Sample breach report" 
    stix_header.add_package_intent ("Incident")

    stix_package.stix_header = stix_header


    # add incident and confidence
    breach = Incident()
    breach.description = "Intrusion into enterprise network"
    breach.confidence = "High"

    # stamp with reporter
    breach.reporter = InformationSource()
    breach.reporter.description = "The person who reported it"

    breach.reporter.time = Time()
    breach.reporter.time.produced_time = datetime.strptime("2014-03-11","%Y-%m-%d") # when they submitted it

    breach.reporter.identity = Identity()
    breach.reporter.identity.name = "Sample Investigations, LLC"
    # set incident-specific timestamps
    breach.time = incidentTime()
    breach.title = "Breach of Cyber Tech Dynamics"
    breach.time.initial_compromise = datetime.strptime("2012-01-30", "%Y-%m-%d") 
    breach.time.incident_discovery = datetime.strptime("2012-05-10", "%Y-%m-%d") 
    breach.time.restoration_achieved = datetime.strptime("2012-08-10", "%Y-%m-%d") 
    breach.time.incident_reported = datetime.strptime("2012-12-10", "%Y-%m-%d") 

    # add the impact
    impact = ImpactAssessment()
    impact.add_effect("Unintended Access")
    breach.impact_assessment = impact

    # add the victim
    breach.add_victim ("Cyber Tech Dynamics")

    stix_package.add_incident(breach)

    return stix_package
Beispiel #4
0
def wrap_maec(maec_package, file_name=None):
    """Wrap a MAEC Package in a STIX TTP/Package. Return the newly created STIX Package.

    Args:
        maec_package: the ``maec.package.package.Package`` instance to wrap in STIX.
        file_name: the name of the input file from which the MAEC Package originated,
            to be used in the Title of the STIX TTP that wraps the MAEC Package. Optional.

    Returns:
        A ``stix.STIXPackage`` instance with a single TTP that wraps the input MAEC Package.
    """

    # Set the namespace to be used in the STIX Package
    stix.utils.set_id_namespace(
        {"https://github.com/MAECProject/maec-to-stix": "MAECtoSTIX"})

    # Create the STIX MAEC Instance
    maec_malware_instance = MAECInstance()
    maec_malware_instance.maec = maec_package

    # Create the STIX TTP that includes the MAEC Instance
    ttp = TTP()
    ttp.behavior = Behavior()
    ttp.behavior.add_malware_instance(maec_malware_instance)

    # Create the STIX Package and add the TTP to it
    stix_package = STIXPackage()
    stix_package.add_ttp(ttp)

    # Create the STIX Header and add it to the Package
    stix_header = STIXHeader()
    if file_name:
        stix_header.title = "STIX TTP wrapper around MAEC file: " + str(
            file_name)
    stix_header.add_package_intent("Malware Characterization")
    # Add the Information Source to the STIX Header
    tool_info = ToolInformation()
    stix_header.information_source = InformationSource()
    tool_info.name = "MAEC to STIX"
    tool_info.version = str(maec_to_stix.__version__)
    stix_header.information_source.tools = ToolInformationList(tool_info)
    stix_package.stix_header = stix_header

    return stix_package
Beispiel #5
0
def wrap_maec(maec_package, file_name=None):
    """Wrap a MAEC Package in a STIX TTP/Package. Return the newly created STIX Package.

    Args:
        maec_package: the ``maec.package.package.Package`` instance to wrap in STIX.
        file_name: the name of the input file from which the MAEC Package originated,
            to be used in the Title of the STIX TTP that wraps the MAEC Package. Optional.

    Returns:
        A ``stix.STIXPackage`` instance with a single TTP that wraps the input MAEC Package.
    """

    # Set the namespace to be used in the STIX Package
    stix.utils.set_id_namespace({"https://github.com/MAECProject/maec-to-stix":"MAECtoSTIX"})

    # Create the STIX MAEC Instance
    maec_malware_instance = MAECInstance()
    maec_malware_instance.maec = maec_package
    
    # Create the STIX TTP that includes the MAEC Instance
    ttp = TTP()
    ttp.behavior = Behavior()
    ttp.behavior.add_malware_instance(maec_malware_instance)
    
    # Create the STIX Package and add the TTP to it
    stix_package = STIXPackage()
    stix_package.add_ttp(ttp)

    # Create the STIX Header and add it to the Package
    stix_header = STIXHeader()
    if file_name:
        stix_header.title = "STIX TTP wrapper around MAEC file: " + str(file_name)
    stix_header.add_package_intent("Malware Characterization")
    # Add the Information Source to the STIX Header
    tool_info = ToolInformation()
    stix_header.information_source = InformationSource()
    tool_info.name = "MAEC to STIX"
    tool_info.version = str(maec_to_stix.__version__)
    stix_header.information_source.tools = ToolInformationList(tool_info)
    stix_package.stix_header = stix_header
    
    return stix_package
def build_stix( ):
    # setup stix document
    stix_package = STIXPackage()
    stix_header = STIXHeader()

    stix_header.description = "Sample breach report" 
    stix_header.add_package_intent ("Incident")

    stix_package.stix_header = stix_header

    # add incident and confidence
    breach = Incident()
    breach.description = "Intrusion into enterprise network"
    breach.confidence = "High"

    # stamp with reporter
    breach.reporter = InformationSource()
    breach.reporter.description = "The person who reported it"

    breach.reporter.time = Time()
    breach.reporter.time.produced_time = datetime.strptime("2014-03-11","%Y-%m-%d") # when they submitted it

    breach.reporter.identity = Identity()
    breach.reporter.identity.name = "Sample Investigations, LLC"


    # incident time is a complex object with support for a bunch of different "when stuff happened" items
    breach.time = incidentTime()
    breach.title = "Breach of Canary Corp"
    breach.time.incident_discovery = datetime.strptime("2013-01-13", "%Y-%m-%d") # when they submitted it

    # add the impact
    impact = ImpactAssessment()
    impact.add_effect("Financial Loss")
    breach.impact_assessment = impact

    # add the victim
    breach.add_victim ("Canary Corp")

    stix_package.add_incident(breach)

    return stix_package
Beispiel #7
0
 def _create_stix_package(self):
     """Create and return a STIX Package with the basic information populated.
     
     Returns:
         A ``stix.STIXPackage`` object with a STIX Header that describes the intent of
         the package in terms of capturing malware artifacts, along with some associated
         metadata.
     """
     stix_package = STIXPackage()
     stix_header = STIXHeader()
     stix_header.add_package_intent("Indicators - Malware Artifacts")
     if self.file_name:
         stix_header.title = "STIX Indicators extracted from MAEC file: " + str(self.file_name)
     # Add the Information Source to the STIX Header
     tool_info = ToolInformation()
     stix_header.information_source = InformationSource()
     tool_info.name = "MAEC to STIX"
     tool_info.version = str(__version__)
     stix_header.information_source.tools = ToolInformationList(tool_info)
     stix_package.stix_header = stix_header
     return stix_package
Beispiel #8
0
def generateContainer(header, intent, stixObject, input_dict):
    container = stixmarx.new()

    stix_package = container.package
    stix_header = STIXHeader()

    stix_header.description = header + " " + input_dict['title']
    stix_header.add_package_intent (intent)

    stix_package.stix_header = stix_header

    # TODO workaround for pyStix error
    if stixObject.__class__ is stix.ttp.TTP:
        stix_package.add_ttp(stixObject)
    else:
        stix_package.add(stixObject)

    marking_specification = generateMarking(input_dict['marking'])
    container.add_component(stixObject, marking_specification)

    return container
Beispiel #9
0
 def _create_stix_package(self):
     """Create and return a STIX Package with the basic information populated.
     
     Returns:
         A ``stix.STIXPackage`` object with a STIX Header that describes the intent of
         the package in terms of capturing malware artifacts, along with some associated
         metadata.
     """
     stix_package = STIXPackage()
     stix_header = STIXHeader()
     stix_header.add_package_intent("Indicators - Malware Artifacts")
     if self.file_name:
         stix_header.title = "STIX Indicators extracted from MAEC file: " + str(
             self.file_name)
     # Add the Information Source to the STIX Header
     tool_info = ToolInformation()
     stix_header.information_source = InformationSource()
     tool_info.name = "MAEC to STIX"
     tool_info.version = str(__version__)
     stix_header.information_source.tools = ToolInformationList(tool_info)
     stix_package.stix_header = stix_header
     return stix_package
Beispiel #10
0
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() 
Beispiel #11
0
    def create_cybox_object(self, jdict, whitelist, config):
        listObservables = []
        NS = cybox.utils.Namespace("cert.siemens.com", "siemens_cert")
        cybox.utils.set_id_namespace(NS)

        """ store information about malware binary that was analyzed """
        if 'target' in jdict and 'category' in jdict['target'] and jdict['target']['category'] == 'file':
            log.debug("handling File information ...")
            main_file_object = self.__create_cybox_main_file(jdict['target']['file'])
            file_md5 = jdict['target']['file']['md5']
        elif 'target' in jdict and 'category' in jdict['target'] and jdict['target']['category'] == 'url':
            log.warning("Not a file analysis report! URL reports not handled")
            return
        else:
            log.error("No target information in report ... skipping")
            return

        """ try to find email that dropped this attachment """
        if config["attachemail"] or config["referenceemail"]:
            log.info("handling email attack vector information ...")
            email_object_properties, email_observables_list, email_stix_path_tuple_list = self.__check_malware_mailing_list(file_md5, log, config)
            if email_object_properties and len(email_object_properties)>0:
                for email_object in email_object_properties:
                    main_file_object.add_related(email_object, "Contained_Within", inline=False)
            else:
                log.warning("failed linking mail object (no objects to link)")
                email_stix_path_tuple_list = []
        else:
            email_object = None
            email_observables = []
            email_stix_path_tuple_list = []

        """ store extended information about malware file """
        if 'static' in jdict:
            log.debug("handling extended File information ...")
            win_executable_extension = self.__create_cybox_win_executable(jdict['target']['file'], jdict['static'])
            if win_executable_extension:
                main_file_object.add_related(win_executable_extension, "Characterized_By", inline=False)
            win_executable_extension = [win_executable_extension]
        else:
            log.warning("No extended File information found")
            win_executable_extension = []

        """ store domains connected to """
        if 'network' in jdict and 'domains' in jdict['network']:
            log.debug("handling Domain information ...")
            domains, addresses = self.__create_cybox_domains(jdict['network']['domains'], whitelist)
            for dom in domains:
                main_file_object.add_related(dom, 'Connected_To', inline=False)
        else:
            domains = []
            addresses = []

        """ store http session information """
        if 'network' in jdict and 'http' in jdict['network']:
            log.debug("handling HTTP information ...")
            http_requests = self.__create_cybox_https(jdict['network']['http'], whitelist)
            for session in http_requests:
                main_file_object.add_related(session, 'Connected_To', inline=False)
        else:
            http_requests = []

        """ store dns queries information about the malware """
        if 'network' in jdict and 'dns' in jdict['network']:
            log.debug("handling DNS information ...")
            queries = self.__create_cybox_dns_queries(jdict['network']['dns'], whitelist)
            for query in queries:
                main_file_object.add_related(query, 'Connected_To', inline=False)
        else:
            queries = []

        """ store information about dropped files """
        if 'dropped' in jdict:
            log.debug('handling dropped files ...')
            dropped = self.__create_cybox_dropped_files(jdict['dropped'], jdict['target']['file']['sha256'])
            for drop in dropped:
                main_file_object.add_related(drop, 'Dropped', inline=False)
        else:
            dropped = []

        """ store virustotal information """
        if 'virustotal' in jdict and 'positives' in jdict['virustotal']:
            log.debug('handling virustotal information ...')
            vtInformationTools = self.__create_stix_virustotal(jdict['virustotal'], log, config)
            vtFound = True
        else:
            vtInformationTools = []
            vtFound = False

        """ create observables """
        if config["attachemail"] and len(email_observables)>0:
            obs = Observables([main_file_object]+email_observables+win_executable_extension+domains+addresses+http_requests+dropped+queries)
        else:
            obs = Observables([main_file_object]+win_executable_extension+domains+addresses+http_requests+dropped+queries)
        """ generate stix id with siemens namespace """
        if config:
            stix_id_generator = stix.utils.IDGenerator(namespace={config["xmlns"]: config["namespace"]})
        else:
            stix_id_generator = stix.utils.IDGenerator(namespace={"cert.siemens.com": "siemens_cert"})
        """ create stix package """
        stix_id = stix_id_generator.create_id()
        stix_package = STIXPackage(observables=obs, id_=stix_id)
        stix_header = STIXHeader()
        stix_header.title = "Analysis report: %s" % (str(main_file_object.file_name).decode('utf8', errors='xmlcharrefreplace'))
        if 'info' in jdict and 'started' in jdict['info']:
            sandbox_report_date = dateparser.parse(jdict['info']['started']+' CET').isoformat()
        else:
            sandbox_report_date = datetime.datetime.now(pytz.timezone('Europe/Berlin')).isoformat()
        stix_header.description = 'Summarized analysis results for file "%s" with MD5 hash "%s" created on %s.' % (str(main_file_object.file_name).decode('utf8', errors='xmlcharrefreplace'), main_file_object.hashes.md5, sandbox_report_date)
        stix_header.add_package_intent("Malware Characterization")
        """ create markings """
        spec = MarkingSpecification()
        spec.idref = stix_id
        spec.controlled_structure = "//node()"
        tlpmark = TLPMarkingStructure()
        if config:
            if not vtFound:
                tlpmark.color = config["color"]
            else:
                tlpmark.color = "GREEN"
        elif vtFound:
            tlpmark.color = "GREEN"
        else:
            tlpmark.color = "AMBER"
        spec.marking_structure = [tlpmark]
        """ attach to header """
        stix_header.handling = Marking([spec])
        stix_information_source = InformationSource()
        stix_information_source.time = Time(produced_time=sandbox_report_date)
        stix_information_source.tools = ToolInformationList([ToolInformation(tool_name="SIEMENS-ANALYSIS-TOOL-ID-12", tool_vendor="ANALYSIS-ID: %s" % (jdict['info']['id']))]+vtInformationTools)
        stix_header.information_source = stix_information_source
        stix_package.stix_header = stix_header
        """ write result xml file """
        xml_file_name = "stix-%s-malware-report.xml" % (file_md5)
        xml_report_file_path = os.path.join(self.reports_path, xml_file_name)
        fp = open(xml_report_file_path, 'w')
        if config:
            fp.write(stix_package.to_xml(ns_dict={config["xmlns"]: config["namespace"]}))
        else:
            fp.write(stix_package.to_xml(ns_dict={'cert.siemens.com': 'siemens_cert'}))
        fp.close()
        if config["copytoshare"]:
            self.__copy_xml_to_ti_share(xml_report_file_path, xml_file_name, config)
            for item in email_stix_path_tuple_list:
                self.__copy_xml_to_ti_share(item[0], item[1], config, "email")
        else:
            log.warning("copy to TI share is disabled: %s" % (config["copytoshare"]))
        return
Beispiel #12
0
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()