Exemple #1
0
def get_signature(sid, rev, **kwargs):
    """
    Get the detail of a signature based of its ID and revision
    
    Variables:
    sid    =>     Signature ID
    rev    =>     Signature revision number
    
    Arguments: 
    None
    
    Data Block:
    None
     
    Result example:
    {"name": "sig_name",          # Signature name    
     "tags": ["PECheck"],         # Signature tags
     "comments": [""],            # Signature comments lines
     "meta": {                    # Meta fields ( **kwargs )
       "id": "SID",                 # Mandatory ID field
       "rule_version": 1 },         # Mandatory Revision field
     "type": "rule",              # Rule type (rule, private rule ...)
     "strings": ['$ = "a"'],      # Rule string section (LIST)
     "condition": ["1 of them"]}  # Rule condition section (LIST)    
    """
    user = kwargs['user']
    data = STORAGE.get_signature("%sr.%s" % (sid, rev))
    if data:
        if not Classification.is_accessible(user['classification'],
                                            data['meta'].get('classification',
                                                             Classification.UNRESTRICTED)):
            return make_api_response("", "Your are not allowed to view this signature.", 403)
        return make_api_response(data)
    else:
        return make_api_response("", "Signature not found. (%s r.%s)" % (sid, rev), 404)
Exemple #2
0
def signature_detail(**kwargs):
    user = kwargs['user']
    sid = angular_safe(request.args.get("sid", None))
    rev = angular_safe(request.args.get("rev", None))

    if not sid or not rev:
        abort(404)

    data = STORAGE.get_signature("%sr.%s" % (sid, rev))

    if not data:
        abort(404)

    if not Classification.is_accessible(
            user['classification'], data['meta'].get(
                'classification', Classification.UNRESTRICTED)):
        abort(403)

    return custom_render("signature_detail.html",
                         sid=sid,
                         rev=rev,
                         organisation=ORGANISATION,
                         **kwargs)
Exemple #3
0
def set_signature(sid, rev, **kwargs):
    """
    [INCOMPLETE]
       - CHECK IF SIGNATURE NAME ALREADY EXISTS
    Update a signature defined by a sid and a rev.
       NOTE: The API will compare they old signature
             with the new one and will make the decision
             to increment the revision number or not. 
    
    Variables:
    sid    =>     Signature ID
    rev    =>     Signature revision number
    
    Arguments: 
    None
    
    Data Block (REQUIRED): # Signature block
    {"name": "sig_name",          # Signature name    
     "tags": ["PECheck"],         # Signature tags
     "comments": [""],            # Signature comments lines
     "meta": {                    # Meta fields ( **kwargs )
       "id": "SID",                 # Mandatory ID field
       "rule_version": 1 },         # Mandatory Revision field
     "type": "rule",              # Rule type (rule, private rule ...)
     "strings": ['$ = "a"'],      # Rule string section (LIST)
     "condition": ["1 of them"]}  # Rule condition section (LIST)    
    
    Result example:
    {"success": true,      #If saving the rule was a success or not
     "sid": "0000000000",  #SID that the rule was assigned (Same as provided)
     "rev": 2 }            #Revision number at which the rule was saved.
    """
    user = kwargs['user']
    key = "%sr.%s" % (sid, rev)
    
    old_data = STORAGE.get_signature(key)
    if old_data:
        data = request.json
        if not Classification.is_accessible(user['classification'],
                                            data['meta'].get('classification',
                                                             Classification.UNRESTRICTED)):
            return make_api_response("", "You are not allowed to change a signature to an "
                                         "higher classification than yours", 403)
    
        if old_data['meta']['al_status'] != data['meta']['al_status']:
            return make_api_response({"success": False}, "You cannot change the signature "
                                                         "status through this API.", 403)
        
        if not Classification.is_accessible(user['classification'],
                                            old_data['meta'].get('classification',
                                                                 Classification.UNRESTRICTED)):
            return make_api_response("", "You are not allowed to change a signature with "
                                         "higher classification than yours", 403)

        if not user['is_admin'] and "global" in data['type']:
            return make_api_response("", "Only admins are allowed to add global signatures.", 403)

        if YARA_PARSER.require_bump(data, old_data):
            data['meta']['rule_version'] = STORAGE.get_last_rev_for_id(sid) + 1 
            data['meta']['creation_date'] = datetime.date.today().isoformat()
            if 'modification_date' in data['meta']:
                del(data['meta']['modification_date'])
            if 'al_state_change_date' in data['meta']:
                del(data['meta']['al_state_change_date'])
            if 'al_state_change_user' in data['meta']:
                del(data['meta']['al_state_change_user'])
            data['meta']['al_status'] = "TESTING"
            key = "%sr.%s" % (sid, data['meta']['rule_version'])
                
        else:
            data['meta']['modification_date'] = datetime.date.today().isoformat()
            if data['meta']['modification_date'] == data['meta'].get('creation_date', None):
                del(data['meta']['modification_date']) 
        
        data['meta']['last_saved_by'] = user['uname']
        yara_version = data['meta'].get('yara_version', None)
        data['depends'], data['modules'] = \
            YARA_PARSER.parse_dependencies(data['condition'], YARA_PARSER.YARA_MODULES.get(yara_version, None))
        res = YARA_PARSER.validate_rule(data)
        if res['valid']:
            data['warning'] = res.get('warning', None)
            STORAGE.save_signature(key, data)
            return make_api_response({"success": True, "sid": data['meta']['id'], "rev": data['meta']['rule_version']})
        else:
            return make_api_response({"success": False}, res, 403)
    else:
        return make_api_response({"success": False}, "Signature not found. %s" % key, 404)
