launcher icon indicating copy to clipboard operation
launcher copied to clipboard

Table Request: Crowdstrike Configuration

Open FritzX6 opened this issue 3 years ago • 6 comments

image

What is being requested?

Crowdstrike Falcon installs a binary called falconctl which can be used to control, configure and debug the Crowdstrike agent. Several individuals have requested a method to gather more details about the state of Crowdstrike and this feels like the fastest/most reliable method.

What would this table look like?

The falconctl tool is only available for macOS and Linux endpoints, no Windows equivalent exists and instead configuration must be retrieved via the Registry and by checking running services.

The output of the falconctl differs (alongside the available options) based on whether you are dealing with macOS or Linux.

macOS

The macOS table can be accomplished via a straightforward dataflatten table because the output can be formatted as a Plist. This PR has been submitted and merged: https://github.com/kolide/launcher/pull/858/files

Linux

The Linux falconctl tool outputs a comma separated list of requested options.

The options available are listed in the /help output of the tool below:

where GET_OPTIONS := { --cid for CustomerId |
                       --aid for AgentId |
                       --apd for App Proxy Disable |
                       --aph for App Proxy Host |
                       --app for App Proxy Port |
                       --rfm-state for indicating whether the sensor is in Reduced Functionality Mode |
                       --rfm-reason to determine reason for sensor running in Reduced Functionality Mode |
                       --trace for determining the configured trace level |
                       --feature to determine the configured sensor feature flags |
                       --metadata-query to determine the configured sensor cloud provider metadata query flags |
                       --version for version of sensor currently running |
                       --message-log for logging messages to disk |
                       --billing to configure the sensor billing type |
                       --tags for sensor grouping tags |
                       --provisioning-token for Provisioning Token |
                       --systags for system tags currently applied to a running sensor }

Important note!

All of the options specified can be returned even if the sensor is not configured/connected, with the exception of the --cid option. If --cid is requested and the sensor is not configured, the output of the command will error out before returning the other requested options as demonstrated below:

$ sudo /opt/CrowdStrike/falconctl -g --rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags --cid
CID is not set. Use falconctl to set the CID
ERROR: failed to process the option --cid

What does the output of this tool look like when it returns data?

The cid and aid values have been redacted for privacy purposes


Scenario 1: Installation State: True CID Set: False Sensor Started: False Options Specified: All options requested except for --cid

$ sudo /opt/CrowdStrike/falconctl -g --rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags
aid is not set, aph is not set, app is not set, rfm-state is not set, rfm-reason is not set, feature is not set, metadata-query=enable (unset default), version = 6.38.13501.0
Could not open systags (is the sensor stopped or in RFM?)
ERROR: failed to process the option --systags

Scenario 2: Installation State: True CID Set: True Sensor Started: False Options Specified: All options requested, including --cid

$ sudo /opt/CrowdStrike/falconctl -g --rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags --cid
cid="ac917ab****************************", aid is not set, aph is not set, app is not set, rfm-state is not set, rfm-reason is not set, feature is not set, metadata-query=enable (unset default), version = 6.38.13501.0
Could not open systags (is the sensor stopped or in RFM?)
ERROR: failed to process the option --systags
Sensor grouping tags are not set, provisioning-token is not set,

Scenario 3: Installation State: True CID Set: True Sensor Started: True Options Specified: All options requested, including --cid

$ sudo /opt/CrowdStrike/falconctl -g --rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags --cid
cid="ac917ab****************************", aid="fe8d01b4****************************", aph is not set, app is not set, rfm-state=true, rfm-reason=Modules file was not found, code=0xC0000034, feature= (hex bitmask: 0), metadata-query=enable (unset default), version = 6.38.13501.0
Could not open systags (is the sensor stopped or in RFM?)
ERROR: failed to process the option --systags
Sensor grouping tags are not set, provisioning-token is not set,

Proposed paths for table implementation:

I know little about string splitting in Go but there are several ways I could imagine accomplishing this task:

1. Return the output of the first line (the one containing comma separated values) in its entirety and perform string splitting in subsequent queries/ctes.

SELECT * FROM kolide_falconctl_linux WHERE get_options = '--rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags --cid'
output = cid="ac917ab****************************", aid="fe8d01b4****************************", aph is not set, app is not set, rfm-state=true, rfm-reason=Modules file was not found, code=0xC0000034, feature= (hex bitmask: 0), metadata-query=enable (unset default), version = 6.38.13501.0
  • Advantages: We don't need to reason about the possibility of the data structure changing or commas being included in the output of one of the options (specifically --systags which I am unsure of the format for)
  • Disadvantages: It is ugly and difficult to digest without further manipulation of output, we potentially drop data on the floor if there is relevant error or NULL data in lines other than the first output.

⭐⭐ My favorite: Alternatively, we could split on newlines and return all lines of output from the command so that we could capture potential errors as well:

SELECT * FROM kolide_falconctl_linux WHERE get_options = '--rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags --cid'

row_id = 1
output = cid="ac917ab****************************", aid="fe8d01b4***************************", aph is not set, app is not set, rfm-state=true, rfm-reason=Modules file was not found, code=0xC0000034, feature= (hex bitmask: 0), metadata-query=enable (unset default), version = 6.38.13501.0

row_id = 2
output = Could not open systags (is the sensor stopped or in RFM?)

row_id = 3
output = ERROR: failed to process the option --systags

row_id = 4
output = Sensor grouping tags are not set, provisioning-token is not set,

2. Split the comma-separated list into simple rows on the , token separator

