cyrusimap / cyrus-imapd

Cyrus IMAP is an email, contacts and calendar server
http://cyrusimap.org
Other
548 stars 150 forks source link

countermeasures to ALPACA attack? #5046

Open lambdafu opened 2 months ago

lambdafu commented 2 months ago

Hi,

I am one of the authors of the ALPACA attack from 2021. I am currently revisiting the evaluated implementations to see how widespread our suggested countermeasures were. See the paper for details. In Table 4, we indicated that Cyrus IMAP 3.2.4 does not reject HTTP requests, allows an unlimited number of errors and has a reflection vector. We also indicate that Cyrus POP3 3.0.8 does not reject HTTP requests and allows an unlimited number of errors. In Table 5, we indicate that these versions of Cyrus were vulnerable for Download (IMAP and POP3) and Reflection (IMAP only) attacks. A reevaluation by Janik Hölling in 2022 found that Cyrus 3.4.2 behaved the same, and that it does not implement strict ALPN or SNI validation. You can find the exploits and docker container for the reevaluation in our artifacts.

I understand that sometimes Cyrus is used with a proxy server like Nginx. To my understanding, nginx implemented strict ALPN validation, so users of Cyrus who put it behind nginx might be fine without any changes in Cyrus.

However, for others, countermeasures native to Cyrus might be appreciated. Did you consider these countermeasures?

elliefm commented 2 months ago

Thanks for the report, I'm looking into it.

It's worth observing that, even though we do reflect limited html contents in an IMAP tag, we at least won't reflect one with a trivially useful payload, because () aren't valid in IMAP tags:

* OK [CAPABILITY IMAP4rev1 IMAP4rev2 AUTH=PLAIN AUTH=LOGIN ENABLE ID LITERAL+ SASL_IR] debian Cyrus IMAP 3.11.0-alpha0-891-ga30e9a7cd server ready
<script>attack()</script> noop
* BAD Invalid tag
lambdafu commented 2 months ago

Thanks for looking into it! As for the payload, I'm not an expert, but if I google "xss bypass parenthesis" I get several pages with suggestions how to avoid parenthesis in XSS payloads. For example, this worked in courier:

<script>alert`XSS`</script> xxx

But I did not do extensive testing. Just wanted to point that out.

elliefm commented 2 months ago

Sure, thanks, that's really appreciated. I did my own search and found a few interesting ways to inject a function call that from an untested visual examination I think would be valid tags according to the IMAP spec. So I'm thinking about violating the spec in order to be more restrictive in the tags we'll accept -- though that will take some care because I don't currently know what kinds of tags real IMAP clients are actually using.

So far I'm thinking of rejecting:

It also seems important to drop the connection outright if the first command has a tag of POST, PUT, etc. There's a couple of ways I can think of to approach that and I'm not yet sure which I prefer:

I suppose a way to limit the impact of rejecting POST/PUT on IMAP clients might be to only reject those tags if the command was also invalid. That'd catch stuff like POST / HTTP/1.1 but won't affect stuff like POST select inbox. I'm not sure if it's possible to trick a browser into sending something that looks like a valid IMAP command in the target resource field of an HTTP request... POST noop HTTP/1.1 would probably work and might be plausible, hmm. So actually, I think I've convinced myself we probably have to reject this tag regardless of whether the command was valid.

lambdafu commented 2 months ago

Restricting tags and blocking HTTP requests are solid application layer countermeasures. If you limit the HTTP detection to the first command, I recommend to make sure that this works correctly with STARTTLS. For example, "Sendmail only detects HTTP requests at the very start of a connection. If STARTTLS is used, the first command inside the connection can be sent by the attacker, bypassing the detection" (Section 6.3 of our paper).

Note that strict ALPN validation is a strong countermeasure, as all common browsers already send ALPN identifiers like "http/1.1". The ALPN identifier "imap" is reserved for IMAP, so any client sending an ALPN extension that does not contain "imap" could be blocked. Then we don't even get to the application layer protocol.

elliefm commented 2 months ago

Thanks, that's a good observation about STARTTLS, I'll keep it in mind. I don't know anything about ALPN, this issue was the first I heard of it, but I'll have a look into that too.

elliefm commented 1 month ago

I've had a skim of the Wikipedia article on ALPN, and the OpenSSL docs for using it. It seems reasonable to implement, but we'd probably tackle it as a separate PR, and implement it for all protocols we implement, ingoing and outgoing, in one fell swoop. So implementation of that might lag somewhat behind the basic mitigations I'm already adding.

elliefm commented 1 month ago

5087 makes all our service daemons perform ALPN negotiations when handling client connections (httpd already did this, now the rest do too). We don't yet have anything for connections where cyrus is the client, but getting one side done is a start!