Пример #1
0
def add_new_actor_identifier(identifier_type,
                             identifier=None,
                             source=None,
                             source_method='',
                             source_reference='',
                             analyst=None):
    """
    Add an Actor Identifier to CRITs.

    :param identifier_type: The Actor Identifier Type.
    :type identifier_type: str
    :param identifier: The Actor Identifier.
    :type identifier: 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 analyst: The user adding this actor.
    :type analyst: str
    :returns: dict with keys:
              "success" (boolean),
              "message" (str),
    """

    actor_identifier = ActorIdentifier.objects(identifier_type=identifier_type,
                                               name=identifier).first()

    if not actor_identifier:
        actor_identifier = ActorIdentifier()
        actor_identifier.set_identifier_type(identifier_type)
        if not actor_identifier.identifier_type:
            return {'success': False, 'message': "Unknown Identifier Type"}
        if not identifier:
            return {'success': False, 'message': "Missing Identifier"}
        actor_identifier.name = identifier.strip()

    if isinstance(source, basestring):
        source = [
            create_embedded_source(source,
                                   reference=source_reference,
                                   method=source_method,
                                   analyst=analyst)
        ]

    if source:
        for s in source:
            actor_identifier.add_source(s)
    else:
        return {"success": False, "message": "Missing source information."}

    actor_identifier.save(username=analyst)
    actor_identifier.reload()

    return {
        'success': True,
        'id': str(actor_identifier.id),
        'message': "Actor Identifier added successfully!"
    }
Пример #2
0
def add_new_actor_identifier(identifier_type, identifier=None, source=None,
                             source_method='', source_reference='',
                             source_tlp=None, user=None):
    """
    Add an Actor Identifier to CRITs.

    :param identifier_type: The Actor Identifier Type.
    :type identifier_type: str
    :param identifier: The Actor Identifier.
    :type identifier: 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: The TLP for this identifier.
    :type source_tlp: str
    :param user: The user adding this actor.
    :type user: :class:`crits.core.user.CRITsUser`
    :returns: dict with keys:
              "success" (boolean),
              "message" (str),
    """

    actor_identifier = ActorIdentifier.objects(identifier_type=identifier_type,
                                               name=identifier).first()

    if not actor_identifier:
        actor_identifier = ActorIdentifier()
        actor_identifier.set_identifier_type(identifier_type)
        if not actor_identifier.identifier_type:
            return {'success': False,
                    'message': "Unknown Identifier Type"}
        if not identifier:
            return {'success': False,
                    'message': "Missing Identifier"}
        actor_identifier.name = identifier.strip()

    if isinstance(source, basestring):
        source = [create_embedded_source(source,
                                         reference=source_reference,
                                         method=source_method,
                                         tlp=source_tlp,
                                         analyst=user.username)]

    if source:
        for s in source:
            actor_identifier.add_source(s)
    else:
        return {"success" : False, "message" : "Missing source information."}

    actor_identifier.save(username=user.username)
    actor_identifier.reload()

    return {'success': True,
            'id': str(actor_identifier.id),
            'message': "Actor Identifier added successfully!"}
Пример #3
0
def comment_add(cleaned_data, obj_type, obj_id, method, subscr, analyst):
    """
    Add a new comment.

    :param cleaned_data: Cleaned data from the Django form submission.
    :type cleaned_data: dict
    :param obj_type: The top-level object type to add the comment to.
    :type obj_type: str
    :param obj_id: The top-level ObjectId to add the comment to.
    :type obj_id: str
    :param method: If this is a reply or not (set method to "reply").
    :type method: str
    :param subscr: The subscription information for the top-level object.
    :type subscr: dict
    :param analyst: The user adding the comment.
    :type analyst: str
    :returns: dict with keys:
              'success' (boolean),
              'message': (str),
              'html' (str) if successful.
    """

    comment = Comment()
    comment.comment = cleaned_data['comment']
    comment.parse_comment()
    comment.set_parent_object(obj_type, obj_id)
    if method == "reply":
        comment.set_parent_comment(cleaned_data['parent_date'],
                                   cleaned_data['parent_analyst'])
    comment.analyst = analyst
    comment.set_url_key(cleaned_data['url_key'])
    source = create_embedded_source(name=get_user_organization(analyst),
                                    analyst=analyst,
                                    needs_tlp=False)
    comment.source = [source]
    try:

        comment.save(username=analyst)
        # this is silly :( in the comment object the dates are still
        # accurate to .###### seconds, but in the database are only
        # accurate to .### seconds. This messes with the template's ability
        # to compare creation and edit times.
        comment.reload()
        comment.comment_to_html()
        html = render_to_string(
            'comments_row_widget.html', {
                'comment': comment,
                'user': {
                    'username': analyst
                },
                'subscription': subscr
            })
        message = "Comment added successfully!"
        result = {'success': True, 'html': html, 'message': message}
    except ValidationError, e:
        result = {'success': False, 'message': e}
Пример #4
0
def comment_add(cleaned_data, obj_type, obj_id, method, subscr, analyst):
    """
    Add a new comment.

    :param cleaned_data: Cleaned data from the Django form submission.
    :type cleaned_data: dict
    :param obj_type: The top-level object type to add the comment to.
    :type obj_type: str
    :param obj_id: The top-level ObjectId to add the comment to.
    :type obj_id: str
    :param method: If this is a reply or not (set method to "reply").
    :type method: str
    :param subscr: The subscription information for the top-level object.
    :type subscr: dict
    :param analyst: The user adding the comment.
    :type analyst: str
    :returns: dict with keys:
              'success' (boolean),
              'message': (str),
              'html' (str) if successful.
    """

    comment = Comment()
    comment.comment = cleaned_data['comment']
    comment.parse_comment()
    comment.set_parent_object(obj_type, obj_id)
    if method == "reply":
        comment.set_parent_comment(cleaned_data['parent_date'],
                                   cleaned_data['parent_analyst'])
    comment.analyst = analyst
    comment.set_url_key(cleaned_data['url_key'])
    source = create_embedded_source(name=get_user_organization(analyst),
                                    analyst=analyst, needs_tlp=False)
    comment.source = [source]
    try:

        comment.save(username=analyst)
        # this is silly :( in the comment object the dates are still
        # accurate to .###### seconds, but in the database are only
        # accurate to .### seconds. This messes with the template's ability
        # to compare creation and edit times.
        comment.reload()
        comment.comment_to_html()
        html = render_to_string('comments_row_widget.html',
                                {'comment': comment,
                                 'user': {'username': analyst},
                                 'subscription': subscr})
        message = "Comment added successfully!"
        result = {'success': True, 'html': html, 'message': message}
    except ValidationError, e:
        result = {'success': False, 'message': e}
