diff --git a/analyzers/GetAzureSignIns/GetAzureSignIns.json b/analyzers/GetEntraIDSignIns/GetEntraIDSignIns.json similarity index 68% rename from analyzers/GetAzureSignIns/GetAzureSignIns.json rename to analyzers/GetEntraIDSignIns/GetEntraIDSignIns.json index abfe47a93..c82434ce4 100644 --- a/analyzers/GetAzureSignIns/GetAzureSignIns.json +++ b/analyzers/GetEntraIDSignIns/GetEntraIDSignIns.json @@ -1,28 +1,28 @@ { - "name": "GetAzureSignIns", + "name": "GetEntraIDSignIns", "version": "1.0", "author": "@jahamilto", "url": "https://github.com/TheHive-Project/Cortex-Analyzers", "license": "AGPL-V3", - "description": "Pull all Azure sign ins for a user within the specified amount of time.", + "description": "Pull all Microsoft Entra ID sign ins for a user within the specified amount of time.", "dataTypeList": ["mail"], - "command": "GetAzureSignIns/GetAzureSignIns.py", - "baseConfig": "GetAzureSignIns", + "command": "GetEntraIDSignIns/GetEntraIDSignIns.py", + "baseConfig": "GetEntraIDSignIns", "configurationItems": [ {"name": "tenant_id", - "description": "Azure Directory/Tenant ID", + "description": "Microsoft Entra ID Tenant ID", "type": "string", "multi": false, "required": true }, {"name": "client_id", - "description": "Client ID/Application ID of Azure AD Registered App", + "description": "Client ID/Application ID of Microsoft Entra ID Registered App", "type": "string", "multi": false, "required": true }, {"name": "client_secret", - "description": "Secret for Azure AD Registered Application", + "description": "Secret for Microsoft Entra ID Registered Application", "type": "string", "multi": false, "required": true @@ -53,7 +53,9 @@ "multi": false, "required": false } - - ] - + ], + "registration_required": true, + "subscription_required": true, + "free_subscription": false, + "service_homepage": "https://www.microsoft.com/security/business/identity-access/microsoft-entra-id" } diff --git a/analyzers/GetAzureSignIns/GetAzureSignIns.py b/analyzers/GetEntraIDSignIns/GetEntraIDSignIns.py old mode 100644 new mode 100755 similarity index 86% rename from analyzers/GetAzureSignIns/GetAzureSignIns.py rename to analyzers/GetEntraIDSignIns/GetEntraIDSignIns.py index 6616e28eb..009a89d63 --- a/analyzers/GetAzureSignIns/GetAzureSignIns.py +++ b/analyzers/GetEntraIDSignIns/GetEntraIDSignIns.py @@ -7,12 +7,12 @@ from cortexutils.analyzer import Analyzer # Initialize Azure Class -class GetAzureSignIns(Analyzer): +class GetEntraIDSignIns(Analyzer): def __init__(self): Analyzer.__init__(self) - self.client_id = self.get_param('config.client_id', None, 'Azure AD Application ID/Client ID Missing') - self.client_secret = self.get_param('config.client_secret', None, 'Azure AD Registered Application Client Secret Missing') - self.tenant_id = self.get_param('config.tenant_id', None, 'Azure AD Tenant ID Mising') + self.client_id = self.get_param('config.client_id', None, 'Microsoft Entra ID Application ID/Client ID Missing') + self.client_secret = self.get_param('config.client_secret', None, 'Microsoft Entra ID Registered Application Client Secret Missing') + self.tenant_id = self.get_param('config.tenant_id', None, 'Microsoft Entra ID Tenant ID Mising') self.time_range = self.get_param('config.lookup_range', 7) self.lookup_limit = self.get_param('config.lookup_limit', 12) self.state = self.get_param('config.state', None) @@ -142,19 +142,21 @@ def run(self): def summary(self, raw): taxonomies = [] - if len(raw['signIns']) == 0: - taxonomies.append(self.build_taxonomy('info', 'AzureSignins', 'SignIns', 'None')) + if len(raw.get('signIns', [])) == 0: + taxonomies.append(self.build_taxonomy('info', 'EntraIDSignins', 'SignIns', 'None')) else: - taxonomies.append(self.build_taxonomy('safe', 'AzureSignins', 'Count', len(raw['signIns']))) + taxonomies.append(self.build_taxonomy('safe', 'EntraIDSignins', 'Count', len(raw['signIns']))) - # If the summary stats are present, then add them. If not, don't. - stats = raw["sum_stats"] - if stats["riskySignIns"] != 0: taxonomies.append(self.build_taxonomy('suspicious', 'AzureSignins', 'Risky', stats[0])) - if stats["externalStateSignIns"] != 0: taxonomies.append(self.build_taxonomy('suspicious', 'AzureSignins', 'OutOfState', stats[1])) - if stats["foreignSignIns"] != 0: taxonomies.append(self.build_taxonomy('malicious', 'AzureSignins', 'ForeignSignIns', stats[2])) - + stats = raw.get("sum_stats", {}) + if stats.get("riskySignIns", 0) != 0: + taxonomies.append(self.build_taxonomy('suspicious', 'EntraIDSignins', 'Risky', stats["riskySignIns"])) + if stats.get("externalStateSignIns", 0) != 0: + taxonomies.append(self.build_taxonomy('suspicious', 'EntraIDSignins', 'OutOfState', stats["externalStateSignIns"])) + if stats.get("foreignSignIns", 0) != 0: + taxonomies.append(self.build_taxonomy('malicious', 'EntraIDSignins', 'ForeignSignIns', stats["foreignSignIns"])) return {'taxonomies': taxonomies} + if __name__ == '__main__': - GetAzureSignIns().run() + GetEntraIDSignIns().run() diff --git a/analyzers/GetAzureSignIns/README.md b/analyzers/GetEntraIDSignIns/README.md similarity index 80% rename from analyzers/GetAzureSignIns/README.md rename to analyzers/GetEntraIDSignIns/README.md index 26c0b6011..55ab06fee 100644 --- a/analyzers/GetAzureSignIns/README.md +++ b/analyzers/GetEntraIDSignIns/README.md @@ -1,15 +1,15 @@ -## Azure Sign In Retreiver +## Microsoft Entra ID Sign In Retriever -This responder allows you to revoke the session tokens for an Azure AD user. Requires the UPN of the account in question, which should be entered as a "mail" oberservable in TheHive. +This responder allows you to revoke the session tokens for an Microsoft Entra ID user. Requires the UPN of the account in question, which should be entered as a "mail" oberservable in TheHive. ### Config To enable the responder, you *need* three values: -1. Azure Tenant ID +1. Microsoft Entra ID Tenant ID 2. Application ID 3. Application Secret -The first two values can be found at any time in the application's Overview page in the Azure portal. The secret must be generated and then stored in a safe place, as it is only fully visible when you first make it. +The first two values can be found at any time in the application's Overview page in the Microsoft Entra ID portal. The secret must be generated and then stored in a safe place, as it is only fully visible when you first make it. You can also specify the limits for how far back the analyzer requests sign ins. You can specify time and count for how many sign ins get returned. @@ -24,7 +24,7 @@ User account with the Global Administrator Role (most of the steps can be done w ### Steps #### Creation -1. Navigate to the [Azure Portal](https://portal.azure.com) and sign in with the relevant administrator account. +1. Navigate to the [Microsoft Entra ID Portal](https://entra.microsoft.com/) and sign in with the relevant administrator account. 2. Navigate to App Registrations, and create a new registration. 3. Provide a display name (this can be anything, and can be changed later). Click Register. @@ -46,4 +46,4 @@ It is possible to add a color coding system to the long report as viewed from Th ### Example -Let's say you are in an organization where almost all of your users will be signing in from a single state. You could color code the table so that out-of-state sign ins are highlighted yellow, and out-of-country sign ins are highlighted in red. To enable customization like this, you must modify this analyzer's long.html to check for values within the full JSON report using the ng-style tag in the *table body > table row* element. An example exists as a comment in the long.html file at line 34. \ No newline at end of file +Let's say you are in an organization where almost all of your users will be signing in from a single state. You could color code the table so that out-of-state sign ins are highlighted yellow, and out-of-country sign ins are highlighted in red. To enable customization like this, you must modify this analyzer's long.html to check for values within the full JSON report using the ng-style tag in the *table body > table row* element. An example exists as a comment in the long.html file at line 34. \ No newline at end of file diff --git a/analyzers/GetAzureSignIns/requirements.txt b/analyzers/GetEntraIDSignIns/requirements.txt similarity index 100% rename from analyzers/GetAzureSignIns/requirements.txt rename to analyzers/GetEntraIDSignIns/requirements.txt diff --git a/responders/AzureTokenRevoker/AzureTokenRevoker.json b/responders/AzureTokenRevoker/AzureTokenRevoker.json deleted file mode 100644 index a1ac4e1e9..000000000 --- a/responders/AzureTokenRevoker/AzureTokenRevoker.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "AzureTokenRevoker", - "version": "1.1", - "author": "Daniel Weiner @dmweiner, revised by @jahamilto", - "url": "https://github.com/TheHive-Project/Cortex-Analyzers", - "license": "AGPL-V3", - "description": "Revoke all Microsoft Azure authentication session tokens for a list of User Principal Names", - "dataTypeList": ["thehive:case_artifact"], - "command": "AzureTokenRevoker/AzureTokenRevoker.py", - "baseConfig": "AzureTokenRevoker", - "configurationItems": [ - {"name": "tenant_id", - "description": "Azure Directory/Tenant ID", - "type": "string", - "multi": false, - "required": true - }, - {"name": "client_id", - "description": "Client ID/Application ID of Azure AD Registered App", - "type": "string", - "multi": false, - "required": true - }, - {"name": "client_secret", - "description": "Secret for Azure AD Registered Application", - "type": "string", - "multi": false, - "required": true - } - ] - -} diff --git a/responders/EntraIDTokenRevoker/EntraIDTokenRevoker.json b/responders/EntraIDTokenRevoker/EntraIDTokenRevoker.json new file mode 100644 index 000000000..25b819d8b --- /dev/null +++ b/responders/EntraIDTokenRevoker/EntraIDTokenRevoker.json @@ -0,0 +1,35 @@ +{ + "name": "EntraIDTokenRevoker", + "version": "1.1", + "author": "Daniel Weiner @dmweiner, revised by @jahamilto", + "url": "https://github.com/TheHive-Project/Cortex-Analyzers", + "license": "AGPL-V3", + "description": "Revoke all Microsoft Entra ID authentication session tokens for a User Principal Name.", + "dataTypeList": ["thehive:case_artifact"], + "command": "EntraIDTokenRevoker/EntraIDTokenRevoker.py", + "baseConfig": "EntraIDTokenRevoker", + "configurationItems": [ + {"name": "tenant_id", + "description": "Microsoft Entra ID Tenant ID", + "type": "string", + "multi": false, + "required": true + }, + {"name": "client_id", + "description": "Client ID/Application ID of Microsoft Entra ID Registered App", + "type": "string", + "multi": false, + "required": true + }, + {"name": "client_secret", + "description": "Secret for Microsoft Entra ID Registered Application", + "type": "string", + "multi": false, + "required": true + } + ], + "registration_required": true, + "subscription_required": true, + "free_subscription": false, + "service_homepage": "https://www.microsoft.com/security/business/identity-access/microsoft-entra-id" +} diff --git a/responders/AzureTokenRevoker/AzureTokenRevoker.py b/responders/EntraIDTokenRevoker/EntraIDTokenRevoker.py similarity index 90% rename from responders/AzureTokenRevoker/AzureTokenRevoker.py rename to responders/EntraIDTokenRevoker/EntraIDTokenRevoker.py index 70c769bc6..897219163 100755 --- a/responders/AzureTokenRevoker/AzureTokenRevoker.py +++ b/responders/EntraIDTokenRevoker/EntraIDTokenRevoker.py @@ -1,70 +1,70 @@ -#!/usr/bin/env python3 -# encoding: utf-8 -# Author: Daniel Weiner @dmweiner, revised by @jahamilto -import requests -import traceback -import datetime -from cortexutils.responder import Responder - -# Initialize Azure Class -class AzureTokenRevoker(Responder): - def __init__(self): - Responder.__init__(self) - self.client_id = self.get_param('config.client_id', None, 'Azure AD Application ID/Client ID Missing') - self.client_secret = self.get_param('config.client_secret', None, 'Azure AD Registered Application Client Secret Missing') - self.tenant_id = self.get_param('config.tenant_id', None, 'Azure AD Tenant ID Mising') - self.time = '' - def run(self): - Responder.run(self) - - if self.get_param('data.dataType') == 'mail': - try: - self.user = self.get_param('data.data', None, 'No UPN supplied to revoke credentials for') - if not self.user: - self.error("No user supplied") - - token_data = { - "grant_type": "client_credentials", - 'client_id': self.client_id, - 'client_secret': self.client_secret, - 'resource': 'https://graph.microsoft.com', - 'scope': 'https://graph.microsoft.com' - } - - - #Authenticate to the graph api - - redirect_uri = "https://login.microsoftonline.com/{}/oauth2/token".format(self.tenant_id) - token_r = requests.post(redirect_uri, data=token_data) - token = token_r.json().get('access_token') - - if token_r.status_code != 200: - self.error('Failure to obtain azure access token: {}'.format(token_r.content)) - - # Set headers for future requests - headers = { - 'Authorization': 'Bearer {}'.format(token) - } - - base_url = 'https://graph.microsoft.com/v1.0/' - - r = requests.post(base_url + 'users/{}/revokeSignInSessions'.format(self.user), headers=headers) - - if r.status_code != 200: - self.error('Failure to revoke access tokens of user {}: {}'.format(self.user, r.content)) - - else: - #record time of successful auth token revokation - self.time = datetime.datetime.utcnow() - - except Exception as ex: - self.error(traceback.format_exc()) - # Build report to return to Cortex - full_report = {"message": "User {} authentication tokens successfully revoked at {}".format(self.user, self.time)} - self.report(full_report) - else: - self.error('Incorrect dataType. "mail" expected.') - - -if __name__ == '__main__': - AzureTokenRevoker().run() +#!/usr/bin/env python3 +# encoding: utf-8 +# Author: Daniel Weiner @dmweiner, revised by @jahamilto +import requests +import traceback +import datetime +from cortexutils.responder import Responder + +# Initialize Azure Class +class EntraIDTokenRevoker(Responder): + def __init__(self): + Responder.__init__(self) + self.client_id = self.get_param('config.client_id', None, 'Microsoft Entra ID Application ID/Client ID Missing') + self.client_secret = self.get_param('config.client_secret', None, 'Microsoft Entra ID Registered Application Client Secret Missing') + self.tenant_id = self.get_param('config.tenant_id', None, 'Microsoft Entra ID Tenant ID Mising') + self.time = '' + def run(self): + Responder.run(self) + + if self.get_param('data.dataType') == 'mail': + try: + self.user = self.get_param('data.data', None, 'No UPN supplied to revoke credentials for') + if not self.user: + self.error("No user supplied") + + token_data = { + "grant_type": "client_credentials", + 'client_id': self.client_id, + 'client_secret': self.client_secret, + 'resource': 'https://graph.microsoft.com', + 'scope': 'https://graph.microsoft.com' + } + + + #Authenticate to the graph api + + redirect_uri = "https://login.microsoftonline.com/{}/oauth2/token".format(self.tenant_id) + token_r = requests.post(redirect_uri, data=token_data) + token = token_r.json().get('access_token') + + if token_r.status_code != 200: + self.error('Failure to obtain azure access token: {}'.format(token_r.content)) + + # Set headers for future requests + headers = { + 'Authorization': 'Bearer {}'.format(token) + } + + base_url = 'https://graph.microsoft.com/v1.0/' + + r = requests.post(base_url + 'users/{}/revokeSignInSessions'.format(self.user), headers=headers) + + if r.status_code != 200: + self.error('Failure to revoke access tokens of user {}: {}'.format(self.user, r.content)) + + else: + #record time of successful auth token revokation + self.time = datetime.datetime.utcnow() + + except Exception as ex: + self.error(traceback.format_exc()) + # Build report to return to Cortex + full_report = {"message": "User {} authentication tokens successfully revoked at {}".format(self.user, self.time)} + self.report(full_report) + else: + self.error('Incorrect dataType. "mail" expected.') + + +if __name__ == '__main__': + EntraIDTokenRevoker().run() diff --git a/responders/AzureTokenRevoker/README.md b/responders/EntraIDTokenRevoker/README.md similarity index 68% rename from responders/AzureTokenRevoker/README.md rename to responders/EntraIDTokenRevoker/README.md index 329c16d2a..32b8e1db6 100644 --- a/responders/AzureTokenRevoker/README.md +++ b/responders/EntraIDTokenRevoker/README.md @@ -1,15 +1,15 @@ -## Azure Sign In Token Revoker Responder +## Microsoft Entra ID Sign In Token Revoker Responder -This responder allows you to revoke the session tokens for an Azure AD user. Requires the UPN of the account in question, which should be entered as a "mail" oberservable in TheHive. +This responder allows you to revoke the session tokens for an Microsoft Entra ID user. Requires the UPN of the account in question, which should be entered as a "mail" observable in TheHive. ### Config To enable the responder, you need three values: -1. Azure Tenant ID +1. Microsoft Entra ID Tenant ID 2. Application ID 3. Application Secret -The first two values can be found at any time in the application's Overview page in the Azure portal. The secret must be generated and then stored in a safe place, as it is only fully visible when you first make it. +The first two values can be found at any time in the application's Overview page in the Microsoft Entra ID portal. The secret must be generated and then stored in a safe place, as it is only fully visible when you first make it. ## Setup @@ -20,7 +20,7 @@ User account with the Global Administrator Role (most of the steps can be done w ### Steps #### Creation -1. Navigate to the [Azure Portal](https://portal.azure.com) and sign in with the relevant administrator account. +1. Navigate to the [Microsoft Entra ID Portal](https://entra.microsoft.com/) and sign in with the relevant administrator account. 2. Navigate to App Registrations, and create a new registration. 3. Provide a display name (this can be anything, and can be changed later). Click Register. diff --git a/responders/AzureTokenRevoker/requirements.txt b/responders/EntraIDTokenRevoker/requirements.txt similarity index 100% rename from responders/AzureTokenRevoker/requirements.txt rename to responders/EntraIDTokenRevoker/requirements.txt diff --git a/thehive-templates/GetAzureSignIns_1_0/long.html b/thehive-templates/GetEntraIDSignIns_1_0/long.html similarity index 98% rename from thehive-templates/GetAzureSignIns_1_0/long.html rename to thehive-templates/GetEntraIDSignIns_1_0/long.html index dfa370148..d9f508b50 100644 --- a/thehive-templates/GetAzureSignIns_1_0/long.html +++ b/thehive-templates/GetEntraIDSignIns_1_0/long.html @@ -1,6 +1,6 @@