Am I affected?
Description
Improper Validation of Consistency within Input vulnerability in Erlang OTP ssl (tls_handshake_1_3, ssl_handshake and tls_client_ticket_store modules) allows a malicious TLS 1.3 server to cause a denial of service of the ssl application on the client node.
The TLS 1.3 client decodes the extensions of a NewSessionTicket message as if they came from EncryptedExtensions. It therefore accepts a 0-length early_data extension, a form that is only valid in ClientHello and EncryptedExtensions. With {session_tickets, auto}, the client stores the ticket in the node-global tls_client_ticket_store. On the next automatic resumption, tls_handshake_1_3:get_max_early_data/1 crashes the store with a case_clause. Repeated crashes can exceed the restart intensity of the ssl supervisors, which use the rest_for_one strategy, and take down ssl for all connections on the node.
This issue affects OTP from OTP 23.3 before OTP 27.3.4.19, OTP 28.5.0.8, and OTP 29.1.2, corresponding to ssl from 10.3 before 11.2.12.14, 11.6.0.7, and 11.7.8.
Technical analysis
1. Decoding. tls_handshake_1_3:decode_handshake/2 decodes the extensions of a NewSessionTicket with the message type encrypted_extensions. ssl_handshake:decode_extensions/4 does not check the message type for most extensions. A 0-length early_data extension therefore decodes to #early_data_indication{}, the ClientHello and EncryptedExtensions form, and not to #early_data_indication_nst{}, the 4-byte max_early_data_size form that RFC 8446 requires in a NewSessionTicket.
2. Storage. In auto mode the client sends the ticket to the node-global tls_client_ticket_store gen_server, which keeps it for later resumption.
3. Crash. When a later connection resumes automatically, the store calls tls_handshake_1_3:get_max_early_data/1 on the stored extensions, from maybe_use_ticket and get_tickets. That function only handles undefined and #early_data_indication_nst{}, so the store process crashes with a case_clause.
4. Escalation. The store is a permanent child of ssl_admin_sup. Each restart of the store also restarts the children after it, because the supervisor uses rest_for_one. A server that keeps sending the malformed ticket makes the crashes repeat. When the crashes exceed the supervisor restart intensity, the failure goes up through ssl_sup and stops the ssl application for the whole node.
The fix makes ssl_handshake:decode_extensions/4 accept each extension form only in the handshake messages where it is permitted, and decodes NewSessionTicket extensions with the message type new_session_ticket.
Weaknesses & attack patterns
Weakness
CWE-1288
·
Improper Validation of Consistency within Input
in catalog →
MITRE ↗
Attack patterns
CAPEC-153
·
Input Data Manipulation
MITRE ↗
A malicious TLS 1.3 server can crash the client node's session ticket store, and by repeating the attack it can stop the ssl application for all TLS connections on that node. Only clients that use {session_tickets, auto} are affected.
Affected — Erlang
modules · source files · routines
Affected — Erlang / ssl Repository ↗
modules · source files · routines
Affected — GitHub / erlang/otp Repository ↗
modules · source files · routines
Workarounds
Do not set {session_tickets, auto} on TLS 1.3 clients. Use manual ticket handling, or keep the default value disabled.
Configurations
Only TLS 1.3 clients that set the ssl option {session_tickets, auto} are affected. The default value of session_tickets is disabled, and clients that use manual ticket handling do not store tickets in the node-global ticket store. The client must also connect to a server that the attacker controls, or that the attacker can impersonate.
References
Credits
CVSS breakdown
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N