Пример #5
0
def add_campaign(name,
                 description,
                 aliases,
                 analyst,
                 bucket_list=None,
                 ticket=None,
                 source=None,
                 id=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.
    :returns: dict with key 'success' (boolean) and 'message' (str).
    """

    # Verify the Campaign does not exist.
    campaign = Campaign.objects(name=name).first()
    if campaign:
        if campaign.check_message_received(id):
            return {'success': False, 'message': 'dup'}

        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)

    if source:
        source = create_embedded_source(name=source, analyst=analyst)
    else:
        source = create_embedded_source(name=get_user_organization(analyst),
                                        analyst=analyst)

    campaign.source = [source]

    # 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)

    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}
Пример #6
0
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
Пример #7
0
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
Пример #8
0
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
Пример #9
0
def add_new_domain(data,
                   request,
                   errors,
                   rowData=None,
                   is_validate_only=False,
                   cache={}):
    """
    Add a new domain to CRITs.

    :param data: The data about the domain.
    :type data: dict
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param errors: A list of current errors to append to.
    :type errors: list
    :param rowData: Any objects that need to be added to the domain.
    :type rowData: dict
    :param is_validate_only: Only validate the data and return any errors.
    :type is_validate_only: boolean
    :param cache: Cached data, typically for performance enhancements
                  during bulk operations.
    :type cache: dict
    :returns: tuple (<result>, <errors>, <retVal>)
    """

    result = False
    retVal = {}
    domain = data['domain']
    add_ip = data.get('add_ip')
    ip = data.get('ip')
    ip_type = data.get('ip_type')

    if add_ip:
        error = validate_and_normalize_ip(ip, ip_type)[1]
        if error:
            errors.append(error)

    if is_validate_only:
        error = get_valid_root_domain(domain)[2]
        if error:
            errors.append(error)

        # check for duplicate domains
        fqdn_domain = retrieve_domain(domain, cache)

        if fqdn_domain:
            if isinstance(fqdn_domain, Domain):
                resp_url = reverse('crits.domains.views.domain_detail',
                                   args=[domain])
                message = ('Warning: Domain already exists: '
                           '<a href="%s">%s</a>' % (resp_url, domain))
                retVal['message'] = message
                retVal['status'] = form_consts.Status.DUPLICATE
                retVal['warning'] = message
        else:
            result_cache = cache.get(form_consts.Domain.CACHED_RESULTS)
            result_cache[domain.lower()] = True

    elif not errors:
        username = request.user.username
        reference = data.get('domain_reference')
        source_name = data.get('domain_source')
        method = data.get('domain_method')
        source = [
            create_embedded_source(source_name,
                                   reference=reference,
                                   method=method,
                                   analyst=username)
        ]
        bucket_list = data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME)
        ticket = data.get(form_consts.Common.TICKET_VARIABLE_NAME)

        if data.get('campaign') and data.get('confidence'):
            campaign = [
                EmbeddedCampaign(name=data.get('campaign'),
                                 confidence=data.get('confidence'),
                                 analyst=username)
            ]
        else:
            campaign = []

        retVal = upsert_domain(domain,
                               source,
                               username,
                               campaign,
                               bucket_list=bucket_list,
                               ticket=ticket,
                               cache=cache)

        if not retVal['success']:
            errors.append(retVal.get('message'))
            retVal['message'] = ""

        else:
            new_domain = retVal['object']
            ip_result = {}
            if add_ip:
                if data.get('same_source'):
                    ip_source = source_name
                    ip_method = method
                    ip_reference = reference
                else:
                    ip_source = data.get('ip_source')
                    ip_method = data.get('ip_method')
                    ip_reference = data.get('ip_reference')
                from crits.ips.handlers import ip_add_update
                ip_result = ip_add_update(ip,
                                          ip_type,
                                          ip_source,
                                          ip_method,
                                          ip_reference,
                                          campaign=campaign,
                                          analyst=username,
                                          bucket_list=bucket_list,
                                          ticket=ticket,
                                          cache=cache)
                if not ip_result['success']:
                    errors.append(ip_result['message'])
                else:
                    #add a relationship with the new IP address
                    new_ip = ip_result['object']
                    if new_domain and new_ip:
                        new_domain.add_relationship(rel_item=new_ip,
                                                    rel_type='Resolved_To',
                                                    analyst=username,
                                                    get_rels=False)
                        new_domain.save(username=username)
                        new_ip.save(username=username)

            #set the URL for viewing the new data
            resp_url = reverse('crits.domains.views.domain_detail',
                               args=[domain])

            if retVal['is_domain_new'] == True:
                retVal['message'] = (
                    'Success! Click here to view the new domain: '
                    '<a href="%s">%s</a>' % (resp_url, domain))
            else:
                message = ('Updated existing domain: <a href="%s">%s</a>' %
                           (resp_url, domain))
                retVal['message'] = message
                retVal[form_consts.Status.
                       STATUS_FIELD] = form_consts.Status.DUPLICATE
                retVal['warning'] = message

            #add indicators
            if data.get('add_indicators'):
                from crits.indicators.handlers import create_indicator_from_tlo
                # If we have an IP object, add an indicator for that.
                if ip_result.get('success'):
                    ip = ip_result['object']
                    result = create_indicator_from_tlo('IP',
                                                       ip,
                                                       username,
                                                       ip_source,
                                                       add_domain=False)
                    ip_ind = result.get('indicator')
                    if not result['success']:
                        errors.append(result['message'])

                # Add an indicator for the domain.
                result = create_indicator_from_tlo('Domain',
                                                   new_domain,
                                                   username,
                                                   source_name,
                                                   add_domain=False)

                if not result['success']:
                    errors.append(result['message'])
                elif ip_result.get('success') and ip_ind:
                    forge_relationship(left_class=result['indicator'],
                                       right_class=ip_ind,
                                       rel_type='Resolved_To',
                                       analyst=username)
            result = True

    # This block validates, and may also add, objects to the Domain
    if retVal.get('success') or is_validate_only == True:
        if rowData:
            objectsData = rowData.get(form_consts.Common.OBJECTS_DATA)

            # add new objects if they exist
            if objectsData:
                objectsData = json.loads(objectsData)
                current_domain = retrieve_domain(domain, cache)
                for object_row_counter, objectData in enumerate(
                        objectsData, 1):
                    if current_domain != None:
                        # if the domain exists then try to add objects to it
                        if isinstance(current_domain, Domain) == True:
                            objectDict = object_array_to_dict(
                                objectData, "Domain", current_domain.id)
                        else:
                            objectDict = object_array_to_dict(
                                objectData, "Domain", "")
                            current_domain = None
                    else:
                        objectDict = object_array_to_dict(
                            objectData, "Domain", "")

                    (obj_result, errors,
                     obj_retVal) = validate_and_add_new_handler_object(
                         None,
                         objectDict,
                         request,
                         errors,
                         object_row_counter,
                         is_validate_only=is_validate_only,
                         cache=cache,
                         obj=current_domain)
                    if not obj_result:
                        retVal['success'] = False

    return result, errors, retVal
Пример #10
0
def add_screenshot(description, tags, source, method, reference, analyst,
                   screenshot, screenshot_ids, oid, otype):
    """
    Add a screenshot or screenshots to a top-level object.

    :param description: The description of the screenshot.
    :type description: str
    :param tags: Tags associated with this screenshot.
    :type tags: str, list
    :param source: The source who provided the screenshot.
    :type source_name: str,
                :class:`crits.core.crits_mongoengine.EmbeddedSource`,
                list of :class:`crits.core.crits_mongoengine.EmbeddedSource`
    :param method: The method of acquiring this screenshot.
    :type method: str
    :param reference: A reference to the source of this screenshot.
    :type reference: str
    :param analyst: The user adding the screenshot.
    :type analyst: str
    :param screenshot: The screenshot to add.
    :type screenshot: file handle
    :param screenshot_ids: A list of ObjectIds of existing screenshots to add.
    :type screenshot_ids: str, list
    :param oid: The ObjectId of the top-level object to add to.
    :type oid: str
    :param otype: The top-level object type.
    :type otype: str
    :returns: dict with keys:
              'success' (boolean),
              'message' (str),
              'id' (str) if successful,
              'html' (str) if successful,
    """

    result = {'success': False}
    if not source:
        result['message'] = "Must provide a source"
        return result
    obj = class_from_id(otype, oid)
    if not obj:
        result['message'] = "Could not find the top-level object."
        return result

    final_screenshots = []

    if screenshot_ids:
        if not isinstance(screenshot_ids, list):
            screenshot_list = screenshot_ids.split(',')
        else:
            screenshot_list = screenshot_ids
        for screenshot_id in screenshot_list:
            screenshot_id = screenshot_id.strip().lower()
            s = Screenshot.objects(id=screenshot_id).first()
            if s:
                if isinstance(source, basestring) and len(source) > 0:
                    s_embed = create_embedded_source(source,
                                                     method=method,
                                                     reference=reference,
                                                     analyst=analyst)
                    s.add_source(s_embed)
                elif isinstance(source, EmbeddedSource):
                    s.add_source(source, method=method, reference=reference)
                elif isinstance(source, list) and len(source) > 0:
                    for x in source:
                        if isinstance(x, EmbeddedSource):
                            s.add_source(x, method=method, reference=reference)

                s.add_tags(tags)
                s.save()
                obj.screenshots.append(screenshot_id)
                obj.save()
                final_screenshots.append(s)
    else:
        md5 = hashlib.md5(screenshot.read()).hexdigest()
        check = Screenshot.objects(md5=md5).first()
        if check:
            s = check
            s.add_tags(tags)
        else:
            s = Screenshot()
            s.analyst = analyst
            s.description = description
            s.md5 = md5
            screenshot.seek(0)
            s.add_screenshot(screenshot, tags)
        if isinstance(source, basestring) and len(source) > 0:
            s_embed = create_embedded_source(source,
                                             method=method,
                                             reference=reference,
                                             analyst=analyst)
            s.add_source(s_embed)
        elif isinstance(source, EmbeddedSource):
            s.add_source(source, method=method, reference=reference)
        elif isinstance(source, list) and len(source) > 0:
            for x in source:
                if isinstance(x, EmbeddedSource):
                    s.add_source(x, method=method, reference=reference)

        if not s.screenshot and not s.thumb:
            result[
                'message'] = "Problem adding screenshot to GridFS. No screenshot uploaded."
            return result
        try:
            s.save(username=analyst)
            final_screenshots.append(s)
        except Exception, e:
            result['message'] = str(e)
            return result
        obj.screenshots.append(str(s.id))
        obj.save(username=analyst)
Пример #11
0
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):
    """
    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
    :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)

    actor.save(username=analyst)

    # 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
