首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从Chrome/Chromium 80+中解密C#中的Cookies (C#)--带有Auth标签的问题

从Chrome/Chromium 80+中解密C#中的Cookies (C#)--带有Auth标签的问题
EN

Stack Overflow用户
提问于 2022-04-02 14:25:19
回答 1查看 1.3K关注 0票数 1

我在解密存储在encrypted_value下Chrome的sqlite中的cookie时遇到了问题。

从sqlite提取的效果很好:

代码语言:javascript
运行
复制
// filePath = absolute cookies.sqlite path
// query = "SELECT creation_utc, host_key, name, encrypted_value, path, expires_utc from cookies WHERE host_key like \"%<target_site>%\"

using (var connection = new SqliteConnection($"Data Source={filePath}"))
{
    connection.Open();

    var command = connection.CreateCommand();
    command.CommandText = query;

    using (var reader = command.ExecuteReader())
    {
          while (reader.Read())
          {
               var creationTime = reader.GetString(0);
               var host = reader.GetString(1);
               var name = reader.GetString(2);
               var value = reader.GetString(3);
               var path = reader.GetString(4);
               var expiryTime = reader.GetString(5);
 
               /* here the below code is placed */
          }
    }

}

然而,在解密值时,我得到了auth标记和预期auth标记之间的不匹配。我在窗户下跑。

下面的代码附有注释,以显示我的推理。

代码语言:javascript
运行
复制
// get encrypted blob from row
byte[] encryptedData = new byte[reader.GetBytes(3, 0, null, 0, int.MaxValue) - 1]; // 3 = encrypted_value column
reader.GetBytes(3, 0, encryptedData, 0, encryptedData.Length);

// Get encrypted key from local state file:
string encKey = File.ReadAllText(filePath + @"/../../../Local State");
encKey = JObject.Parse(encKey)["os_crypt"]["encrypted_key"].ToString();

// The encrypted key starts with the ASCII encoding of DPAPI (i.e. 0x4450415049) and is Base64 encoded,
// i.e. the key must first be Base64 decoded and the first 5 bytes must be removed.
// Afterwards a decryption with win32crypt.CryptUnprotectData is possible.
var decryptedKey = System.Security.Cryptography.ProtectedData.Unprotect(Convert.FromBase64String(encKey).Skip(5).ToArray(), null, System.Security.Cryptography.DataProtectionScope.LocalMachine);

// try decryption
try
{
    // The encrypted data start with the ASCII encoding of v10 (i.e. 0x763130) ...
    if (value.StartsWith("v10"))
    {
        using (var aes = new System.Security.Cryptography.AesGcm(decryptedKey))
        {
            // ... followed by the 12 bytes nonce,
            var nonce = encryptedData[3..15];
            // the actual ciphertext 
            var encData = encryptedData[15..(encryptedData.Length - 16)];
            // and finally the 16 bytes authentication tag.
            var auth_tag = encryptedData[(encryptedData.Length - 16)..(encryptedData.Length)];

            byte[] plaintextBytes = new byte[encData.Length];

            aes.Decrypt(nonce, encData, auth_tag, plaintextBytes);
            value = Encoding.UTF8.GetString(plaintextBytes);
        }
    }
    else
    {
        // TODO
        throw new Exception("[!] Cookie encrypted with DPAPI");
    }
                                    
}
catch (Exception e)
{
    Console.WriteLine(e);
    Console.WriteLine($"[*] Could not decode cookie with encrypted value {value}");
}

我得到的例外是

