diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f8eb5a..3088abd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ All notable changes to this project will be documented in this file. +## [1.2.2] - The goose is loose - 2023-07-17 +### Added +- Better catches for when password for the account needs to be updated, when a conditional access policy blocks user account access, or when the user account is flagged for risky actions. +- Added catch for empty `.conf` fields, will allow more graceful exiting. + +### Changed +- Updated and pinned `aiohttp`, `colored`, `cryptography`, and `selenium` dependencies and updated Python version to 3.10.11. +- Pinned 3.1.0 version of ExchangeOnlineManagement PowerShell module. +- Improved logic for grabbing `validationkey` from requests. + +### Fixed +- Fixed MFA logic for messagetrace.py. +- Fixed data dumper logic, they will only run if something in their section is set to `True`. + ## [1.2.1] - The goose is loose - 2023-06-06 ### Added - Implemented new tables to be pulled from MDE. diff --git a/README.md b/README.md index 4157611..d20b940 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ For more guidance on how to use Untitled Goose Tool, please see: [Untitled Goose ## Getting Started ### Prerequisites -Python 3.7, 3.8, 3.9, or 3.10 (up to 3.10.10) is required to run Untitled Goose Tool with Python. Python 3.10.11 is currently being tested. +Python 3.7, 3.8, 3.9, or 3.10 (up to 3.10.11) is required to run Untitled Goose Tool with Python. Firefox is required for authenticating with Untitled Goose Tool. @@ -684,9 +684,9 @@ $ goosey messagetrace --gather-report --interactive ```sh #For Windows: - webdrivermanager firefox:v0.32.0 --linkpath AUTO + webdrivermanager firefox:v0.33.0 --linkpath AUTO #For *nix recommend install outside of a virtual environment if you are working in one (you might need sudo): - webdrivermanager firefox:v0.32.0 --linkpath /usr/local/bin + webdrivermanager firefox:v0.33.0 --linkpath /usr/local/bin ``` 7. Excessive amount of 429 errors during `goosey honk` diff --git a/cyclonedx_output.json b/cyclonedx_output.json index 805267c..0ab680a 100644 --- a/cyclonedx_output.json +++ b/cyclonedx_output.json @@ -2,26 +2,26 @@ "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4", - "serialNumber": "urn:uuid:e3f22225-e0a8-4ff7-a369-f50caa3e15fb", + "serialNumber": "urn:uuid:2901c5d5-f1ee-49b1-bc86-243bd25781bb", "version": 1, "metadata": { - "timestamp": "2023-06-02T10:38:52-04:00", + "timestamp": "2023-07-17T15:38:39-04:00", "tools": [ { "vendor": "anchore", "name": "syft", - "version": "0.82.0" + "version": "0.85.0" } ], "component": { - "bom-ref": "1964c4ec04b45222", + "bom-ref": "9f51c64f49e33ff9", "type": "file", - "name": "./untitledgoosetool" + "name": "untitledgoosetool" } }, "components": [ { - "bom-ref": "pkg:pypi/gooey@1.0.8.1?package-id=36270366523988d", + "bom-ref": "pkg:pypi/gooey@1.0.8.1?package-id=2e8725a6135b4f82", "type": "library", "name": "Gooey", "version": "1.0.8.1", @@ -86,17 +86,17 @@ }, { "name": "syft:location:0:path", - "value": "setup.py" + "value": "/setup.py" } ] }, { - "bom-ref": "pkg:pypi/aiohttp@3.8.1?package-id=2d83bd819e2e7cb0", + "bom-ref": "pkg:pypi/aiohttp@3.8.4?package-id=cb709e196c491694", "type": "library", "name": "aiohttp", - "version": "3.8.1", - "cpe": "cpe:2.3:a:python-aiohttp:python-aiohttp:3.8.1:*:*:*:*:*:*:*", - "purl": "pkg:pypi/aiohttp@3.8.1", + "version": "3.8.4", + "cpe": "cpe:2.3:a:python-aiohttp:python-aiohttp:3.8.4:*:*:*:*:*:*:*", + "purl": "pkg:pypi/aiohttp@3.8.4", "properties": [ { "name": "syft:package:foundBy", @@ -112,51 +112,273 @@ }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python-aiohttp:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python-aiohttp:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python_aiohttp:python-aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python_aiohttp:python-aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python_aiohttp:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python_aiohttp:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:aiohttp:python-aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:aiohttp:python-aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:aiohttp:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:aiohttp:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python-aiohttp:aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python-aiohttp:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python_aiohttp:aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python_aiohttp:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python:python-aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python:python-aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:aiohttp:aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:aiohttp:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:cpe23", - "value": "cpe:2.3:a:python:aiohttp:3.8.1:*:*:*:*:*:*:*" + "value": "cpe:2.3:a:python:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "name": "syft:location:0:path", - "value": "setup.py" + "value": "/setup.py" + } + ] + }, + { + "bom-ref": "pkg:pypi/colored@1.4.4?package-id=c7b0fb9bcccd72da", + "type": "library", + "name": "colored", + "version": "1.4.4", + "cpe": "cpe:2.3:a:python-colored:python-colored:1.4.4:*:*:*:*:*:*:*", + "purl": "pkg:pypi/colored@1.4.4", + "properties": [ + { + "name": "syft:package:foundBy", + "value": "python-index-cataloger" + }, + { + "name": "syft:package:language", + "value": "python" + }, + { + "name": "syft:package:type", + "value": "python" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-colored:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_colored:python-colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_colored:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:colored:python-colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:colored:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-colored:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_colored:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:python-colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:colored:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "name": "syft:location:0:path", + "value": "/setup.py" + } + ] + }, + { + "bom-ref": "pkg:pypi/cryptography@41.0.1?package-id=9b4891146eaf3965", + "type": "library", + "name": "cryptography", + "version": "41.0.1", + "cpe": "cpe:2.3:a:python-cryptography_project:python-cryptography:41.0.1:*:*:*:*:*:*:*", + "purl": "pkg:pypi/cryptography@41.0.1", + "properties": [ + { + "name": "syft:package:foundBy", + "value": "python-index-cataloger" + }, + { + "name": "syft:package:language", + "value": "python" + }, + { + "name": "syft:package:type", + "value": "python" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-cryptography_project:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-cryptography_project:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-cryptography:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-cryptography:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_cryptography:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_cryptography:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:cryptography:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:cryptography:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-cryptography:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_cryptography:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:cryptography:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "name": "syft:location:0:path", + "value": "/setup.py" + } + ] + }, + { + "bom-ref": "pkg:pypi/selenium@4.10.0?package-id=6ba25d40458e5d0a", + "type": "library", + "name": "selenium", + "version": "4.10.0", + "cpe": "cpe:2.3:a:python-selenium:python-selenium:4.10.0:*:*:*:*:*:*:*", + "purl": "pkg:pypi/selenium@4.10.0", + "properties": [ + { + "name": "syft:package:foundBy", + "value": "python-index-cataloger" + }, + { + "name": "syft:package:language", + "value": "python" + }, + { + "name": "syft:package:type", + "value": "python" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-selenium:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_selenium:python-selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_selenium:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python-selenium:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python_selenium:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:selenium:python-selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:selenium:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:python-selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:selenium:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:cpe23", + "value": "cpe:2.3:a:python:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "name": "syft:location:0:path", + "value": "/setup.py" } ] } diff --git a/goosey/auth.py b/goosey/auth.py index 2007497..8be8aba 100644 --- a/goosey/auth.py +++ b/goosey/auth.py @@ -27,7 +27,7 @@ from seleniumwire import webdriver __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" green = "\x1b[1;32m" @@ -194,6 +194,20 @@ def authenticate_device_code_selenium(self): except Exception as e: pass + try: + if "Your sign-in was successful but does not meet the criteria to access this resource" in browser.find_element(By.ID, "ErrorDescription").text: + browser.quit() + sys.exit("Device code authentication - Your sign-in was successful but does not meet the criteria to access this resource. For example, you might be signing in from a browser, app, or location that is restricted by your admin. Make sure to meet your conditional access policies and try again.") + except Exception as e: + pass + + try: + if "Your account is at risk" in browser.find_element(By.ID, "landingTitle").text: + browser.quit() + sys.exit("Device code authentication - Your account is at risk. Please investigate this issue and try again.") + except Exception as e: + pass + try: if "Approve sign in request" in browser.find_element(By.ID, "idDiv_SAOTCAS_Title").text: self.logger.debug("Device code authentication - Push notification MFA detected.") @@ -263,6 +277,13 @@ def authenticate_device_code_selenium(self): except Exception as e: pass + try: + WebDriverWait(browser, 3).until(EC.presence_of_element_located((By.ID, 'ChangePasswordDescription'))) + browser.quit() + sys.exit("Device code authentication - Password reset required. Change your password and try again.") + except Exception as e: + pass + # Wait for AAD PowerShell prompt WebDriverWait(browser, 60).until(EC.element_to_be_clickable(NEXTBUTTON)).click() @@ -379,7 +400,21 @@ def authenticate_mfa_interactive(self): browser.quit() sys.exit("M365 user authentication - Your organization needs more information to keep your account secure. Manually fix this problem and try again.") except Exception as e: - pass + pass + + try: + if "Your sign-in was successful but does not meet the criteria to access this resource" in browser.find_element(By.ID, "ErrorDescription").text: + browser.quit() + sys.exit("M365 user authentication - Your sign-in was successful but does not meet the criteria to access this resource. For example, you might be signing in from a browser, app, or location that is restricted by your admin. Make sure to meet your conditional access policies and try again.") + except Exception as e: + pass + + try: + if "Your account is at risk" in browser.find_element(By.ID, "landingTitle").text: + browser.quit() + sys.exit("M365 user authentication - Your account is at risk. Please investigate this issue and try again.") + except Exception as e: + pass try: if "Approve sign in request" in browser.find_element(By.ID, "idDiv_SAOTCAS_Title").text: @@ -452,6 +487,15 @@ def authenticate_mfa_interactive(self): time.sleep(5) + try: + WebDriverWait(browser, 3).until(EC.presence_of_element_located((By.ID, 'ChangePasswordDescription'))) + browser.quit() + sys.exit("Device code authentication - Password reset required. Change your password and try again.") + except Exception as e: + pass + + time.sleep(5) + # Switch to second tab browser.execute_script("window.open('');") browser.switch_to.window(browser.window_handles[1]) @@ -476,18 +520,14 @@ def authenticate_mfa_interactive(self): browser.switch_to.window(browser.window_handles[2]) self.logger.debug("Opening third tab: Admin Exchange Portal") if self.exo_us_government == 'false': - browser.get("https://admin.exchange.microsoft.com/") + browser.get("https://admin.exchange.microsoft.com/#/messagetrace") try: - WebDriverWait(browser, 20).until(EC.url_matches('https://admin.exchange.microsoft.com/#/')) - browser.get("https://admin.exchange.microsoft.com/#/messagetrace") WebDriverWait(browser, 20).until((EC.url_matches('https://admin.exchange.microsoft.com/#/messagetrace'))) except Exception as e: pass elif self.exo_us_government == 'true': browser.get("http://admin.exchange.office365.us/#/messagetrace") try: - WebDriverWait(browser, 20).until(EC.url_matches('https://admin.exchange.microsoft.us/#/')) - browser.get("https://admin.exchange.microsoft.us/#/messagetrace") WebDriverWait(browser, 20).until((EC.url_matches('https://admin.exchange.microsoft.us/#/messagetrace'))) except Exception as e: pass @@ -540,12 +580,9 @@ def authenticate_mfa_interactive(self): self.logger.error("Error obtaining " + cookie_str + ": " + str(e)) for request in browser.requests: - if self.exo_us_government == 'false': - if request.url == "https://admin.exchange.microsoft.com/beta/UserProfile": - self.tokendata['validationkey'] = request.headers['validationkey'] - else: - if request.url == "https://admin.exchange.microsoft.us/beta/UserProfile": - self.tokendata['validationkey'] = request.headers['validationkey'] + if request.headers['validationkey']: + self.tokendata['validationkey'] = request.headers['validationkey'] + break if not self.tokendata['validationkey']: self.logger.error("Error obtaining validationkey.") @@ -662,6 +699,10 @@ def parse_config(self, configfile): self.exo_us_government = config_get(config, 'config', 'exo_us_government', self.logger).lower() self.subscriptions = config_get(config, 'config', 'subscriptionid', self.logger) self.m365 = config_get(config, 'config', 'm365', self.logger).lower() + + if self.us_government == '' or self.mde_gcc == '' or self.mde_gcc_high == '' or self.tenant == '' or self.exo_us_government == '' or self.subscriptions == '' or self.m365 == '': + self.logger.error("Empty contents within .conf file. Please edit and try again.") + sys.exit(1) else: self.d4iot_sensor_ip = config_get(config, 'config', 'd4iot_sensor_ip', self.logger) self.d4iot_mgmt_ip = config_get(config, 'config', 'd4iot_mgmt_ip', self.logger) diff --git a/goosey/azure_ad_datadumper.py b/goosey/azure_ad_datadumper.py index b8ad6c9..969f8c9 100644 --- a/goosey/azure_ad_datadumper.py +++ b/goosey/azure_ad_datadumper.py @@ -15,7 +15,7 @@ from goosey.utils import * __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" class AzureAdDataDumper(DataDumper): diff --git a/goosey/azure_dumper.py b/goosey/azure_dumper.py index 81c76df..6bdf150 100644 --- a/goosey/azure_dumper.py +++ b/goosey/azure_dumper.py @@ -29,7 +29,7 @@ from typing import NewType, Optional __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" utc = pytz.UTC @@ -214,7 +214,8 @@ async def dump_portal_pcap(self) -> None: result = await r.json() if 'error' in result: if result['error']['code'] == 'NotFound': - self.logger.debug("Resource not found. Proceeding") + self.logger.debug("Resource not found. Exiting.") + return elif result['error']['code'] == 'ExpiredAuthenticationToken': self.logger.error("Error with authentication token: " + result['error']['message']) self.logger.error("Please re-auth.") @@ -639,7 +640,7 @@ async def dump_storage_accounts(self) -> None: f.write("\n") f.flush() os.fsync(f) - + self.logger.info('Finished getting all Azure storage account information for ' + sub_id + '.') except HttpResponseError: self.logger.debug("Caught HTTP Response Error on subscription " + sub_id) continue diff --git a/goosey/csv.py b/goosey/csv.py index ec1e3f9..9443365 100644 --- a/goosey/csv.py +++ b/goosey/csv.py @@ -14,7 +14,7 @@ from goosey.utils import * __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" if sys.platform == 'win32': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) diff --git a/goosey/d4iot.py b/goosey/d4iot.py index 5e005a8..690210d 100644 --- a/goosey/d4iot.py +++ b/goosey/d4iot.py @@ -22,7 +22,7 @@ from goosey.utils import * __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" if sys.platform == 'win32': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) diff --git a/goosey/d4iot_dumper.py b/goosey/d4iot_dumper.py index f58faf7..1eb3972 100644 --- a/goosey/d4iot_dumper.py +++ b/goosey/d4iot_dumper.py @@ -12,7 +12,7 @@ from goosey.utils import * __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" class DefenderIoTDumper(DataDumper): def __init__(self, output_dir, reports_dir, session, csrftoken, sessionid, config, auth_un_pw, debug): diff --git a/goosey/datadumper.py b/goosey/datadumper.py index c6c8f85..44915b2 100644 --- a/goosey/datadumper.py +++ b/goosey/datadumper.py @@ -4,7 +4,7 @@ from goosey.utils import * __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" class DataDumper(object): def __init__(self, output_dir: str, reports_dir: str, auth: dict, app_auth: dict, session, debug): diff --git a/goosey/graze.py b/goosey/graze.py index 39fe7bc..6e8e508 100644 --- a/goosey/graze.py +++ b/goosey/graze.py @@ -24,7 +24,7 @@ from urllib.parse import unquote __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" warnings.simplefilter('ignore') diff --git a/goosey/guimain.py b/goosey/guimain.py index 59a933f..91900e4 100644 --- a/goosey/guimain.py +++ b/goosey/guimain.py @@ -18,7 +18,7 @@ from goosey.main import main as gooseymain __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" try: from gooey import Gooey, GooeyParser diff --git a/goosey/honk.py b/goosey/honk.py index 94d4a5d..c0a1d68 100644 --- a/goosey/honk.py +++ b/goosey/honk.py @@ -5,6 +5,7 @@ This module performs data collection of various data sources from an Azure/M365 environment. """ +from mimetypes import init import aiohttp import argparse import asyncio @@ -25,7 +26,7 @@ from goosey.utils import * __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" if sys.platform == 'win32': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) @@ -92,7 +93,7 @@ def getargs(honk_parser) -> None: help='Set all of the MDE calls to true', default=False) -async def run(args, config, auth, auth_un_pw=None): +async def run(args, config, auth, init_sections, auth_un_pw=None): """Main async run loop :param args: argparse object with populated namespace @@ -124,26 +125,40 @@ async def run(args, config, auth, auth_un_pw=None): msft_security_auth = auth['app_auth'][key] maindumper = DataDumper(args.output_dir, args.reports_dir, msft_graph_auth, msft_graph_app_auth, session, args.debug) + + m365, azuread, azure, mde = False, False, False, False if args.dry_run: m365dumper = maindumper azureaddumper = maindumper azure_dumper = maindumper mdedumper = maindumper + else: - m365dumper = M365DataDumper(args.output_dir, args.reports_dir, msft_graph_auth, msft_graph_app_auth, maindumper.ahsession, config, args.debug) - azureaddumper = AzureAdDataDumper(args.output_dir, args.reports_dir, msft_graph_auth, msft_graph_app_auth, maindumper.ahsession, config, args.debug) - azure_dumper = AzureDataDumper(args.output_dir, args.reports_dir, maindumper.ahsession, mgmt_app_auth, config, auth_un_pw, args.debug) - mdedumper = MDEDataDumper(args.output_dir, args.reports_dir, msft_graph_auth, msft_security_center_auth, msft_security_auth, maindumper.ahsession, config, args.debug) + if 'm365' in init_sections: + m365dumper = M365DataDumper(args.output_dir, args.reports_dir, msft_graph_auth, msft_graph_app_auth, maindumper.ahsession, config, args.debug) + m365 = True + if 'azuread' in init_sections: + azureaddumper = AzureAdDataDumper(args.output_dir, args.reports_dir, msft_graph_auth, msft_graph_app_auth, maindumper.ahsession, config, args.debug) + azuread = True + if 'azure' in init_sections: + azure_dumper = AzureDataDumper(args.output_dir, args.reports_dir, maindumper.ahsession, mgmt_app_auth, config, auth_un_pw, args.debug) + azure = True + if 'mde' in init_sections: + mdedumper = MDEDataDumper(args.output_dir, args.reports_dir, msft_graph_auth, msft_security_center_auth, msft_security_auth, maindumper.ahsession, config, args.debug) + mde = True async with maindumper.ahsession as ahsession: - tasks = [] - tasks.extend(azure_dumper.data_dump(data_calls['azure'])) - tasks.extend(m365dumper.data_dump(data_calls['m365'])) - tasks.extend(azureaddumper.data_dump(data_calls['azuread'])) - tasks.extend(mdedumper.data_dump(data_calls['mde'])) - + if m365: + tasks.extend(m365dumper.data_dump(data_calls['m365'])) + if azuread: + tasks.extend(azureaddumper.data_dump(data_calls['azuread'])) + if azure: + tasks.extend(azure_dumper.data_dump(data_calls['azure'])) + if mde: + tasks.extend(mdedumper.data_dump(data_calls['mde'])) + await asyncio.gather(*tasks) def _get_section_dict(config, s): @@ -163,12 +178,14 @@ def parse_config(configfile, args, auth=None): else: sections = ['auth'] + init_sections = [] for section in sections: d = _get_section_dict(config, section) data_calls[section] = {} for key in d: if d[key]: data_calls[section][key] = True + init_sections.append(section) if args.azure: for item in [x.replace('dump_', '') for x in dir(AzureDataDumper) if x.startswith('dump_')]: @@ -184,7 +201,7 @@ def parse_config(configfile, args, auth=None): data_calls['mde'][item] = True logger.debug(json.dumps(data_calls, indent=2)) - return config + return config, init_sections def main(args=None, gui=False) -> None: global logger @@ -228,7 +245,7 @@ def main(args=None, gui=False) -> None: if os.path.isfile(args.auth): logger.info("Reading in auth: {}".format(args.auth)) with open(args.auth, 'r') as infile: - auth_un_pw = parse_config(args.auth, args, auth=True) + auth_un_pw, _ = parse_config(args.auth, args, auth=True) else: auth_un_pw = None except Exception as e: @@ -274,12 +291,12 @@ def main(args=None, gui=False) -> None: check_output_dir(f'{args.output_dir}{os.path.sep}m365', logger) check_output_dir(f'{args.output_dir}{os.path.sep}azuread', logger) check_output_dir(f'{args.output_dir}{os.path.sep}mde', logger) - config = parse_config(args.config, args) + config, init_sections = parse_config(args.config, args) logger.info("Goosey beginning to honk.") seconds = time.perf_counter() try: - asyncio.run(run(args, config, auth, auth_un_pw)) + asyncio.run(run(args, config, auth, init_sections, auth_un_pw=auth_un_pw)) except RuntimeError as e: sys.exit(1) elapsed = time.perf_counter() - seconds diff --git a/goosey/m365_datadumper.py b/goosey/m365_datadumper.py index 863c783..d7d24e7 100644 --- a/goosey/m365_datadumper.py +++ b/goosey/m365_datadumper.py @@ -23,7 +23,7 @@ from io import StringIO __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" class M365DataDumper(DataDumper): diff --git a/goosey/main.py b/goosey/main.py index b0311d6..8aa0123 100644 --- a/goosey/main.py +++ b/goosey/main.py @@ -35,7 +35,7 @@ ''' __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" def main(): # Primary argument parser diff --git a/goosey/mde_datadumper.py b/goosey/mde_datadumper.py index c876e37..5673d45 100644 --- a/goosey/mde_datadumper.py +++ b/goosey/mde_datadumper.py @@ -11,7 +11,7 @@ from goosey.utils import * __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" end_29_days_ago = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=29) today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) diff --git a/goosey/messagetrace.py b/goosey/messagetrace.py index 08dc318..02809db 100644 --- a/goosey/messagetrace.py +++ b/goosey/messagetrace.py @@ -40,7 +40,7 @@ ''' __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" logger = None encryption_pw = None @@ -285,7 +285,8 @@ def gather_results(self, args): if not self.headless: opts.add_argument("--headless") - browser = webdriver.Firefox(firefox_profile=ffprofile,options=opts) + opts.profile = ffprofile + browser = webdriver.Firefox(options=opts) try: if browser: @@ -308,27 +309,103 @@ def gather_results(self, args): WebDriverWait(browser, 60).until(EC.element_to_be_clickable(PASSWORDFIELD)).send_keys(self.password) WebDriverWait(browser, 60).until(EC.element_to_be_clickable(NEXTBUTTON)).click() - + try: WebDriverWait(browser, 3).until(EC.presence_of_element_located((By.ID, 'passwordError'))) browser.quit() - sys.exit("Incorrect password. Please correct it and try again.") + sys.exit("Messagetrace user authentication - Incorrect password. Please correct it and try again.") except Exception as e: pass try: WebDriverWait(browser, 3).until(EC.presence_of_element_located((By.ID, 'ChangePasswordDescription'))) browser.quit() - sys.exit("Password reset required. Change your password and try again.") + sys.exit("Messagetrace user authentication - Password reset required. Change your password and try again.") except Exception as e: pass try: WebDriverWait(browser, 3).until(EC.presence_of_element_located((By.ID, 'idDiv_SAASDS_Title'))) browser.quit() - sys.exit("Declined MFA. Please correct it and try again.") + sys.exit("Messagetrace user authentication - Declined MFA. Please correct it and try again.") + except Exception as e: + pass + + try: + if "Your organization needs more information to keep your account secure" in browser.find_element(By.ID, "ProofUpDescription").text: + browser.quit() + sys.exit("Messagetrace user authentication - Your organization needs more information to keep your account secure. Manually fix this problem and try again.") + except Exception as e: + pass + + try: + if "Approve sign in request" in browser.find_element(By.ID, "idDiv_SAOTCAS_Title").text: + self.logger.debug("Messagetrace user authentication - Push notification MFA detected.") + + if browser.find_element(By.ID, "idRichContext_DisplaySign"): + self.logger.debug("Messagetrace user authentication - Number matching MFA detected.") + mfa_code = browser.find_element(By.ID, "idRichContext_DisplaySign").text + self.logger.info("Messagetrace user authentication - Your MFA code is: " + str(mfa_code)) + time.sleep(10) + + time.sleep(20) + + if "Approve sign in request" in browser.find_element(By.ID, "idDiv_SAOTCAS_Title").text: + self.logger.info("Messagetrace user authentication - The MFA request was not approved in time.") + browser.quit() + sys.exit(1) + except Exception as e: + pass + + try: + if "Enter code" in browser.find_element(By.ID, "idDiv_SAOTCC_Title").text: + self.logger.debug("Messagetrace user authentication - OTP MFA detected.") + + if browser.find_element(By.ID, "idTxtBx_SAOTCC_OTC"): + OTP = (By.ID, "idTxtBx_SAOTCC_OTC") + OTP_code = getpass.getpass("Messagetrace user authentication - Please type your OTP code: ") + verify = (By.ID, "idSubmit_SAOTCC_Continue") + + WebDriverWait(browser, 60).until(EC.element_to_be_clickable(OTP)).send_keys(OTP_code) + WebDriverWait(browser, 60).until(EC.element_to_be_clickable(verify)).click() + + if browser.find_element(By.ID, "idDiv_SAOTCC_ErrorMsg_OTC"): + errormsg = browser.find_element(By.ID, "idDiv_SAOTCC_ErrorMsg_OTC").text + self.logger.error("Messagetrace user authentication - OTP error message: " + errormsg) + browser.quit() + sys.exit("Messagetrace user authentication - MFA failed. Please see OTP error message and try again.") except Exception as e: - pass + pass + + try: + if "Verify your identity" in browser.find_element(By.ID, "idDiv_SAOTCS_Title").text: + self.logger.debug("Messagetrace user authentication - Other MFA detected.") + + if "Text" in browser.find_element(By.ID, "idDiv_SAOTCS_Proofs_Section").text: + self.logger.debug("Messagetrace user authentication - Text option found.") + sms = (By.ID, "idDiv_SAOTCS_Proofs_Section") + WebDriverWait(browser, 60).until(EC.element_to_be_clickable(sms)).click() + self.logger.debug("Messagetrace user authentication - SMS OTP requested.") + time.sleep(10) + + if "Enter code" in browser.find_element(By.ID, "idDiv_SAOTCC_Title").text: + self.logger.debug("Messagetrace user authentication - SMS OTP MFA detected.") + + if browser.find_element(By.ID, "idTxtBx_SAOTCC_OTC"): + OTP = (By.ID, "idTxtBx_SAOTCC_OTC") + OTP_code = getpass.getpass("Messagetrace user authentication - Please type your OTP code: ") + verify = (By.ID, "idSubmit_SAOTCC_Continue") + + WebDriverWait(browser, 60).until(EC.element_to_be_clickable(OTP)).send_keys(OTP_code) + WebDriverWait(browser, 60).until(EC.element_to_be_clickable(verify)).click() + + if browser.find_element(By.ID, "idDiv_SAOTCC_ErrorMsg_OTC"): + errormsg = browser.find_element(By.ID, "idDiv_SAOTCC_ErrorMsg_OTC").text + self.logger.error("Messagetrace user authentication - OTP error message: " + errormsg) + browser.quit() + sys.exit("Messagetrace user authentication - MFA failed. Please see OTP error message and try again.") + except Exception as e: + pass # Stay signed in try: diff --git a/goosey/utils.py b/goosey/utils.py index 3b5490e..d6066e1 100644 --- a/goosey/utils.py +++ b/goosey/utils.py @@ -18,7 +18,7 @@ from logging import handlers __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" if sys.platform == 'win32': import msvcrt diff --git a/scripts/EXO.ps1 b/scripts/EXO.ps1 index d2cc0b5..a7f4a3b 100644 --- a/scripts/EXO.ps1 +++ b/scripts/EXO.ps1 @@ -20,18 +20,18 @@ Function Import-PSModules { If ($null -eq (Get-Module ExchangeOnlineManagement -ListAvailable -ErrorAction SilentlyContinue)){ Write-Host "Required module, ExchangeOnlineManagement, is not installed on the system." Write-Host "Installing ExchangeOnlineManagement from default repository" - Install-Module -Name ExchangeOnlineManagement -MinimumVersion 3.1.0 -Force -AllowClobber + Install-Module -Name ExchangeOnlineManagement -RequiredVersion 3.1.0 -Force -AllowClobber Write-Host "Importing ExchangeOnlineManagement" - Import-Module -Name ExchangeOnlineManagement -MinimumVersion 3.1.0 -Force - } ElseIf ($null -eq (Get-InstalledModule ExchangeOnlineManagement -MinimumVersion 2.0.5)) { - Write-Host "Outdated ExchangeOnlineManagement module is installed on the system." + Import-Module -Name ExchangeOnlineManagement -RequiredVersion 3.1.0 -Force + } ElseIf ($null -eq (Get-InstalledModule ExchangeOnlineManagement -RequiredVersion 3.1.0)) { + Write-Host "Incorrect version of ExchangeOnlineManagement module is installed on the system." Write-Host "Installing ExchangeOnlineManagement from default repository" - Install-Module -Name ExchangeOnlineManagement -MinimumVersion 3.1.0 -Force -AllowClobber + Install-Module -Name ExchangeOnlineManagement -RequiredVersion 3.1.0 -Force -AllowClobber Write-Host "Importing ExchangeOnlineManagement" - Import-Module -Name ExchangeOnlineManagement -MinimumVersion 3.1.0 -Force + Import-Module -Name ExchangeOnlineManagement -RequiredVersion 3.1.0 -Force } Else { Write-Host "Importing ExchangeOnlineManagement" - Import-Module -Name ExchangeOnlineManagement -MinimumVersion 3.1.0 -Force + Import-Module -Name ExchangeOnlineManagement -RequiredVersion 3.1.0 -Force } #If you want to change the default export directory, please change the $ExportDir value. diff --git a/scripts/generate_conf.py b/scripts/generate_conf.py index 12d9f24..b9b92ac 100644 --- a/scripts/generate_conf.py +++ b/scripts/generate_conf.py @@ -12,7 +12,7 @@ from goosey.mde_datadumper import MDEDataDumper __author__ = "Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace" -__version__ = "1.2.1" +__version__ = "1.2.2" def main(): auth_s = '[auth]\nusername=\npassword=\nappid=\nclientsecret=\n\n' diff --git a/setup.py b/setup.py index 2ba9196..b395190 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import setup setup(name='goosey', - version='1.2.1', + version='1.2.2', description='AzureAD, Azure and M365 Data Collector', author='Claire Casalnova, Jordan Eberst, Wellington Lee, Victoria Wallace', classifiers=[ @@ -17,26 +17,26 @@ 'Programming Language :: Python :: 3.10', ], packages=['goosey'], - python_requires='>=3.7,<=3.10.10', + python_requires='>=3.7,<=3.10.11', install_requires=[ - 'cryptography>=36.0.1,<39', + 'cryptography==41.0.1', 'requests', 'webdrivermanager', - 'aiohttp==3.8.1', + 'aiohttp==3.8.4', 'async-timeout==4.0.2', 'openpyxl', 'azure-mgmt-web', 'azure-mgmt-storage', 'darkdetect', 'azure-mgmt-network', - 'colored', + 'colored==1.4.4', 'azure-mgmt-resource', 'azure-mgmt-monitor', 'azure-identity', 'azure-mgmt-compute', 'azure-storage-blob', 'azure-mgmt-security', - 'selenium', + 'selenium==4.10.0', 'selenium-wire', 'adal>=1.2.7', 'msrestazure', diff --git a/spdx_output.json b/spdx_output.json index b00b0ed..06d16f0 100644 --- a/spdx_output.json +++ b/spdx_output.json @@ -2,23 +2,24 @@ "spdxVersion": "SPDX-2.3", "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", - "name": "./untitledgoosetool", - "documentNamespace": "https://anchore.com/syft/dir/untitledgoosetool-e824a312-8aba-41ba-ae34-c0c88c97a0c8", + "name": "untitledgoosetool", + "documentNamespace": "https://anchore.com/syft/dir/untitledgoosetool-160b4f99-3a9d-4fc8-963c-2cda67e4135f", "creationInfo": { - "licenseListVersion": "3.20", + "licenseListVersion": "3.21", "creators": [ "Organization: Anchore, Inc", - "Tool: syft-0.82.0" + "Tool: syft-0.85.0" ], - "created": "2023-06-02T14:38:52Z" + "created": "2023-07-17T19:38:39Z" }, "packages": [ { "name": "Gooey", - "SPDXID": "SPDXRef-Package-python-Gooey-36270366523988d", + "SPDXID": "SPDXRef-Package-python-Gooey-2e8725a6135b4f82", "versionInfo": "1.0.8.1", "downloadLocation": "NOASSERTION", - "sourceInfo": "acquired package info from installed python package manifest file: setup.py", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from installed python package manifest file: /setup.py", "licenseConcluded": "NOASSERTION", "licenseDeclared": "NOASSERTION", "copyrightText": "NOASSERTION", @@ -92,10 +93,11 @@ }, { "name": "aiohttp", - "SPDXID": "SPDXRef-Package-python-aiohttp-2d83bd819e2e7cb0", - "versionInfo": "3.8.1", + "SPDXID": "SPDXRef-Package-python-aiohttp-cb709e196c491694", + "versionInfo": "3.8.4", "downloadLocation": "NOASSERTION", - "sourceInfo": "acquired package info from installed python package manifest file: setup.py", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from installed python package manifest file: /setup.py", "licenseConcluded": "NOASSERTION", "licenseDeclared": "NOASSERTION", "copyrightText": "NOASSERTION", @@ -103,75 +105,324 @@ { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python-aiohttp:python-aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python-aiohttp:python-aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python-aiohttp:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python-aiohttp:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python_aiohttp:python-aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python_aiohttp:python-aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python_aiohttp:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python_aiohttp:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:aiohttp:python-aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:aiohttp:python-aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:aiohttp:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:aiohttp:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python-aiohttp:aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python-aiohttp:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python_aiohttp:aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python_aiohttp:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python:python-aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python:python-aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python:python_aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python:python_aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:aiohttp:aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:aiohttp:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "SECURITY", "referenceType": "cpe23Type", - "referenceLocator": "cpe:2.3:a:python:aiohttp:3.8.1:*:*:*:*:*:*:*" + "referenceLocator": "cpe:2.3:a:python:aiohttp:3.8.4:*:*:*:*:*:*:*" }, { "referenceCategory": "PACKAGE-MANAGER", "referenceType": "purl", - "referenceLocator": "pkg:pypi/aiohttp@3.8.1" + "referenceLocator": "pkg:pypi/aiohttp@3.8.4" + } + ] + }, + { + "name": "colored", + "SPDXID": "SPDXRef-Package-python-colored-c7b0fb9bcccd72da", + "versionInfo": "1.4.4", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from installed python package manifest file: /setup.py", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "NOASSERTION", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-colored:python-colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-colored:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_colored:python-colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_colored:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:colored:python-colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:colored:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-colored:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_colored:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:python-colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:python_colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:colored:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:colored:1.4.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:pypi/colored@1.4.4" + } + ] + }, + { + "name": "cryptography", + "SPDXID": "SPDXRef-Package-python-cryptography-9b4891146eaf3965", + "versionInfo": "41.0.1", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from installed python package manifest file: /setup.py", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "NOASSERTION", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-cryptography_project:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-cryptography_project:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-cryptography_project:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-cryptography:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-cryptography:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_cryptography:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_cryptography:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:cryptography:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:cryptography:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-cryptography:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_cryptography:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:python-cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:python_cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:cryptography:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:cryptography:41.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:pypi/cryptography@41.0.1" + } + ] + }, + { + "name": "selenium", + "SPDXID": "SPDXRef-Package-python-selenium-6ba25d40458e5d0a", + "versionInfo": "4.10.0", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from installed python package manifest file: /setup.py", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "NOASSERTION", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-selenium:python-selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-selenium:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_selenium:python-selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_selenium:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python-selenium:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python_selenium:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:selenium:python-selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:selenium:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:python-selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:python_selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:selenium:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:python:selenium:4.10.0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:pypi/selenium@4.10.0" } ] } ], "files": [ { - "fileName": "setup.py", - "SPDXID": "SPDXRef-File-setup.py-8face2fab67d70bd", + "fileName": "/setup.py", + "SPDXID": "SPDXRef-File-setup.py-c829033125510d5a", "checksums": [ { "algorithm": "SHA1", @@ -184,14 +435,32 @@ ], "relationships": [ { - "spdxElementId": "SPDXRef-Package-python-aiohttp-2d83bd819e2e7cb0", - "relatedSpdxElement": "SPDXRef-File-setup.py-8face2fab67d70bd", + "spdxElementId": "SPDXRef-Package-python-Gooey-2e8725a6135b4f82", + "relatedSpdxElement": "SPDXRef-File-setup.py-c829033125510d5a", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-python-selenium-6ba25d40458e5d0a", + "relatedSpdxElement": "SPDXRef-File-setup.py-c829033125510d5a", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-python-cryptography-9b4891146eaf3965", + "relatedSpdxElement": "SPDXRef-File-setup.py-c829033125510d5a", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-python-colored-c7b0fb9bcccd72da", + "relatedSpdxElement": "SPDXRef-File-setup.py-c829033125510d5a", "relationshipType": "OTHER", "comment": "evident-by: indicates the package's existence is evident by the given file" }, { - "spdxElementId": "SPDXRef-Package-python-Gooey-36270366523988d", - "relatedSpdxElement": "SPDXRef-File-setup.py-8face2fab67d70bd", + "spdxElementId": "SPDXRef-Package-python-aiohttp-cb709e196c491694", + "relatedSpdxElement": "SPDXRef-File-setup.py-c829033125510d5a", "relationshipType": "OTHER", "comment": "evident-by: indicates the package's existence is evident by the given file" },