Пример #12
0
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.
    :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 not relationship:
            relationship = "Related_To"
        pcap.add_relationship(rel_item=related_obj,
                              rel_type=relationship,
                              analyst=user,
                              get_rels=False)
        related_obj.save(username=user)
        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
Пример #13
0
def add_screenshot(description, tags, source, method, reference, tlp, analyst,
                   screenshot, screenshot_ids, oid, otype):
    """
    Add a screenshot or screenshots to a top-level object.

    :param description: The description of the screenshot.
    :type description: str
    :param tags: Tags associated with this screenshot.
    :type tags: str, list
    :param source: The source who provided the screenshot.
    :type source_name: str,
                :class:`crits.core.crits_mongoengine.EmbeddedSource`,
                list of :class:`crits.core.crits_mongoengine.EmbeddedSource`
    :param method: The method of acquiring this screenshot.
    :type method: str
    :param reference: A reference to the source of this screenshot.
    :type reference: str
    :param tlp: The TLP Sharing of this screenshot.
    :type tlp: str
    :param analyst: The user adding the screenshot.
    :type analyst: str
    :param screenshot: The screenshot to add.
    :type screenshot: file handle
    :param screenshot_ids: A list of ObjectIds of existing screenshots to add.
    :type screenshot_ids: str, list
    :param oid: The ObjectId of the top-level object to add to.
    :type oid: str
    :param otype: The top-level object type.
    :type otype: str
    :returns: dict with keys:
              'success' (boolean),
              'message' (str),
              'id' (str) if successful,
              'html' (str) if successful,
    """

    result = {'success': False}
    if not source:
        result['message'] = "Must provide a source"
        return result
    obj = class_from_id(otype, oid)
    if not obj:
        result['message'] = "Could not find the top-level object."
        return result

    final_screenshots = []

    if screenshot_ids:
        if not isinstance(screenshot_ids, list):
            screenshot_list = screenshot_ids.split(',')
        else:
            screenshot_list = screenshot_ids
        for screenshot_id in screenshot_list:
            screenshot_id = screenshot_id.strip().lower()
            s = Screenshot.objects(id=screenshot_id).first()
            if s:
                if isinstance(source, basestring) and len(source) > 0:
                    s_embed = create_embedded_source(source, method=method,
                                                    reference=reference,
                                                    analyst=analyst,
                                                     tlp=tlp)
                    s.add_source(s_embed)
                elif isinstance(source, EmbeddedSource):
                    s.add_source(source=source, method=method,
                                 reference=reference, analyst=analyst, tlp=tlp)
                elif isinstance(source, list) and len(source) > 0:
                    for x in source:
                        if isinstance(x, EmbeddedSource):
                            s.add_source(x, method=method, reference=reference,
                                         analyst=analyst, tlp=tlp)
                s.add_tags(tags)
                s.save()
                obj.screenshots.append(screenshot_id)
                obj.save()
                final_screenshots.append(s)
    else:
        md5 = hashlib.md5(screenshot.read()).hexdigest()
        check = Screenshot.objects(md5=md5).first()
        if check:
            s = check
            s.add_tags(tags)
        else:
            s = Screenshot()
            s.analyst = analyst
            s.description = description
            s.md5 = md5
            screenshot.seek(0)
            s.add_screenshot(screenshot, tags)
        if isinstance(source, basestring) and len(source) > 0:
            s_embed = create_embedded_source(source, method=method,
                                             reference=reference,
                                            analyst=analyst,
                                             tlp=tlp)
            s.add_source(s_embed)
        elif isinstance(source, EmbeddedSource):
            s.add_source(source, method=method, reference=reference,
                         analyst=analyst, tlp=tlp)
        elif isinstance(source, list) and len(source) > 0:
            for x in source:
                if isinstance(x, EmbeddedSource):
                    s.add_source(x, method=method, reference=reference,
                                 analyst=analyst, tlp=tlp)
        if not s.screenshot and not s.thumb:
            result['message'] = "Problem adding screenshot to GridFS. No screenshot uploaded."
            return result
        try:
            s.save(username=analyst)
            final_screenshots.append(s)
        except Exception, e:
            result['message'] = str(e)
            return result
        obj.screenshots.append(str(s.id))
        obj.save(username=analyst)
