Skip to content

Commit

Permalink
[backend/frontend] First iteration on custom payloads (#743)
Browse files Browse the repository at this point in the history
  • Loading branch information
SamuelHassine committed Jun 2, 2024
1 parent 65d1ff9 commit 314d236
Show file tree
Hide file tree
Showing 68 changed files with 1,240 additions and 342 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static String computeFailedMessage(@NotNull final EXPECTATION_TYPE expect
? "Not detected"
: PREVENTION.equals(expectationType)
? "Not prevented"
: "Failed";
: "FAILED";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ public List<Contract> contracts() {

private ContractSelect obfuscatorField() {
List<Obfuscator> obfuscators = this.injectorCalderaService.obfuscators();
Map<String, String> obfuscatorChoices = obfuscators.stream()
.collect(Collectors.toMap(Obfuscator::getName, Obfuscator::getName));
Map<String, String> obfuscatorChoices = obfuscators.stream().collect(Collectors.toMap(Obfuscator::getName, Obfuscator::getName));
return selectFieldWithDefault(
"obfuscator",
"Obfuscators",
Expand All @@ -94,19 +93,14 @@ private ContractExpectations expectations() {
detectionExpectation.setType(DETECTION);
detectionExpectation.setName("Expect inject to be detected");
detectionExpectation.setScore(0);

return expectationsField(
"expectations", "Expectations", List.of(preventionExpectation, detectionExpectation)
);
return expectationsField("expectations", "Expectations", List.of(preventionExpectation, detectionExpectation));
}

private List<Contract> abilityContracts(@NotNull final ContractConfig contractConfig) {
// Fields
ContractSelect obfuscatorField = obfuscatorField();
ContractAsset assetField = assetField("assets", "Assets", Multiple);
ContractAssetGroup assetGroupField = assetGroupField("assetgroups", "Asset groups",
Multiple);
// Expectations
ContractAssetGroup assetGroupField = assetGroupField("assetgroups", "Asset groups", Multiple);
ContractExpectations expectationsField = expectations();

List<Ability> abilities = this.injectorCalderaService.abilities();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public ExecutionProcess process(@NotNull final Execution execution, @NotNull fin
execution.addTrace(traceError("Found 0 asset to execute the ability on (likely this inject does not have any target or the targeted asset is inactive and has been purged)"));
}
String contract = inject.getInjectorContract().getId();
if( inject.getInjectorContract().getPayload() != null ) {
// This is a payload, need to create the ability on the fly

}
assets.forEach((asset, aBoolean) -> {
try {
Endpoint executionEndpoint = this.findAndRegisterAssetForExecution(injection.getInjection().getInject(), asset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public CalderaInjector(InjectorService injectorService, CalderaContract contract
false,
"simulation-agent",
executorCommands,
executorClearCommands
executorClearCommands,
true
);
} catch (Exception e) {
log.log(Level.SEVERE, "Error creating Caldera injector (" + e.getMessage() + ")" + "\n" + Arrays.toString(e.getStackTrace()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,13 @@ public class CalderaResultCollector {
private final ThreadPoolTaskScheduler taskScheduler;
private final InjectRepository injectRepository;
private final InjectStatusRepository injectStatusRepository;
private final InjectExpectationService injectExpectationService;
private final CalderaInjectorService calderaService;
private final CalderaInjectorConfig calderaInjectorConfig;
private final EndpointService endpointService;

@PostConstruct
public void init() {
// If enabled, scheduled every X seconds
if (this.config.isEnable()) {
CalderaResultCollectorService service = new CalderaResultCollectorService(this.injectRepository, this.injectStatusRepository, this.injectExpectationService, this.calderaService, this.calderaInjectorConfig, this.endpointService);
CalderaResultCollectorService service = new CalderaResultCollectorService(this.injectRepository, this.injectStatusRepository, this.calderaService);
this.taskScheduler.scheduleAtFixedRate(service, Duration.ofSeconds(60));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,17 @@ public class CalderaResultCollectorService implements Runnable {

private final InjectRepository injectRepository;
private final InjectStatusRepository injectStatusRepository;
private final InjectExpectationService injectExpectationService;
private final CalderaInjectorService calderaService;
private final CalderaInjectorConfig calderaInjectorConfig;
private final EndpointService endpointService;

@Autowired
public CalderaResultCollectorService(
InjectRepository injectRepository,
InjectStatusRepository injectStatusRepository,
InjectExpectationService injectExpectationService,
CalderaInjectorService calderaService,
CalderaInjectorConfig calderaInjectorConfig,
EndpointService endpointService
CalderaInjectorService calderaService
) {
this.injectRepository = injectRepository;
this.injectStatusRepository = injectStatusRepository;
this.injectExpectationService = injectExpectationService;
this.calderaService = calderaService;
this.calderaInjectorConfig = calderaInjectorConfig;
this.endpointService = endpointService;
}

@Override
Expand All @@ -74,15 +65,15 @@ public void run() {
log.log(Level.INFO, "Trying to get result for " + linkId);
resultStatus = this.calderaService.results(linkId);
} catch (Exception e) {
injectStatus.getTraces().add(traceError("Cannot get result for linkID " + linkId + ", injection has failed"));
injectStatus.getTraces().add(traceMaybePrevented("Cannot get result for linkID " + linkId + ", injection has failed"));
log.log(Level.INFO, "Cannot get result for linkID " + linkId + ", injection has failed");
resultStatus.setFail(true);
completedActions.add(resultStatus);
injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1);
}
if (resultStatus.getPaw() == null) {
if (injectStatus.getTrackingSentDate().isBefore(Instant.now().minus(EXPIRATION_TIME / 60, ChronoUnit.MINUTES))) {
injectStatus.getTraces().add(traceError("Cannot get result for linkID " + linkId + ", injection has failed"));
injectStatus.getTraces().add(traceMaybePrevented("Cannot get result for linkID " + linkId + ", injection has failed"));
log.log(Level.INFO, "Cannot get result for linkID " + linkId + ", injection has failed");
resultStatus.setFail(true);
completedActions.add(resultStatus);
Expand All @@ -93,11 +84,7 @@ public void run() {
completedActions.add(resultStatus);
if (resultStatus.isFail()) {
injectStatus.setTrackingTotalError(injectStatus.getTrackingTotalError() + 1);
if (resultStatus.getContent().contains("denied")) {
injectStatus.getTraces().add(traceMaybePrevented("Failed result for linkID " + linkId + " (" + resultStatus.getContent() + ")"));
} else {
injectStatus.getTraces().add(traceError("Failed result for linkID " + linkId + " (" + resultStatus.getContent() + ")"));
}
injectStatus.getTraces().add(traceMaybePrevented("Failed result for linkID " + linkId + " (" + resultStatus.getContent() + ")"));
} else {
injectStatus.setTrackingTotalSuccess(injectStatus.getTrackingTotalSuccess() + 1);
injectStatus.getTraces().add(traceSuccess("Success result for linkID " + linkId + " (" + resultStatus.getContent() + ")"));
Expand All @@ -107,7 +94,7 @@ public void run() {
finalExecutionTime = resultStatus.getFinish();
}
} else if (injectStatus.getTrackingSentDate().isBefore(Instant.now().minus(5L, ChronoUnit.MINUTES))) {
injectStatus.getTraces().add(traceError("Timeout on linkID " + linkId + ", injection has failed"));
injectStatus.getTraces().add(traceMaybePrevented("Timeout on linkID " + linkId + ", injection has failed"));
log.log(Level.INFO, "Timeout on linkID " + linkId + ", injection has failed");
resultStatus.setFail(true);
completedActions.add(resultStatus);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public ChallengeInjector(InjectorService injectorService, ChallengeContract cont
false,
"capture-the-flag",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public List<Contract> contracts() {
// Choices are contextual to a specific exercise.
String messageBody = """
Dear player,<br /><br />
New channel pressure entries have been published.<br /><br />
New media pressure entries have been published.<br /><br />
<#list articles as article>
- <a href="${article.uri}">${article.name}</a><br />
</#list>
Expand All @@ -88,15 +88,15 @@ public List<Contract> contracts() {
.optional(expectationsField)
// Emailing zone
.optional(emailingField)
.mandatory(textField("subject", "Subject", "New channel pressure entries published for ${user.email}",
.mandatory(textField("subject", "Subject", "New media pressure entries published for ${user.email}",
List.of(emailingField)))
.mandatory(richTextareaField("body", "Body", messageBody,
List.of(emailingField)))
.optional(checkboxField("encrypted", "Encrypted", false,
List.of(emailingField)))
.build();
Contract publishArticle = executableContract(contractConfig,
CHANNEL_PUBLISH, Map.of(en, "Publish channel pressure", fr, "Publier de la pression médiatique"), publishInstance, List.of(Endpoint.PLATFORM_TYPE.Internal.name()), false);
CHANNEL_PUBLISH, Map.of(en, "Publish a media pressure", fr, "Publier de la pression médiatique"), publishInstance, List.of(Endpoint.PLATFORM_TYPE.Internal.name()), false);
// Adding generated variables
publishArticle.addVariable(variable(VARIABLE_ARTICLES, "List of articles published by the injection", VariableType.Object, Multiple, List.of(
variable(VARIABLE_ARTICLE + ".id", "Id of the article in the platform", VariableType.String, One),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public ChannelInjector(InjectorService injectorService, ChannelContract contract
false,
"media-pressure",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public EmailInjector(InjectorService injectorService, EmailContract contract) {
false,
"communication",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public LadeInjector(InjectorService injectorService, LadeContract contract) {
false,
"cyber-range",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public ManualInjector(InjectorService injectorService, ManualContract contract)
true,
"generic",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public MastodonInjector(InjectorService injectorService, MastodonContract contra
false,
"social-media",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public OpenCTIInjector(InjectorService injectorService, OpenCTIContract contract
true,
"incident-response",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public OvhSmsInjector(InjectorService injectorService, OvhSmsContract contract)
true,
"communication",
null,
null
null,
false
);
} catch (Exception e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ public class V3_11__Assets extends BaseJavaMigration {
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
Statement select = connection.createStatement();
select.execute("ALTER TABLE assets ADD column asset_process_name varchar(255);");
}
select.execute("ALTER TABLE assets ADD column asset_process_name varchar(255);"); }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.openbas.migration;

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

import java.sql.Connection;
import java.sql.Statement;

@Component
public class V3_12__Payloads extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
Statement select = connection.createStatement();
// Purge
select.execute("TRUNCATE payloads CASCADE;");
select.execute("ALTER TABLE payloads DROP column payload_content;");
select.execute("ALTER TABLE payloads ADD column payload_platforms text[];");
select.execute("ALTER TABLE payloads ADD column command_executor varchar(255);");
select.execute("ALTER TABLE payloads ADD column command_content text;");
select.execute("ALTER TABLE payloads ADD column executable_file varchar(255) constraint executable_file_fk references documents on delete cascade;");
select.execute("ALTER TABLE payloads ADD column file_drop_file varchar(255) constraint file_drop_file_fk references documents on delete cascade;");
select.execute("ALTER TABLE payloads ADD column dns_resolution_hostname text;");
select.execute("ALTER TABLE payloads ADD column network_traffic_ip text;");
select.execute("ALTER TABLE payloads ADD column payload_cleanup_executor varchar(255);");
select.execute("ALTER TABLE payloads ADD column payload_cleanup_command text;");
select.execute("ALTER TABLE payloads ADD column payload_arguments json;");
select.execute("ALTER TABLE payloads ADD column payload_prerequisites json;");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.openbas.migration;

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

import java.sql.Connection;
import java.sql.Statement;

@Component
public class V3_13__Payloads_Attack_Patterns extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
Statement select = connection.createStatement();
// Create relations between contracts and attack_patterns
select.execute("""
CREATE TABLE payloads_attack_patterns (
attack_pattern_id varchar(255) not null
constraint attack_pattern_id_fk
references attack_patterns
on delete cascade,
payload_id varchar(255) not null
constraint payloads_id_fk
references payloads
on delete cascade,
primary key (attack_pattern_id, payload_id)
);
CREATE INDEX idx_payloads_attack_patterns_pattern on payloads_attack_patterns (attack_pattern_id);
CREATE INDEX idx_payloads_attack_patterns_contract on payloads_attack_patterns (payload_id);
""");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.openbas.migration;

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

import java.sql.Statement;

@Component
public class V3_14__Injectors_payload extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Statement select = context.getConnection().createStatement();
select.execute("ALTER TABLE injectors ADD injector_payloads bool default false;");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.openbas.migration;

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

import java.sql.Connection;
import java.sql.Statement;

@Component
public class V3_15__Injector_contracts_Payloads extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
Statement select = connection.createStatement();
// Purge
select.execute("ALTER TABLE injectors_contracts ADD column injector_contract_payload varchar(255) constraint injector_contract_payload_fk references payloads on delete cascade;");
select.execute("CREATE UNIQUE INDEX injector_contract_payload_unique on injectors_contracts (injector_contract_payload, injector_id);");
}
}
Loading

0 comments on commit 314d236

Please sign in to comment.