Пример #1
0
    def post_attachment(self, workspace_name, vuln_id):
        try:
            validate_csrf(request.form.get('csrf_token'))
        except wtforms.ValidationError:
            flask.abort(403)
        vuln_workspace_check = db.session.query(
            VulnerabilityGeneric, Workspace.id).join(Workspace).filter(
                VulnerabilityGeneric.id == vuln_id,
                Workspace.name == workspace_name).first()

        if vuln_workspace_check:
            if 'file' not in request.files:
                flask.abort(400)

            faraday_file = FaradayUploadedFile(request.files['file'].read())
            filename = request.files['file'].filename

            get_or_create(db.session,
                          File,
                          object_id=vuln_id,
                          object_type='vulnerability',
                          name=filename,
                          filename=filename,
                          content=faraday_file)
            db.session.commit()
            return flask.jsonify({'message': 'Evidence upload was successful'})
        else:
            flask.abort(404, "Vulnerability not found")
Пример #2
0
    def bulk_create(self, workspace_name):
        try:
            validate_csrf(flask.request.form.get('csrf_token'))
        except wtforms.ValidationError:
            flask.abort(403)

        def parse_hosts(list_string):
            items = re.findall(r"([.a-zA-Z0-9_-]+)", list_string)
            return items

        workspace = self._get_workspace(workspace_name)

        logger.info("Create hosts from CSV")
        if 'file' not in flask.request.files:
            abort(400, "Missing File in request")
        hosts_file = flask.request.files['file']
        stream = StringIO(hosts_file.stream.read().decode("utf-8"),
                          newline=None)
        FILE_HEADERS = {'description', 'hostnames', 'ip', 'os'}
        try:
            hosts_reader = csv.DictReader(stream)
            if set(hosts_reader.fieldnames) != FILE_HEADERS:
                logger.error("Missing Required headers in CSV (%s)",
                             FILE_HEADERS)
                abort(400,
                      "Missing Required headers in CSV (%s)" % FILE_HEADERS)
            hosts_created_count = 0
            hosts_with_errors_count = 0
            for host_dict in hosts_reader:
                try:
                    hostnames = parse_hosts(host_dict.pop('hostnames'))
                    other_fields = {
                        'owned': False,
                        'mac': u'00:00:00:00:00:00',
                        'default_gateway_ip': u'None'
                    }
                    host_dict.update(other_fields)
                    host = super(HostsView,
                                 self)._perform_create(host_dict,
                                                       workspace_name)
                    host.workspace = workspace
                    for name in hostnames:
                        get_or_create(db.session,
                                      Hostname,
                                      name=name,
                                      host=host,
                                      workspace=host.workspace)
                    db.session.commit()
                except Exception as e:
                    logger.error("Error creating host (%s)", e)
                    hosts_with_errors_count += 1
                else:
                    logger.debug("Host Created (%s)", host_dict)
                    hosts_created_count += 1
            return make_response(
                jsonify(hosts_created=hosts_created_count,
                        hosts_with_errors=hosts_with_errors_count), 200)
        except Exception as e:
            logger.error("Error parsing hosts CSV (%s)", e)
            abort(400, "Error parsing hosts CSV (%s)" % e)
Пример #3
0
 def _perform_create(self, data, **kwargs):
     hostnames = data.pop('hostnames', [])
     host = super()._perform_create(data, **kwargs)
     for name in hostnames:
         get_or_create(db.session, Hostname, name=name, host=host,
                       workspace=host.workspace)
     db.session.commit()
     return host
Пример #4
0
def update_executors(agent, executors):
    incoming_executor_names = set()
    for raw_executor in executors:
        if 'executor_name' not in raw_executor or 'args' not in raw_executor:
            continue
        executor, _ = get_or_create(
            db.session,
            Executor,
            **{
                'name': raw_executor['executor_name'],
                'agent': agent,
            }
        )

        executor.parameters_metadata = raw_executor['args']
        db.session.add(executor)
        db.session.commit()
        incoming_executor_names.add(raw_executor['executor_name'])

    current_executors = Executor.query.filter(Executor.agent == agent)
    for current_executor in current_executors:
        if current_executor.name not in incoming_executor_names:
            db.session.delete(current_executor)
            db.session.commit()

    return True