Пример #14
0
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}
Пример #15
0
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
Пример #16
0
def add_new_domain(data, request, errors, rowData=None, is_validate_only=False, cache={}):
    """
    Add a new domain to CRITs.

    :param data: The data about the domain.
    :type data: dict
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param errors: A list of current errors to append to.
    :type errors: list
    :param rowData: Any objects that need to be added to the domain.
    :type rowData: dict
    :param is_validate_only: Only validate the data and return any errors.
    :type is_validate_only: boolean
    :param cache: Cached data, typically for performance enhancements
                  during bulk uperations.
    :type cache: dict
    :returns: tuple
    """

    username = request.user.username
    result = False
    retVal = {}
    reference = data.get('domain_reference')
    name = data.get('domain_source')
    method = data.get('domain_method')
    source = [create_embedded_source(name, reference=reference, method=method,
                                     analyst=username)]
    bucket_list = data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME)
    ticket = data.get(form_consts.Common.TICKET_VARIABLE_NAME)

    if data.get('campaign') and data.get('confidence'):
        campaign = [EmbeddedCampaign(name=data.get('campaign'),
                                     confidence=data.get('confidence'),
                                     analyst=username)]
    else:
        campaign = []

    (sdomain, fqdn) = get_domain(data['domain'])
    if sdomain == "no_tld_found_error":
        errors.append(u"Error: Invalid domain: " + data['domain'])
    elif is_validate_only == False:
        retVal = upsert_domain(sdomain, fqdn, source, username, campaign,
                               bucket_list=bucket_list, ticket=ticket, cache=cache)
        ip_result = None

        if retVal['success']:
            add_ip = data.get('add_ip')
            if add_ip:
                ip = data.get('ip')
                if data.get('same_source'):
                    ip_source = data.get('domain_source')
                    ip_method = data.get('domain_method')
                    ip_reference = reference
                else:
                    ip_source = data.get('ip_source')
                    ip_method = data.get('ip_method')
                    ip_reference = data.get('ip_reference')
                from crits.ips.handlers import ip_add_update
                ip_result = ip_add_update(ip,
                                          None,
                                          ip_source,
                                          ip_method,
                                          ip_reference,
                                          campaign=campaign,
                                          analyst=username,
                                          bucket_list=bucket_list,
                                          ticket=ticket,
                                          cache=cache)
                if not ip_result['success']:
                    errors.append(ip_result['message'])
                else:
                    #add a relationship with the new IP address
                    new_domain = retVal['object']
                    new_ip = ip_result['object']
                    if new_domain and new_ip:
                        new_domain.add_relationship(rel_item=new_ip,
                                                    rel_type='Resolved_To',
                                                    analyst=username,
                                                    get_rels=False)
                        new_domain.save(username=username)
                        new_ip.save(username=username)

            #set the URL for viewing the new data
            resp_url = reverse('crits.domains.views.domain_detail', args=[fqdn])

            if retVal['is_domain_new'] == True:
                retVal['message'] = ('Success! Click here to view the new domain: '
                                     '<a href="%s">%s</a>' % (resp_url, fqdn))
            else:
                message = ('Updated existing domain: <a href="%s">%s</a>' % (resp_url, fqdn))
                retVal['message'] = message
                retVal[form_consts.Status.STATUS_FIELD] = form_consts.Status.DUPLICATE
                retVal['warning'] = message

            #add indicators
            # add_indicators_for_domain handles adding relationships as well
            if data.get('add_indicators'):
                analyst = username
                from crits.indicators.handlers import add_indicators_for_domain
                if ip_result and ip_result['success']:
                    obj = ip_result['object']
                    errors += add_indicators_for_domain(sdomain,
                                                        fqdn,
                                                        source,
                                                        analyst,
                                                        reference,
                                                        obj,
                                                        bucket_list=bucket_list,
                                                        ticket=ticket)['errors']
                else:
                    errors += add_indicators_for_domain(sdomain,
                                                        fqdn,
                                                        source,
                                                        analyst,
                                                        reference,
                                                        bucket_list=bucket_list,
                                                        ticket=ticket)['errors']
            result = True

        elif 'message' in retVal: #database error? (!c_dom)
            errors.append(retVal['message']) #u"Unknown error: unable to add domain")

    elif is_validate_only == True:
        domain = data['domain']
        fqdn_domain = retrieve_domain(domain, cache);

        if fqdn_domain:
            if isinstance(fqdn_domain, Domain):
                resp_url = reverse('crits.domains.views.domain_detail', args=[fqdn])
                message = ('Warning: Domain already exists: '
                                     '<a href="%s">%s</a>' % (resp_url, fqdn))
                retVal['message'] = message;
                retVal['status'] = form_consts.Status.DUPLICATE;
                retVal['warning'] = message;
        else:
            result_cache = cache.get(form_consts.Domain.CACHED_RESULTS);
            result_cache[domain.lower()] = True;

    # This block tries to add objects to the item
    if retVal.get('success') or is_validate_only == True:
        if rowData:
            objectsData = rowData.get(form_consts.Common.OBJECTS_DATA)

            # add new objects if they exist
            if objectsData:
                objectsData = json.loads(objectsData)
                object_row_counter = 1
                current_domain = retrieve_domain(fqdn, cache)
                for objectData in objectsData:
                    if current_domain != None:
                        # if the domain exists then try to add objects to it
                        if isinstance(current_domain, Domain) == True:
                            objectDict = object_array_to_dict(objectData, "Domain", current_domain.id)
                        else:
                            objectDict = object_array_to_dict(objectData, "Domain", "")
                            current_domain = None;
                    else:
                        objectDict = object_array_to_dict(objectData, "Domain", "")

                    (object_result, object_errors, object_retVal) = validate_and_add_new_handler_object(
                            None, objectDict, request, errors, object_row_counter,
                            is_validate_only=is_validate_only,
                            cache=cache, obj=current_domain)

                    if object_retVal.get('success') == False:
                        retVal['success'] = False
                    if object_retVal.get('message'):
                        errors.append(object_retVal['message'])

                    object_row_counter += 1

    return result, errors, retVal
Пример #17
0
def handle_cert_file(filename,
                     data,
                     source_name,
                     user=None,
                     description=None,
                     related_id=None,
                     related_md5=None,
                     related_type=None,
                     method=None,
                     relationship=None,
                     bucket_list=None,
                     ticket=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_id: ObjectId of a top-level object related to this Certificate.
    :type related_id: 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 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.
    :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

    # 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='',
                                   analyst=user)
        cert.add_source(s)
    elif isinstance(source_name, EmbeddedSource):
        cert.add_source(source_name)
    elif isinstance(source_name, list) and len(source_name) > 0:
        for s in source_name:
            if isinstance(s, EmbeddedSource):
                cert.add_source(s)

    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(cert.analysis) < 1 and data:
        run_triage(data, cert, user)

    # update relationship if a related top-level object is supplied
    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 related_obj and cert:
            if not relationship:
                relationship = "Related_To"
            cert.add_relationship(rel_item=related_obj,
                                  rel_type=relationship,
                                  analyst=user,
                                  get_rels=False)
            related_obj.save(username=user)
            cert.save(username=user)

    status = {
        'success': True,
        'message': 'Uploaded certificate',
        'md5': md5,
    }

    return status
Пример #18
0
def handle_pcap_file(
    filename,
    data,
    source_name,
    user=None,
    description=None,
    related_id=None,
    related_md5=None,
    related_type=None,
    method=None,
    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 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.
    :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 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="", analyst=user)
        pcap.add_source(s)
    elif isinstance(source_name, EmbeddedSource):
        pcap.add_source(source_name)
    elif isinstance(source_name, list) and len(source_name) > 0:
        for s in source_name:
            if isinstance(s, EmbeddedSource):
                pcap.add_source(s)

    # 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 not relationship:
            relationship = "Related_To"
        pcap.add_relationship(rel_item=related_obj, rel_type=relationship, analyst=user, get_rels=False)
        related_obj.save(username=user)
        pcap.save(username=user)

    # run pcap triage
    if is_pcap_new and data:
        pcap.reload()
        run_triage(data, pcap, user)

    status = {"success": True, "message": "Uploaded pcap", "md5": md5, "id": str(pcap.id)}

    return status
