Beispiel #1
0
def load_user_settings(user):
    default_settings = copy.deepcopy(SETTINGS_DEFAULT)
    default_settings[
        'classification'] = Classification.default_user_classification(user)
    options = STORAGE.get_user_options(user['uname'])
    srv_list = [x for x in STORAGE.list_services() if x['enabled']]
    if not options:
        def_srv_list = None
        options = default_settings
    else:
        # Make sure all defaults are there
        for key, item in default_settings.iteritems():
            if key not in options:
                options[key] = item

        # Remove all obsolete keys
        for key in options.keys():
            if key not in default_settings:
                del options[key]

        def_srv_list = options.get('services', None)

    options['service_spec'] = get_default_service_spec(srv_list)
    options['services'] = get_default_service_list(srv_list, def_srv_list)

    # Normalize the user's classification
    options['classification'] = Classification.normalize_classification(
        options['classification'])

    return options
Beispiel #2
0
def submit_file(*args, **kwargs):
    """
    Submit a single file inline
    
    Variables:
    None
    
    Arguments: 
    None
    
    Data Block (REQUIRED): 
    {
     "name": "file.exe",     # Name of the file
     "binary": "A24AB..==",  # Base64 encoded file binary
     "params": {             # Submission parameters
         "key": val,            # Key/Value pair for params that different then defaults
         },                     # Default params can be fetch at /api/v3/user/submission_params/<user>/
     "srv_spec": {           # Service specifics parameters
         "Extract": {
             "password": "******"
             },
         }
    }
    
    Result example:
    {
     "submission":{},        # Submission Block
     "times": {},            # Timing Block
     "state": "submitted",   # Submission state
     "services": {},         # Service selection Block
     "fileinfo": {}          # File information Block
     "files": []             # List of submitted files
     "request": {}           # Request detail block
    }
    """
    user = kwargs['user']

    check_submission_quota(user)
        
    out_dir = os.path.join(TEMP_SUBMIT_DIR, uuid4().get_hex())

    try:
        data = request.json
        if not data:
            return make_api_response({}, "Missing data block", 400)
        
        name = data.get("name", None)
        if not name:
            return make_api_response({}, "Filename missing", 400)
        out_file = os.path.join(out_dir, os.path.basename(name))
        
        binary = data.get("binary", None)
        if not binary:
            return make_api_response({}, "File binary missing", 400)
        else:
            try:
                os.makedirs(out_dir)
            except:
                pass
            
            with open(out_file, "wb") as my_file:
                my_file.write(base64.b64decode(binary))

        # Create task object
        task = STORAGE.get_user_options(user['uname'])
        if not task:
            task = get_default_user_settings(user)

        task.update(data.get("params", {}))
        if 'groups' not in task:
            task['groups'] = user['groups']

        task["params"] = data.get("srv_spec", {})
        if 'services' in task and "selected" not in task:
            task["selected"] = task["services"]

        task['quota_item'] = True
        task['submitter'] = user['uname']
        task['sid'] = str(uuid4())
        if not task['description']:
            task['description'] = "Inspection of file: %s" % name
        
        with forge.get_filestore() as f_transport:
            result = SubmissionWrapper.submit_inline(STORAGE, f_transport, [out_file],
                                                     **remove_ui_specific_options(task))

        if result['submission']['sid'] != task['sid']:
            raise Exception('ID does not match what was returned by the dispatcher. Cancelling request...')
        return make_api_response(result)
        
    finally:
        try:
            # noinspection PyUnboundLocalVariable
            os.unlink(out_file)
        except:
            pass

        try:
            shutil.rmtree(out_dir, ignore_errors=True)
        except:
            pass
