The commands are encrypted but not authenticated, allowing the server to tamper with them
Shnatsel opened this issue · 4 comments
Right now sshx uses AES-CTR, which encrypts data but does not authenticate it. This means that while the server cannot see what the user types, the server can alter the commands transferred or inject its own commands, and there is no cryptographic protection against that. Injecting commands and observing whether they were executed or not can also be sometimes used to decrypt the data transmitted.
To protect against the server injecting its own commands you will need authenticated encryption: https://en.wikipedia.org/wiki/Authenticated_encryption
https://github.com/RustCrypto/AEADs lists Rust implementations of various authenticated encryption constructs. You can switch to AES-GCM-SIV if you want to stick with AES, although I would recommend switching to ChaCha20+Poly1305 since it is simpler and is far more resilient to timing attacks.
Yes, this is true, I am aware of authenticated encryption and the possibility of bit-level tampering with commands. The point of the encryption is to make sure to preserve confidentiality here.
Tampering with commands is not really part of the threat model. The server needs to be trusted in some regard. If the server were compromised and actually modified commands, and it could send arbitrary network messages, then it could just change the HTML payload to the website and show the end user something different.
The point of the encryption is only to preserve confidentiality with a properly running server, so CTR mode was chosen.
We're using AES and not ChaCha20-Poly1305 because it isn't implemented as part of the Web Crypto API, making it slower to run on the client-side browser.
Serving malicious HTML+JS bundle that leaks the key is indeed a far more practical attack.
Since whole connection is already wrapped in TLS and the server is trusted (or it would just serve malicious JS), there is indeed not a whole lot of cases where absence of authentication matters.
Still, situations like these exist. For example, corporate firewalls often intercept all HTTPS traffic; and for an attacker on the local network it would be easy to execute an attack on AES-CTR for lateral movement.
Certain governments intercept HTTPS also (and EU may soon join their ranks), although authentication of the underlying connection only helps if the host still obtains a legitimate sshx binary and never opens the webpage.
Perhaps there is something I am not seeing, but it just seems strange not to authenticate incoming shell commands, or even to use a non-authenticated AES mode given the long history of subtle vulnerabilities of them in the networked context. I see that Web Crypto API supports AES-GCM, perhaps it could be used in place of CTR?
It’s not possible without substantial architectural rework of the streaming protocol that would likely increase complexity, since GCM is not a valid mode of encryption for incomplete streams. That complexity, in addition to being a lot of work for me for no demonstrable gain, would possibly lead to actual security vulnerabilities.