Пример #19
0
def add_new_actor(name, aliases=None, description=None, source=None,
                  source_method='', source_reference='', 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 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 source_tlp: The TLP for this Actor.
    :type source_tlp: 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 user: The user adding this actor.
    :type user: :class:`crits.core.user.CRITsUser`
    :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`
    """

    username = user.username
    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):
        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)}

    if isinstance(campaign, basestring):
        c = EmbeddedCampaign(name=campaign,
                             confidence=confidence,
                             analyst=username)
        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, username)

    if ticket:
        actor.add_ticket(ticket, username)

    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=username)

    if related_obj and actor:
            relationship_type=RelationshipTypes.inverse(relationship=relationship_type)
            actor.add_relationship(related_obj,
                                  relationship_type,
                                  analyst=username,
                                  get_rels=False)
            actor.save(username=username)
            actor.reload()

    # run actor triage
    if is_item_new:
        actor.reload()
        run_triage(actor, user)

    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
Пример #20
0
def add_new_domain(data, request, errors, rowData=None, is_validate_only=False, cache={}):
    """
    Add a new domain to CRITs.

    :param data: The data about the domain.
    :type data: dict
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param errors: A list of current errors to append to.
    :type errors: list
    :param rowData: Any objects that need to be added to the domain.
    :type rowData: dict
    :param is_validate_only: Only validate the data and return any errors.
    :type is_validate_only: boolean
    :param cache: Cached data, typically for performance enhancements
                  during bulk operations.
    :type cache: dict
    :returns: tuple (<result>, <errors>, <retVal>)
    """

    result = False
    retVal = {}
    domain = data['domain']
    add_ip = data.get('add_ip')
    ip = data.get('ip')
    ip_type = data.get('ip_type')

    if add_ip:
        error = validate_and_normalize_ip(ip, ip_type)[1]
        if error:
             errors.append(error)

    if is_validate_only:
        error = get_valid_root_domain(domain)[2]
        if error:
            errors.append(error)

        # check for duplicate domains
        fqdn_domain = retrieve_domain(domain, cache)

        if fqdn_domain:
            if isinstance(fqdn_domain, Domain):
                resp_url = reverse('crits.domains.views.domain_detail', args=[domain])
                message = ('Warning: Domain already exists: '
                                     '<a href="%s">%s</a>' % (resp_url, domain))
                retVal['message'] = message
                retVal['status'] = form_consts.Status.DUPLICATE
                retVal['warning'] = message
        else:
            result_cache = cache.get(form_consts.Domain.CACHED_RESULTS);
            result_cache[domain.lower()] = True

    elif not errors:
        username = request.user.username
        reference = data.get('domain_reference')
        source_name = data.get('domain_source')
        method = data.get('domain_method')
        source = [create_embedded_source(source_name, reference=reference,
                                         method=method, analyst=username)]
        bucket_list = data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME)
        ticket = data.get(form_consts.Common.TICKET_VARIABLE_NAME)

        if data.get('campaign') and data.get('confidence'):
            campaign = [EmbeddedCampaign(name=data.get('campaign'),
                                         confidence=data.get('confidence'),
                                         analyst=username)]
        else:
            campaign = []

        retVal = upsert_domain(domain, source, username, campaign,
                               bucket_list=bucket_list, ticket=ticket, cache=cache)

        if not retVal['success']:
            errors.append(retVal.get('message'))
            retVal['message'] = ""

        else:
            new_domain = retVal['object']
            ip_result = {}
            if add_ip:
                if data.get('same_source'):
                    ip_source = source_name
                    ip_method = method
                    ip_reference = reference
                else:
                    ip_source = data.get('ip_source')
                    ip_method = data.get('ip_method')
                    ip_reference = data.get('ip_reference')
                from crits.ips.handlers import ip_add_update
                ip_result = ip_add_update(ip,
                                          ip_type,
                                          ip_source,
                                          ip_method,
                                          ip_reference,
                                          campaign=campaign,
                                          analyst=username,
                                          bucket_list=bucket_list,
                                          ticket=ticket,
                                          cache=cache)
                if not ip_result['success']:
                    errors.append(ip_result['message'])
                else:
                    #add a relationship with the new IP address
                    new_ip = ip_result['object']
                    if new_domain and new_ip:
                        new_domain.add_relationship(new_ip,
                                                    'Resolved_To',
                                                    analyst=username,
                                                    get_rels=False)
                        new_domain.save(username=username)

            #set the URL for viewing the new data
            resp_url = reverse('crits.domains.views.domain_detail', args=[domain])

            if retVal['is_domain_new'] == True:
                retVal['message'] = ('Success! Click here to view the new domain: '
                                     '<a href="%s">%s</a>' % (resp_url, domain))
            else:
                message = ('Updated existing domain: <a href="%s">%s</a>' % (resp_url, domain))
                retVal['message'] = message
                retVal[form_consts.Status.STATUS_FIELD] = form_consts.Status.DUPLICATE
                retVal['warning'] = message

            #add indicators
            if data.get('add_indicators'):
                from crits.indicators.handlers import create_indicator_from_tlo
                # If we have an IP object, add an indicator for that.
                if ip_result.get('success'):
                    ip = ip_result['object']
                    result = create_indicator_from_tlo('IP',
                                                       ip,
                                                       username,
                                                       ip_source,
                                                       add_domain=False)
                    ip_ind = result.get('indicator')
                    if not result['success']:
                        errors.append(result['message'])

                # Add an indicator for the domain.
                result = create_indicator_from_tlo('Domain',
                                                   new_domain,
                                                   username,
                                                   source_name,
                                                   add_domain=False)

                if not result['success']:
                    errors.append(result['message'])
                elif ip_result.get('success') and ip_ind:
                    forge_relationship(left_class=result['indicator'],
                                       right_class=ip_ind,
                                       rel_type='Resolved_To',
                                       analyst=username)
            result = True

    # This block validates, and may also add, objects to the Domain
    if retVal.get('success') or is_validate_only == True:
        if rowData:
            objectsData = rowData.get(form_consts.Common.OBJECTS_DATA)

            # add new objects if they exist
            if objectsData:
                objectsData = json.loads(objectsData)
                current_domain = retrieve_domain(domain, cache)
                for object_row_counter, objectData in enumerate(objectsData, 1):
                    if current_domain != None:
                        # if the domain exists then try to add objects to it
                        if isinstance(current_domain, Domain) == True:
                            objectDict = object_array_to_dict(objectData,
                                                              "Domain",
                                                              current_domain.id)
                        else:
                            objectDict = object_array_to_dict(objectData,
                                                              "Domain",
                                                              "")
                            current_domain = None;
                    else:
                        objectDict = object_array_to_dict(objectData,
                                                          "Domain",
                                                          "")

                    (obj_result,
                     errors,
                     obj_retVal) = validate_and_add_new_handler_object(
                        None, objectDict, request, errors, object_row_counter,
                        is_validate_only=is_validate_only,
                        cache=cache, obj=current_domain)
                    if not obj_result:
                        retVal['success'] = False

    return result, errors, retVal
Пример #21
0
def ip_add_update(ip_address, ip_type, source=None, source_method=None,
                  source_reference=None, campaign=None, confidence='low', analyst=None,
                  is_add_indicator=False, indicator_reference=None,
                  bucket_list=None, ticket=None, is_validate_only=False, cache={}):
    """
    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
    :returns: dict with keys:
              "success" (boolean),
              "message" (str),
              "object" (if successful) :class:`crits.ips.ip.IP`
    """

    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)

    if bucket_list:
        ip_object.add_bucket_list(bucket_list, analyst)

    if ticket:
        ip_object.add_ticket(ticket, analyst)

    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,
                             indicator_reference,
                             ip_type,
                             analyst,
                             source_method,
                             add_domain=False,
                             add_relationship=True,
                             bucket_list=bucket_list,
                             ticket=ticket,
                             cache=cache)

    # run ip triage
    if is_item_new and is_validate_only == False:
        ip_object.reload()
        run_triage(None, ip_object, analyst)

    retVal['success'] = True
    retVal['object'] = ip_object

    return retVal
Пример #22
0
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
Пример #23
0
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):
    """
    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.
    :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);


    # save signature
    signature.save(username=user)
    signature.reload()

    status = {
        'success':      True,
        'message':      'Uploaded signature',
        '_id':          signature.id,
        'object':       signature
    }

    return status
Пример #24
0
def handle_cert_file(filename, data, source_name, user=None,
                     description=None, related_id=None, related_md5=None,
                     related_type=None, method=None, relationship=None,
                     bucket_list=None, ticket=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_id: ObjectId of a top-level object related to this Certificate.
    :type related_id: 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 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.
    :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='',
                                   analyst=user)
        cert.add_source(s)
    elif isinstance(source_name, EmbeddedSource):
        cert.add_source(source_name)
    elif isinstance(source_name, list) and len(source_name) > 0:
        for s in source_name:
            if isinstance(s, EmbeddedSource):
                cert.add_source(s)

    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(cert.analysis) < 1 and data:
        run_triage(cert, user)

    # update relationship if a related top-level object is supplied
    if related_obj and cert:
        if not relationship:
            relationship = "Related_To"
        cert.add_relationship(rel_item=related_obj,
                              rel_type=relationship,
                              analyst=user,
                              get_rels=False)
        related_obj.save(username=user)
        cert.save(username=user)

    status = {
        'success':      True,
        'message':      'Uploaded certificate',
        'md5':          md5,
        'id':           str(cert.id)
    }

    return status
Пример #25
0
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
Пример #26
0
def add_new_event(title, description, event_type, source, method, reference,
                  date, analyst, bucket_list=None, ticket=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
    :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)

    try:
        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)}
    except ValidationError, e:
        result = {'success': False,
                  'message': e}
Пример #27
0
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}
Пример #28
0
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=None, copy_rels=False,
                         bucket_list=None, ticket=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 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.
    :returns: dict with keys:
              'success' (boolean),
              'message' (str),
              'md5' (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

    rdt = RawDataType.objects(name=data_type).first()
    if not rdt:
        status = {
            'success':   False,
            'message':  'Invalid data type passed in'
        }
        return status

    data = data.encode('utf-8')

    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()

    # create source
    source = create_embedded_source(source_name,
                                    date=timestamp,
                                    reference='',
                                    method=method,
                                    analyst=user)

    # generate raw_data
    is_rawdata_new = False
    raw_data = RawData.objects(md5=md5).first()
    if raw_data:
        raw_data.add_source(source)
    else:
        raw_data = RawData()
        raw_data.created = timestamp
        raw_data.description = description
        raw_data.md5 = md5
        raw_data.source = [source]
        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
    #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:
                        raw_data.add_relationship(rel_id=rel.object_id,
                                                  type_=rel.rel_type,
                                                  rel_type=rel.relationship,
                                                  rel_date=rel.relationship_date,
                                                  analyst=user)


    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);

    # save raw_data
    raw_data.save(username=user)

    # 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,
    }

    return status
Пример #29
0
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):
    """
    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
    :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)

    actor.save(username=analyst)

    # 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
Пример #30
0
def add_new_event(title,
                  description,
                  event_type,
                  source,
                  method,
                  reference,
                  date,
                  analyst,
                  bucket_list=None,
                  ticket=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
    :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)

    try:
        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}
Пример #31
0
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
Пример #32
0
def add_new_domain(data,
                   request,
                   errors,
                   rowData=None,
                   is_validate_only=False,
                   cache={}):
    """
    Add a new domain to CRITs.

    :param data: The data about the domain.
    :type data: dict
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param errors: A list of current errors to append to.
    :type errors: list
    :param rowData: Any objects that need to be added to the domain.
    :type rowData: dict
    :param is_validate_only: Only validate the data and return any errors.
    :type is_validate_only: boolean
    :param cache: Cached data, typically for performance enhancements
                  during bulk uperations.
    :type cache: dict
    :returns: tuple
    """

    username = request.user.username
    result = False
    retVal = {}
    reference = data.get('domain_reference')
    name = data.get('domain_source')
    method = data.get('domain_method')
    source = [
        create_embedded_source(name,
                               reference=reference,
                               method=method,
                               analyst=username)
    ]
    bucket_list = data.get(form_consts.Common.BUCKET_LIST_VARIABLE_NAME)
    ticket = data.get(form_consts.Common.TICKET_VARIABLE_NAME)

    if data.get('campaign') and data.get('confidence'):
        campaign = [
            EmbeddedCampaign(name=data.get('campaign'),
                             confidence=data.get('confidence'),
                             analyst=username)
        ]
    else:
        campaign = []

    (sdomain, fqdn) = get_domain(data['domain'])
    if sdomain == "no_tld_found_error":
        errors.append(u"Error: Invalid domain: " + data['domain'])
    elif is_validate_only == False:
        retVal = upsert_domain(sdomain,
                               fqdn,
                               source,
                               username,
                               campaign,
                               bucket_list=bucket_list,
                               ticket=ticket,
                               cache=cache)
        ip_result = None

        if retVal['success']:
            new_domain = retVal['object']
            add_ip = data.get('add_ip')
            if add_ip:
                ip = data.get('ip')
                ip_type = data.get('ip_type')
                if data.get('same_source'):
                    ip_source = data.get('domain_source')
                    ip_method = data.get('domain_method')
                    ip_reference = reference
                else:
                    ip_source = data.get('ip_source')
                    ip_method = data.get('ip_method')
                    ip_reference = data.get('ip_reference')
                from crits.ips.handlers import ip_add_update
                ip_result = ip_add_update(ip,
                                          ip_type,
                                          ip_source,
                                          ip_method,
                                          ip_reference,
                                          campaign=campaign,
                                          analyst=username,
                                          bucket_list=bucket_list,
                                          ticket=ticket,
                                          cache=cache)
                if not ip_result['success']:
                    errors.append(ip_result['message'])
                else:
                    #add a relationship with the new IP address
                    new_ip = ip_result['object']
                    if new_domain and new_ip:
                        new_domain.add_relationship(rel_item=new_ip,
                                                    rel_type='Resolved_To',
                                                    analyst=username,
                                                    get_rels=False)
                        new_domain.save(username=username)
                        new_ip.save(username=username)

            #set the URL for viewing the new data
            resp_url = reverse('crits.domains.views.domain_detail',
                               args=[fqdn])

            if retVal['is_domain_new'] == True:
                retVal['message'] = (
                    'Success! Click here to view the new domain: '
                    '<a href="%s">%s</a>' % (resp_url, fqdn))
            else:
                message = ('Updated existing domain: <a href="%s">%s</a>' %
                           (resp_url, fqdn))
                retVal['message'] = message
                retVal[form_consts.Status.
                       STATUS_FIELD] = form_consts.Status.DUPLICATE
                retVal['warning'] = message

            #add indicators
            if data.get('add_indicators'):
                from crits.indicators.handlers import create_indicator_from_obj
                # If we have an IP object, add an indicator for that.
                if ip_result and ip_result['success']:
                    obj = ip_result['object']
                    result = create_indicator_from_obj('Address - ipv4-addr',
                                                       'IP', obj.id, obj.ip,
                                                       username)
                    if result['success'] == False:
                        errors.append(result['message'])

                # Add an indicator for the domain.
                result = create_indicator_from_obj('URI - Domain Name',
                                                   'Domain', new_domain.id,
                                                   sdomain, username)
                if result['success'] == False:
                    errors.append(result['message'])
                # If we have an FQDN (ie: it is not the same as sdomain)
                # then add that also.
                if fqdn != sdomain:
                    result = create_indicator_from_obj('URI - Domain Name',
                                                       'Domain', new_domain.id,
                                                       fqdn, username)
                    if result['success'] == False:
                        errors.append(result['message'])
            result = True

        elif 'message' in retVal:  #database error? (!c_dom)
            errors.append(
                retVal['message'])  #u"Unknown error: unable to add domain")

    elif is_validate_only == True:
        domain = data['domain']
        fqdn_domain = retrieve_domain(domain, cache)

        if fqdn_domain:
            if isinstance(fqdn_domain, Domain):
                resp_url = reverse('crits.domains.views.domain_detail',
                                   args=[fqdn])
                message = ('Warning: Domain already exists: '
                           '<a href="%s">%s</a>' % (resp_url, fqdn))
                retVal['message'] = message
                retVal['status'] = form_consts.Status.DUPLICATE
                retVal['warning'] = message
        else:
            result_cache = cache.get(form_consts.Domain.CACHED_RESULTS)
            result_cache[domain.lower()] = True

    # This block tries to add objects to the item
    if retVal.get('success') or is_validate_only == True:
        if rowData:
            objectsData = rowData.get(form_consts.Common.OBJECTS_DATA)

            # add new objects if they exist
            if objectsData:
                objectsData = json.loads(objectsData)
                current_domain = retrieve_domain(fqdn, cache)
                for object_row_counter, objectData in enumerate(
                        objectsData, 1):
                    if current_domain != None:
                        # if the domain exists then try to add objects to it
                        if isinstance(current_domain, Domain) == True:
                            objectDict = object_array_to_dict(
                                objectData, "Domain", current_domain.id)
                        else:
                            objectDict = object_array_to_dict(
                                objectData, "Domain", "")
                            current_domain = None
                    else:
                        objectDict = object_array_to_dict(
                            objectData, "Domain", "")

                    (object_result, object_errors,
                     object_retVal) = validate_and_add_new_handler_object(
                         None,
                         objectDict,
                         request,
                         errors,
                         object_row_counter,
                         is_validate_only=is_validate_only,
                         cache=cache,
                         obj=current_domain)

                    if object_retVal.get('success') == False:
                        retVal['success'] = False
                    if object_retVal.get('message'):
                        errors.append(object_retVal['message'])

    return result, errors, retVal
Пример #33
0
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):
    """
    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
    :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)

    # 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
Пример #34
0
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
Пример #35
0
def add_new_exploit(name, cve=None, description=None, source=None,
                    source_method=None, source_reference=None, campaign=None,
                    confidence=None, user=None, bucket_list=None,
                    ticket=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 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
    :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

    if isinstance(source, basestring):
        source = [create_embedded_source(source,
                                         reference=source_reference,
                                         method=source_method,
                                         analyst=user)]
    elif isinstance(source, EmbeddedSource):
        source = [source]

    if isinstance(campaign, basestring):
        c = EmbeddedCampaign(name=campaign, confidence=confidence, analyst=user)
        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)

    exploit.save(username=user)

    # run exploit triage
    if is_item_new:
        exploit.reload()
        run_triage(exploit, user)

    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