Skip to content

2. Authentication Management & Tokeninfo

WebbinRoot edited this page Jun 30, 2024 · 2 revisions

Adding Authentication/Creds From Initial Workflow

Five Authentication options are supported by GCPwn and detailed below:

  1. No Credentials
  2. ADC (aka google.auth.default())
  3. ADC via JSON File
  4. Standalone Oauth2 Token
  5. Service Account Key

No Credentials: If you don't want to start your session with any credentials, just hit ENTER at the prompt and you will drop into a "None" project with "None" credentials. This is useful if you want to run an unauthenticated module (ex. unauth_bucketbrute)

Input: 
(None:None)> 

ADC Credentials: If you want to supply application default credentials (adc), just enter adc <arbitrary_credential_name. Note this will assume you have already run gcloud auth login and gcloud auth application-default login outside the tool. adc <credname> basically runs google.default.auth() in the background.

Input: adc webbinroot_credentials
[*] Project ID of credentials is: [Project_ID]
[*] Loading in our OAuth2 credentials...
[*] Attempting to refresh the credentials using the stored refresh token. Note this is normal for brand new OAuth2 credentials added/updated.
[*] Credentials sucessfully refreshed...
[*] Credentials sucessfully stored/updated...
[*] Proceeding with up-to-date credentials for webbinroot_credentials...
([Project_ID]:webbinroot_credentials)> 

ADC Credentials Per a JSON File: If you want to supply a specific JSON file in the format below that holds the ADC refresh token (for example, if you pulled data from credentials.db described below as part of your pentest), than you would supply adc <arbitrary_credential_name> <path_to_JSON_file>

# Application Default Credentials JSON Form
{
  "account": "",
  "client_id": "[Client_Id]",
  "client_secret": "[Client_Secret]",
  "quota_project_id": "[Project_ID]",
  "refresh_token": "1//04[REDACTED]",
  "type": "authorized_user",
  "universe_domain": "googleapis.com"
}                                                                                                                                                                                        

# Adding to GCPwn
Input: adc-file webbin_root_adc_file /home/kali/Desktop/gcpwn/file_with_refresh_token.json
[*] Project ID of credentials is Unknown. Set it via workspace with projects set <project_name>.
[*] Loading in our OAuth2 credentials...
[*] Attempting to refresh the credentials using the stored refresh token. Note this is normal for brand new OAuth2 credentials added/updated.
[*] Credentials sucessfully refreshed...
[*] Credentials sucessfully stored/updated...
[*] Proceeding with up-to-date credentials for webbin_root_adc_file...
(None:webbin_root_adc_file)> projects set [Project_ID]
[X] [Project_ID] is not in the list of project_ids. Adding...
([Project_ID]:webbin_root_adc_file)> projects
[*] Current projects known for all credentials: 
  [Project_ID]

Standalone Oauth2 Token: If you want to supply a standalone Oauth2 token (for example, if you pulled an active access token from access_tokens.db described below as part of your pentest), than you can supply this token at the command line via oauth2 <arbitrary_credential_name> <oauth2_token>. We don't know the email of the Oauth2 token as shown below with creds info. See the credential notes for details on using tokeninfo.

Input: oauth2 webbinroot_oauth2_token ya29.a0AXooC[REDACTED]
[*] Project ID of credentials is: Unknown
[*] The project associated with these creds is unknown. To bind the creds to a project specify "creds <credname> set <projectname>". Otherwise you might have limited functionality with resources.
[*] Loading in our OAuth2 credentials...
(Unknown:webbinroot_oauth2_token)> projects set [Project_ID]
[X] [Project_ID] is not in the list of project_ids. Adding...
([Project_ID]:webbinroot_oauth2_token)> projects
[*] Current projects known for all credentials: 
  [Project_ID]
([Project_ID]:webbinroot_oauth2_token)> creds info
Summary for webbinroot_oauth2_token:
Default Project: None
Email: None
Scopes: 

Access Token: ya29.a0AXoo[REDACTED]
All_Projects:
      [PROJECT_ID]

Service Credentials:: If you want to supply service account credentials, than you would just enter service <arbitrary_credential_name> <path_to_JSON_file>

