GHSA-539f-xcgw-2gjg: Addressable display_uri can show misleading hosts containing bidi and invisible characters
Impact
Addressable::IDNA.tounicode decodes Punycode labels (labels beginning with xn--) that contain characters which change how text is displayed without being visible themselves. These include bidirectional controls such as U+202E RIGHT-TO-LEFT OVERRIDE and U+2066–U+2069, zero-width characters, and other invisible format characters. Addressable::URI#displayuri uses tounicode, so it can display a host whose characters appear reordered or which looks identical to a different host. For example, the host of http://xn--abcmoc-dm0c.com/ is displayed as abc, U+202E, moc.com, and the override makes everything after abc render right to left.
Parsing, host, normalizedhost and any connection made from the URI are not affected. Only the displayed form is. Applications that show displayuri to users (link previews, chat and email clients, admin interfaces) can be used to make a malicious domain look like a trusted one.
- In the pure-Ruby IDNA implementation, all such characters are decoded, including those that IDNA's nameprep profile prohibits. - In the native IDNA implementation, used when libidn and the idn-ruby gem are installed, libidn rejects most of them, but not characters added to Unicode after version 3.2, such as U+061C and U+2066–U+2069.
Affected Versions
The pure-Ruby IDNA implementation is affected in Addressable >= 2.0.0. The native IDNA implementation is affected in Addressable >= 2.5.2, when tounicode began accepting characters unassigned in Unicode 3.2. It is fixed in 2.9.1 for both implementations, where such labels are returned unchanged.
Workarounds
- Install libidn and the idn-ruby gem, so that Addressable uses the native IDNA implementation. This reduces the affected characters to those added since Unicode 3.2. - Check displayed hosts for bidirectional and invisible characters (e.g., /[\p{Cc}\p{Cf}\p{DefaultIgnorableCodePoint}]/) and fall back to normalizedhost when one is present.
Credits
Reported by @andrewstellman.
For more information
If there are any questions or comments about this advisory: Open an issue
Other sources
Addressable is an alternative implementation to the URI implementation that is part of Ruby's standard library. From 2.0.0 until 2.9.1, Addressable::IDNA.tounicode can decode Punycode labels that contain bidirectional controls, zero-width characters, control characters, or other default-ignorable format characters. Addressable::URI#displayuri can consequently show a reordered or visually indistinguishable hostname even though host, normalizedhost, and network connections use the original encoded hostname. The pure-Ruby backend accepts the full prohibited set, while the native libidn backend is affected from 2.5.2 for characters added after Unicode 3.2. This issue is fixed in version 2.9.1.
— OSV
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
rubygems/addressableto a version that resolves this vulnerability.Fixed in 2.9.1 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 2.9.1 - Compensating control
Check displayed hosts for bidirectional and invisible characters (e.g., /[\p{Cc}\p{Cf}\p{Default_Ignorable_Code_Point}]/) and fall back to normalized_host when any are present.
- Compensating control
Install libidn and the idn-ruby gem so Addressable uses the native IDNA implementation.
Event History
Frequently Asked Questions
Which applications are exposed to this issue?
Applications that present Addressable::URI#display_uri to users are exposed to misleading hostname rendering. Examples given include link previews, chat and email clients, and administrative interfaces.
Does this affect URI parsing or outbound connections?
No. Parsing, host, normalized_host, and connections made using the URI are not affected; the issue is limited to the displayed form of the hostname.
What must an attacker do to exploit this?
An attacker must supply a URI with a Punycode hostname containing bidirectional control, zero-width, or other invisible format characters, then cause the application to display display_uri to a user. The rendered hostname can appear reordered or resemble a different, trusted hostname.
Does the IDNA implementation change exposure?
Yes. The pure-Ruby IDNA implementation decodes all of the described characters, including ones prohibited by IDNA nameprep. The native implementation used with libidn and the idn-ruby gem rejects most of them.