Пример #1
0
    def put(self, uid=None):
        if not uid:
            try:
                data = convert_rest_request(request.data)
            except TypeError as type_error:
                return error_message(str(type_error),
                                     self.URL,
                                     request_data=request.data)

            result = self._process_data(data)
            if 'error_message' in result:
                logging.warning(
                    'Submission not according to API guidelines! (data could not be parsed)'
                )
                return error_message(result['error_message'],
                                     self.URL,
                                     request_data=data)

            logging.debug('Upload Successful!')
            return success_message(result, self.URL, request_data=data)
        else:
            try:
                update = get_update(request.args)
            except ValueError as value_error:
                return error_message(str(value_error),
                                     self.URL,
                                     request_data={'uid': uid})
            return self._update_analysis(uid, update)
Пример #2
0
    def get(self, compare_id=None):
        '''
        The request data should have the form
        {"uid_list": uid_list, "<optional>redo": True}
        return value: the result dict from the compare
        '''
        try:
            compare_id = unify_string_list(compare_id)
        except Exception:  # FIXME Please specify Exception types - would think at least TypeError might occur
            return error_message(
                'Compare ID must be of the form uid1;uid2(;uid3..)',
                self.URL,
                request_data={'compare_id': compare_id})

        with ConnectTo(CompareDbInterface, self.config) as db_compare_service:
            result = None
            if db_compare_service.compare_result_is_in_db(compare_id):
                result = db_compare_service.get_compare_result(compare_id)
        if result:
            return success_message(result,
                                   self.URL,
                                   request_data={'compare_id': compare_id},
                                   return_code=202)
        else:
            return error_message(
                'Compare not found in database. Please use /rest/start_compare to start the compare.',
                self.URL,
                request_data={'compare_id': compare_id},
                return_code=404)
Пример #3
0
    def put(self):
        '''
        The request data should have the form
        {"uid_list": uid_list, "<optional>redo": True}
        return value: the result dict from the compare
        '''
        try:
            data = convert_rest_request(request.data)
        except TypeError as type_error:
            return error_message(str(type_error),
                                 self.URL,
                                 request_data=request.data)

        try:
            uid_string = ';'.join(data['uid_list'])
            compare_id = normalize_compare_id(uid_string)
            redo = data.get('redo', False)
        except (AttributeError, TypeError, KeyError):
            return error_message(
                'Request should be of the form {"uid_list": uid_list, "redo": boolean}',
                self.URL,
                request_data=data)

        with ConnectTo(CompareDbInterface, self.config) as db_compare_service:
            if not db_compare_service.compare_result_is_in_db(
                    compare_id) or redo:
                return self.start_compare(db_compare_service, compare_id, data,
                                          redo)
        return error_message(
            'Compare already exists. Use "redo" to force re-compare.',
            self.URL,
            request_data=data,
            return_code=200)
Пример #4
0
    def _get_without_uid(self):
        try:
            query, recursive, inverted, offset, limit = self._get_parameters_from_request(
                request.args)
        except ValueError as value_error:
            request_data = {
                k: request.args.get(k)
                for k in ['query', 'limit', 'offset', 'recursive', 'inverted']
            }
            return error_message(str(value_error),
                                 self.URL,
                                 request_data=request_data)

        parameters = dict(offset=offset,
                          limit=limit,
                          query=query,
                          recursive=recursive,
                          inverted=inverted)
        try:
            with ConnectTo(FrontEndDbInterface, self.config) as connection:
                uids = connection.rest_get_firmware_uids(**parameters)
            return success_message(dict(uids=uids), self.URL, parameters)
        except PyMongoError:
            return error_message('Unknown exception on request', self.URL,
                                 parameters)
Пример #5
0
    def post(self):
        '''
        The request data should have the form
        {"rule_file": rule_string, 'uid': firmware_uid}
        The uid parameter is optional and can be specified if the user want's to search in the files of a single firmware.
        rule_string can be something like "rule rule_name {strings: $a = \"foobar\" condition: $a}"
        '''
        try:
            data = convert_rest_request(request.data)
            yara_rules = self._get_yara_rules(data)
            uid = self._get_firmware_uid(data)
        except TypeError as type_error:
            return error_message(str(type_error),
                                 self.URL,
                                 request_data=request.data)
        except RestBinarySearchException as exception:
            return error_message(exception.get_message(),
                                 self.URL,
                                 request_data=request.data)

        with ConnectTo(InterComFrontEndBinding, self.config) as intercom:
            search_id = intercom.add_binary_search_request(yara_rules, uid)

        return success_message(
            {
                'message':
                'Started binary search. Please use GET and the search_id to get the results'
            },
            self.URL,
            request_data={'search_id': search_id})