Пример #5
0
 def _process_attachments(self, obj, attachments):
     old_attachments = db.session.query(File).filter_by(
         object_id=obj.id,
         object_type='vulnerability',
     )
     for old_attachment in old_attachments:
         db.session.delete(old_attachment)
     for filename, attachment in attachments.items():
         faraday_file = FaradayUploadedFile(b64decode(attachment['data']))
         get_or_create(
             db.session,
             File,
             object_id=obj.id,
             object_type='vulnerability',
             name=os.path.splitext(os.path.basename(filename))[0],
             filename=os.path.basename(filename),
             content=faraday_file,
         )
Пример #6
0
 def _process_attachments(self, obj, attachments):
     old_attachments = db.session.query(File).options(
         joinedload(File.creator), joinedload(File.update_user)).filter_by(
             object_id=obj.id,
             object_type='vulnerability',
         )
     for old_attachment in old_attachments:
         db.session.delete(old_attachment)
     for filename, attachment in attachments.items():
         faraday_file = FaradayUploadedFile(b64decode(attachment['data']))
         get_or_create(
             db.session,
             File,
             object_id=obj.id,
             object_type='vulnerability',
             name=Path(filename).stem,
             filename=Path(filename).name,
             content=faraday_file,
         )
Пример #7
0
def add_custom_field_wizard():
    print('This wizard will guide you to ADD custom field to the vulneraiblity model.')
    field_name = click.prompt('Field name')
    field_display_name = click.prompt('Display name')
    field_type = click.prompt('Field type (int, str, list)', type=click.Choice(['int', 'str', 'list']))
    custom_fields = db.session.query(CustomFieldsSchema)

    #Checks the name of the fields wont be a duplicate
    for custom_field in custom_fields:
        if field_name == custom_field.field_name \
            or field_display_name == custom_field.field_display_name:
            print('Custom field already exists, skipping')
            sys.exit(1)

    current_used_orders = set()

    if custom_fields.count():
        print('Custom field current order')
    for custom_field in custom_fields:
        current_used_orders.add(custom_field.field_order)
        print(f'Field {custom_field.field_display_name}, order {custom_field.field_order}')
    field_order = click.prompt('Field order index')
    invalid_field_order = False
    try:
        int(field_order)
    except ValueError:
        invalid_field_order = True

    while invalid_field_order or int(field_order) in current_used_orders:
        print('Field order already used or invalid value, please choose another value')
        field_order = click.prompt('Field order index')
        try:
            int(field_order)
        except ValueError:
            invalid_field_order = True
            continue
        invalid_field_order = False
    confirmation = click.prompt('New CustomField will be added to vulnerability -> Order {order} ({0},{1},{2}) <-, confirm to continue (yes/no)'\
        .format(field_name, field_display_name, field_type, order=field_order))
    if not confirmation:
        sys.exit(1)

    custom_field_data, created = get_or_create(
            db.session,
            CustomFieldsSchema,
            table_name='vulnerability',
            field_name=field_name,
            field_order=field_order,
    )
    if not created:
        print('Custom field already exists, skipping')
        sys.exit(1)
    custom_field_data.field_display_name = field_display_name
    custom_field_data.field_type = field_type
    db.session.commit()
Пример #8
0
 def _get_create_command_object(self, object, object_type):
     cmd_object_relation, created = get_or_create(
         self.session,
         CommandObject,
         workspace_id=self.workspace.id,
         command_id=self.command_id,
         object_type=object_type,
         object_id=object.id,
     )
     cmd_object_relation.created_persistent = False
     if created:
         self.session.add(cmd_object_relation)
         self.session.commit()
Пример #9
0
 def update(self, new_config=None):
     saved_config, created = get_or_create(db.session,
                                           Configuration,
                                           key=self.settings_key)
     if created:
         saved_config.value = self.update_configuration(new_config)
     else:
         # SQLAlchemy doesn't detect in-place mutations to the structure of a JSON type.
         # Thus, we make a deepcopy of the JSON so SQLAlchemy can detect the changes.
         saved_config.value = self.update_configuration(
             new_config, saved_config.value)
     db.session.commit()
     self.__class__.value.fget.cache_clear()
     if self.must_restart_threads:
         os.kill(os.getpid(), signal.SIGUSR1)
