Exemple #1
0
    def load(self):

        objects = []

        with open(self.csv_path, newline='') as csvfile:
            reader = csv.reader(csvfile)
            if self.has_fieldnames:
                # The file has fieldnames, we either ignore it, or validate its validity
                fieldnames = [f.strip().lower() for f in reader.__next__()]
                if not self.fieldnames:
                    self.fieldnames = fieldnames

            if not self.fieldnames:
                raise Exception(f'No fieldnames, impossible to create objects.')
            else:
                # Check if the CSV file has a header, and if it matches with the object template
                tmp_object = MISPObject(self.template_name)
                allowed_fieldnames = list(tmp_object._definition['attributes'].keys())
                for fieldname in self.fieldnames:
                    if fieldname not in allowed_fieldnames:
                        raise Exception(f'{fieldname} is not a valid object relation for {self.template_name}: {allowed_fieldnames}')

            for row in reader:
                tmp_object = MISPObject(self.template_name)
                for object_relation, value in zip(self.fieldnames, row):
                    tmp_object.add_attribute(object_relation, value=value)
                objects.append(tmp_object)
        return objects
Exemple #2
0
def add_hashes(self):
    if self.args.filename is None and self.args.md5 is None and self.args.sha1 is None and self.args.sha256 is None:
        if not __sessions__.is_attached_file(True):
            self.log('error', "Not attached to a file, please set the hashes manually.")
            return False
        file_object = MISPObject('file')
        file_object.add_attribute('filename', value=__sessions__.current.file.name, comment=__sessions__.current.file.tags)
        file_object.add_attribute('md5', value=__sessions__.current.file.md5, comment=__sessions__.current.file.tags)
        file_object.add_attribute('sha1', value=__sessions__.current.file.sha1, comment=__sessions__.current.file.tags)
        file_object.add_attribute('sha256', value=__sessions__.current.file.sha256, comment=__sessions__.current.file.tags)
        __sessions__.current.misp_event.event.add_object(file_object)
    else:
        if self.args.filename:
            if self.args.md5:
                __sessions__.current.misp_event.event.add_attribute('filename|md5', '{}|{}'.format(
                    self.args.filename, self.args.md5))
            if self.args.sha1:
                __sessions__.current.misp_event.event.add_attribute('filename|sha1', '{}|{}'.format(
                    self.args.filename, self.args.sha1))
            if self.args.sha256:
                __sessions__.current.misp_event.event.add_attribute('filename|sha256', '{}|{}'.format(
                    self.args.filename, self.args.sha256))
        else:
            if self.args.md5:
                __sessions__.current.misp_event.event.add_attribute('md5', self.args.md5)
            if self.args.sha1:
                __sessions__.current.misp_event.event.add_attribute('sha1', self.args.sha1)
            if self.args.sha256:
                __sessions__.current.misp_event.event.add_attribute('sha256', self.args.sha256)
    self._change_event()
    def add_dns(self):
        """Add DNS records"""
        network = self.report.get("network", [])
        dns = network.get("dns", [])
        if not dns:
            log.info("No DNS connection found in the report, skipping")
            return False

        for record in dns:
            o = MISPObject(name='dns-record')
            o.add_attribute('text', f"request type:{record['type']}")
            o.add_attribute('queried-domain', record['request'])
            for answer in record.get("answers", []):
                if answer["type"] in ("A", "AAAA"):
                    o.add_attribute('a-record', answer['data'])
                # TODO implement MX/NS

            self.event.add_object(o)
Exemple #4
0
def add_domain_object():
    """Adds a domain object to MISP
    domain-ip description: https://www.misp-project.org/objects.html#_domain_ip
    """
    template = 'domain-ip'
    args = ['text', 'creation_date', 'first_seen', 'last_seen']
    event_id = demisto.getArg('event_id')
    domain = demisto.getArg('name')
    obj = MISPObject(template)
    ips = argToList(demisto.getArg('dns'))
    for ip in ips:
        obj.add_attribute('ip', value=ip)
    obj.add_attribute('domain', value=domain)
    for arg in args:
        value = demisto.getArg(arg)
        if value:
            obj.add_attribute(arg, value=value)
    add_object(event_id, obj)
Exemple #5
0
 def parse_course_of_action(self, o, _):
     misp_object = MISPObject('course-of-action')
     if 'name' in o:
         attribute = {'type': 'text', 'object_relation': 'name', 'value': o.get('name')}
         misp_object.add_attribute(**attribute)
     else:
         return
     if 'description' in o:
         attribute = {'type': 'text', 'object_relation': 'description', 'value': o.get('description')}
         misp_object.add_attribute(**attribute)
     self.misp_event.add_object(**misp_object)
