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

Samples updates #1035

Merged
merged 11 commits into from
Sep 1, 2023
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
3 changes: 2 additions & 1 deletion .github/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -838,4 +838,5 @@ basicConfig
ServiceClass
FalconInterface
UberInterface
APIRequest
APIRequest
hostgroup
10 changes: 8 additions & 2 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ This sample demonstrates the following CrowdStrike Real Time Response and Real T
---

### ProxyTool
This [demonstration](proxytool) leverages the Hosts, Host Groups, and Real-Time Response API to fetch CID or Host Group hosts, and uses the batch command and offline queuing of Real-Time Response API to centrally and conveniently issue Falcon sensor proxy configuration changes.
This [demonstration](proxytool) leverages the Hosts, Host Groups, Sensor Download, and Real-Time Response API to fetch CID or Host Group hosts, and uses the batch command and offline queuing of Real-Time Response API to centrally and conveniently issue Falcon sensor proxy configuration changes.

[![Real Time Response](https://img.shields.io/badge/Service%20Class-ProxyTool-silver?style=for-the-badge&labelColor=red&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAOCAYAAAAi2ky3AAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw1AUhU9TpaIVBzuIOGSoDmJBVEQ3rUIRKoRaoVUHk5f+CE0akhQXR8G14ODPYtXBxVlXB1dBEPwBcXNzUnSREu9LCi1ifPB4H+e9c7jvXkColZhmtY0Cmm6bqURczGRXxNAruhAEMI1hmVnGrCQl4bu+7hHg512MZ/m/+3N1qzmLAQGReIYZpk28Tjy5aRuc94kjrCirxOfEIyYVSPzIdcXjN84FlwWeGTHTqTniCLFYaGGlhVnR1IgniKOqplO+kPFY5bzFWStVWKNO/sNwTl9e4jrtASSwgEVIEKGggg2UYCNGp06KhRTdx338/a5fIpdCrg0wcsyjDA2y6wefwe/eWvnxMS8pHAfaXxznYxAI7QL1quN8HztO/QQIPgNXetNfrgFTn6RXm1r0COjZBi6um5qyB1zuAH1PhmzKrsTnL+TzwPsZjSkL9N4Cnate3xr3OH0A0tSr5A1wcAgMFSh7zeffHa19+/dNo38/hq9yr+iELI0AAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQflDAsTByz7Va2cAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAYBJREFUKM+lkjFIlVEYht/zn3sFkYYUyUnIRcemhCtCU6JQOLiIU+QeJEQg6BBIm0s4RBCBLjq5OEvgJC1uOniJhivesLx17/97/vO9b4NK4g25157hfHCGB773/cA0HZIEAKiMj+LWiOxljG/i96pnCFP58XHnrWX2+9cj0dYl9Yu2FE9/9rXrcAAgs2eSyiBfOe/XRD503h/CuffOubQVUXL+Jh9BllzBbyJJBgDclVkO4Kukd8zzkXJbeUljIldFTstsmSHM6S81ma2KfPKlFdkGAMY4wzx/bbXapMy21My+YizdKNq5mDzLkrxafSxySFKjSWX2oTmjKzz4vN0r2lOFcL/Q3V0/mX95ILMXTTGYVfaut/aP2+oCMAvnZgCcsF5fcR0dg65YHAdwB+QApADvu0AuOe/ftlJAD7Nsgmm6yBjDtfWORJZlNtFyo/lR5Z7MyheKA5ktSur7sTAHazSG27pehjAiaVfkN8b4XFIJ/wOzbOx07VNRUuHy7w98CzCcGPyWywAAAABJRU5ErkJggg==)](proxytool)

Expand All @@ -920,13 +920,19 @@ This sample demonstrates the following CrowdStrike Hosts API operations:
| :--- | :--- |
| [QueryDevicesByFilterScroll](https://www.falconpy.io/Service-Collections/Hosts.html#querydevicesbyfilterscroll) | Search for hosts in your environment by platform, hostname, IP, and other criteria with continuous pagination capability (based on offset pointer which expires after 2 minutes with no maximum limit). |

#### Host Group Response API operations discussed
#### Host Group API operations discussed
This sample demonstrates the following CrowdStrike Host Group API operations:

| Operation | Description |
| :--- | :--- |
| [queryGroupMembers](https://www.falconpy.io/Service-Collections/Host-Group.html#querygroupmembers) | Search for members of a Host Group in your environment by providing a FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria. |

#### Sensor Download API operations discussed
This sample demonstrates the following CrowdStrike Sensor Download API operations:

| Operation | Description |
| :--- | :--- |
| [GetSensorInstallersCCIDByQuery](https://falconpy.io/Service-Collections/Sensor-Download.html#getsensorinstallersccidbyquery) | Get CCID to use with sensor installers. |

#### Real Time Response API operations discussed
This sample demonstrates the following CrowdStrike Real Time Response API operations:
Expand Down
2 changes: 1 addition & 1 deletion samples/malquery/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Results will be stored in _zip_ archive format with the password of `infected`.
In order to run this demonstration, you will need access to CrowdStrike API keys with the following scopes:
| Service Collection | Scope |
| :---- | :---- |
| MalQuery | __READ__ |
| MalQuery | __READ__, __WRITE__ |

### Execution syntax
This example accepts the following input parameters.
Expand Down
19 changes: 14 additions & 5 deletions samples/proxytool/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
![CrowdStrike Falcon](https://raw.githubusercontent.com/CrowdStrike/falconpy/main/docs/asset/cs-logo.png)
![Twitter URL](https://img.shields.io/twitter/url?label=Follow%20%40CrowdStrike&style=social&url=https%3A%2F%2Ftwitter.com%2FCrowdStrike)

# ProxyTool v3.4
This example focuses on leveraging CrowdStrike's Hosts, Host Groups, and Real-Time Response API.
# ProxyTool v3.5
This example focuses on leveraging CrowdStrike's Hosts, Host Groups, Sensor Download, and Real-Time Response API.

It is a script that fetches CID or Host Group hosts, and uses the batch command and offline queuing of Real-Time Response API to centrally
and conveniently issue Falcon sensor proxy configuration changes.

- It uses native RTR commands, which will not trigger a detection/prevention in relation to sensor anti-tampering.
- Because it uses the RTR API it is run centrally through our cloud, it does NOT need to be distributed to each targeted host.
- The script uses the queuing feature of RTR, so hosts don't need to be online at the time the script is executed, they will receive the commands if they connect to our cloud within the next 7 days.
- The script uses the queuing feature of RTR, so hosts don't need to be online at the time the script is executed, they will receive the commands if they connect to our cloud within the next 7 days.
- The script checks that the CID provided as a scope_id argument is the same the API client is working with.

‼️WARNING‼️
This script has the potential to disrupt communications between the Falcon sensor and the cloud. It is recommended users test with a limited Host Group first to troubleshoot any issues.
Expand All @@ -21,6 +22,7 @@ In order to run this demonstration, you will need access to CrowdStrike API keys
| Hosts | __READ__ |
| Host Group | __READ__ |
| Real-Time Response | __WRITE, READ__ |
| Sensor Download | __READ__ |

### Execution syntax
This example accepts the following input parameters.
Expand All @@ -35,17 +37,24 @@ This example accepts the following input parameters.
| `--scope_id` | Either the CID or the Host Group ID | required |
| `--base_url` | CrowdStrike base URL (only required for GovCloud, pass usgov1) | optional |


‼️WARNING‼️
This script can target either a HOST GROUP (passing ´hostgroup´ as scope, and the group ID as scope_id) or the complete CID (passing ´cid´ as scope, and the CID as scope_id).
This script CANNOT target a single HOST. To target a single host, please create a static group with the target host.



If you want to set or change proxy configuration:

```shell
python3 proxytool_3.4.py --falcon_client_id FALCON_CLIENT_ID --falcon_client_secret FALCON_CLIENT_SECRET
python3 proxytool.py --falcon_client_id FALCON_CLIENT_ID --falcon_client_secret FALCON_CLIENT_SECRET
--proxy_hostname PROXY_HOST --proxy_port PROXY_PORT --scope hostgroup --scope_id HOST_GROUP_ID
```

If you want to disable proxy configuration:

```shell
python3 proxytool_3.4.py --falcon_client_id FALCON_CLIENT_ID --falcon_client_secret FALCON_CLIENT_SECRET
python3 proxytool.py --falcon_client_id FALCON_CLIENT_ID --falcon_client_secret FALCON_CLIENT_SECRET
--proxy_disable --scope hostgroup --scope_id HOST_GROUP_ID
```

262 changes: 262 additions & 0 deletions samples/proxytool/proxytool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#!/usr/bin/env python3

r"""ProxyTool - Update Falcon Sensor proxy configurations remotely.
___ ______ __ ____
/ _ \_______ __ ____ _/_ __/__ ___ / / _ __|_ /
/ ___/ __/ _ \\ \ / // // / / _ \/ _ \/ / | |/ //_ <
/_/ /_/ \___/_\_\\_, //_/ \___/\___/_/ |___/____/
/___/

Use RTR API to change Falcon sensor proxy configuration across CID or host group
FalconPy v1.0

CHANGE LOG

16/08/2023 v3.5 Add sanity check when using CID as scope
28/02/2023 v3.4 Add ability to disable/delete proxy config
27/10/2022 v3.3 Use command line arguments instead of external file for config
26/10/2022 v3.2 Add support for Host Group or CID selection
25/10/2022 v3.1 Ported to falconpy SDK instead of reinventing the wheel
23/10/2022 v3.0 Rewrote 2.0 for error handling, logging and fetching host IDs from API
"""
# Import dependencies
import datetime
from argparse import ArgumentParser, RawTextHelpFormatter

# Define logging function
def log(msg):
"""Print the log message to the terminal."""
print(datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + ' ' + str(msg))

# Import SDK
try:
from falconpy import(
Hosts,
OAuth2,
RealTimeResponse,
HostGroup,
SensorDownload
)
except ImportError as err:
log(err)
log("Python falconpy library is required.\n"
"Install with: python3 -m pip install crowdstrike-falconpy"
)
raise SystemExit("Python falconpy library is required.\n"
"Install with: python3 -m pip install crowdstrike-falconpy"
) from err

# Process command line arguments
parser = ArgumentParser(description=__doc__, formatter_class=RawTextHelpFormatter)
req = parser.add_argument_group("required arguments")

req.add_argument("--falcon_client_id",
help="CrowdStrike Falcon API Client ID",
required=True
)

req.add_argument("--falcon_client_secret",
help="CrowdStrike Falcon API Client Secret",
required=True
)

req.add_argument("--proxy_hostname",
help="CrowdStrike Falcon proxy hostname/FQDN",
required=False
)

req.add_argument("--proxy_port",
help="CrowdStrike Falcon proxy port number",
required=False
)

req.add_argument("--proxy_disable",
help="Flag to delete proxy config and disable proxy",
action='store_true',
required=False
)

req.add_argument("--scope",
help="Which hosts to change, can be 'cid' or 'hostgroup'",
choices=['cid', 'hostgroup'],
required=True
)

req.add_argument("--scope_id",
help="CID or Host Group ID",
required=True
)

req.add_argument("-b", "--base_url",
help="CrowdStrike base URL (only required for GovCloud, pass usgov1)",
required=False,
default="auto"
)

args = parser.parse_args()

if args.scope.lower() not in ["cid", "hostgroup"]:
log("The scope needs to be 'cid' or 'hostgroup'")
raise SystemExit("The scope needs to be 'cid' or 'hostgroup'")




# Main routine
def main(): # pylint: disable=R0912,R0915,C0116
log("Starting execution of ProxyTool")

log("Authenticating to API")
auth = OAuth2(client_id=args.falcon_client_id,
client_secret=args.falcon_client_secret,
base_url=args.base_url
)

# Check which CID the API client is operating in, as sanity check. Exit if operating CID does not match provided scope_id.
# Fixes https://github.com/CrowdStrike/falconpy/issues/1018
falcon = SensorDownload(auth_object=auth, base_url=args.base_url)
current_cid = falcon.get_sensor_installer_ccid()["body"]["resources"][0][:-3]
if (args.scope.lower() == "cid" and (args.scope_id.lower() != current_cid.lower())):
log(f"The entered CID [{args.scope_id.upper()}] does not match the API client CID [{current_cid.upper()}].")
raise SystemExit(f"The entered CID [{args.scope_id.upper()}] does not match the API client CID [{current_cid.upper()}].")


# Fetch list of hosts
if args.scope.lower() == "cid":
log(f"Getting all hosts from CID [{args.scope_id}]")
falcon = Hosts(auth_object=auth, base_url=args.base_url)
else:
log(f"Getting all hosts from host group ID [{args.scope_id}]")
falcon = HostGroup(auth_object=auth, base_url=args.base_url)


offset = ""
hosts_all = []

while True:
batch_size = 5000 # 5000 is max supported by API

if args.scope.lower() == "cid":
# Fetch all Windows CID hosts
response = falcon.query_devices_by_filter_scroll(offset=offset,
limit=batch_size,
filter="platform_name:'Windows'"
)

else:
# Fetch all Windows host group ID hosts
if offset == "":
response = falcon.query_group_members(limit=batch_size,
filter="platform_name:'Windows'",
id=args.scope_id
)
else:
response = falcon.query_group_members(offset=offset,
limit=batch_size,
filter="platform_name:'Windows'",
id=args.scope_id
)

offset = response['body']['meta']['pagination']['offset']

for host_id in response['body']['resources']:
hosts_all.append(host_id)

log(f"-- Fetched {len(response['body']['resources'])} hosts, "
f"{len(hosts_all)}/{response['body']['meta']['pagination']['total']}"
)

if len(hosts_all) >= int(response['body']['meta']['pagination']['total']):
break

log(f"-- Retrieved a total of {str(len(hosts_all))} hosts")


# Now that we have the host IDs, we create a batch RTR list of commands to execute it in all hosts

falcon = RealTimeResponse(auth_object=auth, base_url=args.base_url)

# Get batch id

response = falcon.batch_init_sessions(host_ids=hosts_all, queue_offline=True)
batch_id = response['body']['batch_id']

if batch_id:
log(f"Initiated RTR batch with id {batch_id}")
else:
raise SystemExit("Unable to initiate RTR session with hosts.")


# Commands to change proxy config

registry_stores = [
r"HKLM:\SYSTEM\Crowdstrike\{9b03c1d9-3138-44ed-9fae-d9f4c034b88d}\{16e0423f-7058-48c9-a204-725362b67639}\Default",
r"HKLM:\SYSTEM\CurrentControlSet\Services\CSAgent\Sim"
]

if not args.proxy_disable:
# Setting new proxy settings
# Delete DisableProxy, PAC, PN, PP in both locations. Change CsProxyHostname and CsProxyport with new values

registry_keys_to_delete = ["DisableProxy", "PAC", "PN", "PP"]

for store in registry_stores:
for key in registry_keys_to_delete:
response = falcon.batch_active_responder_command(batch_id=batch_id,
base_command="reg delete",
command_string=f"reg delete {store} {key}"
)
if response["status_code"] == 201:
log(f"-- Issuing registry deletion for {key} in {store}")
else:
raise SystemExit(f"Error, Response: {response['status_code']} - {response.text}")
cmd_string = f"reg set {store} CsProxyHostname -ValueType=REG_SZ -Value={args.proxy_hostname}"
response = falcon.batch_active_responder_command(batch_id=batch_id,
base_command="reg set",
command_string=cmd_string
)
if response["status_code"] == 201:
log(f"-- Issuing registry setting of CsProxyHostname to {args.proxy_hostname} in {store}")
else:
raise SystemExit(f"Error, Response: {response['status_code']} - {response.text}")

cmd_string = f"reg set {store} CsProxyport -ValueType=REG_DWORD -Value={args.proxy_port}"
response = falcon.batch_active_responder_command(batch_id=batch_id,
base_command="reg set",
command_string=cmd_string
)
if response["status_code"] == 201:
log(f"-- Issuing registry setting of CsProxyport to {args.proxy_port} in {store}")
else:
raise SystemExit(f"Error, Response: {response['status_code']} - {response.text}")
else:
# Deleting and disabling proxy config
# Delete PAC, PN, PP, CsProxyHostname, CsProxyport in both locations. Set DisableProxy with a non-zero value

registry_keys_to_delete = ["PAC", "PN", "PP", "CsProxyHostname", "CsProxyport"]

for store in registry_stores:
for key in registry_keys_to_delete:
response = falcon.batch_active_responder_command(batch_id=batch_id,
base_command="reg delete",
command_string=f"reg delete {store} {key}"
)
if response["status_code"] == 201:
log(f"-- Issuing registry deletion for {key} in {store}")
else:
raise SystemExit(f"Error, Response: {response['status_code']} - {response.text}")
cmd_string = f"reg set {store} DisableProxy -ValueType=REG_DWORD -Value=1"
response = falcon.batch_active_responder_command(batch_id=batch_id,
base_command="reg set",
command_string=cmd_string
)
if response["status_code"] == 201:
log(f"-- Issuing registry setting of DisableProxy to a non-zero value in {store}")
else:
raise SystemExit(f"Error, Response: {response['status_code']} - {response.text}")

log("-- Finished launching RTR commands, please check progress in the RTR audit logs")
log("End")

if __name__ == "__main__":
main()
6 changes: 6 additions & 0 deletions samples/proxytool/proxytool_3.3.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
Use RTR API to change Falcon sensor proxy configuration across CID or host group
FalconPy v1.0

----------------------------------------------------------------
WARNING
THIS VERSION OF THE SCRIPT IS OBSOLETE AND NO LONGER MAINTAINED.
PLEASE USE THE LATEST VERSION AVAILABLE.
----------------------------------------------------------------

CHANGE LOG

27/10/2022 v3.3 Use command line arguments instead of external file for config
Expand Down
7 changes: 7 additions & 0 deletions samples/proxytool/proxytool_3.4.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
Use RTR API to change Falcon sensor proxy configuration across CID or host group
FalconPy v1.0


----------------------------------------------------------------
WARNING
THIS VERSION OF THE SCRIPT IS OBSOLETE AND NO LONGER MAINTAINED.
PLEASE USE THE LATEST VERSION AVAILABLE.
----------------------------------------------------------------

CHANGE LOG

28/02/2023 v3.4 Add ability to disable/delete proxy config
Expand Down
Loading