Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encrypted cookies in Chrome

Tags:

I am currently working on a C# forms application that needs to access a specific cookie on my computer, which I can do perfectly fine. Here's the issue:

Google stores cookies in SQLite, and I've downloaded Sqlite database browser to help me look at these values. What surprises me is that about half of the cookie values shows as empty (including the one I need), even though they are obviously not.

The db file is located at:

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

On Chrome I have an addon called "Edit This Cookie" which allows me to directly modify cookies on the website I'm on. This addon can read these cookies, and the web browser can parse values through HTTP when needed for different requests, so they are definitely there - still, the SQLite browser, and my custom code both come to the conclusion that the particular value field is empty.

Why is that? What is it that somehow prevents the field from being read by certain applications?

like image 730
Scherling Avatar asked Mar 20 '14 12:03

Scherling


2 Answers

I've run into this same problem, and the code below provides a working example for anyone who is interested. All credit to Scherling, as the DPAPI was spot on.

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();         }     } } 
like image 97
jasper Avatar answered Oct 08 '22 19:10

jasper


Alright, so in case anyone is interested, I found a solution to this problem after alot of trial, error and googling.

Google Chrome cookies DB has 2 columns for storing values: "value" and "encrypted_value", the latter being used when the cookie stored was requested to be encrypted - often the case with certain confidential information and long-time session keys.

After figuring this out, I then needed to find a way to access this key, stored as a Blob value. I found several guides on how to do this, but the one that ended up paying of was: http://www.codeproject.com/Questions/56109/Reading-BLOB-in-Sqlite-using-C-NET-CF-PPC

Simply reading the value is not enough, as it is encrypted. - Google Chrome uses triple DES encryption with the current users password as seed on windows machines. In order to decrypt this in C#, one should use Windows Data Protection API (DPAPI), there are a few guides out there on how to make use of it.

like image 37
Scherling Avatar answered Oct 08 '22 18:10

Scherling