4 ms·
My question was asking to confirm that it indeed will put out a truncated output when given a mid-stream corrupted input (and that it doesn't do something like
by nullc 7y ago
My question was asking to confirm that it indeed will put out a truncated output when given a mid-stream corrupted input (and that it doesn't do something like buffer just to validate).
That behavior should be clearly documented, so that users can be advised that their pipelines need to safely handle that case.
> that thing might need to wait for the end-of-file signal before processing or else potentially operate on a truncated file
Exactly. The docs should say this clearly, or someone will manage to create an interesting vulnerability with it eventually. :)
Could go with a message the points out that encryption doesn't authenticate the source-- which is a not uncommon misuse that shows up with PGP, where people assume that the source is authentic if the input was encrypted, even where no signature is used. (the fact that corrupted input gives an "authentication failed" message might be particularly misleading)
- tptacek 7y agoIt's streaming on-line encryption. That's literally the point of streaming encryption: not buffering whole messages. The rest of your point directly follows from "not buffering whole messages".
- nullc 7y agoIndeed. And the readme and the usage output makes no mention of streaming, buffering, on-line, authentication, or anything related. This is a potential security relevant behavior that most users-- who haven't written or analyzed tools like this-- would find surprising. For those following along, I went and tested it-- since the behavior wasn't documented or clear from the code. If it encounters midstream corruption it truncates the output, exits with a non-zero return and prints some error text std stderr: "Error: chacha20poly1305: message authentication failed\n[ Did age not do what you expected? Could an error be more useful? Tell us: https://filippo.io/age/report https://filippo.io/age/report ]" If the input is truncated, it either does that-- or if the truncation is on a block boundary it prints "Error: unexpected EOF\n[ Did age not do what you expected? Could an error be more useful? Tell us: https://filippo.io/age/report https://filippo.io/age/report ]" instead. It's not a problem, but it should be documented.
- Boulth 7y ago> If it encounters midstream corruption it truncates the output, exits with a non-zero return and prints some error text std stderr: Do you mean it releases output even if the encrypted file is corrupt or tampered with? Isn't this one of the issues in e-fail?
- AgentME 7y agoI think the problem with e-fail was that gpg would output data before verifying it. Age will only output chunks of data after they've been verified.
- mike_hock 7y agoThis is a security footgun and a vulnerability waiting to happen, but bash is at fault, not age. age does the best it can do (while maintaining O(1) memory requirement) by exiting non-zero, but the shell swallows that if it's in the middle of a pipeline.
- labawi 7y agoIMHO it's not that bad. It's actually quite usable, and reasonably easy to handle safely. Use bash: set -eu -o pipefail # unfortunately pipefail is not POSIX and some care when writing scripts. Possibly decrypt to a file first. A proper and likely footgun would be decrypting and passing tainted plaintext and only then exiting nonzero. E.g. decrypt < file | sh # owned Definitely should be documented either way.
- mike_hock 7y agoI agree with all of what you said. The footgun you described can still happen if there's a verification error somewhere in the middle. You could still conceivably craft exploits using only truncation of the plaintext, depending on the situation. No one should "decrypt < file | sh" (or anything | sh without verifying), but they will. Doesn't matter if we have POSIX or non-POSIX shell flags that can fix it, the defaults are bad. There's nothing tools like age can do about that, though. Edit: I was thinking more along the lines of if decrypt < file | postprocess > tempfile then sh tempfile fi where postprocess exits zero. This is where the default shell behavior fails. The "decrypt < file | sh" antipattern is something not even the shell can do anything about.
- feanaro 7y agoThe fact that this is the point of streaming encryption does not preclude the usefulness of pointing it out explicitly. It eliminates a reasoning step by spelling it out, which is always a good thing for critical things, IMO.