Пример #6
0
    def get(self, compare_id=None):
        '''
        The request data should have the form
        {"uid_list": uid_list, "<optional>redo": True}
        return value: the result dict from the compare
        '''
        try:
            compare_id = normalize_compare_id(compare_id)
        except (AttributeError, TypeError):
            return error_message(
                'Compare ID must be of the form uid1;uid2(;uid3..)',
                self.URL,
                request_data={'compare_id': compare_id})

        with ConnectTo(CompareDbInterface, self.config) as db_compare_service:
            result = None
            with suppress(FactCompareException):
                if db_compare_service.compare_result_is_in_db(compare_id):
                    result = db_compare_service.get_compare_result(compare_id)
        if result:
            return success_message(result,
                                   self.URL,
                                   request_data={'compare_id': compare_id},
                                   return_code=202)
        return error_message(
            'Compare not found in database. Please use /rest/start_compare to start the compare.',
            self.URL,
            request_data={'compare_id': compare_id},
            return_code=404)
Пример #7
0
    def get(self, uid=None):
        if not uid:
            paging, success = get_paging(request.args)
            if not success:
                return error_message(paging, self.URL, request_data=request.args)
            offset, limit = paging

            try:
                recursive = get_recursive(request.args)
                query = get_query(request.args)
            except ValueError as value_error:
                return error_message(str(value_error), self.URL, request_data=dict(query=request.args.get('query'), recursive=request.args.get('recursive')))
            if recursive and not query:
                return error_message('recursive search is only permissible with non-empty query', self.URL, request_data=dict(query=request.args.get('query'), recursive=request.args.get('recursive')))

            try:
                with ConnectTo(FrontEndDbInterface, self.config) as connection:
                    uids = connection.rest_get_firmware_uids(offset=offset, limit=limit, query=query, recursive=recursive)

                return success_message(dict(uids=uids), self.URL, dict(offset=offset, limit=limit, query=query, recursive=recursive))
            except Exception:
                return error_message('Unknown exception on request', self.URL, dict(offset=offset, limit=limit, query=query, recursive=recursive))
        else:
            summary = get_summary_flag(request.args)
            if summary:
                with ConnectTo(FrontEndDbInterface, self.config) as connection:
                    firmware = connection.get_complete_object_including_all_summaries(uid)
            else:
                with ConnectTo(FrontEndDbInterface, self.config) as connection:
                    firmware = connection.get_firmware(uid)
            if not firmware or not isinstance(firmware, Firmware):
                return error_message('No firmware with UID {} found'.format(uid), self.URL, dict(uid=uid))

            fitted_firmware = self._fit_firmware(firmware)
            return success_message(dict(firmware=fitted_firmware), self.URL, request_data=dict(uid=uid))
Пример #8
0
def test_error_message_bad_type():
    with pytest.raises(TypeError):
        error_message(None, '/any/url')

    with pytest.raises(TypeError):
        error_message({'Done some stuff': 'Didn\'t look for standards.'},
                      '/any/url')
Пример #9
0
 def get(self, uid):
     with ConnectTo(FsMetadataRoutesDbInterface, self.config) as db:
         results = db.get_analysis_results_for_included_uid(uid)
     endpoint = self.ENDPOINTS[0][0]
     if not results:
         error_message('no results found for uid {}'.format(uid), endpoint, request_data={'uid': uid})
     return success_message({AnalysisPlugin.NAME: results}, endpoint, request_data={'uid': uid})
Пример #10
0
    def _update_analysis(self, uid, update):
        with ConnectTo(FrontEndDbInterface, self.config) as connection:
            firmware = connection.get_firmware(uid)
        if not firmware:
            return error_message('No firmware with UID {} found'.format(uid),
                                 self.URL, dict(uid=uid))

        unpack = 'unpacker' in update
        while 'unpacker' in update:
            update.remove('unpacker')

        firmware.scheduled_analysis = update

        with ConnectTo(InterComFrontEndBinding, self.config) as intercom:
            supported_plugins = intercom.get_available_analysis_plugins().keys(
            )
            for item in update:
                if item not in supported_plugins:
                    return error_message(
                        'Unknown analysis system \'{}\''.format(item),
                        self.URL, dict(uid=uid, update=update))
            intercom.add_re_analyze_task(firmware, unpack)

        if unpack:
            update.append('unpacker')
        return success_message({}, self.URL, dict(uid=uid, update=update))
