kooky icon indicating copy to clipboard operation
kooky copied to clipboard

Chrome (Windows) 127 - unable to decrypt new v20 ABE (app-bound encryption) cookies - "panic: crypto/cipher: input not full blocks"

Open ajkessel opened this issue 1 year ago • 9 comments

Checklist

  • [X] I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • [X] This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

Using this example code, with Windows Chrome 127.0.6533.73.

  cookies, err := chrome.ReadCookies(cookiesFile)

I get this panic:

panic: crypto/cipher: input not full blocks

goroutine 1 [running]:
crypto/cipher.(*cbcDecrypter).CryptBlocks(0x659ca0?, {0xc00001a240?, 0xc0000145d0?, 0x10?}, {0xc00001a213?, 0x9?, 0x1?})
        /snap/go/10730/src/crypto/cipher/cbc.go:145 +0x40b
github.com/browserutils/kooky/internal/chrome.decryptAESCBC({0xc00001a210, 0x2a, 0x2a}, {0x771724, 0x7, 0x7}, 0x1)
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/chrome/chrome.go:310 +0x194
github.com/browserutils/kooky/internal/chrome.(*CookieStore).decrypt.func3({0xc00001a210?, 0xc000165558?, 0x5f4c95?}, {0x771724?, 0x5af1e0?, 0x4721b2?})
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/chrome/chrome.go:240 +0x25
github.com/browserutils/kooky/internal/chrome.(*CookieStore).decrypt(0xc000136210, {0xc00001a210, 0x2a, 0x2a})
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/chrome/chrome.go:265 +0x8ad
github.com/browserutils/kooky/internal/chrome.(*CookieStore).saveCookieValue(0xc000136210, 0xc0000e2000, {0xc0000b8300?, 0xc0000b6050?})
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/chrome/chrome.go:119 +0x9f
github.com/browserutils/kooky/internal/chrome.(*CookieStore).ReadCookies.func1(0x0?, {0xc0000b8300?, 0xc0000b6050?})
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/chrome/chrome.go:92 +0x494
github.com/browserutils/kooky/internal/utils.VisitTableRows.func1(0xc000014518, {{0x14, {0xc000010500, 0x14, 0x20}}, {0xc00002e1f5, 0x7e, 0x7e}, {0xc0000e0000, 0x14, ...}})
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/utils/visittablerows.go:25 +0x96
github.com/go-sqlite/sqlite3.(*DbFile).VisitTableRecords.(*btreeTable).visitRecordsInorder.func1({0x0, 0xc000014518, {0xc00002e1e0, 0x93, 0x93}, 0x0})
        /home/adam/go/pkg/mod/github.com/go-sqlite/[email protected]/btree.go:431 +0x115
github.com/go-sqlite/sqlite3.(*btreeTable).visitRawInorder(0xc0000ac180, 0xc000165a80)
        /home/adam/go/pkg/mod/github.com/go-sqlite/[email protected]/btree.go:395 +0x203
github.com/go-sqlite/sqlite3.(*btreeTable).visitRawInorder(0xc0000ac120, 0xc000165a80)
        /home/adam/go/pkg/mod/github.com/go-sqlite/[email protected]/btree.go:387 +0x1b6
github.com/go-sqlite/sqlite3.(*btreeTable).visitRecordsInorder(...)
        /home/adam/go/pkg/mod/github.com/go-sqlite/[email protected]/btree.go:424
github.com/go-sqlite/sqlite3.(*DbFile).VisitTableRecords(0xc000132b60, {0x5f51bb, 0x7}, 0xc000165ba0)
        /home/adam/go/pkg/mod/github.com/go-sqlite/[email protected]/file.go:313 +0x199
github.com/browserutils/kooky/internal/utils.VisitTableRows(0xc000132b60, {0x5f51bb, 0x7}, 0xc000165de8, 0xc000165c90)
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/utils/visittablerows.go:24 +0x367
github.com/browserutils/kooky/internal/chrome.(*CookieStore).ReadCookies(0xc000136210, {0x0, 0x0, 0xc000006101?})
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/internal/chrome/chrome.go:102 +0x448
github.com/browserutils/kooky/browser/chrome.ReadCookies({0x601ca0, 0x37}, {0x0, 0x0, 0x0})
        /home/adam/go/pkg/mod/github.com/browserutils/[email protected]/browser/chrome/chrome.go:18 +0x155

How to reproduce

Run code

Example code

package main

import (
        "fmt"

        "github.com/browserutils/kooky/browser/chrome"
)