Exemple #6
0
 def parse_vt_object(self, query_result):
     vt_object = MISPObject('virustotal-report')
     vt_object.add_attribute('permalink',
                             type='link',
                             value=query_result['permalink'])
     detection_ratio = '{}/{}'.format(query_result['positives'],
                                      query_result['total'])
     vt_object.add_attribute('detection-ratio',
                             type='text',
                             value=detection_ratio)
     self.misp_event.add_object(**vt_object)
Exemple #7
0
 def handle_object_case(self,
                        attribute_type,
                        attribute_value,
                        compl_data,
                        object_uuid=None):
     misp_object = MISPObject(attribute_type)
     if object_uuid:
         misp_object.uuid = object_uuid
     for attribute in attribute_value:
         misp_object.add_attribute(**attribute)
     if type(compl_data) is dict and "pe_uuid" in compl_data:
         # if some complementary data is a dictionary containing an uuid,
         # it means we are using it to add an object reference
         misp_object.add_reference(compl_data['pe_uuid'], 'included-in')
     self.misp_event.add_object(**misp_object)
 def ip_lookup(self, ip):
     sophos_object = MISPObject('SOPHOSLabs Intelix IP Category Lookup')
     h = {"Authorization": f"{self.accessToken}"}
     r = requests.get(f"https://{self.baseurl}/lookup/ips/v1/{ip}", headers=h)
     if r.status_code == 200:
         j = json.loads(r.text)
         if 'category' in j:
             for c in j['category']:
                 sophos_object.add_attribute('IP Address Categorisation', type='text', value=c)
         else:
             sophos_object.add_attribute('IP Address Categorisation', type='text', value='No category assocaited with IoC')
     self.misp_event.add_object(**sophos_object)
 def parse_url(self, url, recurse=False, uuid=None):
     req = requests.get(self.base_url.format('url'),
                        params={
                            'apikey': self.apikey,
                            'resource': url
                        })
     status_code = req.status_code
     if req.status_code == 200:
         req = req.json()
         vt_uuid = self.parse_vt_object(req)
         if not recurse:
             feature = 'url'
             url_object = MISPObject(feature)
             url_object.add_attribute(feature, type=feature, value=url)
             url_object.add_reference(vt_uuid, 'analyzed-with')
             if uuid:
                 url_object.add_reference(uuid, 'hosted-in')
             self.misp_event.add_object(**url_object)
     return status_code
 def __parse_capec(self, vulnerability_uuid):
     attribute_type = 'text'
     for capec in self.vulnerability['capec']:
         capec_object = MISPObject('attack-pattern')
         for feature in self.capec_features:
             capec_object.add_attribute(feature, **dict(type=attribute_type, value=capec[feature]))
         for related_weakness in capec['related_weakness']:
             attribute = dict(type='weakness', value="CWE-{}".format(related_weakness))
             capec_object.add_attribute('related-weakness', **attribute)
         self.misp_event.add_object(**capec_object)
         self.references[vulnerability_uuid].append(dict(referenced_uuid=capec_object.uuid,
                                                         relationship_type='targeted-by'))