Пример #11
0
    def put(self):
        '''
        The request data should have the form
        {"uid_list": uid_list, "<optional>redo": True}
        return value: the result dict from the compare
        '''
        try:
            data = convert_rest_request(request.data)
        except TypeError as type_error:
            return error_message(str(type_error), self.URL, request_data=request.data)

        try:
            uid_string = ';'.join(data['uid_list'])
            compare_id = unify_string_list(uid_string)
            if 'redo' in data.keys():
                redo = data['redo']
            else:
                redo = False
        except Exception:  # FIXME Please specify Exception types - would think at least TypeError might occur
            return error_message('Request should be of the form {"uid_list": uid_list, "redo": boolean}', self.URL, request_data=data)

        with ConnectTo(CompareDbInterface, self.config) as db_compare_service:
            if not db_compare_service.compare_result_is_in_db(compare_id) or redo:
                err = db_compare_service.object_existence_quick_check(compare_id)
                if err is not None:
                    return error_message(err, self.URL, request_data=data, return_code=404)
                with ConnectTo(InterComFrontEndBinding, self.config) as intercom:
                    intercom.add_compare_task(compare_id, force=redo)
                return success_message({'message': 'Compare started. Please use GET to get the results.'}, self.URL, request_data=data, return_code=202)
        return error_message('Compare already exists. Use "redo" to force re-compare.', self.URL, request_data=data, return_code=200)
Пример #12
0
    def get(self, uid=None):
        if not uid:
            paging, success = get_paging(request.args)
            if not success:
                return error_message(paging, self.URL, request_data=request.args)
            offset, limit = paging

            try:
                query = get_query(request.args)
            except ValueError as value_error:
                return error_message(str(value_error), self.URL, request_data=dict(query=request.args.get('query')))

            try:
                with ConnectTo(FrontEndDbInterface, self.config) as connection:
                    uids = connection.rest_get_file_object_uids(offset=offset, limit=limit, query=query)

                return success_message(dict(uids=uids), self.URL, dict(offset=offset, limit=limit, query=query))
            except Exception:
                return error_message('Unknown exception on request', self.URL, dict(offset=offset, limit=limit, query=query))
        else:
            with ConnectTo(FrontEndDbInterface, self.config) as connection:
                file_object = connection.get_file_object(uid)
            if not file_object:
                return error_message('No file object with UID {} found'.format(uid), self.URL, dict(uid=uid))

            fitted_file_object = self._fit_file_object(file_object)
            return success_message(dict(file_object=fitted_file_object), self.URL, request_data=dict(uid=uid))
Пример #13
0
def test_error_message_succeeds():
    message, code = error_message('my error response', '/any/url')
    assert message['error_message'] == 'my error response'
    assert message['status'] == 1
    assert code == 400

    _, code = error_message('my error response', '/any/url', return_code=304)
    assert code == 304
Пример #14
0
 def get(self, uid):
     results = get_analysis_results_for_included_uid(uid, self.config)
     endpoint = self.ENDPOINTS[0][0]
     if not results:
         error_message('no results found for uid {}'.format(uid),
                       endpoint,
                       request_data={'uid': uid})
     return success_message({AnalysisPlugin.NAME: results},
                            endpoint,
                            request_data={'uid': uid})
Пример #15
0
    def put(self):
        '''
        The request data should have the form
        {"uid_list": uid_list, "<optional>redo": True}
        return value: the result dict from the compare
        '''
        try:
            data = convert_rest_request(request.data)
        except TypeError as type_error:
            return error_message(str(type_error),
                                 self.URL,
                                 request_data=request.data)

        try:
            uid_string = ';'.join(data['uid_list'])
            compare_id = normalize_compare_id(uid_string)
            redo = data.get('redo', False)
        except (AttributeError, TypeError, KeyError):
            return error_message(
                'Request should be of the form {"uid_list": uid_list, "redo": boolean}',
                self.URL,
                request_data=data)

        with ConnectTo(CompareDbInterface, self.config) as db_compare_service:
            if not db_compare_service.compare_result_is_in_db(
                    compare_id) or redo:
                try:
                    db_compare_service.check_objects_exist(compare_id)
                except FactCompareException as exception:
                    return error_message(exception.get_message(),
                                         self.URL,
                                         request_data=data,
                                         return_code=404)
                with ConnectTo(InterComFrontEndBinding,
                               self.config) as intercom:
                    intercom.add_compare_task(compare_id, force=redo)
                return success_message(
                    {
                        'message':
                        'Compare started. Please use GET to get the results.'
                    },
                    self.URL,
                    request_data=data,
                    return_code=202)
        return error_message(
            'Compare already exists. Use "redo" to force re-compare.',
            self.URL,
            request_data=data,
            return_code=200)