# Service Credentials JSON Form
{
  "type": "service_account",
  "project_id": "[Project_ID]",
  "private_key_id": "[private_key_id]",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEv[TRUNCATED]\n-----END PRIVATE KEY-----\n",
  "client_email": "[client_email]",
  "client_id": "[client_id]",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/tes[TRUNCATED]",
  "universe_domain": "googleapis.com"
}

# Adding to GCpwn
Input: service webbinroot_service_key /home/kali/Downloads/my_service_key.json 
Loading in our Service credentials...
([Project_ID]:webbinroot_service_key)> 
  1. [COMING SOON] Passing in credentials.db or access_tokens.db filepaths directly

Swapping/Adding/Updating/Reusing/Expired Credentials from Within Workspace

Swapping Credentials: If you add multiple credentials to a workspace, you can swap between them either with creds swap <target_credname> or creds swap as shown below:

([PROJECT_ID]:credname1)> creds swap

[*] Listing existing credentials...
  [1] credname1(adc) - None
  [2] credname2 (service) - [email]


[*] Choose the username or index you want to assume: 2
Loading in our Service credentials...
([Project_ID]:credname2)> creds swap credname1
[*] Loading in our OAuth2 credentials...
[*] Proceeding with up-to-date credentials for credname1...
([Project_ID]:credname1)> 

Adding/Updating Credentials from Workspace Prompt: Once you choose either add creds or proceed with no creds, you can add/update creds from the command line using a similar technique detailed in the help menu (? or "help"). When updating if you leave off the credname to target, it will update your current set of credentials. When adding credentials, the tool will also only start using those credentials if you add --assume (or else you can just creds swap to them as shown above). Note you can also specify --tokeninfo to get additional info if needed (see later portion of this section)

# Adding Credentials
([Project_ID]:credname1)> creds add my_new_creds --type adc-file --filepath-to-adc /home/kali/Desktop/gcpwn/file_with_refresh_token.json --tokeninfo --assume
[*] Project ID of credentials is Unknown. Set it via workspace with projects set <project_name>.
[*] Loading in our OAuth2 credentials...
[*] Attempting to refresh the credentials using the stored refresh token. Note this is normal for brand new OAuth2 credentials added/updated.
[*] Credentials sucessfully refreshed...
[*] Credentials sucessfully stored/updated...
[*] Checking credentials against /tokeinfo endpoint...
[*] Succeeded in querying tokeninfo. The response is shown below:
{'azp': '[TRUNCATED].apps.googleusercontent.com', 'aud': '[TRUNCATED].apps.googleusercontent.com', 'sub': '117601449940858805917', 'scope': 'https://www.googleapis.com/auth/cloud-platform', 'exp': '1716628384', 'expires_in': '3599', 'email': '[name]@[domain]', 'email_verified': 'true', 'access_type': 'offline'}
UPDATING
[*] Proceeding with up-to-date credentials for my_new_creds...
(None:my_new_creds)> 

# Updating Your Credentials
([Project_ID]:my_new_creds3)> creds update --type adc --tokeninfo
[*] Project ID of credentials is: [Project_ID]
[*] Loading in our OAuth2 credentials...
[*] Attempting to refresh the credentials using the stored refresh token. Note this is normal for brand new OAuth2 credentials added/updated.
[*] Credentials sucessfully refreshed...
[*] Credentials sucessfully stored/updated...
[*] Checking credentials against /tokeinfo endpoint...
[*] Succeeded in querying tokeninfo. The response is shown below:
{'azp': '[TRUNCATED].apps.googleusercontent.com', 'aud': '[TRUNCATED].apps.googleusercontent.com', 'sub': '117601449940858805917', 'scope': 'https://www.googleapis.com/auth/cloud-platform', 'exp': '1716628890', 'expires_in': '3599', 'email': '[name]@[email]', 'email_verified': 'true', 'access_type': 'offline'}
[*] Proceeding with up-to-date credentials for my_new_creds3...
([Project_ID]:my_new_creds3)>

Credential Reuse: Credentials added are stored and you don't need to add them again. When you open GCPwn again, you will see your newly added credentials listed when entering a workspace. Entering a # corresponding to the creds you wants drops you into a command line with them.

> python3 main.py
[*] Found existing sessions:
  [0] New session
  [1] workspace1
  [2] workspace2
