sqlite Chrome中的加密Cookie

5vf7fwbs  于 2023-10-23  发布在  SQLite
关注(0)|答案(7)|浏览(136)

我目前正在开发一个C#表单应用程序,它需要访问我计算机上的特定cookie,我可以做得很好。问题是这样的:
Google将Cookie存储在SQLite中,我下载了SQLite数据库浏览器来帮助我查看这些值。令我惊讶的是,大约有一半的cookie值显示为空(包括我需要的那个),尽管它们显然不是。
db文件位于:

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

在Chrome上,我有一个名为“编辑此Cookie”的插件,它允许我直接修改我所在网站上的Cookie。这个插件可以读取这些cookie,当不同的请求需要时,Web浏览器可以通过HTTP解析值,所以它们肯定在那里-仍然,SQLite浏览器和我的自定义代码都得出结论,特定的值字段是空的。
为什么会这样?是什么以某种方式阻止了某些应用程序读取该字段?

rjjhvcjd

rjjhvcjd1#

我也遇到过同样的问题,下面的代码为任何感兴趣的人提供了一个工作示例。所有的信贷Scherling,因为DPAPI是现场。

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();
        }
    }
}
ecr0jaav

ecr0jaav2#

好吧,如果有人感兴趣,我发现了一个解决这个问题后,大量的试验,错误和谷歌搜索。
Google Chrome cookies数据库有两列用于存储值:“value”和“encrypted_value”,后者用于请求加密存储的cookie时-通常是某些机密信息和长期会话密钥的情况。
弄清楚这一点之后,我需要找到一种方法来访问这个键,它存储为一个Blob值。我找到了几个关于如何做到这一点的指南,但最终得到回报的是:http://www.codeproject.com/Questions/56109/Reading-BLOB-in-Sqlite-using-C-NET-CF-PPC
仅仅阅读值是不够的,因为它是加密的。- 谷歌Chrome使用三重DES加密,当前用户的密码作为Windows机器上的种子。为了在C#中解密,应该使用Windows数据保护API(DP API),有一些关于如何使用它的指南。

sxissh06

sxissh063#

就像碧玉的答案一样,在PowerShell脚本中(当然,根据您的需要定制SQL查询,以及Cookie位置的路径):

$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
f0ofjuux

f0ofjuux4#

问题是,谷歌Chrome加密了你需要读取的数据,所以你必须解密它。首先,获取cookie文件的副本。然后使用SQLite3读取它。之后,获取加密的字节。最后,使用下面的代码来解密它。你需要这些Nugets:

using System.IO;
using System.Net;
using System.Data.SQLite;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto;
using Newtonsoft.Json.Linq;

到目前为止的代码:

File.Copy(Environment.GetEnvironmentVariable("APPDATA") + @"/../Local/Google/Chrome/User Data/Default/Cookies", @"./Cookies",true);
        SQLiteConnection Cnn = new SQLiteConnection("Data Source=" + @"./Cookies" + ";pooling=false");
        Cnn.Open();

        SQLiteCommand cmd = new SQLiteCommand("SELECT host_key, name, value, encrypted_value FROM cookies WHERE name='mvrusername' OR name='mvrcookie' OR name='mikuki4'", Cnn);
        SQLiteDataReader rdr = cmd.ExecuteReader();
        while (rdr.Read())
        {
            byte[] encryptedData = (byte[])rdr["encrypted_value"];
            string encKey = File.ReadAllText(Environment.GetEnvironmentVariable("APPDATA") + @"/../Local/Google/Chrome/User Data/Local State");
            encKey = JObject.Parse(encKey)["os_crypt"]["encrypted_key"].ToString();
            var decodedKey = System.Security.Cryptography.ProtectedData.Unprotect(Convert.FromBase64String(encKey).Skip(5).ToArray(), null, System.Security.Cryptography.DataProtectionScope.LocalMachine);

            const int MAC_BIT_SIZE = 128;
            const int NONCE_BIT_SIZE = 96;

            using (var cipherStream = new MemoryStream(encryptedData))
            using (var cipherReader = new BinaryReader(cipherStream))
            {
                var nonSecretPayload = cipherReader.ReadBytes(3);
                var nonce = cipherReader.ReadBytes(NONCE_BIT_SIZE / 8);
                var cipher = new GcmBlockCipher(new AesEngine());
                var parameters = new AeadParameters(new KeyParameter(decodedKey), MAC_BIT_SIZE, nonce);
                cipher.Init(false, parameters);
                var cipherText = cipherReader.ReadBytes(encryptedData.Length);
                var plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
                try
                {
                    var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
                    cipher.DoFinal(plainText, len);
                }
                catch (InvalidCipherTextException)
                {
                }
                string _cookie= Encoding.Default.GetString(plainText);

            }
        }

//非常感谢https://stackoverflow.com/a/60611673/6481581回答了Chrome 80及以上版本如何改变了cookie的加密方式。

yyyllmsg

yyyllmsg5#

所以我想这样做,而不是每次都写一个临时文件,也没有实现一个单独的类,按照碧玉的解决方案。像jasper一样,我发现访问here可用的System.Data.SQLite.dll更容易、更快。它不像一个单独的类那样优雅,但它对我来说是最好的:

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

我还发现halr9000Add-SqliteAssembly函数在Windows任务调度程序中调度我的脚本时非常有用,并意识到任务调度程序运行x86版本的PowerShell,因此SQLite而不是我在控制台中使用的x64。

laik7k3q

laik7k3q6#

# 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
um6iljoc

um6iljoc7#

只需将“value”设置为您想要的cookie,“encrypted_value”设置为NULL,“priority”设置为0

相关问题