Skip to content

Commit 630612b

Browse files
committed
[backend] Finish the Tanium executor
1 parent 829ef59 commit 630612b

File tree

56 files changed

+208
-177
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+208
-177
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,12 @@ private Endpoint findAndRegisterAssetForExecution(@NotNull final Inject inject,
120120
count++;
121121
// Find an executor agent matching the asset
122122
log.log(Level.INFO, "Listing agents...");
123-
List<Agent> agents = this.calderaService.agents().stream().filter(agent -> agent.getExe_name().contains("executor") && (now().toEpochMilli() - Time.toInstant(agent.getCreated()).toEpochMilli()) < Asset.ACTIVE_THRESHOLD && agent.getHost().equals(assetEndpoint.getHostname()) && Arrays.stream(assetEndpoint.getIps()).anyMatch(s -> Arrays.stream(agent.getHost_ip_addrs()).toList().contains(s))).toList();
123+
List<Agent> agents = this.calderaService.agents().stream().filter(agent ->
124+
agent.getExe_name().contains("executor")
125+
&& (now().toEpochMilli() - Time.toInstant(agent.getCreated()).toEpochMilli()) < Asset.ACTIVE_THRESHOLD
126+
&& (agent.getHost().equals(assetEndpoint.getHostname()) || agent.getHost().split("\\.")[0].equals(assetEndpoint.getHostname().split("\\.")[0]))
127+
&& Arrays.stream(assetEndpoint.getIps()).anyMatch(s -> Arrays.stream(agent.getHost_ip_addrs()).toList().contains(s))
128+
).toList();
124129
log.log(Level.INFO, "List return with " + agents.size() + " agents");
125130
if (!agents.isEmpty()) {
126131
for (int i = 0; i < agents.size(); i++) {

openbas-api/src/main/java/io/openbas/injectors/caldera/CalderaInjector.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ public class CalderaInjector {
2121
public CalderaInjector(InjectorService injectorService, CalderaContract contract, CalderaInjectorConfig calderaInjectorConfig) {
2222
Map<String, String> executorCommands = new HashMap<>();
2323
executorCommands.put(Endpoint.PLATFORM_TYPE.Windows.name(), "$x=\"#{location}\";$location=$x.Replace(\"\\obas.exe\", \"\");[Environment]::CurrentDirectory = $location;$random=-join ((65..90) + (97..122) | Get-Random -Count 5 | % {[char]$_});$filename=\"obas-executor-$random.exe\";$server=\"" + calderaInjectorConfig.getPublicUrl() + "\";$url=\"$server/file/download\";$wc=New-Object System.Net.WebClient;$wc.Headers.add(\"platform\",\"windows\");$wc.Headers.add(\"file\",\"sandcat.go\");$data=$wc.DownloadData($url);[io.file]::WriteAllBytes($filename,$data) | Out-Null;New-NetFirewallRule -DisplayName \"Allow OpenBAS\" -Direction Inbound -Program \"$location\\$filename\" -Action Allow | Out-Null;New-NetFirewallRule -DisplayName \"Allow OpenBAS\" -Direction Outbound -Program \"$location\\$filename\" -Action Allow | Out-Null;Start-Process -FilePath \"$location\\$filename\" -ArgumentList \"-server $server -group red\" -WindowStyle hidden;");
24-
executorCommands.put(Endpoint.PLATFORM_TYPE.Linux.name(), "x=\"#{location}\";location=$(echo \"$location\" | sed \"s#/obas##\");filename=obas-executor-$(tr -dc A-Za-z0-9 </dev/urandom | head -c 5; echo);server=\"" + calderaInjectorConfig.getPublicUrl() + "\";curl -s -X POST -H \"file:sandcat.go\" -H \"platform:linux\" $server/file/download > $location/$filename;chmod +x $location/$filename;nohup $location/$filename -server $server -group red &");
25-
executorCommands.put(Endpoint.PLATFORM_TYPE.MacOS.name(), "x=\"#{location}\";location=$(echo \"$location\" | sed \"s#/obas##\");filename=obas-executor-$(tr -dc A-Za-z0-9 </dev/urandom | head -c 5; echo);server=\"" + calderaInjectorConfig.getPublicUrl() + "\";curl -s -X POST -H \"file:sandcat.go\" -H \"platform:darwin\" -H \"architecture:amd64\" $server/file/download > $location/$filename;chmod +x $location/$filename;nohup $location/$filename -server $server -group red &");
24+
executorCommands.put(Endpoint.PLATFORM_TYPE.Linux.name(), "x=\"#{location}\";location=$(echo \"$x\" | sed \"s#/obas##\");filename=obas-executor-$(tr -dc A-Za-z0-9 </dev/urandom | head -c 5; echo);server=\"" + calderaInjectorConfig.getPublicUrl() + "\";curl -s -X POST -H \"file:sandcat.go\" -H \"platform:linux\" $server/file/download > $location/$filename;chmod +x $location/$filename;$location/$filename -server $server -group red &");
25+
executorCommands.put(Endpoint.PLATFORM_TYPE.MacOS.name(), "x=\"#{location}\";location=$(echo \"$x\" | sed \"s#/obas##\");filename=obas-executor-$(tr -dc A-Za-z0-9 </dev/urandom | head -c 5; echo);server=\"" + calderaInjectorConfig.getPublicUrl() + "\";curl -s -X POST -H \"file:sandcat.go\" -H \"platform:darwin\" -H \"architecture:amd64\" $server/file/download > $location/$filename;chmod +x $location/$filename;$location/$filename -server $server -group red &");
2626
Map<String, String> executorClearCommands = new HashMap<>();
2727
executorClearCommands.put(Endpoint.PLATFORM_TYPE.Windows.name(), "$x=\"#{location}\";$location=$x.Replace(\"\\obas.exe\", \"\");[Environment]::CurrentDirectory = $location;cd \"$location\";Get-ChildItem -Recurse -Filter *executor* | Remove-Item");
28-
executorClearCommands.put(Endpoint.PLATFORM_TYPE.Linux.name(), "x=\"#{location}\";location=$(echo \"$location\" | sed \"s#/obas##\");cd \"$location\"; rm *executor*");
29-
executorClearCommands.put(Endpoint.PLATFORM_TYPE.MacOS.name(), "x=\"#{location}\";location=$(echo \"$location\" | sed \"s#/obas##\");cd \"$location\"; rm *executor*");
28+
executorClearCommands.put(Endpoint.PLATFORM_TYPE.Linux.name(), "x=\"#{location}\";location=$(echo \"$x\" | sed \"s#/obas##\");cd \"$location\"; rm *executor*");
29+
executorClearCommands.put(Endpoint.PLATFORM_TYPE.MacOS.name(), "x=\"#{location}\";location=$(echo \"$x\" | sed \"s#/obas##\");cd \"$location\"; rm *executor*");
3030
try {
3131
injectorService.register(
3232
calderaInjectorConfig.getId(),

openbas-api/src/main/resources/application.properties

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,7 @@ executor.tanium.api-key=<tanium-api-key>
145145
executor.tanium.computer-group-id=1
146146
executor.tanium.action-group-id=4
147147
executor.tanium.windows-package-id=
148-
executor.tanium.linux-package-id=
149-
executor.tanium.mac-os-package-id=
148+
executor.tanium.unix-package-id=
150149

151150
#############
152151
# INJECTORS #

openbas-framework/src/main/java/io/openbas/executors/caldera/service/CalderaExecutorService.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,12 @@ public void run() {
9595
endpoints.forEach(endpoint -> {
9696
List<Endpoint> existingEndpoints = this.endpointService.findAssetsForInjectionByHostname(endpoint.getHostname()).stream().filter(endpoint1 -> Arrays.stream(endpoint1.getIps()).anyMatch(s -> Arrays.stream(endpoint.getIps()).toList().contains(s))).toList();
9797
if (existingEndpoints.isEmpty()) {
98-
this.endpointService.createEndpoint(endpoint);
98+
Optional<Endpoint> endpointByExternalReference = endpointService.findByExternalReference(endpoint.getExternalReference());
99+
if( endpointByExternalReference.isPresent() ) {
100+
this.updateEndpoint(endpoint, List.of(endpointByExternalReference.get()));
101+
} else {
102+
this.endpointService.createEndpoint(endpoint);
103+
}
99104
} else {
100105
this.updateEndpoint(endpoint, existingEndpoints);
101106
}

openbas-framework/src/main/java/io/openbas/executors/tanium/config/TaniumExecutorConfig.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,7 @@ public class TaniumExecutorConfig {
4242

4343
@Getter
4444
@NotBlank
45-
private Integer linuxPackageId;
46-
47-
@Getter
48-
@NotBlank
49-
private Integer macOsPackageId;
45+
private Integer unixPackageId;
5046

5147
public String getGatewayUrl() {
5248
return url + GATEWAY_URI;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"comment":"Exported from Tanium Server 7.6.1.6540 at 2024-05-16T20:24:14","version":2,"object_list":{"package_specs":[{"content_set":{"name":"Base"},"name":"OpenBAS Subprocessor (Unix)","display_name":"OpenBAS Subprocessor (Unix)","files":[],"file_templates":[],"command":"/bin/sh -c \"/bin/echo $1 | base64 -d | sh\"","command_timeout":60,"expire_seconds":660,"hidden_flag":0,"process_group_flag":0,"verify_group":{"name":"","and_flag":0,"not_flag":0,"type":0},"verify_expire_seconds":600,"skip_lock_flag":0,"parameter_definition":"{\"parameters\":[{\"defaultValue\":\"\",\"helpString\":\"\",\"label\":\"command\",\"maxChars\":\"\",\"promptText\":\"\",\"validationExpressions\":[{\"expression\":\".*\",\"helpString\":\"\",\"model\":\"com.tanium.models::ValidationExpression\",\"parameterType\":\"com.tanium.models::ValidationExpression\"}],\"parameterType\":\"com.tanium.components.parameters::TextInputParameter\",\"key\":\"$1\"}]}","metadata":[]},{"content_set":{"name":"Base"},"name":"OpenBAS Subprocessor (Windows)","display_name":"OpenBAS Subprocessor (Windows)","files":[],"file_templates":[],"command":"cmd.exe /d /c powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -NonInteractive -NoProfile -Command \"Invoke-Expression ([System.Text.Encoding]::UTF8.GetString([convert]::FromBase64String('$1')))\"","command_timeout":60,"expire_seconds":660,"hidden_flag":0,"process_group_flag":0,"verify_group":{"name":"","and_flag":0,"not_flag":0,"type":0},"verify_expire_seconds":600,"skip_lock_flag":0,"parameter_definition":"{\"parameters\":[{\"defaultValue\":\"\",\"helpString\":\"\",\"label\":\"command\",\"maxChars\":\"\",\"promptText\":\"\",\"validationExpressions\":[{\"expression\":\".*\",\"helpString\":\"\",\"model\":\"com.tanium.models::ValidationExpression\",\"parameterType\":\"com.tanium.models::ValidationExpression\"}],\"parameterType\":\"com.tanium.components.parameters::TextInputParameter\",\"key\":\"$1\"}]}","metadata":[]}]}}

openbas-framework/src/main/java/io/openbas/executors/tanium/service/TaniumExecutorContextService.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ public void launchExecutorSubprocess(@NotNull final Injector injector, @NotNull
4242
this.taniumExecutorClient.executeAction(asset.getExternalReference(), this.taniumExecutorConfig.getWindowsPackageId(), Base64.getEncoder().encodeToString(command.getBytes()));
4343
}
4444
case Endpoint.PLATFORM_TYPE.Linux -> {
45-
String command = injector.getExecutorCommands().get(Endpoint.PLATFORM_TYPE.Linux.name()).replace("\"#{location}\"", "$PWD.Path");
46-
this.taniumExecutorClient.executeAction(asset.getExternalReference(), this.taniumExecutorConfig.getLinuxPackageId(), Base64.getEncoder().encodeToString(command.getBytes()));
45+
String command = injector.getExecutorCommands().get(Endpoint.PLATFORM_TYPE.Linux.name()).replace("\"#{location}\"", "$(pwd)");
46+
this.taniumExecutorClient.executeAction(asset.getExternalReference(), this.taniumExecutorConfig.getUnixPackageId(), Base64.getEncoder().encodeToString(command.getBytes()));
4747
}
4848
case Endpoint.PLATFORM_TYPE.MacOS -> {
49-
String command = injector.getExecutorCommands().get(Endpoint.PLATFORM_TYPE.MacOS.name()).replace("\"#{location}\"", "$PWD.Path");
50-
this.taniumExecutorClient.executeAction(asset.getExternalReference(), this.taniumExecutorConfig.getMacOsPackageId(), injector.getExecutorCommands().get(Endpoint.PLATFORM_TYPE.MacOS.name()));
49+
String command = injector.getExecutorCommands().get(Endpoint.PLATFORM_TYPE.MacOS.name()).replace("\"#{location}\"", "$(pwd)");
50+
this.taniumExecutorClient.executeAction(asset.getExternalReference(), this.taniumExecutorConfig.getUnixPackageId(), Base64.getEncoder().encodeToString(command.getBytes()));
5151
}
5252
default -> throw new RuntimeException("Unsupported platform: " + platform);
5353
};

openbas-framework/src/main/java/io/openbas/executors/tanium/service/TaniumExecutorService.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
import java.time.LocalDateTime;
2525
import java.time.ZonedDateTime;
2626
import java.time.format.DateTimeFormatter;
27-
import java.util.Arrays;
28-
import java.util.List;
29-
import java.util.Locale;
30-
import java.util.Optional;
27+
import java.util.*;
3128
import java.util.logging.Level;
3229

3330
import static java.time.Instant.now;
@@ -90,7 +87,12 @@ public void run() {
9087
endpoints.forEach(endpoint -> {
9188
List<Endpoint> existingEndpoints = this.endpointService.findAssetsForInjectionByHostname(endpoint.getHostname()).stream().filter(endpoint1 -> Arrays.stream(endpoint1.getIps()).anyMatch(s -> Arrays.stream(endpoint.getIps()).toList().contains(s))).toList();
9289
if (existingEndpoints.isEmpty()) {
93-
this.endpointService.createEndpoint(endpoint);
90+
Optional<Endpoint> endpointByExternalReference = endpointService.findByExternalReference(endpoint.getExternalReference());
91+
if( endpointByExternalReference.isPresent() ) {
92+
this.updateEndpoint(endpoint, List.of(endpointByExternalReference.get()));
93+
} else {
94+
this.endpointService.createEndpoint(endpoint);
95+
}
9496
} else {
9597
this.updateEndpoint(endpoint, existingEndpoints);
9698
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { EndpointStore } from '../../admin/components/assets/endpoints/Endpoint';
22

3-
export interface EndpointsHelper {
3+
export interface EndpointHelper {
44
getEndpoints: () => EndpointStore[];
55
getEndpointsMap: () => Record<string, EndpointStore>;
66
}

openbas-front/src/actions/helper.d.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import type { Challenge, Exercise, Organization, PlatformSettings, Tag, User } from '../utils/api-types';
22
import type { ScenarioStore } from './scenarios/Scenario';
33

4-
export interface UsersHelper {
4+
export interface UserHelper {
55
getMe: () => User;
66
getUsersMap: () => Record<string, User>;
77
}
88

9-
export interface OrganizationsHelper {
9+
export interface OrganizationHelper {
1010
getOrganizations: () => Organization[];
1111
getOrganizationsMap: () => Record<string, Organization>;
1212
}
1313

14-
export interface TagsHelper {
14+
export interface TagHelper {
1515
getTag: (tagId: Tag['tag_id']) => Tag;
1616
getTags: () => Tag[];
1717
getTagsMap: () => Record<string, Tag>;
@@ -26,13 +26,13 @@ export interface LoggedHelper {
2626
getPlatformSettings: () => PlatformSettings;
2727
}
2828

29-
export interface ChallengesHelper {
29+
export interface ChallengeHelper {
3030
getChallengesMap: () => Record<string, Challenge>;
3131
getChallenges: () => Challenge[];
3232
getExerciseChallenges: (exerciseId: Exercise['exercise_id']) => Challenge[];
3333
getScenarioChallenges: (scenarioId: ScenarioStore['scenario_id']) => Challenge[];
3434
}
3535

36-
export interface DocumentsHelper {
36+
export interface DocumentHelper {
3737
getDocumentsMap: () => Record<string, Document>
3838
}

openbas-front/src/admin/components/assets/asset_groups/AssetGroupManagement.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import TagsFilter from '../../common/filters/TagsFilter';
77
import SearchFilter from '../../../../components/SearchFilter';
88
import AssetGroupAddEndpoints from './AssetGroupAddEndpoints';
99
import { useHelper } from '../../../../store';
10-
import type { UsersHelper } from '../../../../actions/helper';
10+
import type { UserHelper } from '../../../../actions/helper';
1111
import useDataLoader from '../../../../utils/hooks/useDataLoader';
1212
import { fetchEndpoints } from '../../../../actions/assets/endpoint-actions';
1313
import { useAppDispatch } from '../../../../utils/hooks';
@@ -16,7 +16,7 @@ import type { AssetGroupsHelper } from '../../../../actions/asset_groups/assetgr
1616
import EndpointsList, { EndpointStoreWithType } from '../endpoints/EndpointsList';
1717
import EndpointPopover from '../endpoints/EndpointPopover';
1818
import useSearchAnFilter from '../../../../utils/SortingFiltering';
19-
import type { EndpointsHelper } from '../../../../actions/assets/asset-helper';
19+
import type { EndpointHelper } from '../../../../actions/assets/asset-helper';
2020
import type { AssetGroupStore } from './AssetGroup';
2121

2222
const useStyles = makeStyles((theme: Theme) => ({
@@ -65,7 +65,7 @@ const AssetGroupManagement: FunctionComponent<Props> = ({
6565
const dispatch = useAppDispatch();
6666

6767
// Fetching data
68-
const { assetGroup, endpointsMap, userAdmin } = useHelper((helper: AssetGroupsHelper & EndpointsHelper & UsersHelper) => ({
68+
const { assetGroup, endpointsMap, userAdmin } = useHelper((helper: AssetGroupsHelper & EndpointHelper & UserHelper) => ({
6969
assetGroup: helper.getAssetGroup(assetGroupId),
7070
endpointsMap: helper.getEndpointsMap(),
7171
userAdmin: helper.getMe()?.user_admin ?? false,

openbas-front/src/admin/components/assets/asset_groups/AssetGroups.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { SelectGroup } from 'mdi-material-ui';
55
import { useSearchParams } from 'react-router-dom';
66
import { useFormatter } from '../../../../components/i18n';
77
import { useHelper } from '../../../../store';
8-
import type { TagsHelper, UsersHelper } from '../../../../actions/helper';
8+
import type { TagHelper, UserHelper } from '../../../../actions/helper';
99
import type { AssetGroupStore } from './AssetGroup';
1010
import ItemTags from '../../../../components/ItemTags';
1111
import AssetGroupPopover from './AssetGroupPopover';
@@ -14,7 +14,7 @@ import { searchAssetGroups } from '../../../../actions/asset_groups/assetgroup-a
1414
import AssetGroupManagement from './AssetGroupManagement';
1515
import Breadcrumbs from '../../../../components/Breadcrumbs';
1616
import PaginationComponent from '../../../../components/common/pagination/PaginationComponent';
17-
import type { EndpointsHelper } from '../../../../actions/assets/asset-helper';
17+
import type { EndpointHelper } from '../../../../actions/assets/asset-helper';
1818
import type { SearchPaginationInput } from '../../../../utils/api-types';
1919
import { initSorting } from '../../../../components/common/pagination/Page';
2020
import SortHeadersComponent from '../../../../components/common/pagination/SortHeadersComponent';
@@ -80,7 +80,7 @@ const AssetGroups = () => {
8080
const [searchId] = searchParams.getAll('id');
8181

8282
// Fetching data
83-
const { userAdmin } = useHelper((helper: EndpointsHelper & UsersHelper & TagsHelper) => ({
83+
const { userAdmin } = useHelper((helper: EndpointHelper & UserHelper & TagHelper) => ({
8484
userAdmin: helper.getMe()?.user_admin ?? false,
8585
}));
8686

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Endpoint } from '../../../../utils/api-types';
22

3-
export type EndpointStore = Omit<Endpoint, 'asset_tags'> & {
3+
export type EndpointStore = Omit<Endpoint, 'asset_executor', 'asset_tags'> & {
44
asset_tags: string[] | undefined;
5+
asset_executor: string | undefined;
56
};

0 commit comments

Comments
 (0)