it-swarm.com.de

Verschlüsselte Cookies in Chrome

Ich arbeite gerade an einer C # -Formular-Anwendung, die auf ein bestimmtes Cookie auf meinem Computer zugreifen muss, was ich sehr gut machen kann. Hier ist das Problem:

Google speichert Cookies in SQLite, und ich habe den Sqlite-Datenbankbrowser heruntergeladen, um mir diese Werte zu erleichtern. Was mich überrascht, ist, dass etwa die Hälfte der Cookie-Werte als leer angezeigt wird (einschließlich der Werte, die ich brauche), auch wenn dies offensichtlich nicht der Fall ist.

Die Datenbankdatei befindet sich unter:

C:\Users\%username%\AppData\Local\Google\Chrome\User Data\Default\Cookies

In Chrome habe ich ein Addon namens "Edit This Cookie", mit dem ich Cookies auf der Website, auf der ich mich befinde, direkt ändern können. Dieses Addon kann diese Cookies lesen, und der Webbrowser kann Werte über HTTP analysieren, wenn dies für verschiedene Anforderungen erforderlich ist. Sie sind also definitiv da - der SQLite-Browser und mein benutzerdefinierter Code kommen beide zu dem Schluss, dass das jeweilige Wertfeld leer ist .

Warum ist das so? Was hindert das Feld irgendwie daran, von bestimmten Anwendungen gelesen zu werden?

14
Scherling

Okay, für den Fall, dass jemand interessiert ist, habe ich nach vielen Versuchen, Fehlern und Googeln eine Lösung für dieses Problem gefunden.

Die Google Chrome-Cookies-Datenbank enthält zwei Spalten zum Speichern von Werten: "value" und "encrypted_value", wobei letzterer verwendet wird, wenn das gespeicherte Cookie zur Verschlüsselung angefordert wurde. Dies ist häufig der Fall bei bestimmten vertraulichen Informationen und langen Sitzungsschlüsseln.

Nachdem ich dies herausgefunden hatte, musste ich einen Weg finden, um auf diesen als Blob-Wert gespeicherten Schlüssel zuzugreifen. Ich habe mehrere Anleitungen dazu gefunden, aber am Ende zahlte ich: http://www.codeproject.com/Questions/56109/Reading-BLOB-in-Sqlite-using-C-NET- CF-PPC

Es reicht nicht aus, den Wert einfach zu lesen, da er verschlüsselt ist. - Google Chrome verwendet die dreifache DES-Verschlüsselung mit dem aktuellen Benutzerkennwort als Startwert auf Windows-Computern. Um dies in C # zu entschlüsseln, sollte die Windows Data Protection API (DPAPI) verwendet werden. Es gibt ein paar Anleitungen, wie man sie verwenden kann.

13
Scherling

Ich bin auf das gleiche Problem gestoßen und der Code unten bietet ein funktionierendes Beispiel für jeden, der daran interessiert ist. Alles Gute an Scherling, da die DPAPI vor Ort war.

public class ChromeCookieReader
{
    public IEnumerable<Tuple<string,string>> ReadCookies(string hostName)
    {
        if (hostName == null) throw new ArgumentNullException("hostName");

        var dbPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Google\Chrome\User Data\Default\Cookies";
        if (!System.IO.File.Exists(dbPath)) throw new System.IO.FileNotFoundException("Cant find cookie store",dbPath); // race condition, but i'll risk it

        var connectionString = "Data Source=" + dbPath + ";pooling=false";

        using (var conn = new System.Data.SQLite.SQLiteConnection(connectionString))
        using (var cmd = conn.CreateCommand())
        {
            var prm = cmd.CreateParameter();
            prm.ParameterName = "hostName";
            prm.Value = hostName;
            cmd.Parameters.Add(prm);

            cmd.CommandText = "SELECT name,encrypted_value FROM cookies WHERE Host_key = @hostName";

            conn.Open();
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    var encryptedData = (byte[]) reader[1];
                    var decodedData = System.Security.Cryptography.ProtectedData.Unprotect(encryptedData, null, System.Security.Cryptography.DataProtectionScope.CurrentUser);
                    var plainText = Encoding.ASCII.GetString(decodedData); // Looks like ASCII

                    yield return Tuple.Create(reader.GetString(0), plainText);
                }
            }
            conn.Close();
        }
    }
}
26
jasper

Wie die Antwort von Jasper in einem PowerShell-Skript (passen Sie die SQL-Abfrage natürlich an Ihre Bedürfnisse und den Pfad zu Ihrem Cookie-Speicherort an):

$cookieLocation = 'C:\Users\John\AppData\Local\Google\Chrome\User Data\Default\cookies'
$tempFileName = [System.IO.Path]::GetTempFileName()

"select writefile('$tempFileName', encrypted_value) from cookies where Host_key = 'localhost' and path = '/api' and name = 'sessionId';" | sqlite3.exe "$cookieLocation"
$cookieAsEncryptedBytes = Get-Content -Encoding Byte "$tempFileName"
Remove-Item "$tempFileName"

