-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stream Cipher Used to Encrypt Last File Block #9
Comments
Plan is to eliminate use of stream mode entirely in Encfs 2.x (for new filesystems). No plan for Encfs 1.x |
Do you already have a plan for what mode to use? CBC with ciphertext stealing seems to be a good option. |
The other option would be to go with CTR for the whole file. With CTR, however, an attacker can flip single bits at will, so it would need to go with MAC enabled by default. If ecryptfs has MACs enabled by default (will check) we should probably too, anyway. |
CTR has the additional problem that the XOR of two cipertext files copied at two different times is the XOR of the plaintext. To fix that leak you'd need random per-block IVs. |
For Encfs2, I'm leaning towards GCM mode (as used in ZFS). |
@vgough Salsa20+Poly1305 would also be a viable (and very fast) alternative, as outlined by Thomas Ptacek in his blog: |
Actually, i don't think large changes like that are neccessary. Blockwise cbc works fine for everything but the last 16 bytes (the aes block size). |
Please don't invent a padding scheme; just pad with PKCS#7 like everyone else. :) |
Thanks for the pointer! However, pkcs#7 seems to require that you read the last bytes of the ciphertext to geht the plaintext length. This is one additional seek for every stat(), we should really avoid that as it kills rsync performance. |
(It's probably more than one seek, because the filesystem has to parse its internal data structures first to locate the data)
|
Isn't that a security issue if you know that the last bytes will be (padded with) zero bytes? Maybe better random bytes? |
Nope, should be fine.
http://en.m.wikipedia.org/wiki/Known-plaintext_attack
Modern ciphers such as Advanced Encryption Standard are not currently known
to be susceptible to known-plaintext attacks.
|
While the current modes of modern ciphers available to encfs might not
currently be susceptible to known-plaintext attacks, these types of attacks
are typical for cryptanalysis and so this assumption could change after
further years of research.
Additionally, encfs offers multiple cipher options. Is this statement true
for all ciphers encfs makes available through OpenSSL?
If given two choices for this implementation, are there impacts in choosing
one over the other?
1. Pad with zeros
2. Pad with any value
|
Trying to predict how to modify ciphers based on what vulnerabilities might be discovered in the future quickly becomes a wild goose chase. I suspect if you submitted a PR that improved the padding without affecting backwards compat, it would fare better. |
A random idea I just thought of: |
In order to make lookups simple, it is preferable that encrypted filenames can be directly computed from plaintext filenames. That way a call to open("foo.txt") doesn't require a directory scan in order to find the encrypted file. Instead, we encrypt "foo.txt" and attempt to open the encrypted name. Allowing hashed names, to extend allowable file lengths, doesn't hurt too badly since it could still be done without a directory traversal. Encoding metadata into filenames would thwart this, since I'm not aware of any portable way to do a prefix match or otherwise avoid walking the entire directory listing. |
Of course. I should have thought it through a bit longer. |
No worries, I appreciate the ideas. I've wanted to do the same myself, just didn't figure out a way to make that work. |
Is there a chance that there - maybe ;-) - will be a solution for the actual version in next time? |
no one who thinks that he can make a fast fix? |
Well, this is an incompatible format change, there is no fast fix i'm
afraid
|
uhh. And what's with an not backwards compatible version which is not 2.0? |
Forward mode would not work either in this case, right? |
It would, because then here you encode data, so you don't expect it to be a multiple of |
Can't we stat() the plaintext file instead? |
Unfortunately this would not help. |
If the write expanded the file, if must be the last block, and it must have padding |
(otherwise forward mode is buggy) |
Not necessarily. Think about a cipher file being dowloaded directly into a reverse-write EncFS (so that it is written decrypted directly to the local disk). |
The every block must have padding. |
A 15 bytes padding ? |
Yes, 15 bytes. |
At that moment, it's the last block, right? |
Look at these use cases : Backup : Restore : I'm not sure backup will need to insert a 15 bytes padding after every block. |
Interesting use case, but there are other problems:
Now, let's assume the ciphertext contains
do? |
// strange duplicate part of your message above deleted Yes, I think this is the last tricky case. Let's take your example. 1000%16 = 8 If we receive a write request with the next 1000 bytes, we will not read the 1000 previous bytes of the block from the plain file, as we have cropped some bytes, but will take them from our internal buffer. |
I was curious if that use case really works, so I did:
And it seems wo work at first glance:
So that was easy, lets overwrite the middle of the file with itself:
Random garbage:
|
However, this (note the odd block size):
works, and I'm not sure why.
On decryption, we have to know if it is the last block, because the last block is handled differently. Where do we have this information from? |
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) :
|
Strangely, in your failing example above, file get truncated by dd at the end of the 123 bytes written block (I reproduced it). |
Oh, my bad! You are right, the truncation is what causes the garbage:
|
From the latest audit (https://defuse.ca/audits/encfs.htm): > EncFS is probably safe as long as the adversary only gets one copy of > the ciphertext and nothing more. EncFS is not safe if the adversary has > the opportunity to see two or more snapshots of the ciphertext at > different times. EncFS attempts to protect files from malicious > modification, but there are serious problems with this feature. vgough/encfs#8 vgough/encfs#9 (critical) vgough/encfs#10 vgough/encfs#11 vgough/encfs#13 vgough/encfs#16 vgough/encfs#17
CryFS (https://www.cryfs.org/) is a software that can be run by non-root users that have access to /dev/fuse. Its command is directly used to mount a directory ("/usr/bin/cryfs basedir mountpoint"), like command "mount". Unmounting a mountpoint is done with "fusermount -u mountpoint", /usr/bin/fusermount being a setuid-root program labeled mount_exec_t. EncFS (https://www.arg0.net/encfs) is a similar software that has been considered insecure since a security audit in 2014 found vulnerabilities that are not yet fixed (like vgough/encfs#9). gocryptfs (https://nuetzlich.net/gocryptfs/) is a similare software that has been inspired by EncFS. Allow users with role sysadm to use all these projects. Signed-off-by: Nicolas Iooss <[email protected]>
CryFS (https://www.cryfs.org/) is a software that can be run by non-root users that have access to /dev/fuse. Its command is directly used to mount a directory ("/usr/bin/cryfs basedir mountpoint"), like command "mount". Unmounting a mountpoint is done with "fusermount -u mountpoint", /usr/bin/fusermount being a setuid-root program labeled mount_exec_t. EncFS (https://www.arg0.net/encfs) is a similar software that has been considered insecure since a security audit in 2014 found vulnerabilities that are not yet fixed (like vgough/encfs#9). gocryptfs (https://nuetzlich.net/gocryptfs/) is a similar software that has been inspired by EncFS. Allow users with role sysadm to use all these projects. Signed-off-by: Nicolas Iooss <[email protected]>
CryFS (https://www.cryfs.org/) is a software that can be run by non-root users that have access to /dev/fuse. Its command is directly used to mount a directory ("/usr/bin/cryfs basedir mountpoint"), like command "mount". Unmounting a mountpoint is done with "fusermount -u mountpoint", /usr/bin/fusermount being a setuid-root program labeled mount_exec_t. EncFS (https://www.arg0.net/encfs) is a similar software that has been considered insecure since a security audit in 2014 found vulnerabilities that are not yet fixed (like vgough/encfs#9). gocryptfs (https://nuetzlich.net/gocryptfs/) is a similar software that has been inspired by EncFS. Allow users with role sysadm to use all these projects. Signed-off-by: Nicolas Iooss <[email protected]> Signed-off-by: Jason Zaman <[email protected]>
What's the current state of this issue? |
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:
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 :
The text was updated successfully, but these errors were encountered: