Untitledgoosetool
Untitled Goose Tool is a robust and flexible hunt and incident response tool that adds novel authentication and data gathering methods in order to run a full investigation against a customer’s Azure Active Directory (AzureAD), Azure, and M365 environments.
Install / Use
/learn @cisagov/UntitledgoosetoolREADME
<p align="center"> The Goose is loose. <br> </p> </div>
Table of Contents
About
Untitled Goose Tool is a robust and flexible hunt and incident response tool that adds novel authentication and data gathering methods in order to run a full investigation against a customer’s Microsoft Entra ID, Azure, and M365 environments. Untitled Goose Tool gathers additional telemetry from Microsoft Defender for Endpoint (MDE) and Defender for Internet of Things (IoT) (D4IoT).
This tool was designed to assist incident response teams by exporting cloud artifacts after an incident for environments that aren't ingesting logs into a Security Information and Events Management (SIEM) or other long term solution for logs.
For more guidance on how to use Untitled Goose Tool, please see: Untitled Goose Tool Fact Sheet
Getting Started
Prerequisites
Python >= 3.9 is required to run Untitled Goose Tool with Python. Python 3.12 is highly recommended as it results in better logging.
On a Windows machine, you will need to make sure to have the Microsoft Visual C++ redistributable package (14.x) installed prior to running the tool.
It's also recommended to run Untitled Goose Tool within a virtual environment.
Mac OSX
pip3 install virtualenv
virtualenv -p python3 .venv
source .venv/bin/activate
Linux
# You may need to run sudo apt-get install python3-venv first
python3 -m venv .venv
source .venv/bin/activate
Windows
# You can also use py -3 -m venv .venv
python -m venv .venv
.venv\Scripts\activate
Requirements
The following EntraID/M365 permissions are required to run Untitled Goose Tool, and provide it read-only access to the tenant.
Please note: The user account should be a cloud-only account (not sync'd to the on-premise environment), this will ensure that the login process stays the same across environments for the tool.
A cloud-only user account and associated EXO service principal with the following permissions:
Exchange Online Admin Center
- View-Only Audit Logs
- View-Only Configuration
- View-Only Recipients
- User Options
A service principal with the following permissions:
API Permissions
Log Analytics API
- Data.Read (Application)
Microsoft Threat Protection:
- AdvancedHunting.Read.All (Application)
WindowsDefenderATP:
- AdvancedQuery.Read.All (Application)
- Alert.Read.All (Application)
- Library.Manage (Application)
- Machine.Read.All (Application)
- SecurityRecommendation.Read.All (Application)
- Software.Read.All (Application)
- Ti.ReadWrite (Application)
- Vulnerability.Read.All (Application)
Microsoft Graph:
- APIConnectors.Read.All (Application)
- AuditLog.Read.All (Application)
- ConsentRequest.Read.All (Application)
- Directory.Read.All (Application)
- Domain.Read.All (Application)
- IdentityProvider.Read.All (Application)
- IdentityRiskEvent.Read.All (Application)
- IdentityRiskyServicePrincipal.Read.All (Application)
- IdentityRiskyUser.Read.All (Application)
- MailboxSettings.Read (Application)
- Policy.Read.All (Application)
- Policy.Read.PermissionGrant (Application)
- Reports.Read.All (Application)
- RoleManagement.Read.All (Application)
- SecurityActions.Read.All (Application)
- SecurityAlert.Read.All (Application)
- SecurityEvents.Read.All (Application)
- UserAuthenticationMethod.Read.All (Application)
Office 365 Exchange Online
- Exchange.ManageAsApp (Application)
Azure Subscription IAM Roles
- Reader
- Storage Blob Data Reader
- Storage Queue Data Reader
Make sure to enable "Allow public client flows" for the service principal.
We have a setup powershell script to setup a service principal with the needed permissions. Additionally the association of the Azure Service Principal with m365 can only be done via powershell currently and is needed for some of the m365 log collection.
Below is an example of running the script which will output the goosey conf command you need to run to build the config files with the proper information
PS > Write-Host "Creating a new Goose Application and Users"
PS > ./Create_SP.ps1 -AppName GooseApp -Create
Additionally the script can delete the Application when you are done using it
PS > Write-Host "Creating a new Goose Application and Users"
PS > ./Create_SP.ps1 -AppName GooseApp -Delete
Installing
To install, clone the repository and then do a pip install:
Regular Install
git clone https://github.com/cisagov/untitledgoosetool.git
cd untitledgoosetool
python3 -m pip install .
Docker
docker build . -t goosey
docker run -it -v $PWD:/workdir goosey goosey honk --debug
Usage
Config
Untitled Goose Tool requires authentication parameters and configuration. To automatically build the configuration file, run the following after installation.
$ goosey conf
A version of this command will be generated when the powershell installation script is run to create/setup the service principal. Below is an example with fake parameter values
$ goosey conf --config_tenant=5fd146ad-8b31-4afa-a72f-6f71df5c7173 --config_subscriptionid=all --auth_appid=24fd6377-79e0-445d-838b-3eaa60d3ca21
After this, .auth, .conf, .auth_d4iot, and .d4iot_conf files should be placed in your current directory. These files are used by Untitled Goose Tool. Unless this was generated with the above parameters, you should fill out the top section [auth] so that Untitled Goose Tool can properly auth to the appropriate resources. However, if you do not feel comfortable about entering your credentials into a file, you can opt to delete the .auth and/or .auth_d4iot and be prompted by the tool for credentials via console instead.
The barebones auth looks like:
[auth]
# The username of your account. ex: AAD_upn@example.onmicrosoft.com
username=
# The password of your account. ex: AAD_password
password=
# The application ID of your service principal
appid=
# The client secret value of your service principal (not the secret ID)
clientsecret=
The barebones config looks like:
[config]
# The tenant ID of your AAD tenant
tenant=
# If you have a GCC High tenant
us_government=False
# If you have a GCC tenant with MDE
mde_gcc=False
# If you have a GCC High tenant with MDE
mde_gcc_high=False
# If your M365 tenant is a government tenant
exo_us_government=False
# If you want to check all of your Azure subscriptions, set this to All, otherwise enter your Azure subscription ID. For multiple IDs, separate it with commas, no spaces
subscriptionid=All
[filters]
# Format should be YYYY-MM-DD. If not set will default to the earliest date for log retention
date_start=
# Format should be YYYY-MM-DD. Will default to the present day
date_end=
[variables]
# Threshold used for ual API requests. Specifies the maximum results pulled per session. Can be between 100 - 50000. The api is optimized to return results faster the larger the threshold, but the whole session has to be repeated if an error occurs as the results are not returned sorted. We recommend 5000 as the threshold, but this can be toggled with
ual_threshold=5000
# Maximum number of ual coroutines/tasks to have running asynchronously. Minimum value is 1.
max_ual_tasks=5
# Start date for an extra time frame for ual to search. Reason for this is because ual takes the longest to pull and while you don't want the oldest data to roll off, you may want to look at another timeframe and do not want to wait for ual to get there and pull the logs. Format should be YYY-MM-DD
ual_extra_start=
# End date for an extra time frame for ual to search. Reason for this is because ual takes the longest to pull and while you don't want the oldest data to roll off, you may want to look at another timeframe and do not want to wait for ual to get there and pull the logs. Format should be YYY-MM-DD
ual_extra_end=
# Threshold for how many logs to pull per query. Usually want to try to max this out as KQL queries are rate limited.
mde_threshold=10000
# can be either 'table' or 'machine'. 'table' will pull directly from the mde tables without filtering. While 'machine' will filter by 'machine' with large tenants 'machine' will likely be prefered as time bounding on the entire table will likely cause issues.
mde_query_mode=table
[azure]
# Dumps activity log from azure
activity_log=False
# Returns all azure subscriptions
all_azure_subscriptions=False
# Dump insights bastion audit logs
bastion_logs=False
# Dump Azure configuration information
configs=False
# Dump D4IOT portal configs
d4iot_portal_configs=False
# Dump D4IOT portal pcaps from alerts
d4iot_portal_pcap=False
# Dump insights audit events for key_vault
key_vault_log=False
# Dump insights network security group flow events
nsg_flow_logs=False
[entraid]
# Dumps Entra ID Audit logs
entraid_audit=False
# Dumps Entra ID provisioning logs
entraid_provisioning=False
# Dumps Entra ID configuration files
configs=False
# Dumps risk detections from identity protection. Requires a minimum of Microsoft Entra ID P1 license and Microsoft Entra Workload ID premium license for full
