bmcweb mTLS: UPN domain suffix matching authenticates parent-domain and TLD-only certificates
binreaper <[email protected]>
| Newsgroups | org.ozlabs.lists.openbmc |
|---|---|
| Message-ID | <Edi-ZB9R4AJAZhrvwWnwKu4TZURV7FTcns18seYmP2-hZHZziG1BkyPF3iS1wJbE2wttI8MEHtDCBiVowlF2YYBjX4Gzl54iafbhmKespAw=@proton.me> |
Hi all, A second of the four bmcweb security findings I reported privately on 2026-02-23 remains unfixed in master. I posted the more severe of the two (HTTP/2 pre-auth body accumulation) to this list earlier today; this is the lower-severity sibling. Same redirect rationale (Ed Tanous's 2026-05-14 instruction to use public channels). A suggested Gerrit change accompanies this post. ## Summary `isUPNMatch()` in `http/mutual_tls.cpp` performs domain suffix matching when validating mTLS client certificates in UserPrincipalName (UPN) mode. The algorithm strips dot-separated labels from right to left and returns true once the UPN domain runs out of labels, regardless of how many hostname labels remain. The result is that a certificate with a UPN of just a TLD (`user@com`) authenticates against any BMC in that TLD, and a parent-domain certificate (`[email protected]`) authenticates against any BMC nested under that parent (`bmc.lab.internal.example.com`). - **Affected component**: bmcweb mTLS authentication, `http/mutual_tls.cpp::isUPNMatch()`. - **Configuration prerequisite**: `CertificateMappingAttribute=UserPrincipalName` (not the default; default is `CommonName`). UPN mode is opt-in but is deployed by several large operators. - **Severity**: CVSS 3.1 6.8 (Medium) — `AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N`. Attack complexity is High because the attacker needs a CA-signed client certificate with a parent-domain or TLD-only UPN; the scope is "anyone holding such a cert against any BMC under that suffix", which can be very broad in enterprise PKI deployments. ## Reproducer (no exploit code required) The behavior is asserted by the project's own existing unit test, which I will not reproduce verbatim per the customary list etiquette, but the form is: ``` EXPECT_TRUE(isUPNMatch("user@com", "hostname.region.domain.com")); ``` That expectation is the bug. Any certificate the BMC will accept whose UPN domain is just `com` will authenticate the bearer against `hostname.region.domain.com`. The same applies to any other suffix relationship. The "patches" landed on master on 2026-04-10 (commits `af44b2bd` "Make UPN domain matching case-insensitive" and `5d4a41fa` more UPN unit tests) touched the exact function and added unit tests, but they only made matching case-insensitive — they did not address the suffix-matching escalation. From the outside the bug looks closed; it is not. ## Suggested fix The Gerrit change linked above replaces the right-to-left label walk with two checks: 1. Exact match: the UPN domain equals the BMC hostname. 2. One-label-prefix tolerance: the UPN domain equals the BMC hostname after stripping a single leading short-hostname label. This preserves the common pattern where the UPN uses the DNS domain (`domain.com`) and the BMC hostname prepends one label (`bmc-01.domain.com`). Any deeper nesting is rejected. Case-insensitivity is retained via `bmcweb::asciiIEquals()`. The existing unit test that asserted the suffix-match behavior is corrected to `EXPECT_FALSE` and two additional positive cases (exact match, one-label prefix) are added. This is a minimal-change fix. An alternative — minimum-label-depth enforcement (require the UPN domain to contain at least one dot) — would prevent only the TLD-only case and leave the parent-domain escalation intact. I went with the exact-plus-one-label form because it covers both bug classes and matches the actual operational pattern that UPN mode is configured for. ## What I'd appreciate A maintainer review of the Gerrit change. The diff is small (~36/-28 across `http/mutual_tls.cpp` and `test/http/mutual_tls.cpp`). If a different shape of fix would land more cleanly with bmcweb's design, I'm happy to revise; if the one-label-prefix tolerance is itself too permissive, I'm happy to tighten further to exact-match-only. ## Timeline - **2026-02-23** — Reported privately to `[email protected]` as the fourth of four findings; acknowledged the same day by Joseph Reynolds and forwarded to the bmcweb maintainers. - **2026-04-10** — `af44b2bd` "Make UPN domain matching case-insensitive" + `5d4a41fa` more UPN unit tests landed on master. These touch the same function but do not address the suffix-matching escalation. - **2026-05-05** — Status-check email to the maintainers. No reply on this finding. - **2026-05-14** — Maintainer reply (Ed Tanous) redirected further correspondence on the remaining findings to public OpenBMC channels. This post is that follow-up. - **2026-05-27** — H2-F1 (the more severe sibling finding) posted to this list with Gerrit change 90580; this post and Gerrit change 90581 cover AUTH-F6. Best regards, binreaper [email protected]