Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[backend/frontend] Adapt backend on new agent logic #2133

Merged
merged 18 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ public void run() {
inactiveEndpoints.forEach(
endpoint -> {
Optional<Endpoint> optionalExistingEndpoint =
this.endpointService.findByExternalReference(endpoint.getExternalReference());
this.endpointService.findByExternalReference(
endpoint.getAgents().getFirst().getExternalReference());
if (optionalExistingEndpoint.isPresent()) {
Endpoint existingEndpoint = optionalExistingEndpoint.get();
if ((now().toEpochMilli() - existingEndpoint.getClearedAt().toEpochMilli())
Expand Down Expand Up @@ -168,16 +169,22 @@ protected Optional<Endpoint> findExistingEndpointForAnAgent(@NotNull final Agent

private Endpoint toEndpoint(@NotNull final Agent agent) {
Endpoint endpoint = new Endpoint();
endpoint.setExecutor(this.executor);
endpoint.setExternalReference(agent.getPaw());
endpoint.setName(agent.getHost());
endpoint.setDescription("Asset collected by Caldera executor context.");
endpoint.setIps(agent.getHost_ip_addrs());
endpoint.setHostname(agent.getHost());
endpoint.setPlatform(toPlatform(agent.getPlatform()));
endpoint.setArch(toArch(agent.getArchitecture()));
endpoint.setProcessName(agent.getExe_name());
endpoint.setLastSeen(toInstant(agent.getLast_seen()));
io.openbas.database.model.Agent agentEndpoint = new io.openbas.database.model.Agent();
agentEndpoint.setExecutor(this.executor);
agentEndpoint.setExternalReference(agent.getPaw());
agentEndpoint.setPrivilege(io.openbas.database.model.Agent.PRIVILEGE.admin);
agentEndpoint.setDeploymentMode(io.openbas.database.model.Agent.DEPLOYMENT_MODE.session);
agentEndpoint.setExecutedByUser(agent.getUsername());
agentEndpoint.setLastSeen(toInstant(agent.getLast_seen()));
agentEndpoint.setProcessName(agent.getExe_name());
agentEndpoint.setAsset(endpoint);
endpoint.setAgents(List.of(agentEndpoint));
return endpoint;
}

Expand All @@ -187,15 +194,16 @@ private List<Endpoint> toEndpoint(@NotNull final List<Agent> agents) {

private void updateEndpoint(
@NotNull final Agent agent, @NotNull final Endpoint existingEndpoint) {
existingEndpoint.setLastSeen(toInstant(agent.getLast_seen()));
existingEndpoint.setExternalReference(agent.getPaw());
existingEndpoint.getAgents().getFirst().setLastSeen(toInstant(agent.getLast_seen()));
existingEndpoint.getAgents().getFirst().setExternalReference(agent.getPaw());
existingEndpoint.getAgents().getFirst().setExecutedByUser(agent.getUsername());
existingEndpoint.getAgents().getFirst().setExecutor(this.executor);
existingEndpoint.setName(agent.getHost());
existingEndpoint.setIps(agent.getHost_ip_addrs());
existingEndpoint.setHostname(agent.getHost());
existingEndpoint.setProcessName(agent.getExe_name());
existingEndpoint.getAgents().getFirst().setProcessName(agent.getExe_name());
existingEndpoint.setPlatform(toPlatform(agent.getPlatform()));
existingEndpoint.setArch(toArch(agent.getArchitecture()));
existingEndpoint.setExecutor(this.executor);
if ((now().toEpochMilli() - existingEndpoint.getClearedAt().toEpochMilli()) > CLEAR_TTL) {
try {
log.info("Clearing endpoint " + existingEndpoint.getHostname());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,25 @@
String result =
this.calderaService.exploit(
obfuscator,
executionEndpoint.getExternalReference(),
executionEndpoint.getAgents().getFirst().getExternalReference(),

Check warning on line 136 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L136

Added line #L136 was not covered by tests
contract,
additionalFields);
if (result.contains("complete")) {
ExploitResult exploitResult =
this.calderaService.exploitResult(
executionEndpoint.getExternalReference(), contract);
executionEndpoint.getAgents().getFirst().getExternalReference(),

Check warning on line 142 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L142

Added line #L142 was not covered by tests
contract);
asyncIds.add(exploitResult.getLinkId());
execution.addTrace(
traceInfo(EXECUTION_TYPE_COMMAND, exploitResult.getCommand()));
// Compute expectations
boolean isInGroup = assets.get(executionEndpoint.getParent());
boolean isInGroup =
assets.get(

Check warning on line 149 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L148-L149

Added lines #L148 - L149 were not covered by tests
executionEndpoint
.getAgents()
.getFirst()
.getParent()
.getAsset());

Check warning on line 154 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L151-L154

Added lines #L151 - L154 were not covered by tests
List<InjectExpectationSignature> injectExpectationSignatures =
new ArrayList<>();
if (injectorContract.getPayload() != null) {
Expand All @@ -153,7 +160,11 @@
injectExpectationSignatures.add(
InjectExpectationSignature.builder()
.type(EXPECTATION_SIGNATURE_TYPE_PROCESS_NAME)
.value(executionEndpoint.getProcessName())
.value(

Check warning on line 163 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L163

Added line #L163 was not covered by tests
executionEndpoint
.getAgents()
.getFirst()
.getProcessName())

Check warning on line 167 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L165-L167

Added lines #L165 - L167 were not covered by tests
.build());
break;
case PayloadType.EXECUTABLE:
Expand Down Expand Up @@ -198,23 +209,27 @@
injectExpectationSignatures.add(
InjectExpectationSignature.builder()
.type(EXPECTATION_SIGNATURE_TYPE_PROCESS_NAME)
.value(executionEndpoint.getProcessName())
.value(
executionEndpoint.getAgents().getFirst().getProcessName())

Check warning on line 213 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L212-L213

Added lines #L212 - L213 were not covered by tests
.build());
}
computeExpectationsForAsset(
expectations,
content,
executionEndpoint.getParent(),
executionEndpoint.getAgents().getFirst().getParent().getAsset(),

Check warning on line 219 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L219

Added line #L219 was not covered by tests
isInGroup,
injectExpectationSignatures);
execution.addTrace(
traceInfo(
"Caldera executed the ability on asset "
+ asset.getName()
+ " using "
+ executionEndpoint.getProcessName()
+ executionEndpoint.getAgents().getFirst().getProcessName()

Check warning on line 227 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L227

Added line #L227 was not covered by tests
+ " (paw: "
+ executionEndpoint.getExternalReference()
+ executionEndpoint
.getAgents()
.getFirst()
.getExternalReference()

Check warning on line 232 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L230-L232

Added lines #L230 - L232 were not covered by tests
+ ", linkID: "
+ exploitResult.getLinkId()
+ ")"));
Expand Down Expand Up @@ -350,7 +365,7 @@
agent.getExe_name().contains("implant")
&& (now().toEpochMilli()
- Time.toInstant(agent.getCreated()).toEpochMilli())
< Asset.ACTIVE_THRESHOLD
< io.openbas.database.model.Agent.ACTIVE_THRESHOLD
&& (agent.getHost().equals(assetEndpoint.getHostname())
|| agent
.getHost()
Expand All @@ -370,16 +385,22 @@
if (resolvedExistingEndpoint.isEmpty()) {
log.log(Level.INFO, "Agent found and not present in the database, creating it...");
Endpoint newEndpoint = new Endpoint();
newEndpoint.setInject(inject);
newEndpoint.setParent(asset);
io.openbas.database.model.Agent newAgent = new io.openbas.database.model.Agent();
newAgent.setInject(inject);
newAgent.setParent(assetEndpoint.getAgents().getFirst());

Check warning on line 390 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L388-L390

Added lines #L388 - L390 were not covered by tests
newEndpoint.setName(assetEndpoint.getName());
newEndpoint.setIps(assetEndpoint.getIps());
newEndpoint.setHostname(assetEndpoint.getHostname());
newEndpoint.setPlatform(assetEndpoint.getPlatform());
newEndpoint.setArch(assetEndpoint.getArch());
newEndpoint.setExternalReference(agent.getPaw());
newEndpoint.setExecutor(assetEndpoint.getExecutor());
newEndpoint.setProcessName(agent.getExe_name());
newAgent.setProcessName(agent.getExe_name());
newAgent.setExecutor(assetEndpoint.getExecutor());
newAgent.setExternalReference(agent.getPaw());
newAgent.setPrivilege(io.openbas.database.model.Agent.PRIVILEGE.admin);
newAgent.setDeploymentMode(io.openbas.database.model.Agent.DEPLOYMENT_MODE.session);
newAgent.setExecutedByUser(agent.getUsername());
newAgent.setAsset(newEndpoint);
newEndpoint.setAgents(List.of(newAgent));

Check warning on line 403 in openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaExecutor.java#L396-L403

Added lines #L396 - L403 were not covered by tests
endpointForExecution = this.endpointService.createEndpoint(newEndpoint);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@
body.put("sleep_min", 3);
body.put("sleep_max", 3);
this.patch(
this.config.getRestApiV2Url() + AGENT_URI + "/" + endpoint.getExternalReference(), body);
this.config.getRestApiV2Url()

Check warning on line 115 in openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java#L115

Added line #L115 was not covered by tests
+ AGENT_URI
+ "/"
+ endpoint.getAgents().getFirst().getExternalReference(),

Check warning on line 118 in openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java#L118

Added line #L118 was not covered by tests
body);
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand All @@ -133,7 +137,10 @@
public void deleteAgent(Endpoint endpoint) {
try {
this.delete(
this.config.getRestApiV2Url() + AGENT_URI + "/" + endpoint.getExternalReference());
this.config.getRestApiV2Url()

Check warning on line 140 in openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java#L140

Added line #L140 was not covered by tests
+ AGENT_URI
+ "/"
+ endpoint.getAgents().getFirst().getExternalReference());

Check warning on line 143 in openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/injectors/caldera/client/CalderaInjectorClient.java#L143

Added line #L143 was not covered by tests
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.openbas.database.model.Endpoint.PLATFORM_TYPE;
import io.openbas.injectors.caldera.client.CalderaInjectorClient;
import io.openbas.injectors.caldera.client.model.*;
import io.openbas.injectors.caldera.client.model.Agent;
import io.openbas.injectors.caldera.model.Obfuscator;
import io.openbas.injectors.caldera.model.ResultStatus;
import jakarta.validation.constraints.NotBlank;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package io.openbas.migration;

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

@Component
public class V3_54__Add_table_agents extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Statement select = context.getConnection().createStatement();
select.execute(
"""
CREATE TABLE agents (
agent_id VARCHAR(255) NOT NULL CONSTRAINT agents_pkey PRIMARY KEY,
agent_asset VARCHAR(255) NOT NULL CONSTRAINT agent_asset_id_fk REFERENCES assets ON DELETE CASCADE,
agent_privilege VARCHAR(255) NOT NULL,
agent_deployment_mode VARCHAR(255) NOT NULL,
agent_executed_by_user VARCHAR(255) NOT NULL,
agent_executor VARCHAR(255) CONSTRAINT agent_executor_id_fk REFERENCES executors ON DELETE CASCADE,
agent_version VARCHAR(255),
agent_parent VARCHAR(255),
agent_inject VARCHAR(255) CONSTRAINT agent_inject_id_fk REFERENCES injects ON DELETE CASCADE,
agent_process_name VARCHAR(255),
agent_external_reference VARCHAR(255),
agent_last_seen TIMESTAMP,
agent_created_at TIMESTAMP DEFAULT now(),
agent_updated_at TIMESTAMP DEFAULT now()
);
CREATE INDEX idx_agent_assets ON agents(agent_asset);
ALTER TABLE agents ADD CONSTRAINT agent_parent_id_fk FOREIGN KEY (agent_parent) REFERENCES agents(agent_id) ON DELETE CASCADE;
""");

// Migration datas
ResultSet resultAgentExecutor =
select.executeQuery(
"SELECT executor_id FROM executors where executor_type='openbas_caldera'");
String executorCalderaId = "";
if (resultAgentExecutor.next()) {
executorCalderaId = resultAgentExecutor.getString("executor_id");

Check warning on line 45 in openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java#L45

Added line #L45 was not covered by tests
}
ResultSet results =
select.executeQuery(
"SELECT * FROM assets WHERE asset_type='Endpoint' AND asset_executor IS NOT NULL");
PreparedStatement statement =
context
.getConnection()
.prepareStatement(
"""
INSERT INTO agents(agent_id, agent_asset, agent_privilege, agent_deployment_mode, agent_executed_by_user, agent_executor,
agent_version, agent_parent, agent_inject, agent_process_name, agent_external_reference, agent_last_seen)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""");
while (results.next()) {
statement.setObject(1, UUID.randomUUID().toString());
statement.setString(2, results.getString("asset_id"));
statement.setString(3, "admin");
statement.setString(

Check warning on line 63 in openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java#L60-L63

Added lines #L60 - L63 were not covered by tests
4, executorCalderaId.equals(results.getString("asset_executor")) ? "session" : "service");
statement.setString(

Check warning on line 65 in openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java#L65

Added line #L65 was not covered by tests
5,
"Windows".equals(results.getString("endpoint_platform"))
? "nt authority\\system"
: "root");
statement.setString(6, results.getString("asset_executor"));
statement.setString(7, results.getString("endpoint_agent_version"));
statement.setString(8, results.getString("asset_parent"));
statement.setString(9, results.getString("asset_inject"));
statement.setString(10, results.getString("asset_process_name"));
statement.setString(11, results.getString("asset_external_reference"));
statement.setTimestamp(12, results.getTimestamp("asset_last_seen"));
statement.addBatch();

Check warning on line 77 in openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/migration/V3_54__Add_table_agents.java#L68-L77

Added lines #L68 - L77 were not covered by tests
}
statement.executeBatch();

// Remove old columns
Statement removeColumns = context.getConnection().createStatement();
removeColumns.execute(
"""
ALTER TABLE assets DROP COLUMN endpoint_agent_version;
ALTER TABLE assets DROP COLUMN asset_last_seen;
ALTER TABLE assets DROP COLUMN asset_executor;
-- can't drop asset_external_reference because used for securityPlatform
ALTER TABLE assets DROP COLUMN asset_parent;
ALTER TABLE assets DROP COLUMN asset_inject;
ALTER TABLE assets DROP COLUMN asset_process_name;
""");
}
}
18 changes: 18 additions & 0 deletions openbas-api/src/main/java/io/openbas/rest/agent/AgentApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.openbas.rest.agent;

import static io.openbas.database.model.User.ROLE_USER;

import io.openbas.rest.agent.service.AgentService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
@Secured(ROLE_USER)
public class AgentApi {

public static final String ENDPOINT_URI = "/api/agents";

private final AgentService agentService;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.openbas.rest.agent.service;

import io.openbas.database.repository.AgentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class AgentService {

private final AgentRepository agentRepository;
}
Loading
Loading