vgough / encfs

EncFS: an Encrypted Filesystem for FUSE.
https://vgough.github.io/encfs/
Other
2.08k stars 276 forks source link

Stream Cipher Used to Encrypt Last File Block #9

Open lipnitsk opened 10 years ago

lipnitsk commented 10 years ago

From: https://defuse.ca/audits/encfs.htm

Exploitability: Unknown Security Impact: High

As reported in [1], EncFS uses a stream cipher mode to encrypt the last file block. The change log says that the ability to add random bytes to a block was added as a workaround for this issue. However, it does not solve the problem, and is not enabled by default.

EncFS needs to use a block mode to encrypt the last block.

EncFS's stream encryption is unorthodox:

1. Run "Shuffle Bytes" on the plaintext.
    N[J+1] = Xor-Sum(i = 0 TO J) { P[i] }
    (N = "shuffled" plaintext value, P = plaintext)
2. Encrypt with (setIVec(IV), key) using CFB mode.
3. Run "Flip Bytes" on the ciphertext.
    This reverses bytes in 64-byte chunks.
4. Run "Shuffle Bytes" on the ciphertext.
5. Encrypt with (setIVec(IV + 1), key) using CFB mode.

Where setIVec(IV) = HMAC(globalIV || (IV), key), and,
    - 'globalIV' is an IV shared across the entire filesystem.
    - 'key' is the encryption key.

This should be removed and replaced with something more standard. As far as I can see, this provides no useful security benefit, however, it is relied upon to prevent the attacks in [1]. This is security by obscurity.

Edit : [1] may be unavailable, so here it is from archives.org :

[Full-disclosure] Multiple Vulnerabilities in EncFS
From: Micha Riser (micha[at]povworld.org)
Date: Thu Aug 26 2010 - 07:05:18 CDT
(...)
3. Last block with single byte is insecure 
------------------------------------------------------- 
The CFB cipher mode is insecure if it is used twice with the same 
initialization vector. In CFB, the first block of the plain text is XOR-ed with 
the encrypted IV: 
  C0 = P0 XOR Ek (IV ) 
Therefore, for two cipher blocks C0 and C0' encrypted with the same IV, it 
holds that: 
  C0 XOR C0' = (P0 XOR Ek (IV )) XOR (P0' XOR Ek (IV )) = P0 XOR P0' 
This means that an attacker gets the XOR of the two plain texts. EncFs uses a 
modified version of CFB which additionally shuffles and reverses bytes. It is not 
clear however, if the modifications generally help against this problem. 

A security problem arises definitely if the last block contains only a single 
byte and an attacker has two versions of the last block. Operating on a single 
byte, the shuffle and reverse operation do nothing. What remains is a double 
encryption with CFB and XOR-ing the two cipher bytes gives the XOR of the 
two plain text bytes due to the reason described above. Encrypting the last 
block with a stream cipher instead of a block cipher saves at most 16 bytes 
(one cipher block). We think it would be better to sacrifice these bytes and in 
exchange rely only on a single encryption mode for all blocks which simplifies 
both the crypto analysis and the implementation.
benrubson commented 6 years ago

I think every 123 bytes block is written using stream cipher (so this creates garbage), until you are ready to write enough bytes (up to blokSize) to read (stream-encode) them again and re-decode the whole block correctly using CBC.

Confirmed (here blockSize is 1024) :

VERBOSE FileNode::write offset 984, data size 123 [FileNode.cpp:247]
VERBOSE streamRead(data, 984, IV) [CipherFileIO.cpp:350]
VERBOSE Called blockWrite [CipherFileIO.cpp:420]
VERBOSE Called streamWrite [CipherFileIO.cpp:429]
benrubson commented 6 years ago

Strangely, in your failing example above, file get truncated by dd at the end of the 123 bytes written block (I reproduced it). There is a bug somewhere :)

rfjakob commented 6 years ago

Oh, my bad! You are right, the truncation is what causes the garbage:

dd if=b/eNZPWSyw0rxU7T37UwNN3,n9 of=c/eNZPWSyw0rxU7T37UwNN3,n9 \
 bs=123 seek=43 skip=43 count=1 conv=notrunc

$ md5sum a/zero d/zero 
2d56b031dc8683c233c016429084f870  a/zero
2d56b031dc8683c233c016429084f870  d/zero
jcguu95 commented 3 years ago

What's the current state of this issue?