Am I affected?
This record states its affected versions in a form that can't be compared automatically.
Description
Improper Handling of Highly Compressed Data (Data Amplification) in esaml_binding in dropbox esaml allows an unauthenticated attacker to exhaust server memory and crash the Erlang VM via a crafted compressed SAMLResponse.
esaml_binding:decode_response/2 base64-decodes the attacker-supplied SAMLResponse, inflates it with zlib:unzip/1 with no bound on the output, then converts the result to a charlist with binary_to_list/1 before parsing. This runs on the SAML consume (ACS) and single-logout endpoints, which accept unauthenticated requests by design, and it runs before any signature check. A small deflate stream reaches a compression ratio near 1000 to 1, so a request body of tens of kilobytes inflates to hundreds of megabytes and then to several gigabytes of list heap, so a few requests exhaust memory and take the node down.
This issue affects esaml: from 0.1.0 onward.
Technical analysis
1. Input. The SAML consume (ACS) and single-logout endpoints read the request body and pass the SAMLResponse form field to esaml_binding:decode_response/2. The attacker's SAMLEncoding field selects the clause. Both clauses inflate: the explicit DEFLATE clause, and the default clause, which tries zlib:unzip/1 inside a catch whenever the body is not plain XML.
2. Unbounded inflate. decode_response/2 evaluates binary_to_list(zlib:unzip(base64:decode(SAMLResponse))). zlib:unzip/1 inflates the whole stream in one call with no cap on output size, and binary_to_list/1 then expands the inflated binary to a charlist, which costs about 16 bytes of heap per byte on a 64-bit VM.
3. Exhaustion before any check. All of this happens before xmerl_scan parses the document and before esaml_sp verifies any signature. A deflate stream of a long run of identical bytes reaches a ratio near 1000 to 1, so a request body of tens of kilobytes produces hundreds of megabytes of binary and then several gigabytes of list heap. A few concurrent requests exhaust memory and crash the node.
Proof of concept
- Build a
SAMLResponseas the base64 of a raw deflate stream of a long run of identical bytes (for example 60 MB of zero bytes), which encodes to roughly 79 KB on the wire. - Post it to the service provider's SAML consume (ACS) endpoint as the
SAMLResponseform field, withSAMLEncodingset to the DEFLATE URI, or omitted to take the default clause. esaml_binding:decode_response/2inflates the stream and converts it to a charlist before any signature check. A single request spikes the Erlang VM by several gigabytes. Repeat to exhaust memory and crash the node.
Weaknesses & attack patterns
Weakness
CWE-409
·
Improper Handling of Highly Compressed Data (Data Amplification)
in catalog →
MITRE ↗
Attack patterns
CAPEC-231
·
Oversized Serialized Data Payloads
MITRE ↗
An unauthenticated attacker reaches a SAML consume or single-logout endpoint and posts a small compressed SAMLResponse that inflates to gigabytes, exhausting memory. A few requests crash the Erlang VM and deny service to every user of the service provider.
Affected — GitHub / handnot2/esaml Repository ↗
modules · source files · routines
Affected — GitHub / arekinath/esaml Repository ↗
modules · source files · routines
Affected — Hex / esaml Hex.pm ↗ Repository ↗
modules · source files · routines
Affected — GitHub / dropbox/esaml Repository ↗
modules · source files · routines
References
Credits
CVSS breakdown
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N