Beispiel #3
0
def ingest_single_file(**kwargs):
    """
    Ingest a single file in the system
        Note:
            Binary and sha256 fields are optional but at least one of them has to be there
            notification_queue, notification_threshold and generate_alert fields are optional
        Note 2:
            The ingest API uses the user's default settings to submit files to the system
            unless these settings are overridden in the 'params' field. Although, there are
            exceptions to that rule. Fields deep_scan, ignore_filtering, ignore_cache,
            ignore_tag are resetted to False because the lead to dangerous behavior in the
            system.

    Variables:
    None

    Arguments:
    None

    Data Block:
    {
     "name": "file.exe",             # Name of the file
     "binary": "A24AB..==",          # Base64 encoded file binary
     "metadata": {                   # Submission Metadata
         "key": val,                    # Key/Value pair for metadata parameters
         },
     "params": {                     # Submission parameters
         "key": val,                    # Key/Value pair for params that differ from the user's defaults
         },                                 # DEFAULT: /api/v3/user/submission_params/<user>/
     "sha256": "1234...CDEF"         # SHA256 hash of the file
     "srv_spec": {                   # Service specifics parameters
         "Extract": {
             "password": "******"
             },
         },
     "type": "SUBMISSION_TYPE"       # Required type field,
     "notification_queue": None,     # Name of the notification queue
     "notification_threshold": None, # Threshold for notification
     "generate_alert": False         # Generate an alert in our alerting system or not
    }

    Result example:
    { "success": true }
    """
    user = kwargs['user']
    out_dir = os.path.join(TEMP_SUBMIT_DIR, uuid4().get_hex())

    with forge.get_filestore() as f_transport:
        try:
            data = request.json
            if not data:
                return make_api_response({}, "Missing data block", 400)

            notification_queue = data.get('notification_queue', None)
            if notification_queue:
                notification_queue = "nq-%s" % notification_queue

            notification_threshold = data.get('notification_threshold', None)
            if not isinstance(notification_threshold,
                              int) and notification_threshold:
                return make_api_response(
                    {}, "notification_threshold should be and int", 400)

            generate_alert = data.get('generate_alert', False)
            if not isinstance(generate_alert, bool):
                return make_api_response({},
                                         "generate_alert should be a boolean",
                                         400)

            name = data.get("name", None)
            if not name:
                return make_api_response({}, "Filename missing", 400)

            ingest_msg_type = data.get("type", None)
            if not ingest_msg_type:
                return make_api_response({}, "Required type field missing",
                                         400)

            out_file = os.path.join(out_dir, os.path.basename(name))
            try:
                os.makedirs(out_dir)
            except:
                pass

            binary = data.get("binary", None)
            if not binary:
                sha256 = data.get('sha256', None)
                if sha256:
                    if f_transport.exists(sha256):
                        f_transport.download(sha256, out_file)
                    else:
                        return make_api_response(
                            {}, "SHA256 does not exist in our datastore", 404)
                else:
                    return make_api_response(
                        {}, "Both file binary and sha256 missing", 400)
            else:
                with open(out_file, "wb") as my_file:
                    my_file.write(base64.b64decode(binary))

            overrides = STORAGE.get_user_options(user['uname'])
            overrides['selected'] = overrides['services']
            overrides.update({
                'deep_scan': False,
                "priority": 150,
                "ignore_cache": False,
                "ignore_filtering": False,
                "ignore_tag": False,
            })
            overrides.update(data.get("params", {}))
            overrides.update({
                'description':
                "[%s] Inspection of file: %s" % (ingest_msg_type, name),
                'generate_alert':
                generate_alert,
                'max_extracted':
                100,
                'max_supplementary':
                100,
                'params':
                data.get("srv_spec", {}),
                'submitter':
                user['uname'],
            })
            if notification_queue:
                overrides.update({
                    "notification_queue":
                    notification_queue,
                    "notification_threshold":
                    notification_threshold
                })

            overrides['priority'] = min(overrides.get("priority", 150), 250)

            metadata = data.get("metadata", {})
            metadata['type'] = ingest_msg_type
            if 'ts' not in metadata:
                metadata['ts'] = now_as_iso()

            digests = identify.get_digests_for_file(out_file)
            digests.pop('path', None)

            sha256 = digests['sha256']
            if not f_transport.exists(sha256):
                f_transport.put(out_file, sha256, location='far')

            msg = {
                "priority": overrides['priority'],
                "type": ingest_msg_type,
                "overrides": remove_ui_specific_options(overrides),
                "metadata": metadata
            }
            msg.update(digests)

            ingest.push(forge.determine_ingest_queue(sha256), msg)

            return make_api_response({"success": True})
        finally:
            try:
                # noinspection PyUnboundLocalVariable
                os.unlink(out_file)
            except:
                pass

            try:
                shutil.rmtree(out_dir, ignore_errors=True)
            except:
                pass