Exemple #11
0
    def all_network(self, results, event):
        """All of the accessed URLS as per the PCAP."""
        urls = set()
        if self.options.get("network", False) and "network" in results.keys():
            urls = set()
            for req in results["network"].get("http", []):
                if req.get("uri") not in whitelist:
                    urls.add(req["uri"])
                if "user-agent" in req:
                    event.add_attribute("user-agent", req["user-agent"])

            domains, ips = {}, set()
            for domain in results.get("network", {}).get("domains", []):
                if domain["domain"] not in whitelist and domain[
                        "ip"] not in whitelist:
                    domains[domain["domain"]] = domain["ip"]
                    ips.add(domain["ip"])

            for block in results.get("network", {}).get("hosts", []):
                if block["ip"] not in whitelist:
                    ips.add(block["ip"])

            for block in results["network"].get("dns", []):  # Added DNS
                if block.get("request", "") and (block["request"]
                                                 not in whitelist):
                    if block["request"] not in domains and block[
                            "request"] not in whitelist:
                        if block["answers"]:
                            domains[
                                block["request"]] = block["answers"][0]["data"]
                            ips.add(domain[block["answers"][0]["data"]])

            # Added CAPE Addresses
            for section in results.get("CAPE", []) or []:
                try:
                    if section.get("cape_config", {}).get("address", []) or []:
                        for ip in section["cape_config"]["address"]:
                            if ip not in ips:
                                ips.add(ip.split(":", 1)[0])
                except Exception as e:
                    print(e)

            for url in sorted(list(urls)):
                event.add_attribute("url", url)
            for ip in sorted(list(ips)):
                event.add_attribute("ip-dst", ip)
            for domain, ips in domains.items():
                obj = MISPObject("domain-ip")
                obj.add_attribute("domain", domain)
                for ip in ips:
                    obj.add_attribute("ip", ip)
                event.add_object(obj)
            self.misp.update_event(event)
 def __parse_misp_csv(self):
     objects = {}
     attribute_fields = self.header[:1] + self.header[2:8]
     for line in self.data:
         a_uuid, _, category, _type, value, comment, ids, timestamp, relation, tag, o_uuid, name, _ = line[:self.fields_number]
         attribute = {t: v.strip('"') for t, v in zip(attribute_fields, (a_uuid, category, _type, value, comment, ids, timestamp))}
         attribute['to_ids'] = True if attribute['to_ids'] == '1' else False
         if tag:
             attribute['Tag'] = [{'name': t.strip()} for t in tag.split(',')]
         if relation:
             if o_uuid not in objects:
                 objects[o_uuid] = MISPObject(name)
             objects[o_uuid].add_attribute(relation, **attribute)
         else:
             self.misp_event.add_attribute(**attribute)
     for uuid, misp_object in objects.items():
         misp_object.uuid = uuid
         self.misp_event.add_object(**misp_object)
Exemple #13
0
 def parse_hash(self, sample, recurse=False, uuid=None, relationship=None):
     req = requests.get(self.base_url.format('file'), params={'apikey': self.apikey, 'resource': sample})
     status_code = req.status_code
     if req.status_code == 200:
         req = req.json()
         vt_uuid = self.parse_vt_object(req)
         file_attributes = []
         for hash_type in ('md5', 'sha1', 'sha256'):
             if req.get(hash_type):
                 file_attributes.append({'type': hash_type, 'object_relation': hash_type,
                                         'value': req[hash_type]})
         if file_attributes:
             file_object = MISPObject('file')
             for attribute in file_attributes:
                 file_object.add_attribute(**attribute)
             file_object.add_reference(vt_uuid, 'analyzed-with')
             if uuid and relationship:
                 file_object.add_reference(uuid, relationship)
             self.misp_event.add_object(**file_object)
     return status_code
Exemple #14
0
def export_pgp(pgp_type, pgp_value):
    dict_metadata = Pgp.pgp.get_metadata(pgp_type, pgp_value)

    obj = MISPObject('pgp-meta')
    obj.first_seen = dict_metadata['first_seen']
    obj.last_seen = dict_metadata['last_seen']

    l_obj_attr = []
    if pgp_type == 'key':
        l_obj_attr.append(obj.add_attribute('key-id', value=pgp_value))
    elif pgp_type == 'name':
        #l_obj_attr.append( obj.add_attribute('key-id', value='debug') )
        l_obj_attr.append(obj.add_attribute('user-id-name', value=pgp_value))
    else:  # mail
        #l_obj_attr.append( obj.add_attribute('key-id', value='debug') )
        l_obj_attr.append(obj.add_attribute('user-id-email', value=pgp_value))
    return obj
Exemple #15
0
 def resolve_dns_objects(self):
     for domain in self.dns_objects['domain']:
         domain_object = self.dns_objects['domain'][domain]
         ip_reference = domain_object['related']
         domain_attribute = domain_object['data']
         if ip_reference in self.dns_objects['ip']:
             misp_object = MISPObject('passive-dns')
             domain_attribute['object_relation'] = "rrname"
             misp_object.add_attribute(**domain_attribute)
             ip = self.dns_objects['ip'][ip_reference]['value']
             ip_attribute = {"type": "text", "value": ip, "object_relation": "rdata"}
             misp_object.add_attribute(**ip_attribute)
             rrtype = "AAAA" if ":" in ip else "A"
             rrtype_attribute = {"type": "text", "value": rrtype, "object_relation": "rrtype"}
             misp_object.add_attribute(**rrtype_attribute)
             self.misp_event.add_object(**misp_object)
         else:
             self.misp_event.add_attribute(**domain_attribute)
     for ip in self.dns_objects['ip']:
         if ip not in self.dns_ips:
             self.misp_event.add_attribute(**self.dns_objects['ip'][ip])
