def get_relationship_type_dropdown(request): """ Get relationship type dropdown data. Should be an AJAX POST. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ if request.method == 'POST': if request.is_ajax(): dd_final = {} for type_ in RelationshipTypes.values(sort=True): dd_final[type_] = type_ result = {'types': dd_final} return HttpResponse(json.dumps(result), mimetype="application/json") else: error = "Expected AJAX" return render_to_response("error.html", {"error" : error }, RequestContext(request)) else: error = "Expected POST" return render_to_response("error.html", {"error" : error }, RequestContext(request))
def add_new_relationship(request): """ Add a new relationship. Should be an AJAX POST. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ if request.method == 'POST' and request.is_ajax(): form = ForgeRelationshipForm(request.POST) user = request.user choices = [(c,c) for c in RelationshipTypes.values(sort=True)] form.fields['forward_relationship'].choices = choices if form.is_valid(): cleaned_data = form.cleaned_data # Get user permission to verify the user can forge relationships... # Should we check permission on both the forward and reverse TLO for this? acl = get_acl_object(cleaned_data.get('forward_type')) if user.has_access_to(acl.RELATIONSHIPS_ADD): results = forge_relationship(type_=cleaned_data.get('forward_type'), id_=cleaned_data.get('forward_value'), right_type=cleaned_data.get('reverse_type'), right_id=cleaned_data.get('dest_id'), rel_type=cleaned_data.get('forward_relationship'), rel_date=cleaned_data.get('relationship_date'), user=request.user.username, rel_reason=cleaned_data.get('rel_reason'), rel_confidence=cleaned_data.get('rel_confidence'), get_rels=True) else: results = {"success":False, "message":"User does not have permission to forge relationships"} if results['success'] == True: relationship = {'type': cleaned_data.get('forward_type'), 'value': cleaned_data.get('forward_value')} message = render_to_string('relationships_listing_widget.html', {'relationship': relationship, 'nohide': True, 'relationships': results['relationships']}, RequestContext(request)) result = {'success': True, 'message': message} else: message = "Error adding relationship: %s" % results['message'] result = {'success': False, 'message': message} else: message = "Invalid Form: %s" % form.errors form = form.as_table() result = {'success': False, 'form': form, 'message': message} return HttpResponse(json.dumps(result), content_type="application/json") else: error = "Expected AJAX POST" return render_to_response("error.html", {"error" : error }, RequestContext(request))
def add_new_relationship(request): """ Add a new relationship. Should be an AJAX POST. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ if request.method == 'POST' and request.is_ajax(): form = ForgeRelationshipForm(request.POST) choices = [(c, c) for c in RelationshipTypes.values(sort=True)] form.fields['forward_relationship'].choices = choices if form.is_valid(): cleaned_data = form.cleaned_data results = forge_relationship( type_=cleaned_data.get('forward_type'), id_=cleaned_data.get('forward_value'), right_type=cleaned_data.get('reverse_type'), right_id=cleaned_data.get('dest_id'), rel_type=cleaned_data.get('forward_relationship'), rel_date=cleaned_data.get('relationship_date'), user=request.user.username, rel_reason=cleaned_data.get('rel_reason'), rel_confidence=cleaned_data.get('rel_confidence'), get_rels=True) if results['success'] == True: set_releasability_flag(cleaned_data.get('forward_type'), cleaned_data.get('forward_value'), request.user.username) relationship = { 'type': cleaned_data.get('forward_type'), 'url_key': cleaned_data.get('forward_value') } message = render_to_string( 'relationships_listing_widget.html', { 'relationship': relationship, 'nohide': True, 'relationships': results['relationships'] }, RequestContext(request)) result = {'success': True, 'message': message} else: message = "Error adding relationship: %s" % results['message'] result = {'success': False, 'message': message} else: message = "Invalid Form: %s" % form.errors form = form.as_table() result = {'success': False, 'form': form, 'message': message} return HttpResponse(json.dumps(result), mimetype="application/json") else: error = "Expected AJAX POST" return render_to_response("error.html", {"error": error}, RequestContext(request))
def __init__(self, *args, **kwargs): super(ForgeRelationshipForm, self).__init__(*args, **kwargs) self.fields['forward_type'].choices = self.fields['reverse_type'].choices = [ (c, c) for c in sorted(settings.CRITS_TYPES.iterkeys()) ] self.fields['forward_relationship'].choices = [ (c, c) for c in RelationshipTypes.values(sort=True) ] self.fields['rel_confidence'].choices = [('unknown', 'unknown'), ('low', 'low'), ('medium', 'medium'), ('high', 'high')] self.fields['rel_confidence'].initial = 'medium'
def __init__(self, *args, **kwargs): super(ForgeRelationshipForm, self).__init__(*args, **kwargs) self.fields['forward_type'].choices = self.fields[ 'reverse_type'].choices = [ (c, c) for c in sorted(settings.CRITS_TYPES.iterkeys()) ] self.fields['forward_relationship'].choices = [ (c, c) for c in RelationshipTypes.values(sort=True) ] self.fields['rel_confidence'].choices = [('unknown', 'unknown'), ('low', 'low'), ('medium', 'medium'), ('high', 'high')] self.fields['rel_confidence'].initial = 'medium'
def add_new_relationship(request): """ Add a new relationship. Should be an AJAX POST. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ if request.method == 'POST' and request.is_ajax(): form = ForgeRelationshipForm(request.POST) choices = [(c,c) for c in RelationshipTypes.values(sort=True)] form.fields['forward_relationship'].choices = choices if form.is_valid(): cleaned_data = form.cleaned_data; results = forge_relationship(type_=cleaned_data.get('forward_type'), id_=cleaned_data.get('forward_value'), right_type=cleaned_data.get('reverse_type'), right_id=cleaned_data.get('dest_id'), rel_type=cleaned_data.get('forward_relationship'), rel_date=cleaned_data.get('relationship_date'), user=request.user.username, rel_reason=cleaned_data.get('rel_reason'), rel_confidence=cleaned_data.get('rel_confidence'), get_rels=True) if results['success'] == True: relationship = {'type': cleaned_data.get('forward_type'), 'value': cleaned_data.get('forward_value')} message = render_to_string('relationships_listing_widget.html', {'relationship': relationship, 'nohide': True, 'relationships': results['relationships']}, RequestContext(request)) result = {'success': True, 'message': message} else: message = "Error adding relationship: %s" % results['message'] result = {'success': False, 'message': message} else: message = "Invalid Form: %s" % form.errors form = form.as_table() result = {'success': False, 'form': form, 'message': message} return HttpResponse(json.dumps(result), mimetype="application/json") else: error = "Expected AJAX POST" return render_to_response("error.html", {"error" : error }, RequestContext(request))
def handle_raw_data_file(data, source_name, user=None, description=None, title=None, data_type=None, tool_name=None, tool_version=None, tool_details=None, link_id=None, method='', reference='', tlp='', copy_rels=False, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add RawData. :param data: The data of the RawData. :type data: str :param source_name: The source which provided this RawData. :type source_name: str, :class:`crits.core.crits_mongoengine.EmbeddedSource`, list of :class:`crits.core.crits_mongoengine.EmbeddedSource` :param user: The user adding the RawData. :type user: str :param description: Description of the RawData. :type description: str :param title: Title of the RawData. :type title: str :param data_type: Datatype of the RawData. :type data_type: str :param tool_name: Name of the tool used to acquire/generate the RawData. :type tool_name: str :param tool_version: Version of the tool. :type tool_version: str :param tool_details: Details about the tool. :type tool_details: str :param link_id: LinkId to tie this to another RawData as a new version. :type link_id: str :param method: The method of acquiring this RawData. :type method: str :param reference: A reference to the source of this RawData. :type reference: str :param tlp: TLP for the source. :type tlp: str :param copy_rels: Copy relationships from the previous version to this one. :type copy_rels: bool :param bucket_list: Bucket(s) to add to this RawData :type bucket_list: str(comma separated) or list. :param ticket: Ticket(s) to add to this RawData :type ticket: str(comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: 'success' (boolean), 'message' (str), '_id' (str) if successful. """ if not data or not title or not data_type: status = { 'success': False, 'message': 'No data object, title, or data type passed in' } return status if not source_name: return {"success" : False, "message" : "Missing source information."} rdt = RawDataType.objects(name=data_type).first() if not rdt: status = { 'success': False, 'message': 'Invalid data type passed in' } return status if len(data) <= 0: status = { 'success': False, 'message': 'Data length <= 0' } return status if isinstance(data, unicode): data=data.encode('utf-8') # generate md5 and timestamp md5 = hashlib.md5(data).hexdigest() timestamp = datetime.datetime.now() # generate raw_data is_rawdata_new = False raw_data = RawData.objects(md5=md5).first() if not raw_data: raw_data = RawData() raw_data.created = timestamp raw_data.description = description raw_data.md5 = md5 # raw_data.source = [source_name] raw_data.data = data raw_data.title = title raw_data.data_type = data_type raw_data.add_tool(name=tool_name, version=tool_version, details=tool_details) is_rawdata_new = True # generate new source information and add to sample if isinstance(source_name, basestring) and len(source_name) > 0: if user.check_source_write(source_name): source = create_embedded_source(source_name, method=method, reference=reference, tlp=tlp, analyst=user.username) raw_data.add_source(source) else: return {"success":False, "message": "User does not have permission to add object using source %s." % source_name} # this will handle adding a new source, or an instance automatically elif isinstance(source_name, EmbeddedSource): raw_data.add_source(source_name, method=method, reference=reference, tlp=tlp, analyst=user.usrname) elif isinstance(source_name, list) and len(source_name) > 0: for s in source_name: if isinstance(s, EmbeddedSource): raw_data.add_source(s, method=method, reference=reference, tlp=tlp, analyst=user.username) #XXX: need to validate this is a UUID if link_id: raw_data.link_id = link_id if copy_rels: rd2 = RawData.objects(link_id=link_id).first() if rd2: if len(rd2.relationships): raw_data.save(username=user) raw_data.reload() for rel in rd2.relationships: # Get object to relate to. rel_item = class_from_id(rel.rel_type, rel.object_id) if rel_item: raw_data.add_relationship(rel_item, rel.relationship, rel_date=rel.relationship_date, analyst=user.username) raw_data.version = len(RawData.objects(link_id=link_id)) + 1 if bucket_list: raw_data.add_bucket_list(bucket_list, user) if ticket: raw_data.add_ticket(ticket, user); related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal raw_data.save(username=user.username) if related_obj and relationship_type and raw_data: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) raw_data.add_relationship(related_obj, relationship_type, analyst=user.username, get_rels=False) raw_data.save(username=user.username) raw_data.reload() # save raw_data raw_data.save(username=user.username) # run raw_data triage if is_rawdata_new: raw_data.reload() run_triage(raw_data, user) status = { 'success': True, 'message': 'Uploaded raw_data', '_id': raw_data.id, 'object': raw_data } return status
def handle_cert_file(filename, data, source_name, user=None, description=None, related_md5=None, method='', reference='', tlp=None, relationship=None, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add a Certificate. :param filename: The filename of the Certificate. :type filename: str :param data: The filedata of the Certificate. :type data: str :param source_name: The source which provided this Certificate. :type source_name: str, :class:`crits.core.crits_mongoengine.EmbeddedSource`, list of :class:`crits.core.crits_mongoengine.EmbeddedSource` :param user: The user adding the Certificate. :type user: str :param description: Description of the Certificate. :type description: str :param related_md5: MD5 of a top-level object related to this Certificate. :type related_md5: str :param related_type: The CRITs type of the related top-level object. :type related_type: str :param method: The method of acquiring this Certificate. :type method: str :param reference: A reference to the source of this Certificate. :type reference: str :param tlp: The TLP for this certificate. :type tlp: str :param relationship: The relationship between the parent and the Certificate. :type relationship: str :param bucket_list: Bucket(s) to add to this Certificate :type bucket_list: str(comma separated) or list. :param ticket: Ticket(s) to add to this Certificate :type ticket: str(comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_id: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: 'success' (boolean), 'message' (str), 'md5' (str) if successful. """ if not data: status = {'success': False, 'message': 'No data object passed in'} return status if len(data) <= 0: status = {'success': False, 'message': 'Data length <= 0'} return status if ((related_type and not (related_id or related_md5)) or (not related_type and (related_id or related_md5))): status = { 'success': False, 'message': 'Must specify both related_type and related_id or related_md5.' } return status related_obj = None if related_id or related_md5: if related_id: related_obj = class_from_id(related_type, related_id) else: related_obj = class_from_value(related_type, related_md5) if not related_obj: status = {'success': False, 'message': 'Related object not found.'} return status # generate md5 and timestamp md5 = hashlib.md5(data).hexdigest() timestamp = datetime.datetime.now() # generate Certificate cert = Certificate.objects(md5=md5).first() if not cert: cert = Certificate() cert.filename = filename cert.created = timestamp cert.size = len(data) cert.description = description cert.md5 = md5 # generate source information and add to certificate if isinstance(source_name, basestring) and len(source_name) > 0: if user.check_source_write(source_name): s = create_embedded_source(source_name, reference=reference, method=method, tlp=tlp, analyst=user.username) else: return { "success": False, "message": "User does not have permission to add objects \ using source %s." % str(source_name) } cert.add_source(s) elif isinstance(source_name, EmbeddedSource): cert.add_source(source_name, method=method, reference=reference, tlp=tlp) elif isinstance(source_name, list) and len(source_name) > 0: for s in source_name: if isinstance(s, EmbeddedSource): cert.add_source(s, method=method, reference=reference, tlp=tlp) if bucket_list: cert.add_bucket_list(bucket_list, user) if ticket: cert.add_ticket(ticket, user) # add file to GridFS if not isinstance(cert.filedata.grid_id, ObjectId): cert.add_file_data(data) # save cert cert.save(username=user) cert.reload() # run certificate triage if AnalysisResult.objects(object_id=str(cert.id)).count() < 1 and data: run_triage(cert, user) # update relationship if a related top-level object is supplied if related_obj and cert: if relationship_type: relationship = RelationshipTypes.inverse( relationship=relationship_type) if not relationship: relationship = RelationshipTypes.RELATED_TO cert.add_relationship(related_obj, relationship, analyst=user, get_rels=False) cert.save(username=user) status = { 'success': True, 'message': 'Uploaded certificate', 'md5': md5, 'id': str(cert.id), 'object': cert } return status
def handle_signature_file(data, source_name, user=None, description=None, title=None, data_type=None, data_type_min_version=None, data_type_max_version=None, data_type_dependency=None, link_id=None, source_method='', source_reference='', source_tlp='', copy_rels=False, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add Signature. :param data: The data of the Signature. :type data: str :param source_name: The source which provided this Signature. :type source_name: str, :class:`crits.core.crits_mongoengine.EmbeddedSource`, list of :class:`crits.core.crits_mongoengine.EmbeddedSource` :param user: The user adding the Signature. :type user: str :param description: Description of the Signature. :type description: str :param title: Title of the Signature. :type title: str :param data_type: Datatype of the Signature. :type data_type: str :param data_type: Datatype of the Signature. :type data_type_min_version: str :param data_type_min_version: Datatype tool minimum version. :type data_type_max_version: str :param data_type_max_version: Datatype tool maximum version. :type data_type_dependency: list :param data_type_dependency: Datatype tool dependency to be run :param link_id: LinkId to tie this to another Signature as a new version. :type link_id: str :param method: The method of acquiring this Signature. :type method: str :param reference: A reference to the source of this Signature. :type reference: str :param copy_rels: Copy relationships from the previous version to this one. :type copy_rels: bool :param bucket_list: Bucket(s) to add to this Signature :type bucket_list: str(comma separated) or list. :param ticket: Ticket(s) to add to this Signature :type ticket: str(comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: 'success' (boolean), 'message' (str), '_id' (str) if successful. """ if not data or not title or not data_type: status = { 'success': False, 'message': 'No data object, title, or data type passed in' } return status if not source_name: return {"success": False, "message": "Missing source information."} rdt = SignatureType.objects(name=data_type).first() if not rdt: status = {'success': False, 'message': 'Invalid data type passed in'} return status if len(data) <= 0: status = {'success': False, 'message': 'Data length <= 0'} return status # generate md5 and timestamp md5 = hashlib.md5(data).hexdigest() timestamp = datetime.datetime.now() # generate signature signature = Signature() signature.created = timestamp signature.description = description signature.md5 = md5 signature.data = data signature.title = title signature.data_type = data_type signature.data_type_min_version = data_type_min_version signature.data_type_max_version = data_type_max_version if data_type_dependency: if type(data_type_dependency) == unicode: data_type_dependency = data_type_dependency.split(",") for item in data_type_dependency: if item: item = item.strip() signature.data_type_dependency.append(str(item)) else: data_type_dependency = [] # generate new source information and add to sample if isinstance(source_name, basestring) and len(source_name) > 0: if user.check_source_write(source_name): source = create_embedded_source(source_name, date=timestamp, method=source_method, reference=source_reference, tlp=source_tlp, analyst=user.username) # this will handle adding a new source, or an instance automatically signature.add_source(source) else: return { "success": False, "message": "User does not have permission to add object using source %s." % source_name } elif isinstance(source_name, EmbeddedSource): signature.add_source(source_name, method=source_method, reference=source_reference, tlp=source_tlp) elif isinstance(source_name, list) and len(source_name) > 0: for s in source_name: if isinstance(s, EmbeddedSource): signature.add_source(s, method=source_method, reference=source_reference, source_tlp=source_tlp) signature.version = len(Signature.objects(link_id=link_id)) + 1 if link_id: signature.link_id = link_id if copy_rels: rd2 = Signature.objects(link_id=link_id).first() if rd2: if len(rd2.relationships): signature.save(username=user.username) signature.reload() for rel in rd2.relationships: # Get object to relate to. rel_item = class_from_id(rel.rel_type, rel.object_id) if rel_item: signature.add_relationship( rel_item, rel.relationship, rel_date=rel.relationship_date, analyst=user.username) if bucket_list: signature.add_bucket_list(bucket_list, user) if ticket: signature.add_ticket(ticket, user) related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: status = {'success': False, 'message': 'Related Object not found.'} return status signature.save(username=user.username) if related_obj and signature and relationship_type: relationship_type = RelationshipTypes.inverse( relationship=relationship_type) signature.add_relationship(related_obj, relationship_type, analyst=user.username, get_rels=False) signature.save(username=user.username) signature.reload() # save signature signature.save(username=user.username) signature.reload() status = { 'success': True, 'message': 'Uploaded signature', '_id': signature.id, 'object': signature } return status
def handle_pcap_file(filename, data, source_name, user=None, description=None, related_id=None, related_md5=None, related_type=None, method='', reference='', tlp='', relationship=None, bucket_list=None, ticket=None): """ Add a PCAP. :param filename: The filename of the PCAP. :type filename: str :param data: The filedata of the PCAP. :type data: str :param source_name: The source which provided this PCAP. :type source_name: str, :class:`crits.core.crits_mongoengine.EmbeddedSource`, list of :class:`crits.core.crits_mongoengine.EmbeddedSource` :param user: The user adding the PCAP. :type user: str :param description: Description of the PCAP. :type description: str :param related_id: ObjectId of a top-level object related to this PCAP. :type related_id: str :param related_md5: MD5 of a top-level object related to this PCAP. :type related_md5: str :param related_type: The CRITs type of the related top-level object. :type related_type: str :param method: The method of acquiring this PCAP. :type method: str :param reference: A reference to the source of this PCAP. :type reference: str :param relationship: The relationship between the parent and the PCAP. :type relationship: str :param bucket_list: Bucket(s) to add to this PCAP. :type bucket_list: str(comma separated) or list. :param ticket: Ticket(s) to add to this PCAP. :type ticket: str(comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: 'success' (boolean), 'message' (str), 'md5' (str) if successful. """ if not data: status = { 'success': False, 'message': 'No data object passed in' } return status if len(data) <= 0: status = { 'success': False, 'message': 'Data length <= 0' } return status if ((related_id or related_md5) and not related_type): status = { 'success': False, 'message': 'Must specify both related_type and related_id or related_md5.' } return status if not source_name: return {"success" : False, "message" : "Missing source information."} related_obj = None if related_id or related_md5: if related_id: related_obj = class_from_id(related_type, related_id) else: related_obj = class_from_value(related_type, related_md5) if not related_obj: status = { 'success': False, 'message': 'Related object not found.' } return status # generate md5 and timestamp md5 = hashlib.md5(data).hexdigest() timestamp = datetime.datetime.now() # generate PCAP is_pcap_new = False pcap = PCAP.objects(md5=md5).first() if not pcap: pcap = PCAP() pcap.filename = filename pcap.created = timestamp pcap.length = len(data) pcap.description = description pcap.md5 = md5 is_pcap_new = True # generate source information and add to pcap if isinstance(source_name, basestring) and len(source_name) > 0: if user.check_source_write(source_name): s = create_embedded_source(source_name, method=method, reference=reference, tlp=tlp, analyst=user.username) else: return {"success":False, "message": "User does not have permission to add object \ using source %s." % source_name} pcap.add_source(s) elif isinstance(source_name, EmbeddedSource): pcap.add_source(source_name, method=method, reference=reference) elif isinstance(source_name, list) and len(source_name) > 0: for s in source_name: if isinstance(s, EmbeddedSource): pcap.add_source(s, method=method, reference=reference) # add file to GridFS if not isinstance(pcap.filedata.grid_id, ObjectId): pcap.add_file_data(data) if bucket_list: pcap.add_bucket_list(bucket_list, user) if ticket: pcap.add_ticket(ticket, user) # save pcap pcap.save(username=user) # update relationship if a related top-level object is supplied if related_obj and pcap: if relationship: relationship=RelationshipTypes.inverse(relationship=relationship) else: relationship = RelationshipTypes.RELATED_TO pcap.add_relationship(related_obj, relationship, analyst=user, get_rels=False) pcap.save(username=user) # run pcap triage if is_pcap_new and data: pcap.reload() run_triage(pcap, user) status = { 'success': True, 'message': 'Uploaded pcap', 'md5': md5, 'id': str(pcap.id), 'object': pcap } return status
def add_new_exploit(name, cve=None, description=None, source=None, source_method=None, source_reference=None, source_tlp=None, campaign=None, confidence=None, user=None, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add an Exploit to CRITs. :param name: The name of the exploit. :type name: str :param cve: CVE for the exploit. :type cve: str :param description: Description of the exploit. :type description: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param source_tlp: TLP value for this source :type source_reference: str :param campaign: A campaign to attribute to this exploit. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param user: The user adding this exploit. :type user: str :param bucket_list: Buckets to assign to this exploit. :type bucket_list: str :param ticket: Ticket to assign to this exploit. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: "success" (boolean), "message" (str), "object" (if successful) :class:`crits.exploits.exploit.Exploit` """ is_item_new = False retVal = {} exploit = Exploit.objects(name=name).first() if not exploit: exploit = Exploit() exploit.name = name if description: exploit.description = description.strip() is_item_new = True username = user.username if isinstance(source, basestring): if user.check_source_write(source): source = [ create_embedded_source(source, reference=source_reference, method=source_method, tlp=source_tlp, analyst=username) ] else: return { "success": False, "message": "User does not have permission to add object \ using source %s." % source } elif isinstance(source, EmbeddedSource): source = [source] if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=username) campaign = [c] if campaign: for camp in campaign: exploit.add_campaign(camp) if source: for s in source: exploit.add_source(s) else: return {"success": False, "message": "Missing source information."} exploit.cve = cve.strip() if bucket_list: exploit.add_bucket_list(bucket_list, user) if ticket: exploit.add_ticket(ticket, user) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal exploit.save(username=username) if related_obj and exploit and relationship_type: relationship_type = RelationshipTypes.inverse( relationship=relationship_type) exploit.add_relationship(related_obj, relationship_type, analyst=user, get_rels=False) exploit.save(username=username) # run exploit triage if is_item_new: exploit.reload() run_triage(exploit, username) resp_url = reverse('crits.exploits.views.exploit_detail', args=[exploit.id]) retVal['message'] = ('Success! Click here to view the new Exploit: ' '<a href="%s">%s</a>' % (resp_url, exploit.name)) retVal['success'] = True retVal['object'] = exploit retVal['id'] = str(exploit.id) return retVal
def handle_pcap_file(filename, data, source_name, user=None, description=None, related_id=None, related_md5=None, related_type=None, method='', reference='', relationship=None, bucket_list=None, ticket=None): """ Add a PCAP. :param filename: The filename of the PCAP. :type filename: str :param data: The filedata of the PCAP. :type data: str :param source_name: The source which provided this PCAP. :type source_name: str, :class:`crits.core.crits_mongoengine.EmbeddedSource`, list of :class:`crits.core.crits_mongoengine.EmbeddedSource` :param user: The user adding the PCAP. :type user: str :param description: Description of the PCAP. :type description: str :param related_id: ObjectId of a top-level object related to this PCAP. :type related_id: str :param related_md5: MD5 of a top-level object related to this PCAP. :type related_md5: str :param related_type: The CRITs type of the related top-level object. :type related_type: str :param method: The method of acquiring this PCAP. :type method: str :param reference: A reference to the source of this PCAP. :type reference: str :param relationship: The relationship between the parent and the PCAP. :type relationship: str :param bucket_list: Bucket(s) to add to this PCAP. :type bucket_list: str(comma separated) or list. :param ticket: Ticket(s) to add to this PCAP. :type ticket: str(comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: 'success' (boolean), 'message' (str), 'md5' (str) if successful. """ if not data: status = {'success': False, 'message': 'No data object passed in'} return status if len(data) <= 0: status = {'success': False, 'message': 'Data length <= 0'} return status if ((related_type and not (related_id or related_md5)) or (not related_type and (related_id or related_md5))): status = { 'success': False, 'message': 'Must specify both related_type and related_id or related_md5.' } return status if not source_name: return {"success": False, "message": "Missing source information."} related_obj = None if related_id or related_md5: if related_id: related_obj = class_from_id(related_type, related_id) else: related_obj = class_from_value(related_type, related_md5) if not related_obj: status = {'success': False, 'message': 'Related object not found.'} return status # generate md5 and timestamp md5 = hashlib.md5(data).hexdigest() timestamp = datetime.datetime.now() # generate PCAP is_pcap_new = False pcap = PCAP.objects(md5=md5).first() if not pcap: pcap = PCAP() pcap.filename = filename pcap.created = timestamp pcap.length = len(data) pcap.description = description pcap.md5 = md5 is_pcap_new = True # generate source information and add to pcap if isinstance(source_name, basestring) and len(source_name) > 0: s = create_embedded_source(source_name, method=method, reference=reference, analyst=user) pcap.add_source(s) elif isinstance(source_name, EmbeddedSource): pcap.add_source(source_name, method=method, reference=reference) elif isinstance(source_name, list) and len(source_name) > 0: for s in source_name: if isinstance(s, EmbeddedSource): pcap.add_source(s, method=method, reference=reference) # add file to GridFS if not isinstance(pcap.filedata.grid_id, ObjectId): pcap.add_file_data(data) if bucket_list: pcap.add_bucket_list(bucket_list, user) if ticket: pcap.add_ticket(ticket, user) # save pcap pcap.save(username=user) # update relationship if a related top-level object is supplied if related_obj and pcap: if relationship: relationship = RelationshipTypes.inverse(relationship=relationship) else: relationship = RelationshipTypes.RELATED_TO pcap.add_relationship(related_obj, relationship, analyst=user, get_rels=False) pcap.save(username=user) # run pcap triage if is_pcap_new and data: pcap.reload() run_triage(pcap, user) status = { 'success': True, 'message': 'Uploaded pcap', 'md5': md5, 'id': str(pcap.id), 'object': pcap } return status
def add_new_event(title, description, event_type, source, method, reference, date, analyst, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add a new Event to CRITs. :param title: Event title. :type title: str :param description: Event description. :type description: str :param event_type: Event type. :type event_type: str :param source: The source which provided this information. :type source: str :param method: THe method of acquiring this information. :type method: str :param reference: Reference to this data. :type reference: str :param date: Date of acquiring this data. :type date: datetime.datetime :param analyst: The user adding this Event. :type analyst: str :param bucket_list: The bucket(s) to associate with this Event. :type: str :param ticket: Ticket to associate with this event. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys "success" (boolean) and "message" (str) """ if not source: return {'success': False, 'message': "Missing source information."} event = Event() event.title = title event.description = description event.set_event_type(event_type) s = create_embedded_source(name=source, reference=reference, method=method, analyst=analyst, date=date) event.add_source(s) if bucket_list: event.add_bucket_list(bucket_list, analyst) if ticket: event.add_ticket(ticket, analyst) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal try: event.save(username=analyst) if related_obj and event and relationship_type: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) event.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) event.save(username=analyst) # run event triage event.reload() run_triage(event, analyst) message = ('<div>Success! Click here to view the new event: <a href=' '"%s">%s</a></div>' % (reverse('crits.events.views.view_event', args=[event.id]), title)) result = {'success': True, 'message': message, 'id': str(event.id), 'object': event} except ValidationError, e: result = {'success': False, 'message': e}
def add_new_backdoor(name, version=None, aliases=None, description=None, source=None, source_method=None, source_reference=None, campaign=None, confidence=None, user=None, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add an Backdoor to CRITs. :param name: The name of the backdoor. :type name: str :param version: Version of the backdoor. :type version: str :param aliases: Aliases for the backdoor. :type aliases: list or str :param description: Description of the backdoor. :type description: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param campaign: A campaign to attribute to this backdoor. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param user: The user adding this backdoor. :type user: str :param bucket_list: Buckets to assign to this backdoor. :type bucket_list: str :param ticket: Ticket to assign to this backdoor. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_id: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: "success" (boolean), "message" (str), "id" (str), "object" (if successful) :class:`crits.backdoors.backdoor.Backdoor` """ retVal = {'success': False, 'message': ''} if isinstance(source, basestring): source = [create_embedded_source(source, reference=source_reference, method=source_method, analyst=user)] elif isinstance(source, EmbeddedSource): source = [source] if not source: retVal['message'] = "Missing source information." return retVal # When creating a backdoor object we can potentially create multiple # objects. If we are given a name but no version we will create an object # with just the name (called the "family backdoor"). If given a name and a # version we will create the family backdoor and the specific backdoor for # that given version. # In case we create more than one backdoor object, store the created ones # in this list. The list is walked later on and attributes applied to each # object. objs = [] # First check if we have the family (name and no version). family = Backdoor.objects(name=name, version='').first() if not family: # Family does not exist, new object. Details are handled later. family = Backdoor() family.name = name family.version = '' objs.append(family) # Now check if we have the specific instance for this name + version. backdoor = None if version: backdoor = Backdoor.objects(name=name, version=version).first() if not backdoor: # Backdoor does not exist, new object. Details are handled later. backdoor = Backdoor() backdoor.name = name backdoor.version = version objs.append(backdoor) # At this point we have a family object and potentially a specific object. # Add the common parameters to all objects in the list and save them. for backdoor in objs: for s in source: backdoor.add_source(s) # Don't overwrite existing description. if description and backdoor.description == '': backdoor.description = description.strip() if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=user) campaign = [c] if campaign: for camp in campaign: backdoor.add_campaign(camp) if aliases: if isinstance(aliases, basestring): aliases = aliases.split(',') for alias in aliases: alias = alias.strip() if alias not in backdoor.aliases: backdoor.aliases.append(alias) if bucket_list: backdoor.add_bucket_list(bucket_list, user) if ticket: backdoor.add_ticket(ticket, user) backdoor.save(username=user) # run backdoor triage backdoor.reload() run_triage(backdoor, user) # Because family objects are put in the list first we will always # return a link to the most specific object created. If there is only # one item in the list it will be the family object. resp_url = reverse('crits.backdoors.views.backdoor_detail', args=[backdoor.id]) retVal['message'] = 'Success: <a href="%s">%s</a>' % (resp_url, backdoor.name) retVal['object'] = backdoor retVal['id'] = str(backdoor.id) # Only relate to the most specific object created. related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal if related_obj and relationship_type and backdoor: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) backdoor.add_relationship(related_obj, relationship_type, analyst=user, get_rels=False) backdoor.save(username=user) backdoor.reload() # If we have a family and specific object, attempt to relate the two. if len(objs) == 2: objs[0].add_relationship(objs[1], RelationshipTypes.RELATED_TO) objs[0].save() retVal['success'] = True return retVal
def upsert_target(data, analyst): """ Add/update target information. :param data: The target information. :type data: dict :param analyst: The user adding the target. :type analyst: str :returns: dict with keys "success" (boolean) and "message" (str) """ if 'email_address' not in data: return {'success': False, 'message': "No email address to look up"} # check for exact match first target = Target.objects(email_address=data['email_address']).first() if not target: # if no exact match, look for case-insensitive match target = Target.objects( email_address__iexact=data['email_address']).first() is_new = False if not target: is_new = True target = Target() target.email_address = data['email_address'].strip().lower() bucket_list = False ticket = False related_id = False if 'department' in data: target.department = data['department'] if 'division' in data: target.division = data['division'] if 'organization_id' in data: target.organization_id = data['organization_id'] if 'firstname' in data: target.firstname = data['firstname'] if 'lastname' in data: target.lastname = data['lastname'] if 'note' in data: target.note = data['note'] if 'title' in data: target.title = data['title'] if 'campaign' in data and 'camp_conf' in data: target.add_campaign( EmbeddedCampaign(name=data['campaign'], confidence=data['camp_conf'], analyst=analyst)) if 'bucket_list' in data: bucket_list = data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME) if 'ticket' in data: ticket = data.get(form_consts.Common.TICKET_VARIABLE_NAME) if 'related_id' in data: related_id = data['related_id'] if 'related_type' in data: related_type = data['related_type'] if 'relationship_type' in data: relationship_type = data['relationship_type'] if bucket_list: target.add_bucket_list(bucket_list, analyst) if ticket: target.add_ticket(ticket, analyst) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal try: target.save(username=analyst) if related_obj and target: relationship_type = RelationshipTypes.inverse( relationship=relationship_type) target.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) target.save(username=analyst) target.reload() if is_new: run_triage(target, analyst) return { 'success': True, 'message': "Target saved successfully", 'id': str(target.id) } except ValidationError, e: return {'success': False, 'message': "Target save failed: %s" % e}
def add_new_actor(name, aliases=None, description=None, source=None, source_method='', source_reference='', campaign=None, confidence=None, analyst=None, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add an Actor to CRITs. :param name: The name of the Actor. :type name: str :param aliases: Aliases for the actor. :type aliases: list or str :param description: Description of the actor. :type description: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param campaign: A campaign to attribute to this actor. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param analyst: The user adding this actor. :type analyst: str :param bucket_list: Buckets to assign to this actor. :type bucket_list: str :param ticket: Ticket to assign to this actor. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_id: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: "success" (boolean), "message" (str), "object" (if successful) :class:`crits.actors.actor.Actor` """ is_item_new = False retVal = {} actor = Actor.objects(name=name).first() if not actor: actor = Actor() actor.name = name if description: actor.description = description.strip() is_item_new = True if isinstance(source, basestring): source = [create_embedded_source(source, reference=source_reference, method=source_method, analyst=analyst)] if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=analyst) campaign = [c] if campaign: for camp in campaign: actor.add_campaign(camp) if source: for s in source: actor.add_source(s) else: return {"success" : False, "message" : "Missing source information."} if not isinstance(aliases, list): aliases = aliases.split(',') for alias in aliases: alias = alias.strip() if alias not in actor.aliases: actor.aliases.append(alias) if bucket_list: actor.add_bucket_list(bucket_list, analyst) if ticket: actor.add_ticket(ticket, analyst) related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal actor.save(username=analyst) if related_obj and actor: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) actor.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) actor.save(username=analyst) actor.reload() # run actor triage if is_item_new: actor.reload() run_triage(actor, analyst) resp_url = reverse('crits.actors.views.actor_detail', args=[actor.id]) retVal['message'] = ('Success! Click here to view the new Actor: ' '<a href="%s">%s</a>' % (resp_url, actor.name)) retVal['success'] = True retVal['object'] = actor retVal['id'] = str(actor.id) return retVal
def add_campaign(name, description, aliases, analyst, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add a Campaign. :param name: The name of the new Campaign. :type name: str :param description: Description of the new Campaign. :type description: str :param aliases: Aliases for the new Campaign. :type aliases: str (comma separated) or list. :param analyst: The user adding the Campaign. :type analyst: str :param bucket_list: Buckets to add to this Campaign. :type bucket_list: str (comma separated) or list. :param ticket: Ticket(s) to add to this Campaign. :type ticket: str (comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_id: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with key 'success' (boolean) and 'message' (str). """ # Verify the Campaign does not exist. campaign = Campaign.objects(name=name).first() if campaign: return {'success': False, 'message': ['Campaign already exists.'], 'id': str(campaign.id)} # Create new campaign. campaign = Campaign(name=name) campaign.edit_description(description) if bucket_list: campaign.add_bucket_list(bucket_list, analyst) if ticket: campaign.add_ticket(ticket, analyst) # Adjust aliases. if isinstance(aliases, basestring): alias_list = aliases.split(',') final_aliases = [a.strip() for a in alias_list] elif isinstance(aliases, list): final_aliases = [a.strip() for a in aliases] else: final_aliases = [] campaign.add_alias(final_aliases) related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal campaign.save(username=analyst) if related_obj and relationship_type and campaign: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) campaign.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) campaign.save(username=analyst) campaign.reload() try: campaign.save(username=analyst) campaign.reload() return {'success': True, 'message': 'Campaign created successfully!', 'id': str(campaign.id)} except ValidationError, e: return {'success': False, 'message': "Invalid value: %s" % e}
def handle_cert_file(filename, data, source_name, user=None, description=None, related_md5=None, method='', reference='', relationship=None, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add a Certificate. :param filename: The filename of the Certificate. :type filename: str :param data: The filedata of the Certificate. :type data: str :param source_name: The source which provided this Certificate. :type source_name: str, :class:`crits.core.crits_mongoengine.EmbeddedSource`, list of :class:`crits.core.crits_mongoengine.EmbeddedSource` :param user: The user adding the Certificate. :type user: str :param description: Description of the Certificate. :type description: str :param related_md5: MD5 of a top-level object related to this Certificate. :type related_md5: str :param related_type: The CRITs type of the related top-level object. :type related_type: str :param method: The method of acquiring this Certificate. :type method: str :param reference: A reference to the source of this Certificate. :type reference: str :param relationship: The relationship between the parent and the Certificate. :type relationship: str :param bucket_list: Bucket(s) to add to this Certificate :type bucket_list: str(comma separated) or list. :param ticket: Ticket(s) to add to this Certificate :type ticket: str(comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_id: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: 'success' (boolean), 'message' (str), 'md5' (str) if successful. """ if not data: status = { 'success': False, 'message': 'No data object passed in' } return status if len(data) <= 0: status = { 'success': False, 'message': 'Data length <= 0' } return status if ((related_type and not (related_id or related_md5)) or (not related_type and (related_id or related_md5))): status = { 'success': False, 'message': 'Must specify both related_type and related_id or related_md5.' } return status related_obj = None if related_id or related_md5: if related_id: related_obj = class_from_id(related_type, related_id) else: related_obj = class_from_value(related_type, related_md5) if not related_obj: status = { 'success': False, 'message': 'Related object not found.' } return status # generate md5 and timestamp md5 = hashlib.md5(data).hexdigest() timestamp = datetime.datetime.now() # generate Certificate cert = Certificate.objects(md5=md5).first() if not cert: cert = Certificate() cert.filename = filename cert.created = timestamp cert.size = len(data) cert.description = description cert.md5 = md5 # generate source information and add to certificate if isinstance(source_name, basestring) and len(source_name) > 0: s = create_embedded_source(source_name, method=method, reference=reference, analyst=user) cert.add_source(s) elif isinstance(source_name, EmbeddedSource): cert.add_source(source_name, method=method, reference=reference) elif isinstance(source_name, list) and len(source_name) > 0: for s in source_name: if isinstance(s, EmbeddedSource): cert.add_source(s, method=method, reference=reference) if bucket_list: cert.add_bucket_list(bucket_list, user) if ticket: cert.add_ticket(ticket, user) # add file to GridFS if not isinstance(cert.filedata.grid_id, ObjectId): cert.add_file_data(data) # save cert cert.save(username=user) cert.reload() # run certificate triage if len(AnalysisResult.objects(object_id=str(cert.id))) < 1 and data: run_triage(cert, user) # update relationship if a related top-level object is supplied if related_obj and cert: if relationship_type: relationship=RelationshipTypes.inverse(relationship=relationship_type) if not relationship: relationship = RelationshipTypes.RELATED_TO cert.add_relationship(related_obj, relationship, analyst=user, get_rels=False) cert.save(username=user) status = { 'success': True, 'message': 'Uploaded certificate', 'md5': md5, 'id': str(cert.id), 'object': cert } return status
fqdn_domain.save(username=username) except Exception, e: return {'success': False, 'message': e} #Add relationships between fqdn, root if fqdn_domain and root_domain: root_domain.add_relationship(fqdn_domain, RelationshipTypes.SUPRA_DOMAIN_OF, analyst=username, get_rels=False) root_domain.save(username=username) fqdn_domain.save(username=username) #Add relationships from object domain is being added from if related_obj and relationship_type: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) if fqdn_domain and (related_obj != fqdn_domain): fqdn_domain.add_relationship(related_obj, relationship_type, analyst=username, get_rels=False) fqdn_domain.save(username=username) if root_domain and (related_obj != root_domain): root_domain.add_relationship(related_obj, relationship_type, analyst=username, get_rels=False) root_domain.save(username=username) # run domain triage if is_fqdn_domain_new:
def add_new_actor(name, aliases=None, description=None, source=None, source_method='', source_reference='', campaign=None, confidence=None, analyst=None, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add an Actor to CRITs. :param name: The name of the Actor. :type name: str :param aliases: Aliases for the actor. :type aliases: list or str :param description: Description of the actor. :type description: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param campaign: A campaign to attribute to this actor. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param analyst: The user adding this actor. :type analyst: str :param bucket_list: Buckets to assign to this actor. :type bucket_list: str :param ticket: Ticket to assign to this actor. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_id: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: "success" (boolean), "message" (str), "object" (if successful) :class:`crits.actors.actor.Actor` """ is_item_new = False retVal = {} actor = Actor.objects(name=name).first() if not actor: actor = Actor() actor.name = name if description: actor.description = description.strip() is_item_new = True if isinstance(source, basestring): source = [ create_embedded_source(source, reference=source_reference, method=source_method, analyst=analyst) ] if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=analyst) campaign = [c] if campaign: for camp in campaign: actor.add_campaign(camp) if source: for s in source: actor.add_source(s) else: return {"success": False, "message": "Missing source information."} if not isinstance(aliases, list): aliases = aliases.split(',') for alias in aliases: alias = alias.strip() if alias not in actor.aliases: actor.aliases.append(alias) if bucket_list: actor.add_bucket_list(bucket_list, analyst) if ticket: actor.add_ticket(ticket, analyst) related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal actor.save(username=analyst) if related_obj and actor: relationship_type = RelationshipTypes.inverse( relationship=relationship_type) actor.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) actor.save(username=analyst) actor.reload() # run actor triage if is_item_new: actor.reload() run_triage(actor, analyst) resp_url = reverse('crits.actors.views.actor_detail', args=[actor.id]) retVal['message'] = ('Success! Click here to view the new Actor: ' '<a href="%s">%s</a>' % (resp_url, actor.name)) retVal['success'] = True retVal['object'] = actor retVal['id'] = str(actor.id) return retVal
def add_new_event(title, description, event_type, source_name, source_method, source_reference, source_tlp, date, user, bucket_list=None, ticket=None, campaign=None, campaign_confidence=None, related_id=None, related_type=None, relationship_type=None): """ Add a new Event to CRITs. :param title: Event title. :type title: str :param description: Event description. :type description: str :param event_type: Event type. :type event_type: str :param source: The source which provided this information. :type source: str :param method: THe method of acquiring this information. :type method: str :param reference: Reference to this data. :type reference: str :param date: Date of acquiring this data. :type date: datetime.datetime :param user: The user adding this Event. :type user: str :param bucket_list: The bucket(s) to associate with this Event. :type: str :param ticket: Ticket to associate with this event. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys "success" (boolean) and "message" (str) :param campaign: Campaign to associate with this Event :type campaign: str :param campaign_confidence: Confidence to associate with the Campaign :type campaign_confidence: str """ if not source_name: return {'success': False, 'message': "Missing source information."} result = dict() event = Event() event.title = title event.description = description event.set_event_type(event_type) if user.check_source_write(source_name): s = create_embedded_source(source_name, reference=source_reference, method=source_method, tlp=source_tlp, analyst=user.username, date=date) else: return {"success": False, "message": "User does not have permission to add object \ using source %s." % source_name} event.add_source(s) valid_campaign_confidence = { 'low': 'low', 'medium': 'medium', 'high': 'high'} valid_campaigns = {} for c in Campaign.objects(active='on'): valid_campaigns[c['name'].lower()] = c['name'] if campaign: if isinstance(campaign, basestring) and len(campaign) > 0: if campaign.lower() not in valid_campaigns: result = {'success':False, 'message':'{} is not a valid campaign.'.format(campaign)} else: confidence = valid_campaign_confidence.get(campaign_confidence, 'low') campaign = EmbeddedCampaign(name=campaign, confidence=confidence, description="", analyst=user.username, date=datetime.datetime.now()) event.add_campaign(campaign) if bucket_list: event.add_bucket_list(bucket_list, user.username) if ticket: event.add_ticket(ticket, user.username) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal try: event.save(username=user.username) if related_obj and event and relationship_type: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) event.add_relationship(related_obj, relationship_type, analyst=user.username, get_rels=False) event.save(username=user.username) # run event triage event.reload() run_triage(event, user.username) message = ('<div>Success! Click here to view the new event: <a href=' '"%s">%s</a></div>' % (reverse('crits-events-views-view_event', args=[event.id]), title)) result = {'success': True, 'message': message, 'id': str(event.id), 'object': event} except ValidationError, e: result = {'success': False, 'message': e}
def upsert_target(data, analyst): """ Add/update target information. :param data: The target information. :type data: dict :param analyst: The user adding the target. :type analyst: str :returns: dict with keys "success" (boolean) and "message" (str) """ if 'email_address' not in data: return {'success': False, 'message': "No email address to look up"} # check for exact match first target = Target.objects(email_address=data['email_address']).first() if not target: # if no exact match, look for case-insensitive match target = Target.objects(email_address__iexact=data['email_address']).first() is_new = False if not target: is_new = True target = Target() target.email_address = data['email_address'].strip().lower() bucket_list = False ticket = False if 'department' in data: target.department = data['department'] if 'division' in data: target.division = data['division'] if 'organization_id' in data: target.organization_id = data['organization_id'] if 'firstname' in data: target.firstname = data['firstname'] if 'lastname' in data: target.lastname = data['lastname'] if 'note' in data: target.note = data['note'] if 'title' in data: target.title = data['title'] if 'campaign' in data and 'camp_conf' in data: target.add_campaign(EmbeddedCampaign(name=data['campaign'], confidence=data['camp_conf'], analyst=analyst)) if 'bucket_list' in data: bucket_list = data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME) if 'ticket' in data: ticket = data.get(form_consts.Common.TICKET_VARIABLE_NAME) if 'related_id' in data: related_id = data['related_id'] if 'related_type' in data: related_type = data['related_type'] if 'relationship_type' in data: relationship_type = data['relationship_type'] if bucket_list: target.add_bucket_list(bucket_list, analyst) if ticket: target.add_ticket(ticket, analyst) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal try: target.save(username=analyst) if related_obj and target: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) target.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) target.save(username=analyst) target.reload() if is_new: run_triage(target, analyst) return {'success': True, 'message': "Target saved successfully", 'id': str(target.id)} except ValidationError, e: return {'success': False, 'message': "Target save failed: %s" % e}
def add_new_backdoor(name, version=None, aliases=None, description=None, source=None, source_method=None, source_reference=None, source_tlp=None, campaign=None, confidence=None, user=None, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None): """ Add an Backdoor to CRITs. :param name: The name of the backdoor. :type name: str :param version: Version of the backdoor. :type version: str :param aliases: Aliases for the backdoor. :type aliases: list or str :param description: Description of the backdoor. :type description: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param campaign: A campaign to attribute to this backdoor. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param user: The user adding this backdoor. :type user: CRITsUser :param bucket_list: Buckets to assign to this backdoor. :type bucket_list: str :param ticket: Ticket to assign to this backdoor. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_id: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: "success" (boolean), "message" (str), "id" (str), "object" (if successful) :class:`crits.backdoors.backdoor.Backdoor` """ retVal = {'success': False, 'message': ''} username = user.username if isinstance(source, basestring): if user.check_source_write(source): source = [ create_embedded_source(source, reference=source_reference, method=source_method, tlp=source_tlp, analyst=username) ] else: return { "success": False, "message": "User does not have permission to add objects \ using source %s." % str(source) } elif isinstance(source, EmbeddedSource): source = [source] if not source: retVal['message'] = "Missing source information." return retVal # When creating a backdoor object we can potentially create multiple # objects. If we are given a name but no version we will create an object # with just the name (called the "family backdoor"). If given a name and a # version we will create the family backdoor and the specific backdoor for # that given version. # In case we create more than one backdoor object, store the created ones # in this list. The list is walked later on and attributes applied to each # object. objs = [] # First check if we have the family (name and no version). family = Backdoor.objects(name=name, version='').first() if not family: # Family does not exist, new object. Details are handled later. family = Backdoor() family.name = name family.version = '' objs.append(family) # Now check if we have the specific instance for this name + version. backdoor = None if version: backdoor = Backdoor.objects(name=name, version=version).first() if not backdoor: # Backdoor does not exist, new object. Details are handled later. backdoor = Backdoor() backdoor.name = name backdoor.version = version objs.append(backdoor) # At this point we have a family object and potentially a specific object. # Add the common parameters to all objects in the list and save them. for backdoor in objs: for s in source: backdoor.add_source(s) # Don't overwrite existing description. if description and backdoor.description == '': backdoor.description = description.strip() if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=username) campaign = [c] if campaign: for camp in campaign: backdoor.add_campaign(camp) if aliases: if isinstance(aliases, basestring): aliases = aliases.split(',') for alias in aliases: alias = alias.strip() if alias not in backdoor.aliases: backdoor.aliases.append(alias) if bucket_list: backdoor.add_bucket_list(bucket_list, username) if ticket: backdoor.add_ticket(ticket, username) backdoor.save(username=username) # run backdoor triage backdoor.reload() run_triage(backdoor, username) # Because family objects are put in the list first we will always # return a link to the most specific object created. If there is only # one item in the list it will be the family object. resp_url = reverse('crits-backdoors-views-backdoor_detail', args=[backdoor.id]) retVal['message'] = 'Success: <a href="%s">%s</a>' % (resp_url, backdoor.name) retVal['object'] = backdoor retVal['id'] = str(backdoor.id) # Only relate to the most specific object created. related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal if related_obj and relationship_type and backdoor: relationship_type = RelationshipTypes.inverse( relationship=relationship_type) backdoor.add_relationship(related_obj, relationship_type, analyst=username, get_rels=False) backdoor.save(username=username) backdoor.reload() # If we have a family and specific object, attempt to relate the two. if len(objs) == 2: objs[0].add_relationship(objs[1], RelationshipTypes.RELATED_TO) objs[0].save() retVal['success'] = True return retVal
def add_new_event(title, description, event_type, source, method, reference, date, analyst, bucket_list=None, ticket=None, campaign=None, campaign_confidence=None, related_id=None, related_type=None, relationship_type=None): """ Add a new Event to CRITs. :param title: Event title. :type title: str :param description: Event description. :type description: str :param event_type: Event type. :type event_type: str :param source: The source which provided this information. :type source: str :param method: THe method of acquiring this information. :type method: str :param reference: Reference to this data. :type reference: str :param date: Date of acquiring this data. :type date: datetime.datetime :param analyst: The user adding this Event. :type analyst: str :param bucket_list: The bucket(s) to associate with this Event. :type: str :param ticket: Ticket to associate with this event. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys "success" (boolean) and "message" (str) :param campaign: Campaign to associate with this Event :type campaign: str :param campaign_confidence: Confidence to associate with the Campaign :type campaign_confidence: str """ result = dict() if not source: return {'success': False, 'message': "Missing source information."} event = Event() event.title = title event.description = description event.set_event_type(event_type) s = create_embedded_source(name=source, reference=reference, method=method, analyst=analyst, date=date) event.add_source(s) valid_campaign_confidence = { 'low': 'low', 'medium': 'medium', 'high': 'high' } valid_campaigns = {} for c in Campaign.objects(active='on'): valid_campaigns[c['name'].lower()] = c['name'] if campaign: if isinstance(campaign, basestring) and len(campaign) > 0: if campaign.lower() not in valid_campaigns: result = { 'success': False, 'message': '{} is not a valid campaign.'.format(campaign) } else: confidence = valid_campaign_confidence.get( campaign_confidence, 'low') campaign = EmbeddedCampaign(name=campaign, confidence=confidence, description="", analyst=analyst, date=datetime.datetime.now()) event.add_campaign(campaign) if bucket_list: event.add_bucket_list(bucket_list, analyst) if ticket: event.add_ticket(ticket, analyst) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal try: event.save(username=analyst) if related_obj and event and relationship_type: relationship_type = RelationshipTypes.inverse( relationship=relationship_type) event.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) event.save(username=analyst) # run event triage event.reload() run_triage(event, analyst) message = ( '<div>Success! Click here to view the new event: <a href=' '"%s">%s</a></div>' % (reverse('crits.events.views.view_event', args=[event.id]), title)) result = { 'success': True, 'message': message, 'id': str(event.id), 'object': event } except ValidationError, e: result = {'success': False, 'message': e}
def add_new_exploit(name, cve=None, description=None, source=None, source_method=None, source_reference=None, source_tlp=None, campaign=None, confidence=None, user=None, bucket_list=None, ticket=None,related_id=None, related_type=None, relationship_type=None): """ Add an Exploit to CRITs. :param name: The name of the exploit. :type name: str :param cve: CVE for the exploit. :type cve: str :param description: Description of the exploit. :type description: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param source_tlp: TLP value for this source :type source_reference: str :param campaign: A campaign to attribute to this exploit. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param user: The user adding this exploit. :type user: str :param bucket_list: Buckets to assign to this exploit. :type bucket_list: str :param ticket: Ticket to assign to this exploit. :type ticket: str :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: "success" (boolean), "message" (str), "object" (if successful) :class:`crits.exploits.exploit.Exploit` """ is_item_new = False retVal = {} exploit = Exploit.objects(name=name).first() if not exploit: exploit = Exploit() exploit.name = name if description: exploit.description = description.strip() is_item_new = True username = user.username if isinstance(source, basestring): if user.check_source_write(source): source = [create_embedded_source(source, reference=source_reference, method=source_method, tlp=source_tlp, analyst=username)] else: return {"success": False, "message": "User does not have permission to add object \ using source %s." % source} elif isinstance(source, EmbeddedSource): source = [source] if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=username) campaign = [c] if campaign: for camp in campaign: exploit.add_campaign(camp) if source: for s in source: exploit.add_source(s) else: return {"success" : False, "message" : "Missing source information."} exploit.cve = cve.strip() if bucket_list: exploit.add_bucket_list(bucket_list, user) if ticket: exploit.add_ticket(ticket, user) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal exploit.save(username=username) if related_obj and exploit and relationship_type: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) exploit.add_relationship(related_obj, relationship_type, analyst=user, get_rels=False) exploit.save(username=username) # run exploit triage if is_item_new: exploit.reload() run_triage(exploit, username) resp_url = reverse('crits-exploits-views-exploit_detail', args=[exploit.id]) retVal['message'] = ('Success! Click here to view the new Exploit: ' '<a href="%s">%s</a>' % (resp_url, exploit.name)) retVal['success'] = True retVal['object'] = exploit retVal['id'] = str(exploit.id) return retVal
from django import forms from django.forms.widgets import RadioSelect from crits.campaigns.campaign import Campaign from crits.core import form_consts from crits.core.forms import add_bucketlist_to_form, add_ticket_to_form from crits.core.handlers import get_source_names, get_item_names from crits.backdoors.handlers import get_backdoor_names from crits.core.user_tools import get_user_organization from crits.vocabulary.relationships import RelationshipTypes relationship_choices = [(c, c) for c in RelationshipTypes.values(sort=True)] class UnzipSampleForm(forms.Form): """ Django form to handle unziping a sample. """ error_css_class = 'error' required_css_class = 'required' password = forms.CharField(widget=forms.TextInput, required=False) class XORSearchForm(forms.Form): """ Django form to handle performing an XOR search. """ error_css_class = 'error' required_css_class = 'required' string = forms.CharField(widget=forms.TextInput, required=False)
def ip_add_update(ip_address, ip_type, source=None, source_method='', source_reference='', campaign=None, confidence='low', analyst=None, is_add_indicator=False, indicator_reference='', bucket_list=None, ticket=None, is_validate_only=False, cache={}, related_id=None, related_type=None, relationship_type=None): """ Add/update an IP address. :param ip_address: The IP to add/update. :type ip_address: str :param ip_type: The type of IP this is. :type ip_type: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param campaign: A campaign to attribute to this IP address. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param analyst: The user adding/updating this IP. :type analyst: str :param is_add_indicator: Also add an Indicator for this IP. :type is_add_indicator: bool :param indicator_reference: Reference for the indicator. :type indicator_reference: str :param bucket_list: Buckets to assign to this IP. :type bucket_list: str :param ticket: Ticket to assign to this IP. :type ticket: str :param is_validate_only: Only validate, do not add/update. :type is_validate_only: bool :param cache: Cached data, typically for performance enhancements during bulk operations. :type cache: dict :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: "success" (boolean), "message" (str), "object" (if successful) :class:`crits.ips.ip.IP` """ if not source: return {"success" : False, "message" : "Missing source information."} (ip_address, error) = validate_and_normalize_ip(ip_address, ip_type) if error: return {"success": False, "message": error} retVal = {} is_item_new = False ip_object = None cached_results = cache.get(form_consts.IP.CACHED_RESULTS) if cached_results != None: ip_object = cached_results.get(ip_address) else: ip_object = IP.objects(ip=ip_address).first() if not ip_object: ip_object = IP() ip_object.ip = ip_address ip_object.ip_type = ip_type is_item_new = True if cached_results != None: cached_results[ip_address] = ip_object if isinstance(source, basestring): source = [create_embedded_source(source, reference=source_reference, method=source_method, analyst=analyst)] if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=analyst) campaign = [c] if campaign: for camp in campaign: ip_object.add_campaign(camp) if source: for s in source: ip_object.add_source(s) else: return {"success" : False, "message" : "Missing source information."} if bucket_list: ip_object.add_bucket_list(bucket_list, analyst) if ticket: ip_object.add_ticket(ticket, analyst) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal resp_url = reverse('crits.ips.views.ip_detail', args=[ip_object.ip]) if is_validate_only == False: ip_object.save(username=analyst) #set the URL for viewing the new data if is_item_new == True: retVal['message'] = ('Success! Click here to view the new IP: ' '<a href="%s">%s</a>' % (resp_url, ip_object.ip)) else: message = ('Updated existing IP: ' '<a href="%s">%s</a>' % (resp_url, ip_object.ip)) retVal['message'] = message retVal['status'] = form_consts.Status.DUPLICATE retVal['warning'] = message elif is_validate_only == True: if ip_object.id != None and is_item_new == False: message = ('Warning: IP already exists: ' '<a href="%s">%s</a>' % (resp_url, ip_object.ip)) retVal['message'] = message retVal['status'] = form_consts.Status.DUPLICATE retVal['warning'] = message if is_add_indicator: from crits.indicators.handlers import handle_indicator_ind handle_indicator_ind(ip_address, source, ip_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, analyst, source_method, indicator_reference, add_domain=False, add_relationship=True, bucket_list=bucket_list, ticket=ticket, cache=cache) if related_obj and ip_object and relationship_type: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) ip_object.add_relationship(related_obj, relationship_type, analyst=analyst, get_rels=False) ip_object.save(username=analyst) # run ip triage if is_item_new and is_validate_only == False: ip_object.reload() run_triage(ip_object, analyst) retVal['success'] = True retVal['object'] = ip_object return retVal
from django import forms from django.forms.utils import ErrorList from crits.campaigns.campaign import Campaign from crits.core import form_consts from crits.core.forms import add_bucketlist_to_form, add_ticket_to_form from crits.core.handlers import get_item_names from crits.vocabulary.relationships import RelationshipTypes from crits.vocabulary.acls import Common, TargetACL relationship_choices = [(c, c) for c in RelationshipTypes.values(sort=True)] class TargetInfoForm(forms.Form): """ Django form for adding/updating target information. """ error_css_class = 'error' required_css_class = 'required' firstname = forms.CharField(widget=forms.TextInput(attrs={'size': '50'}), required=False) lastname = forms.CharField(widget=forms.TextInput(attrs={'size': '50'}), required=False) division = forms.CharField(widget=forms.TextInput(attrs={'size': '50'}), required=False) department = forms.CharField(widget=forms.TextInput(attrs={'size': '50'}), required=False) email_address = forms.CharField(widget=forms.TextInput(attrs={'size': '50'}), required=True) organization_id = forms.CharField(widget=forms.TextInput(attrs={'size': '50'}),
def handle_signature_file( data, source_name, user=None, description=None, title=None, data_type=None, data_type_min_version=None, data_type_max_version=None, data_type_dependency=None, link_id=None, method="", reference="", copy_rels=False, bucket_list=None, ticket=None, related_id=None, related_type=None, relationship_type=None, ): """ Add Signature. :param data: The data of the Signature. :type data: str :param source_name: The source which provided this Signature. :type source_name: str, :class:`crits.core.crits_mongoengine.EmbeddedSource`, list of :class:`crits.core.crits_mongoengine.EmbeddedSource` :param user: The user adding the Signature. :type user: str :param description: Description of the Signature. :type description: str :param title: Title of the Signature. :type title: str :param data_type: Datatype of the Signature. :type data_type: str :param data_type: Datatype of the Signature. :type data_type_min_version: str :param data_type_min_version: Datatype tool minimum version. :type data_type_max_version: str :param data_type_max_version: Datatype tool maximum version. :type data_type_dependency: list :param data_type_dependency: Datatype tool dependency to be run :param link_id: LinkId to tie this to another Signature as a new version. :type link_id: str :param method: The method of acquiring this Signature. :type method: str :param reference: A reference to the source of this Signature. :type reference: str :param copy_rels: Copy relationships from the previous version to this one. :type copy_rels: bool :param bucket_list: Bucket(s) to add to this Signature :type bucket_list: str(comma separated) or list. :param ticket: Ticket(s) to add to this Signature :type ticket: str(comma separated) or list. :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :returns: dict with keys: 'success' (boolean), 'message' (str), '_id' (str) if successful. """ if not data or not title or not data_type: status = {"success": False, "message": "No data object, title, or data type passed in"} return status if not source_name: return {"success": False, "message": "Missing source information."} rdt = SignatureType.objects(name=data_type).first() if not rdt: status = {"success": False, "message": "Invalid data type passed in"} return status if len(data) <= 0: status = {"success": False, "message": "Data length <= 0"} return status # generate md5 and timestamp md5 = hashlib.md5(data).hexdigest() timestamp = datetime.datetime.now() # generate signature signature = Signature() signature.created = timestamp signature.description = description signature.md5 = md5 signature.data = data signature.title = title signature.data_type = data_type signature.data_type_min_version = data_type_min_version signature.data_type_max_version = data_type_max_version if data_type_dependency: if type(data_type_dependency) == unicode: data_type_dependency = data_type_dependency.split(",") for item in data_type_dependency: if item: item = item.strip() signature.data_type_dependency.append(str(item)) else: data_type_dependency = [] # generate new source information and add to sample if isinstance(source_name, basestring) and len(source_name) > 0: source = create_embedded_source(source_name, date=timestamp, method=method, reference=reference, analyst=user) # this will handle adding a new source, or an instance automatically signature.add_source(source) elif isinstance(source_name, EmbeddedSource): signature.add_source(source_name, method=method, reference=reference) elif isinstance(source_name, list) and len(source_name) > 0: for s in source_name: if isinstance(s, EmbeddedSource): signature.add_source(s, method=method, reference=reference) signature.version = len(Signature.objects(link_id=link_id)) + 1 if link_id: signature.link_id = link_id if copy_rels: rd2 = Signature.objects(link_id=link_id).first() if rd2: if len(rd2.relationships): signature.save(username=user) signature.reload() for rel in rd2.relationships: # Get object to relate to. rel_item = class_from_id(rel.rel_type, rel.object_id) if rel_item: signature.add_relationship( rel_item, rel.relationship, rel_date=rel.relationship_date, analyst=user ) if bucket_list: signature.add_bucket_list(bucket_list, user) if ticket: signature.add_ticket(ticket, user) related_obj = None if related_id and related_type: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal["success"] = False retVal["message"] = "Related Object not found." return retVal signature.save(username=user) if related_obj and signature and relationship_type: relationship_type = RelationshipTypes.inverse(relationship=relationship_type) signature.add_relationship(related_obj, relationship_type, analyst=user, get_rels=False) signature.save(username=user) signature.reload() # save signature signature.save(username=user) signature.reload() status = {"success": True, "message": "Uploaded signature", "_id": signature.id, "object": signature} return status
def ip_add_update(ip_address, ip_type, source=None, source_method='', source_reference='', source_tlp=None, campaign=None, confidence='low', user=None, is_add_indicator=False, indicator_reference='', bucket_list=None, ticket=None, is_validate_only=False, cache={}, related_id=None, related_type=None, relationship_type=None, description=''): """ Add/update an IP address. :param ip_address: The IP to add/update. :type ip_address: str :param ip_type: The type of IP this is. :type ip_type: str :param source: Name of the source which provided this information. :type source: str :param source_method: Method of acquiring this data. :type source_method: str :param source_reference: A reference to this data. :type source_reference: str :param campaign: A campaign to attribute to this IP address. :type campaign: str :param confidence: Confidence level in the campaign attribution. :type confidence: str ("low", "medium", "high") :param user: The user adding/updating this IP. :type user: str :param is_add_indicator: Also add an Indicator for this IP. :type is_add_indicator: bool :param indicator_reference: Reference for the indicator. :type indicator_reference: str :param bucket_list: Buckets to assign to this IP. :type bucket_list: str :param ticket: Ticket to assign to this IP. :type ticket: str :param is_validate_only: Only validate, do not add/update. :type is_validate_only: bool :param cache: Cached data, typically for performance enhancements during bulk operations. :type cache: dict :param related_id: ID of object to create relationship with :type related_id: str :param related_type: Type of object to create relationship with :type related_type: str :param relationship_type: Type of relationship to create. :type relationship_type: str :param description: A description for this IP :type description: str :returns: dict with keys: "success" (boolean), "message" (str), "object" (if successful) :class:`crits.ips.ip.IP` """ if not source: return {"success" : False, "message" : "Missing source information."} source_name = source (ip_address, error) = validate_and_normalize_ip(ip_address, ip_type) if error: return {"success": False, "message": error} retVal = {} is_item_new = False ip_object = None cached_results = cache.get(form_consts.IP.CACHED_RESULTS) if cached_results != None: ip_object = cached_results.get(ip_address) else: ip_object = IP.objects(ip=ip_address).first() if not ip_object: ip_object = IP() ip_object.ip = ip_address ip_object.ip_type = ip_type is_item_new = True if cached_results != None: cached_results[ip_address] = ip_object if not ip_object.description: ip_object.description = description or '' elif ip_object.description != description: ip_object.description += "\n" + (description or '') if isinstance(source_name, basestring): if user.check_source_write(source): source = [create_embedded_source(source, reference=source_reference, method=source_method, tlp=source_tlp, analyst=user.username)] else: return {"success":False, "message": "User does not have permission to add object \ using source %s." % source} if isinstance(campaign, basestring): c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=user.username) campaign = [c] if campaign: for camp in campaign: ip_object.add_campaign(camp) if source: for s in source: ip_object.add_source(s) else: return {"success" : False, "message" : "Missing source information."} if bucket_list: ip_object.add_bucket_list(bucket_list, user.username) if ticket: ip_object.add_ticket(ticket, user.username) related_obj = None if related_id: related_obj = class_from_id(related_type, related_id) if not related_obj: retVal['success'] = False retVal['message'] = 'Related Object not found.' return retVal resp_url = reverse('crits.ips.views.ip_detail', args=[ip_object.ip]) if is_validate_only == False: ip_object.save(username=user.username) #set the URL for viewing the new data if is_item_new == True: retVal['message'] = ('Success! Click here to view the new IP: ' '<a href="%s">%s</a>' % (resp_url, ip_object.ip)) else: message = ('Updated existing IP: ' '<a href="%s">%s</a>' % (resp_url, ip_object.ip)) retVal['message'] = message retVal['status'] = form_consts.Status.DUPLICATE retVal['warning'] = message elif is_validate_only == True: if ip_object.id != None and is_item_new == False: message = ('Warning: IP already exists: ' '<a href="%s">%s</a>' % (resp_url, ip_object.ip)) retVal['message'] = message retVal['status'] = form_consts.Status.DUPLICATE retVal['warning'] = message if is_add_indicator: from crits.indicators.handlers import handle_indicator_ind result = handle_indicator_ind(ip_address, source_name, ip_type, IndicatorThreatTypes.UNKNOWN, IndicatorAttackTypes.UNKNOWN, user, source_method=source_method, source_reference = indicator_reference, source_tlp = source_tlp, add_domain=False, add_relationship=True, bucket_list=bucket_list, ticket=ticket, cache=cache) if related_obj and ip_object and relationship_type: relationship_type=RelationshipTypes.inverse(relationship=relationship_type) ip_object.add_relationship(related_obj, relationship_type, analyst=user.username, get_rels=False) ip_object.save(username=user.username) # run ip triage if is_item_new and is_validate_only == False: ip_object.reload() run_triage(ip_object, user) retVal['success'] = True retVal['object'] = ip_object return retVal
def gather_relationships(obj_type, obj_id, user, depth, types): objects = {} nodes = [] links = [] tlos = { 'Actor': [], 'Backdoor': [], 'Campaign': [], 'Certificate': [], 'Comment': [], 'Domain': [], 'Email': [], 'Event': [], 'Exploit': [], 'Indicator': [], 'IP': [], 'PCAP': [], 'RawData': [], 'Sample': [], 'Target': [] } # These would be used if we move to force labels #labelAnchors = [] #labelAnchorLinks = [] sources = user_sources(user) if not sources: return { 'nodes': nodes, 'links': links } field_dict = { 'Actor': 'name', 'Backdoor': 'name', 'Campaign': 'name', 'Certificate': 'md5', 'Comment': 'object_id', 'Domain': 'domain', 'Email': 'date', 'Event': 'title', 'Exploit': 'name', 'Indicator': 'value', 'IP': 'ip', 'PCAP': 'md5', 'RawData': 'title', 'Sample': 'md5', 'Target': 'email_address' } # Define the styles for each of the data types. Absent these, the vis.js library will # auto-select sensible defaults tlo_styles_dict = { 'Actor': { 'shape': 'dot', 'size': 25, 'color': '#900C0C', 'color_border': '#700C0C', 'color_highlight': '#90FCFC', 'color_highlight_border': '#900C0C' }, 'Backdoor': { 'shape': 'dot', 'size': 10, 'color': '#5A2C75', 'color_border': '#3A1C55', 'color_highlight': '#7040B0', 'color_highlight_border': '#5A2C75' }, 'Campaign': { 'shape': 'dot', 'size': 40, 'color': '#FF3737', 'color_border': '#D72020', 'color_highlight': '#FF6868', 'color_highlight_border': '#FF3737' }, 'Certificate': { 'shape': 'dot', 'size': 10, 'color': '#FFA837', 'color_border': '#D08020', 'color_highlight': '#FFC060', 'color_highlight_border': '#FFA837' }, 'Domain': { 'shape': 'dot', 'size': 20, 'color': '#33EB33', 'color_border': '#25C025', 'color_highlight': '#55FF55', 'color_highlight_border': '#33EB33' }, 'Email': { 'shape': 'dot', 'size': 25, 'color': '#FF8989', 'color_border': '#CF7070', 'color_highlight': '#FFB0B0', 'color_highlight_border': '#FF8989' }, 'Event': { 'shape': 'dot', 'size': 35, 'color': '#B05151', 'color_border': '#904040', 'color_highlight': '#D07171', 'color_highlight_border': '#B05151' }, 'Exploit': { 'shape': 'dot', 'size': 10, 'color': '#8CA336', 'color_border': '#709020', 'color_highlight': '#A8CC60', 'color_highlight_border': '#8CA336' }, 'Indicator': { 'shape': 'dot', 'size': 10, 'color': '#B08751', 'color_border': '#907050', 'color_highlight': '#CCA075', 'color_highlight_border': '#B08751' }, 'IP': { 'shape': 'dot', 'size': 20, 'color': '#90570C', 'color_border': '#77400C', 'color_highlight': '#B06037', 'color_highlight_border': '#90570C' }, 'PCAP': { 'shape': 'dot', 'size': 10, 'color': '#FFCC89', 'color_border': '#D0A860', 'color_highlight': '#FFE0B0', 'color_highlight_border': '#FFCC89' }, 'Raw Data': { 'shape': 'dot', 'size': 10, 'color': '#4A7797', 'color_border': '#306080', 'color_highlight': '#6090B8', 'color_highlight_border': '#4A7797' }, 'Sample': { 'shape': 'dot', 'size': 25, 'color': '#8CCBF8', 'color_border': '#70AADC', 'color_highlight': '#A0D0FF', 'color_highlight_border': '#8CCBF8' }, 'Target': { 'shape': 'dot', 'size': 10, 'color': '#4AA24A', 'color_border': '#308030', 'color_highlight': '#60C860', 'color_highlight_border': '#4AA24A' } } def inner_collect(obj_type, obj_id, sources, depth): # Don't keep going if we've already processed this object if obj_id in objects: return klass = class_from_type(obj_type) if not klass: return if hasattr(klass, 'source'): obj = klass.objects(id=obj_id, source__name__in=sources).first() else: obj = klass.objects(id=obj_id).first() if not obj: return objects[obj_id] = obj if depth == 0: return depth -= 1 for r in obj.relationships: inner_collect(r.rel_type, str(r.object_id), sources, depth) # If we traverse into a Campaign object, walk everything tagged # with that campaign along with related objects. if obj_type == 'Campaign': for c in field_dict.keys(): klass = class_from_type(c) # Not every object in field_dict can be tagged with a campaign. # For example, comments. if not hasattr(klass, 'campaign'): continue tagged_objs = klass.objects(campaign__name=obj.name) for tobj in tagged_objs: inner_collect(tobj._meta['crits_type'], str(tobj.id), sources, depth) # END OF INNER COLLECT try: depth = int(depth) except ValueError: depth = 3 inner_collect(obj_type, str(obj_id), sources, depth) # This dictionary is used to describe the position of each object # in the nodes list. The key is an object ID and the value is a # tuple where the first item is the position in the node list and # the second is a list of object IDs related to this object. # # Once all the nodes are created and this dictionary is populated # it is used to create the links. # # Here is a simple obj_graph for three objects (A, B and C) that # are related such that they form a triangle (A<->B, B<->C, C<->A): # # { # 'A': (0, ['B', 'C']), # 'B': (1, ['A', 'C']), # 'C': (2, ['B', 'A']) # } # # The integers are the position in the node array and are used as # the target. The items in the list are used as lookups back into # the dictionary for the source. obj_graph = {} campaign_cache = {} node_position = 0 tlo_labels = {} tlo_relationships = {} for (obj_id, obj) in objects.iteritems(): if obj_id in obj_graph: continue obj_type = obj._meta['crits_type'] #import pprint obj_master = obj._meta klass = class_from_type(obj_type) obj = klass.objects(id=obj_id).first() # YES! THIS WORKS! ''' if obj_type=="Sample": sample = obj.filename else: sample = vars(obj) ''' # Add the obj_id and label to the tlo_labels dict # e.g. tlo_labels={'<md5>': '<obj_id>'} label = str(obj_type+" | "+getattr(obj, field_dict[obj_type], '')) tlo_labels[label]=str(obj.id) tlos[obj_type].append(obj) ### Get TLO Relationships tlo_relationships[str(obj_id)]={} all_relationships = obj.relationships for rel in all_relationships: tlo_relationships[str(obj_id)][str(rel.object_id)]=str(rel.relationship) ### A bunch of the stuff below here can probably go... value = getattr(obj, field_dict[obj_type], '') if obj_type == 'Backdoor': # Append a version or family if obj.version == '': value += " (family)" else: value += " (v:%s)" % obj.version href = reverse('crits.core.views.details', args=(obj_type, obj_id)) if len(types) != 0 and obj_type not in types: continue # For every campaign on this object, make a new node in the list. if 'Campaign' in types and hasattr(obj, 'campaign'): for i, campaign in enumerate(obj.campaign): name = "%s" % obj.campaign[i].name if name not in campaign_cache: campaign_cache[name] = get_campaign_details(name, user) (x, campaign_details) = campaign_cache[name] if 'error' in campaign_details: continue campaign_id = str(campaign_details['campaign_detail'].id) # If this campaign already exists as a node then # add a relationship to the current object if campaign_id in obj_graph: (tnode, source_ids) = obj_graph[campaign_id] source_ids.append(obj_id) else: total = 0 for count in campaign_details['counts'].values(): total += count campaign = name + " (" + str(total) + ")" campaign_href = reverse('crits.core.views.details', args=('Campaign', campaign_id)) n = dict(tlo_styles_dict['Campaign']) n['label'] = campaign n['url'] = campaign_href n['type'] = n['group'] = 'Campaign' n['crits_status'] = 'Analyzed' n['id'] = campaign_id nodes.append(n) obj_graph[campaign_id] = (node_position, [obj_id]) node_position += 1 # n will contain the vis.js-schema data to load into the graph n = {} if obj_type in tlo_styles_dict: n = dict(tlo_styles_dict[obj_type]) n['label'] = '%s' % value else: n = { 'label': '%s' % value, 'shape': 'dot' } n['url'] = href n['crits_status'] = obj['status']; n['id'] = obj_id n['type'] = n['group'] = obj_type n['visible'] = True nodes.append(n) obj_graph[obj_id] = (node_position, [str(r.object_id) for r in obj.relationships]) node_position += 1 #### PROCESS DATA FOR MISP DISPLAY #### step1 = {} # This should be tlos.items() if Python 3 for obj_type, objs in tlos.iteritems(): for obj in objs: if obj_type not in step1: step1[str(obj_type)]={} ''' Changing this up so it's {'Sample': {'58dabfca97553032a1f7f0c5': {'label': '098f6bcd4621d373cade4e832627b4f6', 'md5': '098f6bcd4621d373cade4e832627b4f6', 'filename': 'whatever'} } } ''' if str(obj.id) not in step1[str(obj_type)]: step1[str(obj_type)][str(obj.id)]={} # Set the label as the first key step1[str(obj_type)][str(obj.id)]['label']=str(getattr(obj, field_dict[obj_type], '')) # Proces objects according to type if str(obj_type)=="Sample": # Grab the Sample attributes step1[str(obj_type)][str(obj.id)]['filename']=str(obj.filename) step1[str(obj_type)][str(obj.id)]['filetype']=str(obj.filetype) step1[str(obj_type)][str(obj.id)]['md5']=str(obj.md5) step1[str(obj_type)][str(obj.id)]['mimetype']=str(obj.mimetype) step1[str(obj_type)][str(obj.id)]['sha1']=str(obj.sha1) step1[str(obj_type)][str(obj.id)]['sha256']=str(obj.sha256) step1[str(obj_type)][str(obj.id)]['size']=str(obj.size) step1[str(obj_type)][str(obj.id)]['ssdeep']=str(obj.ssdeep) step1[str(obj_type)][str(obj.id)]['impfuzzy']=str(obj.impfuzzy) elif str(obj_type)=="Email": # Grab the Email attributes step1[str(obj_type)][str(obj.id)]['email_cc']=str(obj.cc) step1[str(obj_type)][str(obj.id)]['email_date']=str(obj.date) step1[str(obj_type)][str(obj.id)]['email_from_address']=str(obj.from_address) step1[str(obj_type)][str(obj.id)]['email_helo']=str(obj.helo) step1[str(obj_type)][str(obj.id)]['email_isodate']=str(obj.isodate) step1[str(obj_type)][str(obj.id)]['email_message_id']=str(obj.message_id) step1[str(obj_type)][str(obj.id)]['email_originating_ip']=str(obj.originating_ip) step1[str(obj_type)][str(obj.id)]['email_reply_to']=str(obj.reply_to) step1[str(obj_type)][str(obj.id)]['email_sender']=str(obj.sender) step1[str(obj_type)][str(obj.id)]['email_subject']=str(obj.subject) step1[str(obj_type)][str(obj.id)]['email_to']=str(obj.to) step1[str(obj_type)][str(obj.id)]['email_x_originating_ip']=str(obj.x_originating_ip) step1[str(obj_type)][str(obj.id)]['email_x_mailer']=str(obj.x_mailer) elif str(obj_type)=="Domain": step1[str(obj_type)][str(obj.id)]['domain']=str(obj.domain) elif str(obj_type)=="Indicator": step1[str(obj_type)][str(obj.id)]['type']=str(obj.ind_type) elif str(obj_type)=="Event": step1[str(obj_type)][str(obj.id)]['event_title']=str(obj.title) step1[str(obj_type)][str(obj.id)]['event_type']=str(obj.event_type) elif str(obj_type)=="IP": step1[str(obj_type)][str(obj.id)]['ip']=str(obj.ip) #step1[str(obj_type)][str(obj.id)]['ip_type']=str(obj.ip_type) n['tlo_labels']=tlo_labels n['step1']=step1 n['tlo_relationships']=tlo_relationships ''' n['tlo_labels']=pprint.pformat(tlo_labels) n['step1']=pprint.pformat(step1) n['tlo_relationships']=pprint.pformat(tlo_relationships) ''' #### END NMD Debug # This dictionary is used to track the links that have been created. # When a new link is created the inverse is added to this dictionary as # a key. This is because the link between A->B is the same as B->A. When # the link for A->B is made, we insert it into this dictionary and then # lookup the inverse when creating any new relationships. This ensures # that when B->A is handled it will be ignored. link_dict = {} for (tid, (tnode, source_ids)) in obj_graph.iteritems(): for sid in source_ids: # If the graph is cut off the related object may not have been # collected. If the inverse relationship is already done, no # need to do this one too. if sid not in obj_graph or (tid + sid) in link_dict: continue link = { 'from': sid, 'to': tid } links.append(link) link_dict[sid + tid] = True #labelAnchors.append({'node': n, # 'url': href}) #labelAnchors.append({'node': n, # 'url': href}) #alink = { # 'source': (len(nodes) - 1) * 2, # 'target': (len(nodes) - 1) * 2 + 1, # 'weight': 1, #} #labelAnchorLinks.append(alink) # Get all CRITs relationship types from crits.vocabulary.relationships import RelationshipTypes rel_types=[c for c in RelationshipTypes.values(sort=True)] # Get all MISP Categories and Types misp_obj=MISPEvent() misp_cats = misp_obj.categories misp_types = misp_obj.category_type_mapping ''' from crits.services.service import CRITsService svc_obj = CRITsService.objects(name='misp_service') misp_config = svc_obj.config.to_dict() ''' return { 'nodes': nodes, 'links': links, 'rel_types': rel_types, 'misp_cats': misp_cats, 'misp_types': misp_types, #'misp_config': misp_config, #'tlos': tlos, #'tlo_labels': tlo_labels, #'tlo_relationships': tlo_relationships, #'labelAnchors': labelAnchors, #'labelAnchorLinks': labelAnchorLinks, }