sseemayer / keepass-rs

Rust KeePass database file parser for KDB, KDBX3 and KDBX4, with experimental support for KDBX4 writing.
https://docs.rs/keepass
MIT License
116 stars 39 forks source link

Panic when decrypted .kdbx file #32

Closed Susurrus closed 3 years ago

Susurrus commented 3 years ago

I ran into an issue decrypting my .kdbx file using keepass-diff and was told to report it here as I believe It's in issue at src/hmac_block_stream.rs:21. Full backtrace follows:

$ RUST_BACKTRACE=1 cargo run -- file1.kdbx file2.kdbx --same-password
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/keepass-diff /home/susurrus/Personal/OneRing.kdbx /home/susurrus/Personal/OneRing.sync-conflict-20210404-004755-OP4M5NG.kdbx --same-password`
Password for both files: 
thread 'main' panicked at 'range end index 1398351512 out of range for slice of length 237116', /home/susurrus/.cargo/registry/src/github.com-1ecc6299db9ec823/keepass-0.4.7/src/hmac_block_stream.rs:21:22
stack backtrace:
   0: rust_begin_unwind
             at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panicking.rs:495:5
   1: core::panicking::panic_fmt
             at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/panicking.rs:92:14
   2: core::slice::index::slice_end_index_len_fail
             at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/slice/index.rs:41:5
   3: <core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index
             at /home/susurrus/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:238:13
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /home/susurrus/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:15:9
   5: keepass::hmac_block_stream::read_hmac_block_stream
             at /home/susurrus/.cargo/registry/src/github.com-1ecc6299db9ec823/keepass-0.4.7/src/hmac_block_stream.rs:21:22
   6: keepass::parse::kdbx4::parse
             at /home/susurrus/.cargo/registry/src/github.com-1ecc6299db9ec823/keepass-0.4.7/src/parse/kdbx4.rs:260:9
   7: keepass::db::Database::open
             at /home/susurrus/.cargo/registry/src/github.com-1ecc6299db9ec823/keepass-0.4.7/src/db.rs:262:17
   8: keepass_diff::kdbx_to_group::{{closure}}
             at ./src/main.rs:189:22
   9: core::result::Result<T,E>::and_then
             at /home/susurrus/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:708:22
  10: keepass_diff::kdbx_to_group
             at ./src/main.rs:186:5
  11: keepass_diff::main
             at ./src/main.rs:152:24
  12: core::ops::function::FnOnce::call_once
             at /home/susurrus/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

I didn't see any binary within this library to assist with testing and verifying keepass files, but KeePassXC 2.6.4 can open it successfully, so I assume that there is an issue in this library. I can do some Rust coding, so can contribute here if it'll help, though I don't know this library or the keepass format very well. Any suggestions for where to start to try to debug this? Given the size of this value, I'm wondering if there's a byte-order issue with the indexing here.

Originally reported in Narigo/keepass-diff#32.

sseemayer commented 3 years ago

Thanks for reporting this! I am thinking about how to help in debugging this, since the issue is likely related to your database and you probably will not be willing to share this together with the key. Can you provide a minimal reproducible example with anything confidential removed?

In a nutshell, the KDBX format consists of a header and a data (aka payload) part, both under various layers of encryption. The Hmac block stream is used to verify the integrity of the main payload before decryption. See the linked KDBX format docs section "Improved Data Authentication" for details on how it is supposed to work.

According to the description of the Hmac Block stream, the block size is definitely 4 bytes (32 bits) and little endian. I rather worry that some other corruption has occurred, so debugging this will probably amount to tracing the raw binary data and checking if it makes sense.

Susurrus commented 3 years ago

I just tried to reproduce this today, and everything worked fine. I wonder if this was an error introduced by KeepassDX that was fixed in an update and since I've opened and resaved the "corrupted" one, it was fixed automatically. Anyways, since I can't reproduce this, going ahead and closing it.