Exemple #16
0
 def parse_report(self, query_result):
     if query_result.get('asn'):
         asn_mapping = {'network': ('ip-src', 'subnet-announced'),
                        'country': ('text', 'country')}
         asn_object = MISPObject('asn')
         asn_object.add_attribute('asn', type='AS', value=query_result['asn'])
         for key, value in asn_mapping.items():
             if query_result.get(key):
                 attribute_type, relation = value
                 asn_object.add_attribute(relation, type=attribute_type, value=query_result[key])
         self.misp_event.add_object(**asn_object)
     self.parse_urls(query_result)
     if query_result.get('resolutions'):
         self.parse_resolutions(query_result['resolutions'])
def export_cryptocurrency(crypto_type, crypto_address):
    dict_metadata = Cryptocurrency.cryptocurrency.get_metadata(crypto_type, crypto_address)

    obj = MISPObject('coin-address')
    obj.first_seen = dict_metadata['first_seen']
    obj.last_seen = dict_metadata['last_seen']

    l_obj_attr = []
    l_obj_attr.append( obj.add_attribute('address', value=crypto_address) )
    crypto_symbol = Cryptocurrency.get_cryptocurrency_symbol(crypto_type)
    if crypto_symbol:
        l_obj_attr.append( obj.add_attribute('symbol', value=crypto_symbol) )

    return obj
Exemple #18
0
def handler(q=False):
    """ the main handler function which gets a JSON dict as input and returns a results dict """

    if q is False:
        return False

    q = json.loads(q)
    if "config" not in q or "api-key" not in q["config"]:
        return {"error": "Ransomcoindb API key is missing"}
    if not q.get('attribute') or not check_input_attribute(q['attribute'], requirements=('type', 'value')):
        return {'error': f'{standard_error_message}, {checking_error}.'}
    if q['attribute']['type'] not in mispattributes['input']:
        return {'error': 'Unsupported attribute type.'}
    api_key = q["config"]["api-key"]
    r = {"results": []}

    """ the "q" query coming in should look something like this:
        {'config': {'api-key': '<api key here>'},
         'md5': 'md5 or sha1 or sha256 or btc',
         'module': 'ransomcoindb',
         'persistent': 1}
    """
    attribute = q['attribute']
    answer = ransomcoindb.get_data_by('BTC', attribute['type'], attribute['value'], api_key)
    """ The results data type should be:
      r =  { 'results': [ {'types': 'md5', 'values': [ a list of all md5s or all binaries related to this btc address ]  } ] }
    """
    if attribute['type'] in ['md5', 'sha1', 'sha256']:
        r['results'].append({'types': 'btc', 'values': [a['btc'] for a in answer]})
    elif attribute['type'] == 'btc':
        # better: create a MISP object
        files = []
        for a in answer:
            obj = MISPObject('file')
            obj.add_attribute('md5', a['md5'])
            obj.add_attribute('sha1', a['sha1'])
            obj.add_attribute('sha256', a['sha256'])
            files.append(obj)
        r['results'] = {'Object': [json.loads(f.to_json()) for f in files]}
    return r
 def parse_vt_object(self, query_result):
     if query_result['response_code'] == 1:
         vt_object = MISPObject('virustotal-report')
         vt_object.add_attribute('permalink',
                                 type='link',
                                 value=query_result['permalink'])
         detection_ratio = '{}/{}'.format(query_result['positives'],
                                          query_result['total'])
         vt_object.add_attribute('detection-ratio',
                                 type='text',
                                 value=detection_ratio,
                                 disable_correlation=True)
         self.misp_event.add_object(**vt_object)
         return vt_object.uuid
def export_decoded(sha1_string):

    decoded_metadata = Decoded.get_decoded_metadata(sha1_string, tag=True)

    obj = MISPObject('file')
    obj.first_seen = decoded_metadata['first_seen']
    obj.last_seen = decoded_metadata['last_seen']

    l_obj_attr = []
    l_obj_attr.append( obj.add_attribute('sha1', value=sha1_string) )
    l_obj_attr.append( obj.add_attribute('mimetype', value=Decoded.get_decoded_item_type(sha1_string)) )
    l_obj_attr.append( obj.add_attribute('malware-sample', value=sha1_string, data=Decoded.get_decoded_file_content(sha1_string)) )

    # add tags
    if decoded_metadata['tags']:
        tag_misp_object_attributes(l_obj_attr, decoded_metadata['tags'])

    return obj