Пример #16
0
def test_messages_with_request_data():
    request_data = {'for_example': 'some uids'}
    message, _ = success_message({'my': 'data'}, '/any/url', request_data=request_data)
    assert message['request'] == request_data

    message, _ = error_message('my_error', '/any/url', request_data=request_data)
    assert message['request'] == request_data
Пример #17
0
 def _put_with_uid(self, uid):
     try:
         update = get_update(request.args)
     except ValueError as value_error:
         return error_message(str(value_error),
                              self.URL,
                              request_data={'uid': uid})
     return self._update_analysis(uid, update)
Пример #18
0
    def _get_with_uid(self, uid):
        with ConnectTo(FrontEndDbInterface, self.config) as connection:
            file_object = connection.get_file_object(uid)
        if not file_object:
            return error_message('No file object with UID {} found'.format(uid), self.URL, dict(uid=uid))

        fitted_file_object = self._fit_file_object(file_object)
        return success_message(dict(file_object=fitted_file_object), self.URL, request_data=dict(uid=uid))
Пример #19
0
    def _get_without_uid(self):
        paging, success = get_paging(request.args)
        if not success:
            return error_message(paging, self.URL, request_data=request.args)
        offset, limit = paging

        try:
            query = get_query(request.args)
        except ValueError as value_error:
            return error_message(str(value_error), self.URL, request_data=dict(query=request.args.get('query')))

        try:
            with ConnectTo(FrontEndDbInterface, self.config) as connection:
                uids = connection.rest_get_file_object_uids(offset=offset, limit=limit, query=query)

            return success_message(dict(uids=uids), self.URL, dict(offset=offset, limit=limit, query=query))
        except Exception:
            return error_message('Unknown exception on request', self.URL, dict(offset=offset, limit=limit, query=query))
Пример #20
0
    def _put_without_uid(self):
        try:
            data = convert_rest_request(request.data)
        except TypeError as type_error:
            return error_message(str(type_error),
                                 self.URL,
                                 request_data=request.data)

        result = self._process_data(data)
        if 'error_message' in result:
            logging.warning(
                'Submission not according to API guidelines! (data could not be parsed)'
            )
            return error_message(result['error_message'],
                                 self.URL,
                                 request_data=data)

        logging.debug('Upload Successful!')
        return success_message(result, self.URL, request_data=data)
Пример #21
0
    def _get_without_uid(self):
        paging, success = get_paging(request.args)
        if not success:
            return error_message(paging, self.URL, request_data=request.args)
        offset, limit = paging

        try:
            recursive = get_recursive(request.args)
            query = get_query(request.args)
        except ValueError as value_error:
            return error_message(str(value_error),
                                 self.URL,
                                 request_data=dict(
                                     query=request.args.get('query'),
                                     recursive=request.args.get('recursive')))
        if recursive and not query:
            return error_message(
                'recursive search is only permissible with non-empty query',
                self.URL,
                request_data=dict(query=request.args.get('query'),
                                  recursive=request.args.get('recursive')))

        try:
            with ConnectTo(FrontEndDbInterface, self.config) as connection:
                uids = connection.rest_get_firmware_uids(offset=offset,
                                                         limit=limit,
                                                         query=query,
                                                         recursive=recursive)

            return success_message(
                dict(uids=uids), self.URL,
                dict(offset=offset,
                     limit=limit,
                     query=query,
                     recursive=recursive))
        except Exception:
            return error_message(
                'Unknown exception on request', self.URL,
                dict(offset=offset,
                     limit=limit,
                     query=query,
                     recursive=recursive))
Пример #22
0
    def _get_without_uid(self):
        try:
            query = get_query(request.args)
            offset, limit = get_paging(request.args)
        except ValueError as value_error:
            request_data = {
                k: request.args.get(k)
                for k in ['query', 'limit', 'offset']
            }
            return error_message(str(value_error),
                                 self.URL,
                                 request_data=request_data)

        parameters = dict(offset=offset, limit=limit, query=query)
        try:
            with ConnectTo(FrontEndDbInterface, self.config) as connection:
                uids = connection.rest_get_file_object_uids(**parameters)
            return success_message(dict(uids=uids), self.URL, parameters)
        except PyMongoError:
            return error_message('Unknown exception on request', self.URL,
                                 parameters)