Add-Type -AssemblyName System.Security
$cookieAsBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($cookieAsEncryptedBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
$cookie = [System.Text.Encoding]::ASCII.GetString($cookieAsBytes)
$cookie
6
dgtc

Also wollte ich dies tun, ohne jedes Mal in eine Tempfile zu schreiben, aber auch ohne eine separate Klasse gemäß der Jasper-Lösung. Wie jasper fand ich es einfacher und schneller auf die verfügbare System.Data.SQLite.dll hier zuzugreifen. Es ist nicht so elegant wie eine separate Klasse, aber es hat für mich am besten funktioniert:

Add-Type -AssemblyName System.Security
Add-Type -Path 'C:\Program Files\System.Data.SQLite\2015\bin\x64\System.Data.SQLite.dll'

Function Get-Last-Cookie {
    Param(
        [Parameter(Mandatory=$True)] $valueName,
        [Parameter(Mandatory=$True)] $hostKey,
        [Parameter(Mandatory=$True)] $dbDataSource
    )

    $conn = New-Object -TypeName System.Data.SQLite.SQLiteConnection
    $conn.ConnectionString = "Data Source=$dbDataSource"
    $conn.Open()

    $command = $conn.CreateCommand()
    $query = "SELECT encrypted_value FROM cookies WHERE name='$valueName' `
              AND Host_key='$hostKey' ORDER BY creation_utc DESC LIMIT 1"
    $command.CommandText = $query
    $adapter = New-Object -TypeName System.Data.SQLite.SQLiteDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    [void]$adapter.Fill($dataset)
    $command.Dispose();
    $conn.Close();
    $cookieAsEncryptedBytes = $dataset.Tables[0].Rows[0].ItemArray[0]
    $cookieAsBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($cookieAsEncryptedBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
    return [System.Text.Encoding]::ASCII.GetString($cookieAsBytes)
}

$localAppDataPath = [Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)
$cookieDbPath = 'Google\Chrome\User Data\Default\Cookies'
$dbDataSource = Join-Path -Path $localAppDataPath -ChildPath $cookieDbPath

$plainCookie = Get-Last-Cookie 'acct' '.stackoverflow.com' $dbDataSource
Write-Host $plainCookie

Ich fand auch die Add-SqliteAssembly - Funktion von halr9000 als sehr hilfreich, wenn es darum ging, mein Skript im Windows-Taskplaner zu planen. Dabei wurde mir klar, dass der Taskplaner die x86-Version von PowerShell und somit SQLite ausführt anstatt des x64, das ich in der Konsole verwendete.

1
mjblay
    # this powershell scripts exports your cookies to a format curl and wget understand
    # Obs ! Each profile has its own cookes file , replace me (ysg ;o) with your win usr name
    # aka wget -x --load-cookies cookies.txt http://stackoverflow.com/questions/22532870/encrypted-cookies-in-chrome

    $cookieLocation = 'C:\Users\ysg\AppData\Local\Google\Chrome\User Data\Profile 1\Cookies'
    $curl_cookies_file="C:\var\ygeo.reports.app.futurice.com.cookies.doc-pub-Host.txt"
    $tempFileName1 = [System.IO.Path]::GetTempFileName()
    $tempFileName2 = [System.IO.Path]::GetTempFileName()

    # adjust your filter in the where clause ...
    "select writefile('$tempFileName1', encrypted_value) from cookies where Host_key = '.futurice.com' ;" | sqlite3.exe "$cookieLocation"
    $cookieAsEncryptedBytes = Get-Content -Encoding Byte "$tempFileName1"
    Remove-Item "$tempFileName1"


    Add-Type -AssemblyName System.Security
    $cookieAsBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($cookieAsEncryptedBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
    $cookie = [System.Text.Encoding]::ASCII.GetString($cookieAsBytes)
    $unquoted_cookie=$cookie -replace '"', ""

    # adjust your filter in the where clause ...
    "
    select  
        Host_key
     , CASE WHEN httponly=0 THEN 'FALSE' ELSE 'TRUE' END
     , path
     , CASE WHEN secure=0 THEN 'FALSE' ELSE 'TRUE' END
     , expires_utc
     , name 
     , '$unquoted_cookie'
    from cookies where Host_key = '.futurice.com' ;" | sqlite3.exe -separator " " "$cookieLocation" > $curl_cookies_file

    Get-ChildItem *.txt | ForEach-Object { (Get-Content $_) | Out-File -Encoding ASCII $_ }

    # check the meta data table
    #"PRAGMA table_info([cookies]);" | sqlite3.exe "$cookieLocation"

    # src: https://github.com/daftano/cookies.txt/blob/master/src/popup.js
    #content += escapeForPre(cookie.domain);
    #content += "\t";
    #content += escapeForPre((!cookie.hostOnly).toString().toUpperCase());
    #content += "\t";     
    #content += escapeForPre(cookie.path); 
    #content += "\t";     
    #content += escapeForPre(cookie.secure.toString().toUpperCase());
    #content += "\t";     
    #content += escapeForPre(cookie.expirationDate ? Math.round(cookie.expirationDate) : "0");
    #content += "\t";     
    #content += escapeForPre(cookie.name);
    #content += "\t";     
    #content += escapeForPre(cookie.value);
    #content += "\n";
    #
    #0|creation_utc|INTEGER|1||1
    #1|Host_key|TEXT|1||0
    #2|name|TEXT|1||0
    #3|value|TEXT|1||0
    #4|path|TEXT|1||0
    #5|expires_utc|INTEGER|1||0
    #6|secure|INTEGER|1||0
    #7|httponly|INTEGER|1||0
    #8|last_access_utc|INTEGER|1||0
    #9|has_expires|INTEGER|1|1|0
    #10|persistent|INTEGER|1|1|0
    #11|priority|INTEGER|1|1|0
    #12|encrypted_value|BLOB|0|''|0
    #13|firstpartyonly|INTEGER|1|0|0
0
Yordan Georgiev