Exemple #21
0
 def _create_file_object(self, file_info):
     file_object = MISPObject('file')
     filename_attribute = {'type': 'filename'}
     filename_attribute.update(self.attribute)
     if file_info['classification'] != "UNCLASSIFIED":
         tag = {'Tag': [{'name': file_info['classification'].lower()}]}
         filename_attribute.update(tag)
         for feature, attribute in self._file_mapping.items():
             attribute.update(tag)
             file_object.add_attribute(value=file_info[feature],
                                       **attribute)
         return filename_attribute, file_object
     for feature, attribute in self._file_mapping.items():
         file_object.add_attribute(value=file_info[feature], **attribute)
     return filename_attribute, file_object
Exemple #22
0
    def to_misp_object(self, tag: bool) -> MISPObject:
        obj = MISPObject(name="email")

        if self.sender:
            classifications = classifications_to_str(self.classifications)
            attr = obj.add_attribute("from",
                                     value=self.sender,
                                     to_ids=self.is_ioc,
                                     comment=classifications)
            if tag:
                self.tag_artifact_attribute(attr)

        if self.subject:
            obj.add_attribute("subject", value=self.subject, to_ids=False)

        for recipient in self.recipients:
            obj.add_attribute("to", value=recipient, to_ids=False)

        return obj
def export_domain(domain):
    domain_obj = Domain.Domain(domain)
    dict_metadata = domain_obj.get_domain_metadata(tags=True)
    dict_metadata['ports'] = ['80', '223', '443']

    # create domain-ip obj
    obj = MISPObject('domain-ip', standalone=True)
    obj.first_seen = dict_metadata['first_seen']
    obj.last_seen = dict_metadata['last_check']

    l_obj_attr = []
    l_obj_attr.append( obj.add_attribute('first-seen', value=dict_metadata['first_seen']) )
    l_obj_attr.append( obj.add_attribute('last-seen', value=dict_metadata['last_check']) )
    l_obj_attr.append( obj.add_attribute('domain', value=domain) )
    for port in dict_metadata['ports']:
        l_obj_attr.append( obj.add_attribute('port', value=port) )

    # add tags
    if dict_metadata['tags']:
        tag_misp_object_attributes(l_obj_attr, dict_metadata['tags'])

    #print(obj.to_json())
    return obj
 def __parse_weakness(self, vulnerability_uuid):
     attribute_type = 'text'
     cwe_string, cwe_id = self.vulnerability['cwe'].split('-')
     cwes = requests.get(self.api_url.replace('/cve/', '/cwe'))
     if cwes.status_code == 200:
         for cwe in cwes.json():
             if cwe['id'] == cwe_id:
                 weakness_object = MISPObject('weakness')
                 weakness_object.add_attribute('id', **dict(type=attribute_type, value='-'.join([cwe_string, cwe_id])))
                 for feature, relation in self.weakness_mapping.items():
                     if cwe.get(feature):
                         weakness_object.add_attribute(relation, **dict(type=attribute_type, value=cwe[feature]))
                 self.misp_event.add_object(**weakness_object)
                 self.references[vulnerability_uuid].append(dict(referenced_uuid=weakness_object.uuid,
                                                                 relationship_type='weakened-by'))
                 break
 def parse(self, value):
     try:
         results = self.pdns.query(self.attribute.value)
     except Exception:
         self.result = {'error': 'There is an authentication error, please make sure you supply correct credentials.'}
         return
     mapping = {'count': 'counter', 'origin': 'text',
                'time_first': 'datetime', 'rrtype': 'text',
                'rrname': 'text', 'rdata': 'text',
                'time_last': 'datetime'}
     for result in results:
         pdns_object = MISPObject('passive-dns')
         for relation, attribute_type in mapping.items():
             pdns_object.add_attribute(relation, type=attribute_type, value=result[relation])
         pdns_object.add_reference(self.attribute.uuid, 'associated-to')
         self.misp_event.add_object(**pdns_object)
def handler(q=False):
    """ the main handler function which gets a JSON dict as input and returns a results dict """

    if q is False:
        return False

    q = json.loads(q)
    api_key = q["config"]["api-key"]
    r = {"results": []}
    """ the "q" query coming in should look something like this:
        {'config': {'api-key': '<api key here>'},
         'md5': 'md5 or sha1 or sha256 or btc',
         'module': 'ransomcoindb',
         'persistent': 1}
    """
    attribute = q['attribute']
    answer = ransomcoindb.get_data_by('BTC', attribute['type'],
                                      attribute['value'], api_key)
    """ The results data type should be:
      r =  { 'results': [ {'types': 'md5', 'values': [ a list of all md5s or all binaries related to this btc address ]  } ] }
    """
    if attribute['type'] in ['md5', 'sha1', 'sha256']:
        r['results'].append({
            'types': 'btc',
            'values': [a['btc'] for a in answer]
        })
    elif attribute['type'] == 'btc':
        # better: create a MISP object
        files = []
        for a in answer:
            obj = MISPObject('file')
            obj.add_attribute('md5', a['md5'])
            obj.add_attribute('sha1', a['sha1'])
            obj.add_attribute('sha256', a['sha256'])
            files.append(obj)
        r['results'] = {'Object': [json.loads(f.to_json()) for f in files]}
    return r
