Описание
Eclipse Jetty Digest Authentication: ISO-8859-1 lossy encoding allows authentication bypass via character substitution
Summary
The DigestAuthentication.apply() method in Jetty's HTTP client uses getBytes(StandardCharsets.ISO_8859_1) at three locations (lines 171, 179, 196) to compute Digest auth response hashes. ISO-8859-1 silently replaces any character above U+00FF (Chinese, Japanese, Cyrillic, Arabic, Emoji, etc.) with 0x3F (?), causing all such characters to produce identical hash contributions. An attacker who knows a victim's username can bypass Digest authentication by replacing all non-Latin-1 characters in the password with ? characters, since the collision password produces the same MD5-based Digest response hash as the original password.
Details
Root Cause
In jetty-core/jetty-client/src/main/java/org/eclipse/jetty/client/DigestAuthentication.java, the apply() method computes the three Digest auth hashes (H(A1), H(A2), and the final response) using ISO-8859-1 character encoding:
ISO-8859-1 (Latin-1) can only encode characters in the range U+0000–U+00FF. Any character outside this range — including all CJK, Cyrillic, Arabic, Greek, Hangul, and emoji characters — is silently replaced with the byte 0x3F (?). String.getBytes(ISO_8859_1) in Java performs this replacement without any warning or exception.
PoC
Multi-language confirmation — all four language passwords below produce the same hash:
Impact
Scenario 1: Authentication Bypass (Collision Attack)
If a service using Jetty for Digest authentication has a user with a non-Latin-1 password (e.g., Chinese, Japanese, Russian), an attacker can authenticate as that user using a collision password where all non-Latin-1 characters are replaced with ?:
- Original password:
我爱Java!密码123★ - Collision password:
??Java!??123? - Both produce identical MD5 hashes under ISO-8859-1 → Authentication succeeds
This affects any password containing characters > U+00FF, which covers:
- Chinese (CJK): U+4E00–U+9FFF
- Japanese (Hiragana/Katakana/Kanji): U+3040–U+30FF, U+4E00+
- Korean (Hangul): U+AC00–U+D7AF
- Cyrillic: U+0400–U+04FF (Russian, Ukrainian, Bulgarian, etc.)
- Arabic: U+0600–U+06FF
- Greek: U+0370–U+03FF
- Latin Extended: U+0100–U+024F (accented European characters like ĉ, ğ, ñ when > U+00FF)
- Emoji / Symbols > U+00FF
Scenario 2: Denial of Service for Non-Latin-1 Users
Most modern web applications store password hashes computed using UTF-8. When Jetty's Digest client computes a hash with ISO-8859-1, the bytes differ from what the server stored/expects. This means any user with non-ASCII (Latin-1+) characters in their password can never successfully authenticate via Digest auth — even the legitimate user. This is not just a security issue but a functional correctness bug that silently breaks authentication for most non-European-language users.
Ссылки
- https://github.com/jetty/jetty.project/security/advisories/GHSA-2fvj-hgj9-j2gr
- https://github.com/jetty/jetty.project/issues/15136
- https://github.com/jetty/jetty.project/pull/15160
- https://github.com/jetty/jetty.project/pull/15183
- https://github.com/jetty/jetty.project/commit/4bcdbc7db387ce9e20e2c7571a7250280466221d
- https://github.com/jetty/jetty.project/commit/d0bb829ccecbf19e3ad3d32f2649b2800f01222d
- https://github.com/jetty/jetty.project/releases/tag/jetty-12.0.36
- https://github.com/jetty/jetty.project/releases/tag/jetty-12.1.10
Пакеты
org.eclipse.jetty:jetty-security
>= 9.4.0.v20161208, <= 9.4.58.v20250814
9.4.63
org.eclipse.jetty:jetty-security
>= 10.0.0, <= 10.0.26
10.0.31
org.eclipse.jetty:jetty-security
>= 11.0.0, <= 11.0.26
11.0.31
org.eclipse.jetty:jetty-security
>= 12.0.0, <= 12.0.35
12.0.36
org.eclipse.jetty.ee8:jetty-ee8-security
>= 12.0.0, <= 12.0.35
12.0.36
org.eclipse.jetty.ee9:jetty-ee9-security
>= 12.0.0, <= 12.0.35
12.0.36
org.eclipse.jetty:jetty-security
>= 12.1.0, <= 12.1.9
12.1.10
org.eclipse.jetty.ee8:jetty-ee8-security
>= 12.1.0, <= 12.1.9
12.1.10
org.eclipse.jetty.ee9:jetty-ee9-security
>= 12.1.0, <= 12.1.9
12.1.10