Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion docs/docs/usage/evaluate/findings/findings.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ Each Finding is deduplicated by its combination of value, type, and field. If th

Additional types exist for Active Directory findings (SID, delegation, Kerberoastable accounts, ASREPRoastable accounts, etc.).

## Sensitive Findings

Some Finding types carry secret material. Credentials Findings, whose value is a `username:password`
or `username:hash` pair, are flagged as **sensitive**: their value is redacted everywhere the
platform returns it (list, detail, Simulation, Scenario, Endpoint and Inject views), so
`jdoe:Sup3rS3cret` is displayed and returned by the API as `jdoe:******`.

The identity part is kept so you can still recognise which account was compromised; the secret part
is never disclosed.

!!! warning "The secret is not deleted"

The full value is still stored in the database, because deduplication, correlation and attack
path computation rely on it. Only its API representation is redacted: it is not possible to
retrieve the cleartext value of a sensitive Finding through the REST API.

Sensitivity is decided per Finding type, not per Finding: Credentials is the only sensitive type
today. Findings created before the upgrade are flagged retroactively, so previously detected
credentials are redacted as well.

## Findings list

Navigate to **Findings** in the left menu to see all Findings in an aggregated view. The list groups Findings by unique value and type, merging Assets from all occurrences into a single row.
Expand All @@ -42,7 +62,7 @@ Each row displays:
| Column | Description |
|---|---|
| Type | The Finding category (CVE, Port, Credentials, etc.) |
| Value | The technical value (monospace display) |
| Value | The technical value (monospace display), redacted for sensitive Findings |
| Assets | Endpoints where the Finding was detected |
| Asset groups | Asset groups containing affected endpoints |
| First seen | When the Finding was first detected |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.openaev.migration;

import java.sql.Statement;
import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import org.springframework.stereotype.Component;