Exemple #27
0
 def parse_dropped_files(self):
     droppedinfo = self.data['droppedinfo']
     if droppedinfo:
         for droppedfile in droppedinfo['hash']:
             file_object = MISPObject('file')
             for key, mapping in dropped_file_mapping.items():
                 attribute_type, object_relation = mapping
                 file_object.add_attribute(
                     object_relation, **{
                         'type': attribute_type,
                         'value': droppedfile[key],
                         'to_ids': False
                     })
             if droppedfile['@malicious'] == 'true':
                 file_object.add_attribute(
                     'state', **{
                         'type': 'text',
                         'value': 'Malicious',
                         'to_ids': False
                     })
             for h in droppedfile['value']:
                 hash_type = dropped_hash_mapping[h['@algo']]
                 file_object.add_attribute(
                     hash_type, **{
                         'type': hash_type,
                         'value': h['$'],
                         'to_ids': False
                     })
             self.misp_event.add_object(**file_object)
             self.references[self.process_references[(
                 int(droppedfile['@targetid']),
                 droppedfile['@process'])]].append({
                     'referenced_uuid':
                     file_object.uuid,
                     'relationship_type':
                     'drops'
                 })
Exemple #28
0
def parse_result(attribute, values):
    event = MISPEvent()
    initial_attribute = MISPAttribute()
    initial_attribute.from_dict(**attribute)
    event.add_attribute(**initial_attribute)
    mapping = {'asn': ('AS', 'asn'), 'prefix': ('ip-src', 'subnet-announced')}
    print(values)
    for last_seen, response in values['response'].items():
        asn = MISPObject('asn')
        asn.add_attribute('last-seen', **{
            'type': 'datetime',
            'value': last_seen
        })
        for feature, attribute_fields in mapping.items():
            attribute_type, object_relation = attribute_fields
            asn.add_attribute(
                object_relation, **{
                    'type': attribute_type,
                    'value': response[feature]
                })
        asn.add_reference(initial_attribute.uuid, 'related-to')
        event.add_object(**asn)
    event = json.loads(event.to_json())
    return {key: event[key] for key in ('Attribute', 'Object')}
Exemple #29
0
 def parse_ip(self, ip, recurse=False):
     req = requests.get(self.base_url.format('ip-address'), params={'apikey': self.apikey, 'ip': ip})
     if req.status_code != 200:
         return req.status_code
     req = req.json()
     if req.get('asn'):
         asn_mapping = {'network': ('ip-src', 'subnet-announced'),
                        'country': ('text', 'country')}
         asn_object = MISPObject('asn')
         asn_object.add_attribute('asn', type='AS', value=req['asn'])
         for key, value in asn_mapping.items():
             if req.get(key):
                 attribute_type, relation = value
                 asn_object.add_attribute(relation, type=attribute_type, value=req[key])
         self.misp_event.add_object(**asn_object)
     uuid = self.parse_resolutions(req['resolutions']) if req.get('resolutions') else None
     return self.parse_related_urls(req, recurse, uuid)
Exemple #30
0
 def add_original_file(self, original_filename):
     with open(self.filename, 'rb') as f:
         sample = b64encode(f.read()).decode('utf-8')
     original_file = MISPObject('original-imported-file')
     original_file.add_attribute(
         **{
             'type': 'attachment',
             'value': original_filename,
             'object_relation': 'imported-sample',
             'data': sample
         })
     original_file.add_attribute(
         **{
             'type': 'text',
             'object_relation': 'format',
             'value': self.stix_version
         })
     self.misp_event.add_object(**original_file)
