def obj_create(self, bundle, **kwargs): """ Handles creating Certificates through the API. :param bundle: Bundle containing the information to create the Certificate. :type bundle: Tastypie Bundle object. :returns: HttpResponse. """ content = {"return_code": 1, "type": "Certificate"} analyst = bundle.request.user.username file_ = bundle.data.get("filedata", None) if not file_: content["message"] = "Upload type of 'file' but no file uploaded." self.crits_response(content) filedata = file_.read() filename = str(file_) source = bundle.data.get("source", None) method = bundle.data.get("method", None) reference = bundle.data.get("reference", None) description = bundle.data.get("reference", None) relationship = bundle.data.get("relationship", None) related_id = bundle.data.get("related_id", None) related_md5 = bundle.data.get("related_md5", None) related_type = bundle.data.get("related_type", None) bucket_list = bundle.data.get("bucket_list", None) ticket = bundle.data.get("ticket", None) result = handle_cert_file( filename, filedata, source, analyst, description, related_id=related_id, related_md5=related_md5, related_type=related_type, method=method, reference=reference, relationship=relationship, bucket_list=bucket_list, ticket=ticket, ) if result.get("id"): url = reverse( "api_dispatch_detail", kwargs={"resource_name": "certificates", "api_name": "v1", "pk": result.get("id")}, ) content["url"] = url content["id"] = result.get("id") if result["success"]: content["return_code"] = 0 content["message"] = result["message"] self.crits_response(content)
def obj_create(self, bundle, **kwargs): """ Handles creating Certificates through the API. :param bundle: Bundle containing the information to create the Certificate. :type bundle: Tastypie Bundle object. :returns: HttpResponse. """ content = {'return_code': 1, 'type': 'Certificate'} analyst = bundle.request.user.username file_ = bundle.data.get('filedata', None) if not file_: content['message'] = "Upload type of 'file' but no file uploaded." self.crits_response(content) filedata = file_.read() filename = str(file_) source = bundle.data.get('source', None) method = bundle.data.get('method', None) reference = bundle.data.get('reference', None) description = bundle.data.get('reference', None) relationship = bundle.data.get('relationship', None) related_id = bundle.data.get('related_id', None) related_md5 = bundle.data.get('related_md5', None) related_type = bundle.data.get('related_type', None) bucket_list = bundle.data.get('bucket_list', None) ticket = bundle.data.get('ticket', None) result = handle_cert_file(filename, filedata, source, analyst, description, related_id=related_id, related_md5=related_md5, related_type=related_type, method=method, reference=reference, relationship=relationship, bucket_list=bucket_list, ticket=ticket) if result.get('id'): url = reverse('api_dispatch_detail', kwargs={ 'resource_name': 'certificates', 'api_name': 'v1', 'pk': result.get('id') }) content['url'] = url content['id'] = result.get('id') if result['success']: content['return_code'] = 0 content['message'] = result['message'] self.crits_response(content)
def obj_create(self, bundle, **kwargs): """ Handles creating Certificates through the API. :param bundle: Bundle containing the information to create the Certificate. :type bundle: Tastypie Bundle object. :returns: HttpResponse. """ content = {'return_code': 1, 'type': 'Certificate'} analyst = bundle.request.user.username file_ = bundle.data.get('filedata', None) if not file_: content['message'] = "Upload type of 'file' but no file uploaded." self.crits_response(content) filedata = file_.read() filename = str(file_) source = bundle.data.get('source', None) method = bundle.data.get('method', None) reference = bundle.data.get('reference', None) description = bundle.data.get('reference', None) relationship = bundle.data.get('relationship', None) related_id = bundle.data.get('related_id', None) related_md5 = bundle.data.get('related_md5', None) related_type = bundle.data.get('related_type', None) bucket_list = bundle.data.get('bucket_list', None) ticket = bundle.data.get('ticket', None) result = handle_cert_file(filename, filedata, source, analyst, description, related_id=related_id, related_md5=related_md5, related_type = related_type, method=method, reference=reference, relationship=relationship, bucket_list=bucket_list, ticket=ticket) if result.get('id'): url = reverse('api_dispatch_detail', kwargs={'resource_name': 'certificates', 'api_name': 'v1', 'pk': result.get('id')}) content['url'] = url content['id'] = result.get('id') if result['success']: content['return_code'] = 0 content['message'] = result['message'] self.crits_response(content)
def upload_certificate(request): """ Add a new Certificate to CRITs. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ if request.method == 'POST': form = UploadCertificateForm(request.user, request.POST, request.FILES) if form.is_valid(): filedata = request.FILES['filedata'] filename = filedata.name data = filedata.read() # XXX: Should be using chunks here. source = form.cleaned_data.get('source') user = request.user.username description = form.cleaned_data.get('description', '') related = form.cleaned_data.get('related_id', '') related_type = form.cleaned_data.get('related_type', '') relationship_type = form.cleaned_data.get('relationship_type','') bucket_list = form.cleaned_data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME) ticket = form.cleaned_data.get(form_consts.Common.TICKET_VARIABLE_NAME) method = form.cleaned_data.get('method', '') or 'Upload' reference = form.cleaned_data.get('reference', '') status = handle_cert_file(filename, data, source, user, description, related_id=related, related_type=related_type, relationship_type=relationship_type, method=method, reference=reference, bucket_list=bucket_list, ticket=ticket) if status['success']: return render_to_response('file_upload_response.html', {'response': json.dumps({ 'message': 'Certificate uploaded successfully! <a href="%s">View Certificate</a>' % reverse('crits.certificates.views.certificate_details', args=[status['md5']]), 'success': True})}, RequestContext(request)) else: return render_to_response('file_upload_response.html', {'response': json.dumps({ 'success': False, 'message': status['message']})} , RequestContext(request)) else: return render_to_response('file_upload_response.html', {'response': json.dumps({'success': False, 'form': form.as_table()})}, RequestContext(request)) else: return render_to_response('error.html', {'error': "Expected POST."}, RequestContext(request))
def upload_certificate(request): """ Add a new Certificate to CRITs. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ user = request.user if request.method == 'POST': form = UploadCertificateForm(user, request.POST, request.FILES) if form.is_valid(): if user.has_access_to(CertificateACL.WRITE): filedata = request.FILES['filedata'] filename = filedata.name data = filedata.read() # XXX: Should be using chunks here. source = form.cleaned_data.get('source_name') description = form.cleaned_data.get('description', '') related = form.cleaned_data.get('related_id', '') related_type = form.cleaned_data.get('related_type', '') relationship_type = form.cleaned_data.get('relationship_type','') bucket_list = form.cleaned_data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME) ticket = form.cleaned_data.get(form_consts.Common.TICKET_VARIABLE_NAME) method = form.cleaned_data.get('source_method', '') or 'Upload' reference = form.cleaned_data.get('source_reference', '') tlp = form.cleaned_data.get('source_tlp', None) status = handle_cert_file(filename, data, source, user, description, related_id=related, related_type=related_type, relationship_type=relationship_type, method=method, reference=reference, tlp=tlp, bucket_list=bucket_list, ticket=ticket) else: status = {'success':False, 'message':'User does not have permission to add Certificate.'} if status['success']: return render(request, 'file_upload_response.html', {'response': json.dumps({ 'message': 'Certificate uploaded successfully! <a href="%s">View Certificate</a>' % reverse('crits-certificates-views-certificate_details', args=[status['md5']]), 'success': True})}, ) else: return render(request, 'file_upload_response.html', {'response': json.dumps({ 'success': False})}) else: return render(request, 'file_upload_response.html', {'response': json.dumps({'success': False})}) else: return render(request, 'error.html', {'error': "Expected POST."})
def upload_certificate(request): """ Add a new Certificate to CRITs. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ if request.method == 'POST': form = UploadCertificateForm(request.user, request.POST, request.FILES) if form.is_valid(): filedata = request.FILES['filedata'] filename = filedata.name data = filedata.read() # XXX: Should be using chunks here. source = form.cleaned_data.get('source') user = request.user.username description = form.cleaned_data.get('description', '') parent = form.cleaned_data.get('parent_id', '') parent_type = form.cleaned_data.get('parent_type', '') bucket_list = form.cleaned_data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME) ticket = form.cleaned_data.get(form_consts.Common.TICKET_VARIABLE_NAME) method = 'Upload' status = handle_cert_file(filename, data, source, user, description, parent_id=parent, parent_type=parent_type, method=method, bucket_list=bucket_list, ticket=ticket) if status['success']: return render_to_response('file_upload_response.html', {'response': json.dumps({ 'message': 'Certificate uploaded successfully! <a href="%s">View Certificate</a>' % reverse('crits.certificates.views.certificate_details', args=[status['md5']]), 'success': True})}, RequestContext(request)) else: return render_to_response('file_upload_response.html', {'response': json.dumps({ 'success': False, 'message': status['message']})} , RequestContext(request)) else: return render_to_response('file_upload_response.html', {'response': json.dumps({'success': False, 'form': form.as_table()})}, RequestContext(request)) else: return render_to_response('error.html', {'error': "Expected POST."}, RequestContext(request))
def obj_create(self, bundle, **kwargs): """ Handles creating Certificates through the API. :param bundle: Bundle containing the information to create the Certificate. :type bundle: Tastypie Bundle object. :returns: Bundle object. :raises BadRequest: If filedata is not provided or creation fails. """ analyst = bundle.request.user.username file_ = bundle.data.get('filedata', None) if not file_: raise BadRequest("Upload type of 'file' but no file uploaded.") filedata = file_.read() filename = str(file_) source = bundle.data.get('source', None) method = bundle.data.get('method', None) description = bundle.data.get('reference', None) relationship = bundle.data.get('relationship', None) parent_id = bundle.data.get('related_id', None) parent_md5 = bundle.data.get('related_md5', None) parent_type = bundle.data.get('related_type', None) bucket_list = bundle.data.get('bucket_list', None) ticket = bundle.data.get('ticket', None) result = handle_cert_file(filename, filedata, source, analyst, description, parent_id=parent_id, parent_md5=parent_md5, parent_type = parent_type, method=method, relationship=relationship, bucket_list=bucket_list, ticket=ticket) if result['success']: return bundle else: raise BadRequest(result['message'])
def obj_create(self, bundle, **kwargs): """ Handles creating Certificates through the API. :param bundle: Bundle containing the information to create the Certificate. :type bundle: Tastypie Bundle object. :returns: Bundle object. :raises BadRequest: If filedata is not provided or creation fails. """ analyst = bundle.request.user.username file_ = bundle.data.get('filedata', None) if not file_: raise BadRequest("Upload type of 'file' but no file uploaded.") filedata = file_.read() filename = str(file_) source = bundle.data.get('source', None) method = bundle.data.get('method', None) description = bundle.data.get('reference', None) relationship = bundle.data.get('relationship', None) parent_id = bundle.data.get('related_id', None) parent_md5 = bundle.data.get('related_md5', None) parent_type = bundle.data.get('related_type', None) bucket_list = bundle.data.get('bucket_list', None) ticket = bundle.data.get('ticket', None) result = handle_cert_file(filename, filedata, source, analyst, description, parent_id=parent_id, parent_md5=parent_md5, parent_type=parent_type, method=method, relationship=relationship, bucket_list=bucket_list, ticket=ticket) if result['success']: return bundle else: raise BadRequest(result['message'])
def parse_observables(self, observables): """ Parse list of observables in STIX doc. :param observables: List of STIX observables. :type observables: List of STIX observables. """ analyst = self.source_instance.analyst for obs in observables: # for each STIX observable if obs.observable_composition: object_list = obs.observable_composition.observables else: object_list = [obs] for obs_comp in object_list: if not obs_comp.object_ or not obs_comp.object_.properties: self.failed.append( ("No valid object_properties was found!", type(obs_comp).__name__, obs_comp.id_)) # note for display in UI continue try: # try to create CRITs object from observable item = obs_comp.object_.properties if isinstance(item, Address): if item.category in ('cidr', 'ipv4-addr', 'ipv4-net', 'ipv4-netmask', 'ipv6-addr', 'ipv6-net', 'ipv6-netmask', 'ipv6-subnet'): imp_type = "IP" for value in item.address_value.values: ip = str(value).strip() iptype = get_crits_ip_type(item.category) if iptype: res = ip_add_update(ip, iptype, [self.source], analyst=analyst, id=self.package.id_) self.parse_res(imp_type, obs, res) if isinstance(item, DomainName): imp_type = "Domain" for value in item.value.values: res = upsert_domain(str(value), [self.source], username=analyst, id=self.package.id_) self.parse_res(imp_type, obs, res) elif isinstance(item, Artifact): # Not sure if this is right, and I believe these can be # encoded in a couple different ways. imp_type = "RawData" rawdata = item.data.decode('utf-8') description = "None" # TODO: find out proper ways to determine title, datatype, # tool_name, tool_version title = "Artifact for Event: STIX Document %s" % self.package.id_ res = handle_raw_data_file( rawdata, self.source.name, user=analyst, description=description, title=title, data_type="Text", tool_name="STIX", tool_version=None, method=self.source_instance.method, reference=self.source_instance.reference) self.parse_res(imp_type, obs, res) elif (isinstance(item, File) and item.custom_properties and item.custom_properties[0].name == "crits_type" and item.custom_properties[0]._value == "Certificate"): imp_type = "Certificate" description = "None" filename = str(item.file_name) data = None for obj in item.parent.related_objects: if isinstance(obj.properties, Artifact): data = obj.properties.data res = handle_cert_file(filename, data, self.source, user=analyst, description=description) self.parse_res(imp_type, obs, res) elif isinstance(item, File) and self.has_network_artifact(item): imp_type = "PCAP" description = "None" filename = str(item.file_name) data = None for obj in item.parent.related_objects: if (isinstance(obj.properties, Artifact) and obj.properties.type_ == Artifact.TYPE_NETWORK): data = obj.properties.data res = handle_pcap_file(filename, data, self.source, user=analyst, description=description) self.parse_res(imp_type, obs, res) elif isinstance(item, File): imp_type = "Sample" filename = str(item.file_name) md5 = item.md5 data = None for obj in item.parent.related_objects: if (isinstance(obj.properties, Artifact) and obj.properties.type_ == Artifact.TYPE_FILE): data = obj.properties.data res = handle_file(filename, data, self.source, user=analyst, md5_digest=md5, is_return_only_md5=False, id=self.package.id_) self.parse_res(imp_type, obs, res) if item.extracted_features: self.parse_filenames(item.extracted_features, res['object'].id) elif isinstance(item, EmailMessage): imp_type = "Email" data = {} data['source'] = self.source.name data['source_method'] = self.source_instance.method data[ 'source_reference'] = self.source_instance.reference data['raw_body'] = str(item.raw_body) data['raw_header'] = str(item.raw_header) data['helo'] = str(item.email_server) if item.header: data['message_id'] = str(item.header.message_id) data['subject'] = str(item.header.subject) data['sender'] = str(item.header.sender) data['reply_to'] = str(item.header.reply_to) data['x_originating_ip'] = str( item.header.x_originating_ip) data['x_mailer'] = str(item.header.x_mailer) data['boundary'] = str(item.header.boundary) data['from_address'] = str(item.header.from_) data['date'] = item.header.date.value if item.header.to: data['to'] = [str(r) for r in item.header.to] if item.header.cc: data['cc'] = [str(r) for r in item.header.cc] res = handle_email_fields(data, analyst, "STIX", id=self.package.id_) # Should check for attachments and add them here. self.parse_res(imp_type, obs, res) if res.get('status') and item.attachments: for attach in item.attachments: rel_id = attach.to_dict()['object_reference'] self.relationships.append( (obs.id_, "Contains", rel_id, "High")) else: # try to parse all other possibilities as Indicator imp_type = "Indicator" obj = make_crits_object(item) if obj.object_type == 'Address': # This was already caught above continue else: ind_type = obj.object_type for value in obj.value: if value and ind_type: res = handle_indicator_ind( value.strip(), self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True) self.parse_res(imp_type, obs, res) except Exception, e: # probably caused by cybox object we don't handle self.failed.append( (e.message, type(item).__name__, item.parent.id_)) # note for display in UI
def parse_observables(self, observables): """ Parse list of observables in STIX doc. :param observables: List of STIX observables. :type observables: List of STIX observables. """ analyst = self.source_instance.analyst for obs in observables: # for each STIX observable if not obs.object_ or not obs.object_.properties: self.failed.append(("No valid object_properties was found!", type(obs).__name__, obs.id_)) # note for display in UI continue try: # try to create CRITs object from observable item = obs.object_.properties if isinstance(item, Address): if item.category in ('cidr', 'ipv4-addr', 'ipv4-net', 'ipv4-netmask', 'ipv6-addr', 'ipv6-net', 'ipv6-netmask'): imp_type = "IP" for value in item.address_value.values: ip = str(value).strip() iptype = get_crits_ip_type(item.category) if iptype: res = ip_add_update(ip, iptype, [self.source], analyst=analyst, is_add_indicator=True) self.parse_res(imp_type, obs, res) if isinstance(item, DomainName): imp_type = "Domain" for value in item.value.values: res = upsert_domain(str(value), [self.source], username=analyst) self.parse_res(imp_type, obs, res) elif isinstance(item, Artifact): # Not sure if this is right, and I believe these can be # encoded in a couple different ways. imp_type = "RawData" rawdata = item.data.decode('utf-8') description = "None" # TODO: find out proper ways to determine title, datatype, # tool_name, tool_version title = "Artifact for Event: STIX Document %s" % self.package.id_ res = handle_raw_data_file(rawdata, self.source.name, user=analyst, description=description, title=title, data_type="Text", tool_name="STIX", tool_version=None, method=self.source_instance.method, reference=self.source_instance.reference) self.parse_res(imp_type, obs, res) elif (isinstance(item, File) and item.custom_properties and item.custom_properties[0].name == "crits_type" and item.custom_properties[0]._value == "Certificate"): imp_type = "Certificate" description = "None" filename = str(item.file_name) data = None for obj in item.parent.related_objects: if isinstance(obj.properties, Artifact): data = obj.properties.data res = handle_cert_file(filename, data, self.source, user=analyst, description=description) self.parse_res(imp_type, obs, res) elif isinstance(item, File) and self.has_network_artifact(item): imp_type = "PCAP" description = "None" filename = str(item.file_name) data = None for obj in item.parent.related_objects: if (isinstance(obj.properties, Artifact) and obj.properties.type_ == Artifact.TYPE_NETWORK): data = obj.properties.data res = handle_pcap_file(filename, data, self.source, user=analyst, description=description) self.parse_res(imp_type, obs, res) elif isinstance(item, File): imp_type = "Sample" filename = str(item.file_name) md5 = item.md5 data = None for obj in item.parent.related_objects: if (isinstance(obj.properties, Artifact) and obj.properties.type_ == Artifact.TYPE_FILE): data = obj.properties.data res = handle_file(filename, data, self.source, user=analyst, md5_digest=md5, is_return_only_md5=False) self.parse_res(imp_type, obs, res) elif isinstance(item, EmailMessage): imp_type = "Email" data = {} data['source'] = self.source.name data['source_method'] = self.source_instance.method data['source_reference'] = self.source_instance.reference data['raw_body'] = str(item.raw_body) data['raw_header'] = str(item.raw_header) data['helo'] = str(item.email_server) if item.header: data['message_id'] = str(item.header.message_id) data['subject'] = str(item.header.subject) data['sender'] = str(item.header.sender) data['reply_to'] = str(item.header.reply_to) data['x_originating_ip'] = str(item.header.x_originating_ip) data['x_mailer'] = str(item.header.x_mailer) data['boundary'] = str(item.header.boundary) data['from_address'] = str(item.header.from_) data['date'] = item.header.date.value if item.header.to: data['to'] = [str(r) for r in item.header.to.to_list()] res = handle_email_fields(data, analyst, "STIX") # Should check for attachments and add them here. self.parse_res(imp_type, obs, res) if res.get('status') and item.attachments: for attach in item.attachments: rel_id = attach.to_dict()['object_reference'] self.relationships.append((obs.id_, "Contains", rel_id, "High")) else: # try to parse all other possibilities as Indicator imp_type = "Indicator" obj = make_crits_object(item) if obj.object_type == 'Address': # This was already caught above continue else: ind_type = obj.object_type for value in obj.value: if value and ind_type: res = handle_indicator_ind(value.strip(), self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True) self.parse_res(imp_type, obs, res) except Exception, e: # probably caused by cybox object we don't handle self.failed.append((e.message, type(item).__name__, item.parent.id_)) # note for display in UI
class MachOInfoService(Service): name = "machoinfo" version = '0.0.1' supported_types = ['Sample'] description = "Generate metadata about Mach-O binaries." @staticmethod def valid_for(obj): if obj.filedata.grid_id == None: raise ServiceConfigError("Missing filedata.") data = obj.filedata.read() if len(data) < 4: raise ServiceConfigError("Need at least 4 bytes.") # Reset the read pointer. obj.filedata.seek(0) if not struct.unpack('@I', data[:4])[0] in [ MachOEntity.FAT_MAGIC, MachOEntity.FAT_CIGAM, MachOEntity.MH_MAGIC, MachOEntity.MH_CIGAM, MachOEntity.MH_MAGIC_64, MachOEntity.MH_CIGAM_64 ]: raise ServiceConfigError("Bad magic.") def run(self, obj, config): data = obj.filedata.read() mop = MachOParser(data) try: mop.parse() except MachOParserError, e: self._error("ERROR: %s" % e) return i = 0 for entity in mop.entities: result = { 'entity': i, 'sub_files': entity.nfat, 'cpu_type': entity.cpu_type_str, 'cpu_subtype': entity.cpu_subtype_str, 'filetype': entity.filetype_str, 'flaglist': ', '.join(entity.flaglist), 'commands': len(entity.cmdlist) } entity_string = "%s %s %s" % ( entity.magic_str, entity.cpu_type_str, entity.cpu_subtype_str) self._add_result('Headers', entity_string, result) i += 1 i = 0 for entity in mop.entities: if entity.is_universal(): i += 1 continue # Nothing more to print for universal files for cmd in entity.cmdlist: self._add_result('Entity %i - Commands' % i, entity.cmd_name(cmd['cmd']), {}) i += 1 i = 0 for entity in mop.entities: if entity.is_universal(): i += 1 continue # Nothing more to print for universal files # first let's do "imports" for cmd in entity.cmdlist: if cmd['cmd'] == MachOEntity.LC_LOAD_DYLINKER: self._add_result( 'Entity %i - %s' % (i, entity.cmd_name(cmd['cmd'])), cmd['dylinker'], {}) for cmd in entity.cmdlist: if cmd['cmd'] in [ MachOEntity.LC_LOAD_DYLIB, MachOEntity.LC_ID_DYLIB ]: result = { 'timestamp': cmd.get('timestamp', ''), 'current_version': cmd.get('cv', ''), 'compat_version': cmd.get('cpv'), } self._add_result( 'Entity %i - %s' % (i, entity.cmd_name(cmd['cmd'])), cmd.get('dylib', ''), result) for cmd in entity.cmdlist: if cmd['cmd'] == MachOEntity.LC_CODE_SIGNATURE: e = 'Entity %i - %s' % (i, entity.cmd_name(cmd['cmd'])) for sig in cmd.get('signatures', []): if sig['type'] == MachOEntity.CODE_DIRECTORY: result = { 'ver': sig['ver'], 'identifier': sig['identifier'], 'hashtype': sig['hashtype'], } self._add_result(e, sig['hash'], result) elif sig['type'] == MachOEntity.CERT_BLOB: data = sig['pkcs7'] filename = hashlib.md5(data).hexdigest() handle_cert_file( filename, data, obj.source, related_id=str(obj.id), related_type=obj._meta['crits_type'], method=self.name, relationship='Extracted_From', user=self.current_task.username) self._add_result("cert_added", filename, {'md5': filename}) e = 'Entity %i - Version Info' % i result = {} for cmd in entity.cmdlist: if cmd['cmd'] == MachOEntity.LC_UUID: result['uuid'] = cmd['uuid'] elif cmd['cmd'] in [ MachOEntity.LC_VERSION_MIN_MACOSX, MachOEntity.LC_VERSION_MIN_IPHONEOS ]: result['os_ver'] = cmd['ver'] result['sdk_ver'] = cmd['sdk'] elif cmd['cmd'] == MachOEntity.LC_SOURCE_VERSION: result['source_version'] = cmd['ver'] if result: self._add_result(e, result['uuid'], result) e = 'Entity %i - Segments' % i j = 0 segment_list = [] for cmd in entity.cmdlist: if cmd['cmd'] in [ MachOEntity.LC_SEGMENT, MachOEntity.LC_SEGMENT_64 ]: segname = cmd['segname'] if not segname: segname = "NO_NAME" result = { 'segname': segname, 'filesize': cmd['filesize'], 'vmsize': cmd['vmsize'], 'num_sections': len(cmd['sectlist']) } segment_list.append(result) for sect in cmd['sectlist']: result = { 'md5': sect['md5'], 'addr': sect['addr'], 'type': sect['type'], 'size': sect['size'], 'offset': sect['offset'], 'flaglist': ', '.join(sect['flaglist']) } self._add_result(e + ' section %i' % j, sect['sectname'], result) j += 1 for result in segment_list: self._add_result( e, '%s - %i' % (result['segname'], result['num_sections']), result) for cmd in entity.cmdlist: if cmd['cmd'] == MachOEntity.LC_SYMTAB: for sym in cmd['symbols']: result = { 'Stab type': sym.get('stab_type', 'Not stab'), 'Limited Global Scope': sym.get('limited_global_scope', 'Not set'), 'Type': sym.get('n_type', 'Not set'), 'External': sym.get('External', 'Not set'), } self._add_result( 'Entity %i - %s' % (i, entity.cmd_name(cmd['cmd'])), sym.get('string', ''), result) i += 1
def parse_cybox_object(self, cbx_obj, description='', ind_id=None): """ Parse a CybOX object form a STIX doc. An object can contain multiple related_objects, which in turn can have their own related_objects, so this handles those recursively. :param cbx_obj: The CybOX object to parse. :type cbx_obj: A CybOX object. :param description: Parent-level (e.g. Observable) description. :type description: str :param ind_id: The ID of a parent STIX Indicator. :type ind_id: str """ # check for missing attributes if not cbx_obj or not cbx_obj.properties: if cbx_obj.idref: # just a reference, so nothing to parse return else: cbx_id = getattr(cbx_obj, 'id_', 'None') self.failed.append(("No valid object_properties was found!", "Observable (%s)" % cbx_id, cbx_id)) # note for display in UI return # Don't parse if already been parsed # This is for artifacts that are related to CybOX File Objects if cbx_obj.id_ in self.parsed: return try: # try to create CRITs object from Cybox Object analyst = self.source_instance.analyst item = cbx_obj.properties val = cbx_obj.id_ if isinstance(item, Address) and not ind_id: if item.category in ('cidr', 'ipv4-addr', 'ipv4-net', 'ipv4-netmask', 'ipv6-addr', 'ipv6-net', 'ipv6-netmask'): imp_type = "IP" for value in item.address_value.values: val = str(value).strip() if self.preview: res = None else: iptype = get_crits_ip_type(item.category) if iptype: res = ip_add_update(val, iptype, [self.source], analyst=analyst, is_add_indicator=True) else: res = { 'success': False, 'reason': 'No IP Type' } self.parse_res(imp_type, val, cbx_obj, res, ind_id) if (not ind_id and (isinstance(item, DomainName) or (isinstance(item, URI) and item.type_ == 'Domain Name'))): imp_type = "Domain" for val in item.value.values: if self.preview: res = None else: res = upsert_domain(str(val), [self.source], username=analyst) self.parse_res(imp_type, str(val), cbx_obj, res, ind_id) elif isinstance(item, HTTPSession): imp_type = "RawData" val = cbx_obj.id_ try: c_req = item.http_request_response[0].http_client_request hdr = c_req.http_request_header if hdr.raw_header: data = hdr.raw_header.value title = "HTTP Header from STIX: %s" % self.package.id_ method = self.source_instance.method ref = self.source_instance.reference if self.preview: res = None val = title else: res = handle_raw_data_file(data, self.source.name, user=analyst, description=description, title=title, data_type="HTTP Header", tool_name="STIX", tool_version=None, method=method, reference=ref) else: imp_type = "Indicator" ind_type = "HTTP Request Header Fields - User-Agent" val = hdr.parsed_header.user_agent.value val = ','.join(val) if isinstance(val, list) else val if self.preview: res = None else: res = handle_indicator_ind( val, self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_relationship=True, description=description) except: msg = "Unsupported use of 'HTTPSession' object." res = {'success': False, 'reason': msg} self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, WhoisEntry): # No sure where else to put this imp_type = "RawData" val = cbx_obj.id_ if item.remarks: data = item.remarks.value title = "WHOIS Entry from STIX: %s" % self.package.id_ if self.preview: res = None val = title else: res = handle_raw_data_file( data, self.source.name, user=analyst, description=description, title=title, data_type="Text", tool_name="WHOIS", tool_version=None, method=self.source_instance.method, reference=self.source_instance.reference) else: msg = "Unsupported use of 'WhoisEntry' object." res = {'success': False, 'reason': msg} self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, Artifact): # Not sure if this is right, and I believe these can be # encoded in a couple different ways. imp_type = "RawData" val = cbx_obj.id_ rawdata = item.data.decode('utf-8') # TODO: find out proper ways to determine title, datatype, # tool_name, tool_version title = "Artifact for Event: STIX Document %s" % self.package.id_ if self.preview: res = None val = title else: res = handle_raw_data_file( rawdata, self.source.name, user=analyst, description=description, title=title, data_type="Text", tool_name="STIX", tool_version=None, method=self.source_instance.method, reference=self.source_instance.reference) self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif (isinstance(item, File) and item.custom_properties and item.custom_properties[0].name == "crits_type" and item.custom_properties[0]._value == "Certificate"): imp_type = "Certificate" val = str(item.file_name) data = None if self.preview: res = None else: for rel_obj in item.parent.related_objects: if isinstance(rel_obj.properties, Artifact): data = rel_obj.properties.data self.parsed.append(rel_obj.id_) res = handle_cert_file(val, data, self.source, user=analyst, description=description) self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, File) and self.has_network_artifact(item): imp_type = "PCAP" val = str(item.file_name) data = None if self.preview: res = None else: for rel_obj in item.parent.related_objects: if (isinstance(rel_obj.properties, Artifact) and rel_obj.properties.type_ == Artifact.TYPE_NETWORK): data = rel_obj.properties.data self.parsed.append(rel_obj.id_) res = handle_pcap_file(val, data, self.source, user=analyst, description=description) self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, File): imp_type = "Sample" md5 = item.md5 if md5: md5 = md5.lower() val = str(item.file_name or md5) # add sha1/sha256/ssdeep once handle_file supports it size = item.size_in_bytes data = None if item.file_path: path = "File Path: " + str(item.file_path) description += "\n" + path for rel_obj in item.parent.related_objects: if (isinstance(rel_obj.properties, Artifact) and rel_obj.properties.type_ == Artifact.TYPE_FILE): data = rel_obj.properties.data self.parsed.append(rel_obj.id_) if not md5 and not data and val and val != "None": imp_type = "Indicator" if self.preview: res = None else: res = handle_indicator_ind( val, self.source, "Win File", IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True, description=description) elif md5 or data: if self.preview: res = None else: res = handle_file(val, data, self.source, user=analyst, md5_digest=md5, is_return_only_md5=False, size=size, description=description) else: val = cbx_obj.id_ msg = "CybOX 'File' object has no MD5, data, or filename" res = {'success': False, 'reason': msg} self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, EmailMessage): imp_type = 'Email' id_list = [] data = {} val = cbx_obj.id_ get_attach = False data['raw_body'] = str(item.raw_body) data['raw_header'] = str(item.raw_header) data['helo'] = str(item.email_server) if item.header: data['subject'] = str(item.header.subject) if item.header.date: data['date'] = item.header.date.value val = "Date: %s, Subject: %s" % (data.get( 'date', 'None'), data['subject']) data['message_id'] = str(item.header.message_id) data['sender'] = str(item.header.sender) data['reply_to'] = str(item.header.reply_to) data['x_originating_ip'] = str( item.header.x_originating_ip) data['x_mailer'] = str(item.header.x_mailer) data['boundary'] = str(item.header.boundary) data['from_address'] = str(item.header.from_) if item.header.to: data['to'] = [str(r) for r in item.header.to.to_list()] if data.get('date'): # Email TLOs must have a date data['source'] = self.source.name data['source_method'] = self.source_instance.method data['source_reference'] = self.source_instance.reference if self.preview: res = None else: res = handle_email_fields(data, analyst, "STIX") self.parse_res(imp_type, val, cbx_obj, res, ind_id) if not self.preview and res.get('status'): id_list.append(cbx_obj.id_) # save ID for atchmnt rels get_attach = True else: # Can't be an Email TLO, so save fields for x, key in enumerate(data): if data[key] and data[key] != "None": if key in ('raw_header', 'raw_body'): if key == 'raw_header': title = "Email Header from STIX Email: %s" d_type = "Email Header" else: title = "Email Body from STIX Email: %s" d_type = "Email Body" imp_type = 'RawData' title = title % cbx_obj.id_ if self.preview: res = None else: res = handle_raw_data_file( data[key], self.source, analyst, description, title, d_type, "STIX", self.stix_version) self.parse_res(imp_type, title, cbx_obj, res, ind_id) elif key == 'to': imp_type = 'Target' for y, addr in enumerate(data[key]): tgt_dict = {'email_address': addr} if self.preview: res = None else: res = upsert_target(tgt_dict, analyst) if res['success']: get_attach = True tmp_obj = copy(cbx_obj) tmp_obj.id_ = '%s-%s-%s' % (cbx_obj.id_, x, y) self.parse_res(imp_type, addr, tmp_obj, res, ind_id) self.ind2obj.setdefault( cbx_obj.id_, []).append(tmp_obj.id_) id_list.append(tmp_obj.id_) else: imp_type = 'Indicator' if key in ('sender', 'reply_to', 'from_address'): ind_type = "Address - e-mail" elif 'ip' in key: ind_type = "Address - ipv4-addr" elif key == 'raw_body': ind_type = "Email Message" else: ind_type = "String" if self.preview: res = None else: res = handle_indicator_ind( data[key], self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True, description=description) if res['success']: get_attach = True tmp_obj = copy(cbx_obj) tmp_obj.id_ = '%s-%s' % (cbx_obj.id_, x) self.parse_res(imp_type, data[key], tmp_obj, res, ind_id) self.ind2obj.setdefault(cbx_obj.id_, []).append(tmp_obj.id_) id_list.append(tmp_obj.id_) if not self.preview: # Setup relationships between all Email attributes for oid in id_list: for oid2 in id_list: if oid != oid2: self.relationships.append( (oid, RelationshipTypes.RELATED_TO, oid2, "High")) # Should check for attachments and add them here. if get_attach and item.attachments: for attach in item.attachments: rel_id = attach.to_dict()['object_reference'] for oid in id_list: self.relationships.append( (oid, RelationshipTypes.CONTAINS, rel_id, "High")) else: # try to parse all other possibilities as Indicator imp_type = "Indicator" val = cbx_obj.id_ c_obj = make_crits_object(item) # Ignore what was already caught above if (ind_id or c_obj.object_type not in IPTypes.values()): ind_type = c_obj.object_type for val in [str(v).strip() for v in c_obj.value if v]: if ind_type: # handle domains mislabeled as URLs if c_obj.object_type == 'URI' and '/' not in val: ind_type = "Domain" if self.preview: res = None else: res = handle_indicator_ind( val, self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True, description=description) self.parse_res(imp_type, val, cbx_obj, res, ind_id) except Exception, e: # probably caused by cybox object we don't handle self.failed.append((e.message, "%s (%s)" % (imp_type, val), cbx_obj.id_)) # note for display in UI
def finish_task(self, task): """ Finish a task. """ logger.debug("Finishing task %s" % task) self.update_task(task) obj = class_from_type(task.context.crits_type) query = self.get_db_query(task.context) sample = obj.objects(__raw__=query).first() if task.files: logger.debug("Adding samples") for f in task.files: logger.debug("Adding %s" % f['filename']) #TODO: add in backdoor?, user from crits.samples.handlers import handle_file handle_file(f['filename'], f['data'], sample.source, related_md5=task.context.identifier, campaign=sample.campaign, method=task.service.name, relationship=f['relationship'], user=task.context.username, ) else: logger.debug("No samples to add.") if task.certificates: logger.debug("Adding certificates") for f in task.certificates: logger.debug("Adding %s" % f['filename']) from crits.certificates.handlers import handle_cert_file # XXX: Add campaign from source? handle_cert_file(f['filename'], f['data'], sample.source, related_md5=task.context.identifier, related_type=task.context.crits_type, method=task.service.name, relationship=f['relationship'], user=task.context.username, ) else: logger.debug("No certificates to add.") if task.pcaps: logger.debug("Adding PCAPs") for f in task.pcaps: logger.debug("Adding %s" % f['filename']) from crits.pcaps.handlers import handle_pcap_file # XXX: Add campaign from source? handle_pcap_file(f['filename'], f['data'], sample.source, related_md5=task.context.identifier, related_type=task.context.crits_type, method=task.service.name, relationship=f['relationship'], user=task.context.username, ) else: logger.debug("No PCAPs to add.")
def finish_task(self, task): """ Finish a task. """ logger.debug("Finishing task %s" % task) self.update_task(task) obj = class_from_type(task.context.crits_type) query = self.get_db_query(task.context) sample = obj.objects(__raw__=query).first() if task.files: logger.debug("Adding samples") for f in task.files: logger.debug("Adding %s" % f['filename']) #TODO: add in backdoor?, user from crits.samples.handlers import handle_file handle_file(f['filename'], f['data'], sample.source, parent_md5=task.context.identifier, campaign=sample.campaign, method=task.service.name, relationship=f['relationship'], user=task.context.username, ) else: logger.debug("No samples to add.") if task.certificates: logger.debug("Adding certificates") for f in task.certificates: logger.debug("Adding %s" % f['filename']) from crits.certificates.handlers import handle_cert_file # XXX: Add campaign from source? handle_cert_file(f['filename'], f['data'], sample.source, parent_md5=task.context.identifier, parent_type=task.context.crits_type, method=task.service.name, relationship=f['relationship'], user=task.context.username, ) else: logger.debug("No certificates to add.") if task.pcaps: logger.debug("Adding PCAPs") for f in task.pcaps: logger.debug("Adding %s" % f['filename']) from crits.pcaps.handlers import handle_pcap_file # XXX: Add campaign from source? handle_pcap_file(f['filename'], f['data'], sample.source, parent_md5=task.context.identifier, parent_type=task.context.crits_type, method=task.service.name, relationship=f['relationship'], user=task.context.username, ) else: logger.debug("No PCAPs to add.")
def parse_cybox_object(self, cbx_obj, description='', ind_id=None): """ Parse a CybOX object form a STIX doc. An object can contain multiple related_objects, which in turn can have their own related_objects, so this handles those recursively. :param cbx_obj: The CybOX object to parse. :type cbx_obj: A CybOX object. :param description: Parent-level (e.g. Observable) description. :type description: str :param ind_id: The ID of a parent STIX Indicator. :type ind_id: str """ # check for missing attributes if not cbx_obj or not cbx_obj.properties: if cbx_obj.idref: # just a reference, so nothing to parse return else: cbx_id = getattr(cbx_obj, 'id_', 'None') self.failed.append(("No valid object_properties was found!", "Observable (%s)" % cbx_id, cbx_id)) # note for display in UI return # Don't parse if already been parsed # This is for artifacts that are related to CybOX File Objects if cbx_obj.id_ in self.parsed: return try: # try to create CRITs object from Cybox Object analyst = self.source_instance.analyst item = cbx_obj.properties val = cbx_obj.id_ if isinstance(item, Address) and not ind_id: if item.category in ('cidr', 'ipv4-addr', 'ipv4-net', 'ipv4-netmask', 'ipv6-addr', 'ipv6-net', 'ipv6-netmask'): imp_type = "IP" for value in item.address_value.values: val = str(value).strip() if self.preview: res = None else: iptype = get_crits_ip_type(item.category) if iptype: res = ip_add_update(val, iptype, [self.source], analyst=analyst, is_add_indicator=True) else: res = {'success': False, 'reason': 'No IP Type'} self.parse_res(imp_type, val, cbx_obj, res, ind_id) if (not ind_id and (isinstance(item, DomainName) or (isinstance(item, URI) and item.type_ == 'Domain Name'))): imp_type = "Domain" for val in item.value.values: if self.preview: res = None else: res = upsert_domain(str(val), [self.source], username=analyst) self.parse_res(imp_type, str(val), cbx_obj, res, ind_id) elif isinstance(item, HTTPSession): imp_type = "RawData" val = cbx_obj.id_ try: c_req = item.http_request_response[0].http_client_request hdr = c_req.http_request_header if hdr.raw_header: data = hdr.raw_header.value title = "HTTP Header from STIX: %s" % self.package.id_ method = self.source_instance.method ref = self.source_instance.reference if self.preview: res = None val = title else: res = handle_raw_data_file(data, self.source.name, user=analyst, description=description, title=title, data_type="HTTP Header", tool_name="STIX", tool_version=None, method=method, reference=ref) else: imp_type = "Indicator" ind_type = "HTTP Request Header Fields - User-Agent" val = hdr.parsed_header.user_agent.value val = ','.join(val) if isinstance(val, list) else val if self.preview: res = None else: res = handle_indicator_ind(val, self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_relationship=True, description=description) except: msg = "Unsupported use of 'HTTPSession' object." res = {'success': False, 'reason': msg} self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, WhoisEntry): # No sure where else to put this imp_type = "RawData" val = cbx_obj.id_ if item.remarks: data = item.remarks.value title = "WHOIS Entry from STIX: %s" % self.package.id_ if self.preview: res = None val = title else: res = handle_raw_data_file(data, self.source.name, user=analyst, description=description, title=title, data_type="Text", tool_name="WHOIS", tool_version=None, method=self.source_instance.method, reference=self.source_instance.reference) else: msg = "Unsupported use of 'WhoisEntry' object." res = {'success': False, 'reason': msg} self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, Artifact): # Not sure if this is right, and I believe these can be # encoded in a couple different ways. imp_type = "RawData" val = cbx_obj.id_ rawdata = item.data.decode('utf-8') # TODO: find out proper ways to determine title, datatype, # tool_name, tool_version title = "Artifact for Event: STIX Document %s" % self.package.id_ if self.preview: res = None val = title else: res = handle_raw_data_file(rawdata, self.source.name, user=analyst, description=description, title=title, data_type="Text", tool_name="STIX", tool_version=None, method=self.source_instance.method, reference=self.source_instance.reference) self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif (isinstance(item, File) and item.custom_properties and item.custom_properties[0].name == "crits_type" and item.custom_properties[0]._value == "Certificate"): imp_type = "Certificate" val = str(item.file_name) data = None if self.preview: res = None else: for rel_obj in item.parent.related_objects: if isinstance(rel_obj.properties, Artifact): data = rel_obj.properties.data self.parsed.append(rel_obj.id_) res = handle_cert_file(val, data, self.source, user=analyst, description=description) self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, File) and self.has_network_artifact(item): imp_type = "PCAP" val = str(item.file_name) data = None if self.preview: res = None else: for rel_obj in item.parent.related_objects: if (isinstance(rel_obj.properties, Artifact) and rel_obj.properties.type_ == Artifact.TYPE_NETWORK): data = rel_obj.properties.data self.parsed.append(rel_obj.id_) res = handle_pcap_file(val, data, self.source, user=analyst, description=description) self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, File): imp_type = "Sample" md5 = item.md5 if md5: md5 = md5.lower() val = str(item.file_name or md5) # add sha1/sha256/ssdeep once handle_file supports it size = item.size_in_bytes data = None if item.file_path: path = "File Path: " + str(item.file_path) description += "\n" + path for rel_obj in item.parent.related_objects: if (isinstance(rel_obj.properties, Artifact) and rel_obj.properties.type_ == Artifact.TYPE_FILE): data = rel_obj.properties.data self.parsed.append(rel_obj.id_) if not md5 and not data and val and val != "None": imp_type = "Indicator" if self.preview: res = None else: res = handle_indicator_ind(val, self.source, "Win File", IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True, description=description) elif md5 or data: if self.preview: res = None else: res = handle_file(val, data, self.source, user=analyst, md5_digest=md5, is_return_only_md5=False, size=size, description=description) else: val = cbx_obj.id_ msg = "CybOX 'File' object has no MD5, data, or filename" res = {'success': False, 'reason': msg} self.parse_res(imp_type, val, cbx_obj, res, ind_id) elif isinstance(item, EmailMessage): imp_type = 'Email' id_list = [] data = {} val = cbx_obj.id_ get_attach = False data['raw_body'] = str(item.raw_body) data['raw_header'] = str(item.raw_header) data['helo'] = str(item.email_server) if item.header: data['subject'] = str(item.header.subject) if item.header.date: data['date'] = item.header.date.value val = "Date: %s, Subject: %s" % (data.get('date', 'None'), data['subject']) data['message_id'] = str(item.header.message_id) data['sender'] = str(item.header.sender) data['reply_to'] = str(item.header.reply_to) data['x_originating_ip'] = str(item.header.x_originating_ip) data['x_mailer'] = str(item.header.x_mailer) data['boundary'] = str(item.header.boundary) data['from_address'] = str(item.header.from_) if item.header.to: data['to'] = [str(r) for r in item.header.to.to_list()] if data.get('date'): # Email TLOs must have a date data['source'] = self.source.name data['source_method'] = self.source_instance.method data['source_reference'] = self.source_instance.reference if self.preview: res = None else: res = handle_email_fields(data, analyst, "STIX") self.parse_res(imp_type, val, cbx_obj, res, ind_id) if not self.preview and res.get('status'): id_list.append(cbx_obj.id_) # save ID for atchmnt rels get_attach = True else: # Can't be an Email TLO, so save fields for x, key in enumerate(data): if data[key] and data[key] != "None": if key in ('raw_header', 'raw_body'): if key == 'raw_header': title = "Email Header from STIX Email: %s" d_type = "Email Header" else: title = "Email Body from STIX Email: %s" d_type = "Email Body" imp_type = 'RawData' title = title % cbx_obj.id_ if self.preview: res = None else: res = handle_raw_data_file(data[key], self.source, analyst, description, title, d_type, "STIX", self.stix_version) self.parse_res(imp_type, title, cbx_obj, res, ind_id) elif key == 'to': imp_type = 'Target' for y, addr in enumerate(data[key]): tgt_dict = {'email_address': addr} if self.preview: res = None else: res = upsert_target(tgt_dict, analyst) if res['success']: get_attach = True tmp_obj = copy(cbx_obj) tmp_obj.id_ = '%s-%s-%s' % (cbx_obj.id_, x, y) self.parse_res(imp_type, addr, tmp_obj, res, ind_id) self.ind2obj.setdefault(cbx_obj.id_, []).append(tmp_obj.id_) id_list.append(tmp_obj.id_) else: imp_type = 'Indicator' if key in ('sender', 'reply_to', 'from_address'): ind_type = "Address - e-mail" elif 'ip' in key: ind_type = "Address - ipv4-addr" elif key == 'raw_body': ind_type = "Email Message" else: ind_type = "String" if self.preview: res = None else: res = handle_indicator_ind(data[key], self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True, description=description) if res['success']: get_attach = True tmp_obj = copy(cbx_obj) tmp_obj.id_ = '%s-%s' % (cbx_obj.id_, x) self.parse_res(imp_type, data[key], tmp_obj, res, ind_id) self.ind2obj.setdefault(cbx_obj.id_, []).append(tmp_obj.id_) id_list.append(tmp_obj.id_) if not self.preview: # Setup relationships between all Email attributes for oid in id_list: for oid2 in id_list: if oid != oid2: self.relationships.append((oid, RelationshipTypes.RELATED_TO, oid2, "High")) # Should check for attachments and add them here. if get_attach and item.attachments: for attach in item.attachments: rel_id = attach.to_dict()['object_reference'] for oid in id_list: self.relationships.append((oid, RelationshipTypes.CONTAINS, rel_id, "High")) else: # try to parse all other possibilities as Indicator imp_type = "Indicator" val = cbx_obj.id_ c_obj = make_crits_object(item) # Ignore what was already caught above if (ind_id or c_obj.object_type not in IPTypes.values()): ind_type = c_obj.object_type for val in [str(v).strip() for v in c_obj.value if v]: if ind_type: # handle domains mislabeled as URLs if c_obj.object_type == 'URI' and '/' not in val: ind_type = "Domain" if self.preview: res = None else: res = handle_indicator_ind(val, self.source, ind_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, add_domain=True, add_relationship=True, description=description) self.parse_res(imp_type, val, cbx_obj, res, ind_id) except Exception, e: # probably caused by cybox object we don't handle self.failed.append((e.message, "%s (%s)" % (imp_type, val), cbx_obj.id_)) # note for display in UI
def upload_certificate(request): """ Add a new Certificate to CRITs. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ user = request.user if request.method == 'POST': form = UploadCertificateForm(user, request.POST, request.FILES) if form.is_valid(): if user.has_access_to(CertificateACL.WRITE): filedata = request.FILES['filedata'] filename = filedata.name data = filedata.read() # XXX: Should be using chunks here. source = form.cleaned_data.get('source_name') description = form.cleaned_data.get('description', '') related = form.cleaned_data.get('related_id', '') related_type = form.cleaned_data.get('related_type', '') relationship_type = form.cleaned_data.get( 'relationship_type', '') bucket_list = form.cleaned_data.get( form_consts.Common.BUCKET_LIST_VARIABLE_NAME) ticket = form.cleaned_data.get( form_consts.Common.TICKET_VARIABLE_NAME) method = form.cleaned_data.get('source_method', '') or 'Upload' reference = form.cleaned_data.get('source_reference', '') tlp = form.cleaned_data.get('source_tlp', None) status = handle_cert_file(filename, data, source, user, description, related_id=related, related_type=related_type, relationship_type=relationship_type, method=method, reference=reference, tlp=tlp, bucket_list=bucket_list, ticket=ticket) else: status = { 'success': False, 'message': 'User does not have permission to add Certificate.' } if status['success']: return render( request, 'file_upload_response.html', { 'response': json.dumps({ 'message': 'Certificate uploaded successfully! <a href="%s">View Certificate</a>' % reverse( 'crits-certificates-views-certificate_details', args=[status['md5']]), 'success': True }) }, ) else: return render(request, 'file_upload_response.html', {'response': json.dumps({'success': False})}) else: return render(request, 'file_upload_response.html', {'response': json.dumps({'success': False})}) else: return render(request, 'error.html', {'error': "Expected POST."})