/**
* Flags findings whose value holds sensitive material, so the API can redact them.
*
* <p>The column defaults to {@code false}: only the finding types declared sensitive by their
* output processor are flagged. Credentials findings are the only ones today - their value is
* {@code username:password} or {@code username:hash} - so existing rows of that type are backfilled
* to keep already detected credentials masked, not only the ones detected after the upgrade.
*
* <p>The stored value stays cleartext (deduplication, correlation and attack paths rely on it); the
* redaction happens at serialization time.
*/
@Component
public class V6_20260824180000000__Add_finding_is_sensitive extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
try (Statement statement = context.getConnection().createStatement()) {
statement.execute(
"""
ALTER TABLE findings
ADD COLUMN IF NOT EXISTS finding_is_sensitive BOOLEAN NOT NULL DEFAULT FALSE;
""");

statement.execute(
"""
UPDATE findings
SET finding_is_sensitive = TRUE
WHERE finding_type = 'Credentials'
AND finding_is_sensitive IS FALSE;
""");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public AccountWithPasswordNotRequiredOutputProcessor(FindingService findingServi
new ContractOutputField(ACCOUNT, ContractOutputTechnicalType.Text, true),
new ContractOutputField(STATUS, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public ActionOutputOutputProcessor(FindingService findingService) {
ContractOutputType.ActionOutput,
ContractOutputTechnicalType.Text,
List.of(),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public AdminUsernameOutputProcessor(FindingService findingService) {
new ContractOutputField(ASSET_ID, ContractOutputTechnicalType.Text, false),
new ContractOutputField(USERNAME, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public AsreproastableAccountOutputProcessor(FindingService findingService) {
new ContractOutputField(USERNAME, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HASH, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ public CVEOutputProcessor(
new ContractOutputField(ID, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, true),
new ContractOutputField(SEVERITY, ContractOutputTechnicalType.Text, true)),
findingService);
findingService,
NOT_SENSITIVE);
this.injectExpectationService = injectExpectationService;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public ComputerOutputProcessor(FindingService findingService) {
new ContractOutputField(ASSET_ID, ContractOutputTechnicalType.Text, false),
new ContractOutputField(COMPUTER_NAME, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public CredentialsOutputProcessor(FindingService findingService) {
new ContractOutputField(PASSWORD, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HASH, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public DelegationOutputProcessor(FindingService findingService) {
new ContractOutputField(DELEGATION_TYPE, ContractOutputTechnicalType.Text, false),
new ContractOutputField(RIGHTS_TO, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public EmailOutputProcessor(FindingService findingService) {
List.of(
new ContractOutputField(ASSET_ID, ContractOutputTechnicalType.Text, false),
new ContractOutputField(EMAIL, ContractOutputTechnicalType.Text, true)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ public FileOutputProcessor(FindingService findingService) {
new ContractOutputField(PATH, ContractOutputTechnicalType.Text, false),
new ContractOutputField(SHARE, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,37 @@
import io.openaev.rest.inject.service.ExecutionProcessingContext;
import java.util.Collections;
import java.util.List;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/** Abstract base class for output processors that are capable of generating findings. */
@Slf4j
public abstract class FindingCapableOutputProcessor extends AbstractOutputProcessor {

/** Sensitivity decision of a finding type, hardcoded by each processor. */
protected static final boolean SENSITIVE = true;

protected static final boolean NOT_SENSITIVE = false;

protected final FindingService findingService;

/**
* Whether the findings produced by this processor hold sensitive material (secrets, hashes...).
* The sensitivity is a property of the finding TYPE, decided once per processor, and is persisted
* on every finding it creates so the API can redact the value when serializing it. The database
* keeps the cleartext value.
*/
@Getter private final boolean sensitive;

protected FindingCapableOutputProcessor(
ContractOutputType type,
ContractOutputTechnicalType technicalType,
List<ContractOutputField> fields,
FindingService findingService) {
FindingService findingService,
boolean sensitive) {
super(type, technicalType, fields);
this.findingService = findingService;
this.sensitive = sensitive;
}

/**
Expand All @@ -44,7 +60,8 @@ public final void process(
this::toFindingValue,
this::toFindingAssets,
this::toFindingTeams,
this::toFindingUsers);
this::toFindingUsers,
this.sensitive);
Comment thread
heditar marked this conversation as resolved.
afterFindings(executionContext, structuredOutputNode);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public GroupOutputProcessor(FindingService findingService) {
new ContractOutputField(MEMBER_COUNT, ContractOutputTechnicalType.Text, false),
new ContractOutputField(RID, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ public class IPv4OutputProcessor extends FindingCapableOutputProcessor {
private static final InetAddressValidator VALIDATOR = InetAddressValidator.getInstance();

public IPv4OutputProcessor(FindingService findingService) {
super(ContractOutputType.IPv4, ContractOutputTechnicalType.Text, List.of(), findingService);
super(
ContractOutputType.IPv4,
ContractOutputTechnicalType.Text,
List.of(),
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ public class IPv6OutputProcessor extends FindingCapableOutputProcessor {
private static final InetAddressValidator VALIDATOR = InetAddressValidator.getInstance();

public IPv6OutputProcessor(FindingService findingService) {
super(ContractOutputType.IPv6, ContractOutputTechnicalType.Text, List.of(), findingService);
super(
ContractOutputType.IPv6,
ContractOutputTechnicalType.Text,
List.of(),
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public KerberoastableAccountOutputProcessor(FindingService findingService) {
new ContractOutputField(USERNAME, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HASH, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
public class NumberOutputProcessor extends FindingCapableOutputProcessor {

public NumberOutputProcessor(FindingService findingService) {
super(ContractOutputType.Number, ContractOutputTechnicalType.Number, List.of(), findingService);
super(
ContractOutputType.Number,
ContractOutputTechnicalType.Number,
List.of(),
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public PasswordPolicyOutputProcessor(FindingService findingService) {
new ContractOutputField(KEY, ContractOutputTechnicalType.Text, true),
new ContractOutputField(VALUE, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
public class PortOutputProcessor extends FindingCapableOutputProcessor {

public PortOutputProcessor(FindingService findingService) {
super(ContractOutputType.Port, ContractOutputTechnicalType.Number, List.of(), findingService);
super(
ContractOutputType.Port,
ContractOutputTechnicalType.Number,
List.of(),
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public PortScanOutputProcessor(FindingService findingService) {
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, true),
new ContractOutputField(PORT, ContractOutputTechnicalType.Number, true),
new ContractOutputField(SERVICE, ContractOutputTechnicalType.Text, true)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public ShareOutputProcessor(FindingService findingService) {
new ContractOutputField(SHARE_NAME, ContractOutputTechnicalType.Text, true),
new ContractOutputField(PERMISSIONS, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public SidOutputProcessor(FindingService findingService) {
new ContractOutputField(ASSET_ID, ContractOutputTechnicalType.Text, false),
new ContractOutputField(SID, ContractOutputTechnicalType.Text, true),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
public class TextOutputProcessor extends FindingCapableOutputProcessor {

public TextOutputProcessor(FindingService findingService) {
super(ContractOutputType.Text, ContractOutputTechnicalType.Text, List.of(), findingService);
super(
ContractOutputType.Text,
ContractOutputTechnicalType.Text,
List.of(),
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public UsernameOutputProcessor(FindingService findingService) {
new ContractOutputField(USERNAME, ContractOutputTechnicalType.Text, true),
new ContractOutputField(DOMAIN, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public VulnerabilityOutputProcessor(FindingService findingService) {
new ContractOutputField(STATUS, ContractOutputTechnicalType.Text, true),
new ContractOutputField(DETAILS, ContractOutputTechnicalType.Text, false),
new ContractOutputField(HOST, ContractOutputTechnicalType.Text, false)),
findingService);
findingService,
NOT_SENSITIVE);
}

@Override
Expand Down
Loading
Loading