Exemple #31
0
 def parse_object(self, o, labels):
     object_type = self.get_misp_type(labels)
     name = 'file' if object_type == 'WindowsPEBinaryFile' else object_type
     object_category = self.get_misp_category(labels)
     stix_type = o._type
     misp_object = MISPObject(name)
     misp_object['meta-category'] = object_category
     if stix_type == 'indicator':
         pattern = o.get('pattern').replace('\\\\', '\\').split(' AND ')
         pattern[0] = pattern[0][1:]
         pattern[-1] = pattern[-1][:-1]
         attributes = self.objects_mapping[object_type]['pattern'](pattern)
     if stix_type == 'observed-data':
         observable = o.get('objects')
         attributes = self.objects_mapping[object_type]['observable'](observable)
     if isinstance(attributes, tuple):
         attributes, pe_uuid = attributes
         misp_object.add_reference(pe_uuid, 'included-in')
     for attribute in attributes:
         misp_object.add_attribute(**attribute)
     misp_object.to_ids = bool(labels[1].split('=')[1])
     self.misp_event.add_object(**misp_object)
Exemple #32
0
    def parse_system_behavior(self):
        system = self.data['behavior']['system']
        if system.get('processes'):
            process_activities = {
                'fileactivities': self.parse_fileactivities,
                'registryactivities': self.parse_registryactivities
            }
            for process in system['processes']['process']:
                no_correlation = False
                general = process['general']
                if general['name'] in disable_correlations:
                    no_correlation = True

                process_object = MISPObject('process')
                for feature, relation in process_object_fields.items():
                    process_object.add_attribute(
                        relation, **{
                            'type': 'text',
                            'value': general[feature],
                            'disable_correlation': no_correlation,
                            'to_ids': False
                        })
                start_time = datetime.strptime(
                    '{} {}'.format(general['date'], general['time']),
                    '%d/%m/%Y %H:%M:%S')
                process_object.add_attribute(
                    'start-time', **{
                        'type': 'datetime',
                        'value': start_time,
                        'disable_correlation': no_correlation,
                        'to_ids': False
                    })
                self.misp_event.add_object(**process_object)
                for field, to_call in process_activities.items():
                    if process.get(field):
                        to_call(process_object.uuid, process[field])
                self.references[self.analysisinfo_uuid].append(
                    dict(referenced_uuid=process_object.uuid,
                         relationship_type='calls'))
                self.process_references[(
                    general['targetid'],
                    general['path'])] = process_object.uuid