Пример #10
0
    def post_attachment(self, workspace_name, vuln_id):
        """
        ---
        post:
          tags: ["Vulnerability", "File"]
          description: Creates a new attachment in the vuln
          responses:
            201:
              description: Created
        tags: ["Vulnerability", "File"]
        responses:
          200:
            description: Ok
        """

        vuln_workspace_check = db.session.query(
            VulnerabilityGeneric, Workspace.id).join(Workspace).filter(
                VulnerabilityGeneric.id == vuln_id,
                Workspace.name == workspace_name).first()

        if vuln_workspace_check:
            if 'file' not in request.files:
                flask.abort(400)
            vuln = VulnerabilitySchema().dump(vuln_workspace_check[0])
            filename = request.files['file'].filename
            _attachments = vuln['_attachments']
            if filename in _attachments:
                message = 'Evidence already exists in vuln'
                return make_response(
                    flask.jsonify(message=message, success=False, code=400),
                    400)
            else:
                faraday_file = FaradayUploadedFile(
                    request.files['file'].read())
                instance, created = get_or_create(db.session,
                                                  File,
                                                  object_id=vuln_id,
                                                  object_type='vulnerability',
                                                  name=filename,
                                                  filename=filename,
                                                  content=faraday_file)
                db.session.commit()
                message = 'Evidence upload was successful'
                return flask.jsonify({'message': message})
        else:
            flask.abort(404, "Vulnerability not found")
Пример #11
0
def manage(action, json_data, name):
    load_settings()
    if name:
        name = name.lower()
    available_settings = get_all_settings()
    if action in ('show', 'update'):
        if not name:
            click.secho(f"You must indicate a settings name to {action}",
                        fg="red")
            sys.exit(1)
        else:
            if name not in available_settings:
                click.secho(f'Invalid settings: {name}', fg='red')
                return
        settings = get_settings(name)
        if action == "show":
            click.secho(f"Settings for: {name}", fg="green")
            for key, value in settings.value.items():
                click.secho(f"{key}: {value}")
        elif action == "update":
            new_settings = {}
            click.secho(f"Update settings for: {name}", fg="green")
            for key, value in settings.value.items():
                if json_data is not None:
                    json_value = json_data.get(key, None)
                    if type(json_value) != type(value) or json_value is None:
                        click.secho(
                            f"Missing or Invalid value for {key} [{json_value}]",
                            fg="red")
                        sys.exit(1)
                    else:
                        new_value = json_value
                else:
                    new_value = click.prompt(f'{key}', default=value)
                new_settings[key] = new_value
            try:
                settings.validate_configuration(new_settings)
            except InvalidConfigurationError as e:
                click.secho(f"Invalid configuration for: {name}", fg="red")
                click.secho(e, fg="red")
                sys.exit(1)
            else:
                settings_message = "\n".join(
                    [f"{key}: {value}" for key, value in new_settings.items()])
                confirm = json_data is not None
                if not confirm:
                    confirm = click.confirm(
                        f"Do you confirm your changes on {name}?"
                        f"\n----------------------"
                        f"\n{settings_message}\n",
                        default=True)
                if confirm:
                    with get_app().app_context():
                        saved_config, created = get_or_create(
                            db.session,
                            Configuration,
                            key=settings.settings_key)
                        if created:
                            saved_config.value = settings.update_configuration(
                                new_settings)
                        else:
                            # SQLAlchemy doesn't detect in-place mutations to the structure of a JSON type.
                            # Thus, we make a deepcopy of the JSON so SQLAlchemy can detect the changes.
                            saved_config.value = settings.update_configuration(
                                new_settings, saved_config.value)
                        db.session.commit()
                        click.secho("Updated!!", fg='green')
                else:
                    click.secho("No changes where made to the settings",
                                fg="green")

    else:
        click.secho("Available settings:", fg="green")
        for i in available_settings:
            click.secho(i)