SELECT * FROM kolide_falconctl_linux WHERE get_options = '--rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags --cid'
+--------------------------------------------+
| option                                     |
+--------------------------------------------+
| cid="ac917ab****************************"  |
| aid="fe8d01b4***************************"  |
| aph is not set                             |
| app is not set                             |
| rfm-state=true                             |
| rfm-reason=Modules file was not found      |
| code=0xC0000034                            |
| feature= (hex bitmask: 0)                  |
| metadata-query=enable (unset default)      |
| version = 6.38.13501.0                     |
+--------------------------------------------+
  • Advantages: Slightly more digestible, relatively simple string splitting, multi-row output, still relatively resilient to variable output.
  • Disadvantages: Additional SQL-based evaluation must be done for evaluating output (eg. casting things to booleans, nulls, etc.)

3. Attempt to string split within comma-separated list on other tokens (eg. = and some sort of regex {option_name}is)

SELECT * FROM kolide_falconctl_linux WHERE get_options = '--rfm-state --aid --version --metadata-query --rfm-reason --tags --feature --app --aph --provisioning-token --systags --cid'
+----------------+---------------------------------------+
| option         | value                                 |
+----------------+---------------------------------------+
| cid            | "ac917ab****************************" |
| aid            | "fe8d01b4***************************" |
| aph            | not set                               |
| app            | not set                               |
| rfm-state      | TRUE                                  |
| rfm-reason     | Modules file was not found            |
| code           | 0xC0000034                            |
| feature        | (hex bitmask: 0)                      |
| metadata-query | enable (unset default)                |
| version        | 6.38.13501.0                          |
+----------------+---------------------------------------+
  • Advantages: Reasonably digestible, relatively simple string splitting, multi-row output
  • Disadvantages: Things start becoming slightly more susceptible to breakage from unexpected output.

4. (Not Recommended) Attempt to return all values as distinct columns and call the --cid get_option separately for a simple table that pefectly parses and outputs all available data:

SELECT * FROM kolide_falconctl_linux;

+---------------------------------------+---------------------------------------+---------+---------+-----------+----------------------------+------------+------------------+------------------------+--------------+--------------------+----------+------+
| cid                                   | aid                                   | aph     | app     | rfm-state | rfm-reason                 | code       | feature          | metadata-query         | version      | provisioning_token | sys-tags | tags |
+---------------------------------------+---------------------------------------+---------+---------+-----------+----------------------------+------------+------------------+------------------------+--------------+--------------------+----------+------+
| "ac917ab****************************" | "fe8d01b4***************************" | not set | not set | TRUE      | Modules file was not found | 0xC0000034 | (hex bitmask: 0) | enable (unset default) | 6.38.13501.0 |                    |          |      |
+---------------------------------------+---------------------------------------+---------+---------+-----------+----------------------------+------------+------------------+------------------------+--------------+--------------------+----------+------+
  • Advantages: Most digestible, most easy to work with for a novice user
  • Disadvantages: A lot of engineering trouble for something that I predict will be susceptible to errors from parsing unexpected output

FritzX6 avatar Jan 31 '22 17:01 FritzX6

The Linux falconctl has different command options and subsequently different output:

sudo /opt/CrowdStrike/falconctl -g GET_OPTIONS

--cid for CustomerId
--aid for AgentId
--apd for App Proxy Disable
--aph for App Proxy Host
--app for App Proxy Port
--rfm-state for indicating whether the sensor is in Reduced Functionality Mode
--rfm-reason to determine reason for sensor running in Reduced Functionality Mode
--trace for determining the configured trace level
--feature to determine the configured sensor feature flags
--metadata-query to determine the configured sensor cloud provider metadata query flags
--version for version of sensor currently running
--message-log for logging messages to disk
--billing to configure the sensor billing type
--tags for sensor grouping tags
--provisioning-token for Provisioning Token
--systags for system tags currently applied to a running sensor

FritzX6 avatar Aug 15 '22 20:08 FritzX6

Sounds like we might now have enough data this this is a good first issue.

directionless avatar Sep 04 '22 00:09 directionless

I am broadly opposed to run time solutions that involve relaying output back line by line, and I think I favor (3) here.

Given the data we have, I'm not convinced we know enough to parse systags, and I think we should probably omit it until we know more.

If this works like I'd expect a sensor to work, I'm not sure it's meaningful to return anything if CID isn't set. So I'd be inclined to always request cid and leave everything null if it's not set. (My assumption here, is that the CID being set will trigger a download and override everthing. So it's just meaningless/stale data)

directionless avatar Sep 09 '22 19:09 directionless

Output from passing every option:

$ sudo /opt/CrowdStrike/falconctl -g --cid --aid --apd --aph --app --rfm-state --rfm-reason --trace --feature --metadata-query --version --message-log --billing --tags --provisioning-token --systags 

cid="ac917ab****************************", aid="fe8d01b4***************************", apd is not set, aph is not set, app is not set, rfm-state=true, rfm-reason=Unspecified, code=0xC0000225, trace is not set, feature= (hex bitmask: 0), metadata-query=enable (unset default), version = 6.44.14108.0
Could not read message log setting from config file
ERROR: failed to process the option --message-log

goronfreeman avatar Sep 20 '22 19:09 goronfreeman

@FritzX6 As I understand it, this is probably going to need to invoke falconctl 3 times. Once for the CID, once for the systags, and once for the remaining options. Given that, how do you feel about 3 tables?

directionless avatar Sep 29 '22 20:09 directionless

As I understand it:

  • macOS: #858
  • linux: #903
  • windows: No option here, use services and the registry

directionless avatar Oct 04 '22 14:10 directionless