Exemple #33
0
def check_hashes(self):
    if self.offline_mode:
        self.log('error', 'Offline mode, unable to query VirusTotal')
        return
    event_id = self._get_eventid()
    if event_id is None:
        return
    event = self.misp.get(event_id)
    if self._has_error_message(event):
        return

    misp_event = MISPEvent()
    misp_event.load(event)
    hashes_to_expand = {}
    hashes_expanded = []  # Thoses hashes are known and already processed
    local_samples_hashes = []
    partial_objects = {}
    for o in misp_event.Object:
        if o.name != 'file':
            continue
        if o.has_attributes_by_relation(['md5', 'sha1', 'sha256']):
            # This object has all the hashes we care about
            tmphashes = []
            tmphashes += [h.value for h in o.get_attributes_by_relation('md5')]
            tmphashes += [h.value for h in o.get_attributes_by_relation('sha1')]
            tmphashes += [h.value for h in o.get_attributes_by_relation('sha256')]
            # Make sure to query VT for the sha256, even if expanded locally
            hashes_to_expand[o.get_attributes_by_relation('sha256')[0].value] = o.get_attributes_by_relation('sha256')[0]
            if o.has_attributes_by_relation(['malware-sample']):
                # ... and it has a malware sample
                local_samples_hashes += tmphashes
            hashes_expanded += tmphashes
        elif o.has_attributes_by_relation(['malware-sample']):
            # This object has a malware sample, but is missing hashes. We can expand locally.
            # get the MD5 from the malware-sample attribute
            malware_sample = o.get_attributes_by_relation('malware-sample')[0]  # at most one sample/file object
            local_samples_hashes.append(malware_sample.value.split('|')[1])
            local_samples_hashes += [h.value for h in o.get_attributes_by_relation('md5')]
            local_samples_hashes += [h.value for h in o.get_attributes_by_relation('sha1')]
            local_samples_hashes += [h.value for h in o.get_attributes_by_relation('sha256')]
            if self.args.populate:
                # The object is missing hashes, keeping track of it for expansion if it isn't already done.
                partial_objects[o.uuid] = malware_sample

        else:
            sha256 = {attribute.value: attribute for attribute in o.get_attributes_by_relation('sha256')}
            sha1 = {attribute.value: attribute for attribute in o.get_attributes_by_relation('sha1')}
            md5 = {attribute.value: attribute for attribute in o.get_attributes_by_relation('md5')}
            if sha256:
                hashes_to_expand.update(sha256)
            elif sha1:
                hashes_to_expand.update(sha1)
            elif md5:
                hashes_to_expand.update(md5)

    for ref_uuid, sample in partial_objects.items():
        if sample.value.split('|')[1] in hashes_expanded:
            # Already expanded in an other object
            continue
        new_obj, hashes = self._expand_local_sample(pseudofile=sample.malware_binary,
                                                    filename=sample.value.split('|')[0],
                                                    refobj=ref_uuid,
                                                    default_attributes_paramaters=sample)
        misp_event.Object += new_obj
        local_samples_hashes += hashes
        # Make sure to query VT for the sha256, even if expanded locally
        hashes_to_expand[hashes[0]] = sample

    hashes_expanded += local_samples_hashes
    for a in misp_event.attributes:
        if a.type == 'malware-sample' and a.value.split('|')[1] not in hashes_expanded:
            new_obj, hashes = self._expand_local_sample(pseudofile=a.malware_binary,
                                                        filename=a.value.split('|')[0],
                                                        default_attributes_paramaters=a)
            misp_event.Object += new_obj
            local_samples_hashes += hashes
            # Make sure to query VT for the sha256, even if expanded locally
            hashes_to_expand[hashes[0]] = a
        elif a.type in ('filename|md5', 'filename|sha1', 'filename|sha256'):
            # We don't care if the hashes are in hashes_expanded or hashes_to_expand: they are firtered out later anyway
            fname, hashval = a.value.split('|')
            hashes_to_expand[hashval] = a
        elif a.type in ('md5', 'sha1', 'sha256'):
            # We don't care if the hashes are in hashes_expanded or hashes_to_expand: they are firtered out later anyway
            hashes_to_expand[a.value] = a

    unk_vt_hashes = []
    if cfg.virustotal.virustotal_has_private_key is False:
        quota = 4
        timeout = datetime.datetime.now() + datetime.timedelta(minutes=1)

    hashes_expanded += local_samples_hashes
    processed_on_vt = []
    # Make sure to start getting reports for the longest possible hashes (reduce risks of collisions)
    for to_expand in sorted(list(set(hashes_to_expand)), key=len):
        if to_expand in processed_on_vt:
            # Always run VT, once per sample
            continue
        original_attribute = hashes_to_expand[to_expand]
        if original_attribute.get('object_id'):
            original_object_id = original_attribute.get('object_id')
        vt_object = self._make_VT_object(to_expand, original_attribute)
        if not vt_object:
            unk_vt_hashes.append(to_expand)
            continue
        result = vt_object.get_report()
        md5 = result['md5']
        sha1 = result['sha1']
        sha256 = result['sha256']
        processed_on_vt += [sha256, sha1, md5]
        if all(h in local_samples_hashes for h in [md5, sha1, sha256]):
            self.log('success', 'Sample available in MISP:')
        else:
            self.log('success', 'Sample available in VT:')
        self.log('item', '{}\n\t{}\n\t{}\n\t{}'.format(result["permalink"], md5, sha1, sha256))
        if self.args.populate:
            if not all(h in hashes_expanded for h in [md5, sha1, sha256]):
                # If all the "new" expanded hashes are in the hashes_expanded list, skip
                file_object = MISPObject('file', default_attributes_paramaters=original_attribute)
                file_object.add_attribute('md5', value=md5)
                file_object.add_attribute('sha1', value=sha1)
                file_object.add_attribute('sha256', value=sha256)
                file_object.add_reference(vt_object.uuid, 'analysed-with')
                misp_event.Object.append(file_object)
                hashes_expanded += [md5, sha1, sha256]
            else:
                if not original_object_id or original_object_id == '0':
                    # Not an object, but the hashes are in an other object, skipping
                    continue
                else:
                    # We already have a MISP object, adding the link to the new VT object
                    file_object = misp_event.get_object_by_id(original_object_id)
                    file_object.add_reference(vt_object.uuid, 'analysed-with')
            misp_event.Object.append(vt_object)

        if cfg.virustotal.virustotal_has_private_key is False:
            if quota > 0:
                quota -= 1
            else:
                waiting_time = (timeout - datetime.datetime.now()).seconds
                if waiting_time > 0:
                    self.log('warning', 'No private API key, 4 queries/min is the limit. Waiting for {} seconds.'.format(waiting_time))
                    time.sleep(waiting_time)
                quota = 4
                timeout = datetime.datetime.now() + datetime.timedelta(minutes=1)

    if self.args.populate:
        self._populate(misp_event)
    if len(unk_vt_hashes) > 0:
        self.log('error', 'Unknown on VT:')
        for h in unk_vt_hashes:
            self.log('item', '{}'.format(h))