Пример #23
0
    def get(self, uid):
        '''
        The uid of the file_object in question has to be given in the url
        The return format will be {"binary": b64_encoded_binary, "file_name": file_name}
        '''
        with ConnectTo(FrontEndDbInterface, self.config) as db_service:
            existence = db_service.existence_quick_check(uid)
        if not existence:
            return error_message(
                'No firmware with UID {} found in database'.format(uid),
                self.URL,
                request_data={'uid': uid},
                return_code=404)

        try:
            tar_flag = get_tar_flag(request.args)
        except ValueError as value_error:
            return error_message(str(value_error),
                                 self.URL,
                                 request_data=dict(
                                     uid=uid, tar=request.args.get('tar')))

        with ConnectTo(InterComFrontEndBinding, self.config) as intercom:
            if not tar_flag:
                binary, file_name = intercom.get_binary_and_filename(uid)
            else:
                binary, file_name = intercom.get_repacked_binary_and_file_name(
                    uid)

        response = {
            'binary': standard_b64encode(binary).decode(),
            'file_name': file_name,
            'SHA256': get_sha256(binary)
        }
        return success_message(response,
                               self.URL,
                               request_data={
                                   'uid': uid,
                                   'tar': tar_flag
                               })
Пример #24
0
    def get(self, search_id=None):
        '''
        The search_id is needed to fetch the corresponding search result.
        The result of the search request can only be fetched once. After this the search needs to be started again.
        The results have the form:
        {'binary_search_results': {'<rule_name_1>': ['<matching_uid_1>', ...], '<rule_name_2>': [...], ...}
        '''

        if search_id is None:
            return error_message(
                'The request is missing a search_id (.../binary_search/<search_id>).',
                self.URL)

        with ConnectTo(InterComFrontEndBinding, self.config) as intercom:
            result, _ = intercom.get_binary_search_result(search_id)

        if result is None:
            return error_message(
                'The result is not ready yet or it has already been fetched',
                self.URL)

        return success_message({'binary_search_results': result}, self.URL)
Пример #25
0
 def start_compare(self, db_compare_service, compare_id, data, redo):
     try:
         db_compare_service.check_objects_exist(compare_id)
     except FactCompareException as exception:
         return error_message(exception.get_message(),
                              self.URL,
                              request_data=data,
                              return_code=404)
     with ConnectTo(InterComFrontEndBinding, self.config) as intercom:
         intercom.add_compare_task(compare_id, force=redo)
     return success_message(
         {'message': 'Compare started. Please use GET to get the results.'},
         self.URL,
         request_data=data,
         return_code=202)
Пример #26
0
    def _get_with_uid(self, uid):
        summary = get_summary_flag(request.args)
        if summary:
            with ConnectTo(FrontEndDbInterface, self.config) as connection:
                firmware = connection.get_complete_object_including_all_summaries(
                    uid)
        else:
            with ConnectTo(FrontEndDbInterface, self.config) as connection:
                firmware = connection.get_firmware(uid)
        if not firmware or not isinstance(firmware, Firmware):
            return error_message('No firmware with UID {} found'.format(uid),
                                 self.URL, dict(uid=uid))

        fitted_firmware = self._fit_firmware(firmware)
        return success_message(dict(firmware=fitted_firmware),
                               self.URL,
                               request_data=dict(uid=uid))
Пример #27
0
    def get(self):
        components = ["frontend", "database", "backend"]
        status = {}
        with ConnectTo(StatisticDbViewer, self.config) as stats_db:
            for component in components:
                status[component] = stats_db.get_statistic(component)

        with ConnectTo(InterComFrontEndBinding, self.config) as sc:
            plugins = sc.get_available_analysis_plugins()

        if not status:
            return error_message('Unknown Issue. Cannot Stat FACT.',
                                 self.URL,
                                 return_code=404)

        response = {
            'system_status': status,
            'plugins': self._condense_plugin_information(plugins),
        }
        return success_message(response, self.URL)
Пример #28
0
    def get(self, uid):
        '''
        The uid of the file_object in question has to be given in the url
        The return format will be {"binary": b64_encoded_binary, "file_name": file_name}
        '''
        with ConnectTo(FrontEndDbInterface, self.config) as db_service:
            existence = db_service.existence_quick_check(uid)
        if not existence:
            return error_message(
                'No firmware with UID {} found in database'.format(uid),
                self.URL,
                request_data={'uid': uid},
                return_code=404)

        with ConnectTo(InterComFrontEndBinding, self.config) as intercom:
            binary, file_name = intercom.get_binary_and_filename(uid)

        response = {
            'binary': standard_b64encode(binary).decode(),
            'file_name': file_name,
            'SHA256': get_sha256(binary)
        }
        return success_message(response, self.URL, request_data={'uid': uid})