Beispiel #4
0
def resubmit_for_dynamic(srl, *args, **kwargs): 
    """
    Resubmit a file for dynamic analysis
    
    Variables:
    srl         => Resource locator (SHA256)
    
    Arguments (Optional): 
    copy_sid    => Mimic the attributes of this SID.
    name        => Name of the file for the submission
    
    Data Block:
    None
    
    Result example:
    {
     "submission":{},       # Submission Block
     "request": {},         # Request Block
     "times": {},           # Timing Block
     "state": "submitted",  # Submission state
     "services": {},        # Service selection Block
     "fileinfo": {}         # File information Block
     }
    """
    user = kwargs['user']
    copy_sid = request.args.get('copy_sid', None)
    name = request.args.get('name', srl)
    
    if copy_sid:
        submission = STORAGE.get_submission(copy_sid)
    else:
        submission = None
        
    if submission:
        if not Classification.is_accessible(user['classification'], submission['classification']):
            return make_api_response("", "You are not allowed to re-submit a submission that you don't have access to",
                                     403)
            
        task = {k: v for k, v in submission['submission'].iteritems() if k not in STRIP_KW}
        task.update({k: v for k, v in submission['services'].iteritems() if k not in STRIP_KW})
        task['classification'] = submission['classification']
        
    else:
        params = STORAGE.get_user_options(user['uname'])
        task = {k: v for k, v in params.iteritems() if k not in STRIP_KW}
        task['selected'] = params["services"]
        task['classification'] = params['classification']

    task['sha256'] = srl
    with forge.get_filestore() as f_transport:
        if not f_transport.exists(srl):
            return make_api_response({}, "File %s cannot be found on the server therefore it cannot be resubmitted."
                                         % srl, status_code=404)

        task['path'] = name
        task['submitter'] = user['uname']
        if 'priority' not in task:
            task['priority'] = 500
        task['description'] = "Resubmit %s for Dynamic Analysis" % name
        if "Dynamic Analysis" not in task['selected']:
            task['selected'].append("Dynamic Analysis")

        submit_result = SubmissionWrapper.submit(f_transport, STORAGE, **task)

    return make_api_response(submit_result)
Beispiel #5
0
        def base(*args, **kwargs):
            # Validate User-Agent
            user_agent = request.environ.get("HTTP_USER_AGENT",
                                             "Unknown browser")
            if "MSIE 8" in user_agent or "MSIE 9" in user_agent or "MSIE 7" in user_agent or "MSIE 6" in user_agent:
                return redirect(redirect_helper("/unsupported.html"))

            # Create Path
            path = request.path + "?" + request.query_string

            # Login
            try:
                session_id = flsk_session.get("session_id", None)

                if not session_id:
                    abort(401)

                session = KV_SESSION.get(session_id)

                if not session:
                    abort(401)
                else:
                    session = json.loads(session)
                    cur_time = now()
                    if session.get('expire_at', 0) < cur_time:
                        KV_SESSION.pop(session_id)
                        abort(401)
                    else:
                        session['expire_at'] = cur_time + session.get(
                            'duration', 3600)

                if request.headers.get("X-Forward-For", None) != session.get('ip', None) or \
                        request.headers.get("User-Agent", None) != session.get('user_agent', None):
                    abort(401)

                KV_SESSION.set(session_id, session)

                logged_in_uname = session.get("username", None)

                if not set(self.required_priv).intersection(
                        set(session.get("privileges", []))):
                    abort(401)

                user = login(logged_in_uname, path)
                if self.require_admin and not user['is_admin']:
                    raise AccessDeniedException(
                        "Url '%s' requires ADMIN privileges" % request.path)
            except AccessDeniedException:
                raise

            if self.audit:
                json_blob = request.json
                if not isinstance(json_blob, dict):
                    json_blob = {}
                params_list = list(args) + \
                    ["%s=%s" % (k, v) for k, v in kwargs.iteritems() if k in AUDIT_KW_TARGET] + \
                    ["%s=%s" % (k, v) for k, v in request.args.iteritems() if k in AUDIT_KW_TARGET] + \
                    ["%s=%s" % (k, v) for k, v in json_blob.iteritems() if k in AUDIT_KW_TARGET]
                AUDIT_LOG.info("%s [%s] :: %s(%s)" %
                               (logged_in_uname, user['classification'],
                                func.func_name, ", ".join(params_list)))

            # Dump Generic KWARGS
            kwargs['build_master'] = "%s.%s" % (BUILD_MASTER, BUILD_LOWER)
            kwargs['user'] = user
            kwargs['user_js'] = json.dumps(user)
            kwargs['debug'] = str(DEBUG).lower()
            kwargs['menu'] = create_menu(user, path)
            kwargs['avatar'] = STORAGE.get_user_avatar(user['uname'])
            kwargs['is_prod'] = SYSTEM_NAME == "production"
            options = STORAGE.get_user_options(user['uname'])
            if not request.path == "/terms.html":
                if not user.get('agrees_with_tos', False) and config.ui.get(
                        "tos", None) is not None:
                    return redirect(redirect_helper("/terms.html"))
                if not options and not request.path == "/settings.html":
                    return redirect(redirect_helper("/settings.html?forced"))

            if self.load_options:
                kwargs['options'] = json.dumps(options)

            kwargs["build_no"] = BUILD_NO

            return func(*args, **kwargs)