Exemple #4
0
def change_status(sid, rev, status, **kwargs):
    """
    [INCOMPLETE]
       - DISABLE OTHER REVISION OF THE SAME SIGNTURE WHEN DEPLOYING ONE
    Change the status of a signature
       
    Variables:
    sid    =>  ID of the signature
    rev    =>  Revision number of the signature
    status  =>  New state
    
    Arguments: 
    None
    
    Data Block:
    None
    
    Result example:
    { "success" : true }      #If saving the rule was a success or not
    """
    DEPLOYED_STATUSES = ['DEPLOYED', 'NOISY', 'DISABLED']
    DRAFT_STATUSES = ['STAGING', 'TESTING']
    STALE_STATUSES = ['INVALID']
    user = kwargs['user']
    if status == 'INVALID':
        return make_api_response("",
                                 "INVALID signature status is reserved for service use only.",
                                 403)
    if not user['is_admin'] and status in DEPLOYED_STATUSES:
        return make_api_response("",
                                 "Only admins are allowed to change the signature status to a deployed status.",
                                 403)
    
    key = "%sr.%s" % (sid, rev)
    data = STORAGE.get_signature(key)
    if data:
        if not Classification.is_accessible(user['classification'], data['meta'].get('classification',
                                                                                     Classification.UNRESTRICTED)):
            return make_api_response("", "You are not allowed change status on this signature", 403)
    
        if data['meta']['al_status'] in STALE_STATUSES and status not in DRAFT_STATUSES:
            return make_api_response("",
                                     "Only action available while signature in {} status is to change "
                                     "signature to a DRAFT status"
                                     .format(data['meta']['al_status']),
                                     403)

        if data['meta']['al_status'] in DEPLOYED_STATUSES and status in DRAFT_STATUSES:
            return make_api_response("", "You cannot change the status of signature %s r.%s from %s to %s." %
                                     (sid, rev, data['meta']['al_status'], status), 403)

        query = "meta.al_status:{status} AND _yz_rk:{sid}* AND NOT _yz_rk:{key}"
        today = datetime.date.today().isoformat()
        uname = user['uname']

        if status not in ['DISABLED', 'INVALID', 'TESTING']:
            for other in STORAGE.get_signatures(
                STORAGE.list_filtered_signature_keys(
                    query.format(key=key, sid=sid, status=status)
                )
            ):
                other['meta']['al_state_change_date'] = today
                other['meta']['al_state_change_user'] = uname
                other['meta']['al_status'] = 'DISABLED'

                other_sid = other['meta']['id']
                other_rev = other['meta']['rule_version']
                other_key = "%sr.%s" % (other_sid, other_rev)
                STORAGE.save_signature(other_key, other)

        data['meta']['al_state_change_date'] = today
        data['meta']['al_state_change_user'] = uname
        data['meta']['al_status'] = status

        STORAGE.save_signature(key, data)
        return make_api_response({"success": True})
    else:
        return make_api_response("", "Signature not found. (%s r.%s)" % (sid, rev), 404)