Skip to content

Commit

Permalink
[backend/frontend] Categorize payload by architecture (#1189)
Browse files Browse the repository at this point in the history
  • Loading branch information
isselparra authored Oct 16, 2024
1 parent 43dc264 commit 6e516e1
Show file tree
Hide file tree
Showing 37 changed files with 495 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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_44__Add_column_executable_arch extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
Statement statement = connection.createStatement();
statement.execute("ALTER TABLE payloads ADD executable_arch varchar(255);");
statement.execute("UPDATE payloads SET executable_arch = 'x86_64' WHERE payload_type ='Executable';");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.List;

@RestController
@RequestMapping("/api/atomic_testings")
@RequestMapping("/api/atomic-testings")
@PreAuthorize("isAdmin()")
@RequiredArgsConstructor
public class AtomicTestingApi extends RestBehavior {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ private void selectForInjectorContract(
injectorContractPayloadJoin.get("type").alias("payload_type"),
payloadCollectorJoin.get("type").alias("collector_type"),
injectorContractInjectorJoin.get("type").alias("injector_contract_injector_type"),
attackPatternIdsExpression.alias("injector_contract_attack_patterns")
attackPatternIdsExpression.alias("injector_contract_attack_patterns"),
injectorContractPayloadJoin.get("executableArch").alias("payload_executable_arch")
).distinct(true);

// GROUP BY
Expand All @@ -146,7 +147,8 @@ private List<InjectorContractOutput> execInjectorContract(TypedQuery<Tuple> quer
tuple.get("payload_type", String.class),
tuple.get("collector_type", String.class),
tuple.get("injector_contract_injector_type", String.class),
tuple.get("injector_contract_attack_patterns", String[].class)
tuple.get("injector_contract_attack_patterns", String[].class),
tuple.get("payload_executable_arch", Endpoint.PLATFORM_ARCH.class)
))
.toList();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.openbas.rest.injector_contract.output;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openbas.database.model.Endpoint;
import io.openbas.database.model.Endpoint.PLATFORM_TYPE;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
Expand Down Expand Up @@ -33,6 +34,9 @@ public class InjectorContractOutput {
@JsonProperty("injector_contract_attack_patterns")
private List<String> attackPatterns;

@JsonProperty("injector_contract_arch")
private Endpoint.PLATFORM_ARCH arch;

public InjectorContractOutput(
String id,
Map<String, String> labels,
Expand All @@ -41,7 +45,8 @@ public InjectorContractOutput(
String payloadType,
String collectorType,
String injectorType,
String[] attackPatterns) {
String[] attackPatterns,
Endpoint.PLATFORM_ARCH arch) {
this.id = id;
this.labels = labels;
this.content = content;
Expand All @@ -50,5 +55,6 @@ public InjectorContractOutput(
this.injectorType = injectorType;

this.attackPatterns = attackPatterns != null ? new ArrayList<>(Arrays.asList(attackPatterns)) : new ArrayList<>();
this.arch = arch;
}
}
81 changes: 51 additions & 30 deletions openbas-api/src/main/java/io/openbas/rest/payload/PayloadApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.openbas.database.model.*;
import io.openbas.database.repository.*;
import io.openbas.integrations.PayloadService;
import io.openbas.rest.exception.BadRequestException;
import io.openbas.rest.exception.ElementNotFoundException;
import io.openbas.rest.helper.RestBehavior;
import io.openbas.rest.payload.form.PayloadCreateInput;
Expand Down Expand Up @@ -91,25 +92,26 @@ public Payload payload(@PathVariable String payloadId) {
@PreAuthorize("isPlanner()")
@Transactional(rollbackOn = Exception.class)
public Payload createPayload(@Valid @RequestBody PayloadCreateInput input) {
switch (input.getType()) {
case "Command":
switch (PayloadType.fromString(input.getType())) {
case PayloadType.COMMAND:
Command commandPayload = new Command();
commandPayload.setUpdateAttributes(input);
commandPayload.setAttackPatterns(fromIterable(attackPatternRepository.findAllById(input.getAttackPatternsIds())));
commandPayload.setTags(iterableToSet(tagRepository.findAllById(input.getTagIds())));
commandPayload = payloadRepository.save(commandPayload);
this.payloadService.updateInjectorContractsForPayload(commandPayload);
return commandPayload;
case "Executable":
case PayloadType.EXECUTABLE:
Executable executablePayload = new Executable();
executablePayload.setUpdateAttributes(input);
executablePayload.setAttackPatterns(fromIterable(attackPatternRepository.findAllById(input.getAttackPatternsIds())));
executablePayload.setTags(iterableToSet(tagRepository.findAllById(input.getTagIds())));
executablePayload.setExecutableFile(documentRepository.findById(input.getExecutableFile()).orElseThrow());
PayloadCreateInput validatedInput = validateExecutableCreateInput(input);
executablePayload.setUpdateAttributes(validatedInput);
executablePayload.setAttackPatterns(fromIterable(attackPatternRepository.findAllById(validatedInput.getAttackPatternsIds())));
executablePayload.setTags(iterableToSet(tagRepository.findAllById(validatedInput.getTagIds())));
executablePayload.setExecutableFile(documentRepository.findById(validatedInput.getExecutableFile()).orElseThrow());
executablePayload = payloadRepository.save(executablePayload);
this.payloadService.updateInjectorContractsForPayload(executablePayload);
return executablePayload;
case "FileDrop":
case PayloadType.FILE_DROP:
FileDrop fileDropPayload = new FileDrop();
fileDropPayload.setUpdateAttributes(input);
fileDropPayload.setAttackPatterns(fromIterable(attackPatternRepository.findAllById(input.getAttackPatternsIds())));
Expand All @@ -118,15 +120,15 @@ public Payload createPayload(@Valid @RequestBody PayloadCreateInput input) {
fileDropPayload = payloadRepository.save(fileDropPayload);
this.payloadService.updateInjectorContractsForPayload(fileDropPayload);
return fileDropPayload;
case "DnsResolution":
case PayloadType.DNS_RESOLUTION:
DnsResolution dnsResolutionPayload = new DnsResolution();
dnsResolutionPayload.setUpdateAttributes(input);
dnsResolutionPayload.setAttackPatterns(fromIterable(attackPatternRepository.findAllById(input.getAttackPatternsIds())));
dnsResolutionPayload.setTags(iterableToSet(tagRepository.findAllById(input.getTagIds())));
dnsResolutionPayload = payloadRepository.save(dnsResolutionPayload);
this.payloadService.updateInjectorContractsForPayload(dnsResolutionPayload);
return dnsResolutionPayload;
case "NetworkTraffic":
case PayloadType.NETWORK_TRAFFIC:
NetworkTraffic networkTrafficPayload = new NetworkTraffic();
networkTrafficPayload.setUpdateAttributes(input);
networkTrafficPayload.setAttackPatterns(fromIterable(attackPatternRepository.findAllById(input.getAttackPatternsIds())));
Expand All @@ -139,6 +141,24 @@ public Payload createPayload(@Valid @RequestBody PayloadCreateInput input) {
}
}

private static PayloadCreateInput validateExecutableCreateInput(PayloadCreateInput input) {
Optional<Endpoint.PLATFORM_ARCH> maybeArch = Optional.ofNullable(input.getExecutableArch());
if (maybeArch.isPresent()) {
return input;
} else {
throw new BadRequestException("Executable arch is missing");
}
}

private static PayloadUpdateInput validateExecutableUpdateInput(PayloadUpdateInput input) {
Optional<Endpoint.PLATFORM_ARCH> maybeArch = Optional.ofNullable(input.getExecutableArch());
if (maybeArch.isPresent()) {
return input;
} else {
throw new BadRequestException("Executable arch is missing");
}
}

@PutMapping("/api/payloads/{payloadId}")
@PreAuthorize("isPlanner()")
@Transactional(rollbackOn = Exception.class)
Expand All @@ -149,34 +169,35 @@ public Payload updatePayload(
payload.setAttackPatterns(fromIterable(attackPatternRepository.findAllById(input.getAttackPatternsIds())));
payload.setTags(iterableToSet(tagRepository.findAllById(input.getTagIds())));
payload.setUpdatedAt(Instant.now());
switch (payload.getType()) {
case "Command":
switch (PayloadType.fromString(payload.getType())) {
case PayloadType.COMMAND:
Command payloadCommand = (Command) Hibernate.unproxy(payload);
payloadCommand.setUpdateAttributes(input);
payloadCommand = payloadRepository.save(payloadCommand);
this.payloadService.updateInjectorContractsForPayload(payloadCommand);
return payloadCommand;
case "Executable":
case PayloadType.EXECUTABLE:
PayloadUpdateInput validatedInput = validateExecutableUpdateInput(input);
Executable payloadExecutable = (Executable) Hibernate.unproxy(payload);
payloadExecutable.setUpdateAttributes(input);
payloadExecutable.setExecutableFile(documentRepository.findById(input.getExecutableFile()).orElseThrow());
payloadExecutable.setUpdateAttributes(validatedInput);
payloadExecutable.setExecutableFile(documentRepository.findById(validatedInput.getExecutableFile()).orElseThrow());
payloadExecutable = payloadRepository.save(payloadExecutable);
this.payloadService.updateInjectorContractsForPayload(payloadExecutable);
return payloadExecutable;
case "FileDrop":
case PayloadType.FILE_DROP:
FileDrop payloadFileDrop = (FileDrop) Hibernate.unproxy(payload);
payloadFileDrop.setUpdateAttributes(input);
payloadFileDrop.setFileDropFile(documentRepository.findById(input.getFileDropFile()).orElseThrow());
payloadFileDrop = payloadRepository.save(payloadFileDrop);
this.payloadService.updateInjectorContractsForPayload(payloadFileDrop);
return payloadFileDrop;
case "DnsResolution":
case PayloadType.DNS_RESOLUTION:
DnsResolution payloadDnsResolution = (DnsResolution) Hibernate.unproxy(payload);
payloadDnsResolution.setUpdateAttributes(input);
payloadDnsResolution = payloadRepository.save(payloadDnsResolution);
this.payloadService.updateInjectorContractsForPayload(payloadDnsResolution);
return payloadDnsResolution;
case "NetworkTraffic":
case PayloadType.NETWORK_TRAFFIC:
NetworkTraffic payloadNetworkTraffic = (NetworkTraffic) Hibernate.unproxy(payload);
payloadNetworkTraffic.setUpdateAttributes(input);
payloadNetworkTraffic = payloadRepository.save(payloadNetworkTraffic);
Expand Down Expand Up @@ -207,34 +228,34 @@ public Payload upsertPayload(@Valid @RequestBody PayloadUpsertInput input) {
existingPayload.setAttackPatterns(fromIterable(attackPatternRepository.findAllByExternalIdInIgnoreCase(input.getAttackPatternsExternalIds())));
existingPayload.setTags(iterableToSet(tagRepository.findAllById(input.getTagIds())));
existingPayload.setUpdatedAt(Instant.now());
switch (existingPayload.getType()) {
case "Command":
switch (PayloadType.fromString(existingPayload.getType())) {
case PayloadType.COMMAND:
Command payloadCommand = (Command) Hibernate.unproxy(existingPayload);
payloadCommand.setUpdateAttributes(input);
payloadCommand = payloadRepository.save(payloadCommand);
this.payloadService.updateInjectorContractsForPayload(payloadCommand);
return payloadCommand;
case "Executable":
case PayloadType.EXECUTABLE:
Executable payloadExecutable = (Executable) Hibernate.unproxy(existingPayload);
payloadExecutable.setUpdateAttributes(input);
payloadExecutable.setExecutableFile(documentRepository.findById(input.getExecutableFile()).orElseThrow());
payloadExecutable = payloadRepository.save(payloadExecutable);
this.payloadService.updateInjectorContractsForPayload(payloadExecutable);
return payloadExecutable;
case "FileDrop":
case PayloadType.FILE_DROP:
FileDrop payloadFileDrop = (FileDrop) Hibernate.unproxy(existingPayload);
payloadFileDrop.setUpdateAttributes(input);
payloadFileDrop.setFileDropFile(documentRepository.findById(input.getFileDropFile()).orElseThrow());
payloadFileDrop = payloadRepository.save(payloadFileDrop);
this.payloadService.updateInjectorContractsForPayload(payloadFileDrop);
return payloadFileDrop;
case "DnsResolution":
case PayloadType.DNS_RESOLUTION:
DnsResolution payloadDnsResolution = (DnsResolution) Hibernate.unproxy(existingPayload);
payloadDnsResolution.setUpdateAttributes(input);
payloadDnsResolution = payloadRepository.save(payloadDnsResolution);
this.payloadService.updateInjectorContractsForPayload(payloadDnsResolution);
return payloadDnsResolution;
case "NetworkTraffic":
case PayloadType.NETWORK_TRAFFIC:
NetworkTraffic payloadNetworkTraffic = (NetworkTraffic) Hibernate.unproxy(existingPayload);
payloadNetworkTraffic.setUpdateAttributes(input);
payloadNetworkTraffic = payloadRepository.save(payloadNetworkTraffic);
Expand All @@ -244,8 +265,8 @@ public Payload upsertPayload(@Valid @RequestBody PayloadUpsertInput input) {
throw new UnsupportedOperationException("Payload type " + existingPayload.getType() + " is not supported");
}
} else {
switch (input.getType()) {
case "Command":
switch (PayloadType.fromString(input.getType())) {
case PayloadType.COMMAND:
Command commandPayload = new Command();
commandPayload.setUpdateAttributes(input);
if( input.getCollector() != null ) {
Expand All @@ -256,7 +277,7 @@ public Payload upsertPayload(@Valid @RequestBody PayloadUpsertInput input) {
commandPayload = payloadRepository.save(commandPayload);
this.payloadService.updateInjectorContractsForPayload(commandPayload);
return commandPayload;
case "Executable":
case PayloadType.EXECUTABLE:
Executable executablePayload = new Executable();
executablePayload.setUpdateAttributes(input);
if( input.getCollector() != null ) {
Expand All @@ -268,7 +289,7 @@ public Payload upsertPayload(@Valid @RequestBody PayloadUpsertInput input) {
executablePayload = payloadRepository.save(executablePayload);
this.payloadService.updateInjectorContractsForPayload(executablePayload);
return executablePayload;
case "FileDrop":
case PayloadType.FILE_DROP:
FileDrop fileDropPayload = new FileDrop();
fileDropPayload.setUpdateAttributes(input);
if( input.getCollector() != null ) {
Expand All @@ -280,7 +301,7 @@ public Payload upsertPayload(@Valid @RequestBody PayloadUpsertInput input) {
fileDropPayload = payloadRepository.save(fileDropPayload);
this.payloadService.updateInjectorContractsForPayload(fileDropPayload);
return fileDropPayload;
case "DnsResolution":
case PayloadType.DNS_RESOLUTION:
DnsResolution dnsResolutionPayload = new DnsResolution();
dnsResolutionPayload.setUpdateAttributes(input);
if( input.getCollector() != null ) {
Expand All @@ -291,7 +312,7 @@ public Payload upsertPayload(@Valid @RequestBody PayloadUpsertInput input) {
dnsResolutionPayload = payloadRepository.save(dnsResolutionPayload);
this.payloadService.updateInjectorContractsForPayload(dnsResolutionPayload);
return dnsResolutionPayload;
case "NetworkTraffic":
case PayloadType.NETWORK_TRAFFIC:
NetworkTraffic networkTrafficPayload = new NetworkTraffic();
networkTrafficPayload.setUpdateAttributes(input);
if( input.getCollector() != null ) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.openbas.rest.payload.form;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openbas.database.model.Endpoint;
import io.openbas.database.model.Endpoint.PLATFORM_TYPE;
import io.openbas.database.model.Payload.PAYLOAD_SOURCE;
import io.openbas.database.model.Payload.PAYLOAD_STATUS;
Expand Down Expand Up @@ -50,6 +51,9 @@ public class PayloadCreateInput {
@JsonProperty("command_content")
private String content;

@JsonProperty("executable_arch")
private Endpoint.PLATFORM_ARCH executableArch;

@JsonProperty("executable_file")
private String executableFile;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.openbas.rest.payload.form;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openbas.database.model.Endpoint;
import io.openbas.database.model.Endpoint.PLATFORM_TYPE;
import io.openbas.database.model.PayloadArgument;
import io.openbas.database.model.PayloadPrerequisite;
Expand Down Expand Up @@ -32,6 +33,9 @@ public class PayloadUpdateInput {
@JsonProperty("command_content")
private String content;

@JsonProperty("executable_arch")
private Endpoint.PLATFORM_ARCH executableArch;

@JsonProperty("executable_file")
private String executableFile;

Expand Down
4 changes: 2 additions & 2 deletions openbas-api/src/main/java/io/openbas/schema/SchemaApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ public List<PropertySchemaDTO> schemas(
@RequestBody @Valid @NotNull List<String> filterNames) throws ClassNotFoundException {
String completeClassName = "io.openbas.database.model." + className;
if (filterableOnly) {
return SchemaUtils.schema(Class.forName(completeClassName))
return SchemaUtils.schemaWithSubtypes(Class.forName(completeClassName))
.stream()
.filter(PropertySchema::isFilterable)
.filter(p -> filterNames.isEmpty() || filterNames.contains(p.getJsonName()))
.map(PropertySchemaDTO::new)
.toList();
}
return SchemaUtils.schema(Class.forName(completeClassName))
return SchemaUtils.schemaWithSubtypes(Class.forName(completeClassName))
.stream()
.filter(p -> filterNames.isEmpty() || filterNames.contains(p.getJsonName()))
.map(PropertySchemaDTO::new)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class InjectHelperTest {
void injectsToRunTest() {
// -- PREPARE --
Exercise exercise = new Exercise();
exercise.setName("Exercice name");
exercise.setName("Exercise name");
exercise.setStart(Instant.now());
exercise.setFrom("[email protected]");
exercise.setReplyTos(List.of("[email protected]"));
Expand Down
Loading

0 comments on commit 6e516e1

Please sign in to comment.