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