func main() {
  cookiesFile := "[path to cookies file]"
  cookies, err := chrome.ReadCookies(cookiesFile)
  if err != nil {
    // TODO: handle the error
    fmt.Println(err)
    return
  }

  for _, cookie := range cookies {
    fmt.Println(cookie)
  }
}```

### Kooky version

v0.2.2

### Go compiler version

go1.23.2 linux/amd64

### Browser

Chrome 127.0.6533.73 

### Operating system and version

WSL/Windows 10

ajkessel avatar Oct 30 '24 14:10 ajkessel

I'm getting the same. Anyone have ideas?

kylecarbs avatar Nov 01 '24 16:11 kylecarbs

Because chrome introduce Application-Bound (App-Bound) encryption since 127. Reference: https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html

For windows, could disable the feature via registry key Software\Policies\Google\Chrome\ApplicationBoundEncryptionEnabled.

Don't know how to disable the feature for macOS chrome.

hiberabyss avatar Nov 18 '24 11:11 hiberabyss

Because chrome introduce Application-Bound (App-Bound) encryption since 127. Reference: https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html ... Don't know how to disable the feature for macOS chrome.

I don't think it has to be disabled necessarily. IIUC it seems like the encryption key is derived from the user's login password + a passphrase stored in the Mac keyring. See https://github.com/kawakatz/macCookies/blob/e97ccea49b4d816862cf8a7ac67b075eb56fab2e/pkg/decrypt/decrypt.go#L84-L90

vergenzt avatar Dec 07 '24 01:12 vergenzt

I encountered this issue in regular (non-wsl) linux (ubuntu 22).
It only affects certain sites/cookies, which trigger the inputs not full blocks panic.
I tried to debug it a bit, and it appears to be an issue with the sqlite code extracting the encrypted_value of the cookies:
The encrypted_value in the sqlite cookies DB is way longer than the value kookys tries to decrypt. When logging the received encrypted_value ( 76313176fc3d3e3b93201d910c6e454f816a47bd739729af5e) in chrome_linux.go right before decryption in L.240 it had 49 chars (25 byte), but the value in my DB (76313176FC3D3E3B93201D910C6E454F816A47BD739729AF5E002D3B0759F75468BAB3ED7FB4000D0EA707A22041CA5848A04F28E901C1D60B2AD50646130994966108882496C9A0C43A3728285BEF9C4F8E6E9B3946E9AB9C61A566ABB2782F03703CC919A6446685826D2BDBF17EDC39D7A8 is 230 char (115 byte). As you can see the value logged by kooky matches the first part of the actual value in the DB.
I also double checked for e.g. issue with my cookies DB using the browser_cookie3 python library, and it extracted the full encrypted_value and decrypted it successfully.

(All testing done on the v0.2.2 release, the padding changes fixed last year don't affect this issue, since they only result in the decrypted value having useless padding, and don't affect the decryption itself.)

What-is-water93 avatar Jun 02 '25 12:06 What-is-water93

I wonder if there's some kind of way of encoding longer values in sqlite that Kooky doesn't understand?

zellyn avatar Jun 02 '25 15:06 zellyn

Appears like it might be some type interference going wrong, the column encrypted_value is an interface {}(string) when it panics, and otherwise an interface {}([]uint8) i.e. byte, which I believe is the correct one.

Domain where kooky works

  • Image
  • value is interface {}([]uint8) [118,49,49,231,237,178,220,39,119,118,114,156,35,21,206,9,255,74,167,253,170,134,130,230,23,207,168,45,251,145,242,117,248,51,240,216,169,145,169,121,122,103,1,197,155,168,114,93,248,222,0,147,21,73,207,233,56,135,191,172,212,112,58,39,...+115 more]

Domain where kooky does not work

  • Image
  • value is interface {}(string) "v11v\xfc=>;\x93 \x1d\x91\fnEO\x81jG\xbds\x97)\xaf^"

Since the used sqlite library didnt get any update since 2018 there might be something that changed in this 7 years. No issue with firefox though.

What-is-water93 avatar Jun 02 '25 16:06 What-is-water93

Hi @What-is-water93, that changing slice type should be from here: https://github.com/go-sqlite/sqlite3/blob/304649c/btree.go#L141-L204

srlehn avatar Jul 10 '25 20:07 srlehn

I have turned this specific panic into an error (00fc21c) as it often happened with chrome changes etc. Now one erroneous cookie won't break the retrieval of many. The bug itself needs fixing too naturally.

srlehn avatar Jul 12 '25 07:07 srlehn

This error happens because Chrome changed the way they encrypt and decrypt cookies on OSX. They now use: AES-256-GCM not the older AES-128-CBC with PBKDF2 ("saltysalt"). There was a pull request I spotted a few months ago that mentioned it too (can't find it).

I found this out because I was rolling out my own cookie decryptor in Free Pascal, and the old libs I wrote stopped working on OSX. So rather than reinvent the wheel I tried out kooky and it suffers the same problem.

I've checked the source, and it appears kooky is using the old method of encryption/decryption: https://github.com/browserutils/kooky/blob/v0.2.4/internal/chrome/chrome.go#L325-L340

The new way Chrome handles encryption and decryption is with AES-256-GCM. You can see this in the source code here: https://github.com/chromium/chromium/blob/a5ad0606f64f1081683d4f78b37bf94aa8fc95a5/components/os_crypt/async/common/encryptor.cc

There's nothing official mentioned about this change.

I could probably work on this since I'm going to use Go for my current project anyway, and I need this.

jjhax avatar Jul 19 '25 18:07 jjhax