代码语言:javascript
运行
复制
System.Security.Cryptography.CryptographicException: The computed authentication tag did not match the input authentication tag.
at System.Security.Cryptography.AesAEAD.Decrypt(SafeAlgorithmHandle algorithm, SafeKeyHandle keyHandle, ReadOnlySpan`1 nonce, ReadOnlySpan`1 associatedData, ReadOnlySpan`1 ciphertext, ReadOnlySpan`1 tag, Span`1 plaintext, Boolean clearPlaintextOnFailure)
at System.Security.Cryptography.AesGcm.Decrypt(Byte[] nonce, Byte[] ciphertext, Byte[] tag, Byte[] plaintext, Byte[] associatedData)
at <REDACTED>:line 123                                  

我相当肯定,我正确的解析了现在,密文和auth_tag,但显然没有?我不知道这个问题是从何而来的。

而且,这是在保存cookie的同一个用户/浏览器上运行的。

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2022-05-07 23:02:21

我发现自己也有同样的问题,下面是解决办法:

代码语言:javascript
运行
复制
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Data.Sqlite;

public class ChromeCookieRetriever
{
    class LocalStateDto
    {
        [JsonPropertyName("os_crypt")]
        public OsCrypt OsCrypt { get; set; }
    }

    class OsCrypt
    {
        [JsonPropertyName("encrypted_key")]
        public string EncryptedKey { get; set; }
    }

    private const string CookiesFileName = @"Default\Network\Cookies";
    private const string LocalStateFileName = "Local State";

    public ChromeCookieRetriever()
    {
    }

    public ICollection<Cookie> GetCookies(string baseFolder)
    {
        byte[] key = GetKey(baseFolder);
        ICollection<Cookie> cookies = ReadFromDb(baseFolder, key);
        return cookies;
    }
    
    private byte[] GetKey(string baseFolder)
    {
        string file = Path.Combine(baseFolder, LocalStateFileName);
        string localStateContent = File.ReadAllText(file);
        LocalStateDto localState = JsonSerializer.Deserialize<LocalStateDto>(localStateContent);
        string encryptedKey = localState?.OsCrypt?.EncryptedKey;

        var keyWithPrefix = Convert.FromBase64String(encryptedKey);
        var key = keyWithPrefix[5..];
        var masterKey = ProtectedData.Unprotect(key, null, DataProtectionScope.CurrentUser);
        return masterKey;
    }
    
    private ICollection<Cookie> ReadFromDb(string baseFolder, byte[] key)
    {
        ICollection<Cookie> result = new List<Cookie>();
        string dbFileName = Path.Combine(baseFolder, CookiesFileName);
        using (SqliteConnection connection = new SqliteConnection($"Data Source={dbFileName}"))
        {
            connection.Open();

            long expireTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            SqliteCommand command = connection.CreateCommand();
            command.CommandText =
                @"select   creation_utc,
                           host_key,
                           top_frame_site_key,
                           name,
                           value,
                           encrypted_value,
                           path,
                           expires_utc,
                           is_secure,
                           is_httponly,
                           last_access_utc,
                           has_expires,
                           is_persistent,
                           priority,
                           samesite,
                           source_scheme,
                           source_port,
                           is_same_party
                    from cookies
                    WHERE has_expires = 0 or (has_expires = 1 and expires_utc > $expireTime)
                    ";
            command.Parameters.AddWithValue("$expireTime", expireTime);
            using (SqliteDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    string name = reader["name"].ToString();
                    string path = reader["path"].ToString();
                    string domain = reader["host_key"].ToString();
                    byte[] encrypted_value = (byte[])reader["encrypted_value"];


                    string value = DecryptCookie(key, encrypted_value);

                    Cookie cookie = new Cookie(name, value, path, domain);
                    result.Add(cookie);
                }
            }

            return result;
        }
    }

    private string DecryptCookie(byte[] masterKey, byte[] cookie)
    {
        byte[] nonce = cookie[3..15];
        byte[] ciphertext = cookie[15..(cookie.Length - 16)];
        byte[] tag = cookie[(cookie.Length - 16)..(cookie.Length)];

        byte[] resultBytes = new byte[ciphertext.Length];
        
        using AesGcm aesGcm = new AesGcm(masterKey);
        aesGcm.Decrypt(nonce, ciphertext, tag, resultBytes);
        string cookieValue = Encoding.UTF8.GetString(resultBytes);
        return cookieValue;
    }
}

努基特的用途:

代码语言:javascript
运行
复制
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.4" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="6.0.0" />

资料来源:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71718371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档