Choose an option: 2
GCPwn - https://github.com/NetSPI/gcpwn
[TRUNCATED]
Welcome to your workspace! Type 'help' or '?' to see available commands.

[*] Listing existing credentials...
  [1] credname1 (adc) - None
  [2] webbinroot_service_key (service) - test-217@testnothingenabled.iam.gserviceaccount.com


Submit the name or index of an existing credential from above, 
or add NEW credentials via Application Default Credentails (adc - google.auth.default()), a file pointing to
adc credentials, a standalone OAuth2 Token, or Service credentials. See wiki for details on each. To proceed 
[TRUNCATED]

Input: 1
[*] Loading in our OAuth2 credentials...
[*] Proceeding with up-to-date credentials for credname1...
([project_ID]:credname1)> 

Token Refresh/Expiration: Access tokens generated in ADC via the refresh token do expire eventually. GCPwn for adc and adc-file will check if credentials are expired when loading them, and try to auto-update/refresh them for you so there is no interruption. This won't always work depending on the creds (which will be communicated via tool), and standalone Oauth2 tokens will NOT be able to check to this. So if an Oauth2 token starts returning errors after some time, its probably expired.

[*] Listing existing credentials...
  [1] webbinroot_credentials (adc) - []
  [2] webbinroot_oauth2_tokeninfo (oauth2) - [EMAIL]

[TRUNCATED]

Input: 1
[*] Loading in our OAuth2 credentials...
[X] Expired Credentials. Timestamp expiration for the access_token was 2024-05-25 07:32:10.067716. Refresh is required
[*] Attempting to refresh the credentials using the stored refresh token. Note this is normal for brand new OAuth2 credentials added/updated.
[*] Credentials sucessfully refreshed...
[*] Credentials sucessfully stored/updated...
[*] Proceeding with up-to-date credentials for credname1...
([Project_ID]:credname1)>     

Tokeninfo & Credential Emails/Scopes

TokenInfo: Oauth2 Access tokens by themselves can't be decoded to determine what the project_id or email is for their respective caller (they are "opaque"). Google has an official endpoint called "tokeninfo" detailed here. By default GCPwn does not send tokens added to tokeninfo, but if you append "tokeninfo" when entering the credentials, they will be sent to https://oauth2.googleapis.com/tokeninfo?access_token=[token] when added, and the returned data (email & scope primarily) will be saved to your credential profile. Example is shown below for our oauth2 example. Note how adding "tokeninfo" reveals the email & scopes in the creds info call now

Input: oauth2 credname1 ya29.a0AX[REDACTED] tokeninfo
[*] Checking credentials against /tokeinfo endpoint...
[*] Succeeded in querying tokeninfo. The response is shown below:
{'azp': '[TRUNCATED].apps.googleusercontent.com', 'aud': '[TRUNCATED].apps.googleusercontent.com', 'sub': '117601449940858805917', 'scope': 'https://www.googleapis.com/auth/cloud-platform', 'exp': '1716622332', 'expires_in': '1158', 'email': '[name]@[domain]', 'email_verified': 'true', 'access_type': 'offline'}
[*] Project ID of credentials is Unknown. Set it via workspace with projects set <project_name>.
[*] Loading in our OAuth2 credentials...
(None:credname1)> projects set [PROJECT_ID]
[X] [Project_ID] is not in the list of project_ids. Adding...
([Project_ID]:credname1)> creds info
Summary for credname1:
Default Project: None
Email:[name]@[domain]
Scopes: 
      https://www.googleapis.com/auth/cloud-platform 
Access Token: ya29.a0AXoo[REDACTED]
All_Projects:
      [PROJECT_ID]

Credential Properties Set: Credentials have email, scopes, and sometimes acccess_token attributes. You can set a credential name's email/scopes manually if needed as seen below (as opposed to trying to go the automated route through tokeninfo)

([Project_ID]:my_new_creds3)> creds info
Summary for my_new_creds3:
Default Project: [Project_ID]
Email: [name1]@[domain1]
[TRUNCATED]

([Project_ID]:my_new_creds3)> creds set --email [name2]@gmail.com
[*] Credentials my_new_creds3 updated successfully.

([Project_ID]:my_new_creds3)> creds info
Summary for my_new_creds3:
Default Project: [Project_ID]
Email: [name2]@gmail.com
[TRUNCATED]