From 7e065008052834c318a64e7128367142fe8cd804 Mon Sep 17 00:00:00 2001 From: Pablo Santiago Date: Sun, 29 Dec 2024 17:25:20 +0100 Subject: [PATCH 1/2] Generate hash value per execution and use it to identify fixed findings --- src/backend/executions/models.py | 1 + src/backend/findings/queues.py | 18 ++++++------------ src/backend/tools/executors/base.py | 18 +++++++++++++++--- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/backend/executions/models.py b/src/backend/executions/models.py index cf6e3e2b..34bf5fa4 100644 --- a/src/backend/executions/models.py +++ b/src/backend/executions/models.py @@ -28,6 +28,7 @@ class Execution(BaseModel): enqueued_at = models.DateTimeField(blank=True, null=True) start = models.DateTimeField(blank=True, null=True) end = models.DateTimeField(blank=True, null=True) + hash = models.TextField(max_length=128, blank=True, null=True) defectdojo_test_id = models.IntegerField(blank=True, null=True) def __str__(self) -> str: diff --git a/src/backend/findings/queues.py b/src/backend/findings/queues.py index e0cfa50a..d75a3a78 100644 --- a/src/backend/findings/queues.py +++ b/src/backend/findings/queues.py @@ -63,15 +63,9 @@ def consume(execution: Execution, findings: list[Finding]) -> None: platform.process_alert(alert, finding) break if settings.auto_fix_findings: - # TODO: TEST! - completed_executions = Execution.objects.filter( - configuration=execution.configuration, - task__target=execution.task.target, - # task__wordlists__in=execution.task.wordlists.all(), - # task__input_technologies__in=execution.task.input_technologies.all(), - # task__input_vulnerabilities__in=execution.task.input_vulnerabilities.all(), - status=Status.COMPLETED, - ).exclude(id=execution.id) + previous_executions = Execution.objects.filter( + hash=execution.hash, status=Status.COMPLETED + ) for finding_type in [ OSINT, Host, @@ -83,7 +77,7 @@ def consume(execution: Execution, findings: list[Finding]) -> None: Exploit, ]: finding_type.objects.fix( - finding_type.objects.filter( # .exclude(executions__id=execution.id) - executions__in=completed_executions - ).all() + finding_type.objects.exclude(executions__id=execution.id) + .filter(executions__in=previous_executions) + .all() ) diff --git a/src/backend/tools/executors/base.py b/src/backend/tools/executors/base.py index c83d930f..3ff6ed59 100644 --- a/src/backend/tools/executors/base.py +++ b/src/backend/tools/executors/base.py @@ -18,6 +18,7 @@ from http_headers.models import HttpHeader from parameters.models import InputTechnology, InputVulnerability from rekono.settings import CONFIG +from security.cryptography.hashing import hash from settings.models import Settings from target_ports.models import TargetPort from tools.models import Intensity @@ -41,6 +42,7 @@ def __init__(self, execution: Execution) -> None: / f'{str(uuid.uuid4())}.{execution.configuration.tool.output_format or "txt"}' ) self.arguments: list[str] = [] + self.environment: dict[str, Any] = {} self.findings_used_in_execution: dict[Any, BaseInput] = {} self.authentication: Optional[Authentication] = None @@ -256,8 +258,18 @@ def _on_completed(self, output: str) -> None: if self.execution.configuration.tool.output_format and self.report.is_file(): self.execution.output_file = self.report self.execution.output_plain = output + self.execution.hash = hash( + " ".join( + [f"{k}={v}" for k, v in self.environment.items()] + + [ + a + for a in self.arguments + if str(self.report).lower() not in a.lower() + ] + ).lower() + ) self.execution.save( - update_fields=["status", "end", "output_file", "output_plain"] + update_fields=["status", "end", "output_file", "output_plain", "hash"] ) self._on_task_end() @@ -288,10 +300,10 @@ def execute( logger.error(f"[Tool] {str(error)}") self._on_skip(str(error)) return - environment = self._get_environment() + self.environment = self._get_environment() self._before_running() try: - output = "" if CONFIG.testing else self._run(environment) + output = "" if CONFIG.testing else self._run(self.environment) except (RuntimeError, Exception) as error: logger.error( f"[Tool] {self.execution.configuration.tool.name} execution finish with errors" From 198bcf71154d86e3ea8e3d4d9dd47391e8dad078 Mon Sep 17 00:00:00 2001 From: Pablo Santiago Date: Sun, 29 Dec 2024 17:30:03 +0100 Subject: [PATCH 2/2] Change variable name --- src/backend/findings/queues.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/findings/queues.py b/src/backend/findings/queues.py index d75a3a78..9ae03fe7 100644 --- a/src/backend/findings/queues.py +++ b/src/backend/findings/queues.py @@ -63,7 +63,7 @@ def consume(execution: Execution, findings: list[Finding]) -> None: platform.process_alert(alert, finding) break if settings.auto_fix_findings: - previous_executions = Execution.objects.filter( + same_executions = Execution.objects.filter( hash=execution.hash, status=Status.COMPLETED ) for finding_type in [ @@ -78,6 +78,6 @@ def consume(execution: Execution, findings: list[Finding]) -> None: ]: finding_type.objects.fix( finding_type.objects.exclude(executions__id=execution.id) - .filter(executions__in=previous_executions) + .filter(executions__in=same_executions) .all() )