# REPRO-2026-00222: SimpleHelp OIDC authentication accepts unsigned/forged ID tokens, enabling remote authentication bypass and possible MFA bypass in versions 5.5.15 and earlier and 6.0 prereleases prior to the fixed release. ## Summary Status: published Severity: critical Type: security Confidence: high ## Identifiers REPRO ID: REPRO-2026-00222 CVE: CVE-2026-48558 ## Package Name: SimpleHelp Ecosystem: other (commercial, Java-based server application) Affected: SimpleHelp 5.5.15 and earlier; 6.0 prerelease versions before 6.0 RC2 Fixed: 5.5.16; 6.0 RC2 / 6.0 prerelease (20260327-150806) ## Root Cause ## Summary SimpleHelp 5.5.15 accepts a forged OpenID Connect (OIDC) ID token during the real technician-login OIDC callback flow. In the reproduced configuration, an unauthenticated client requests a legitimate SimpleHelp OIDC login URL from `/auth/v1/account/oidc_get`, receives a server-generated pending `state`, completes the callback at `/oidc`, and supplies an attacker-controlled JWT with `alg: none` and a bogus signature. The vulnerable 5.5.15 server creates a fully authenticated technician session for the forged identity `attacker` / `Forged Attacker`; the patched 5.5.16 server rejects the same forged token and remains unauthenticated. ## Impact - **Package/component affected:** SimpleHelp server technician authentication, specifically the OIDC authentication provider and `/oidc` callback path. - **Affected versions:** SimpleHelp 5.5.15 and earlier, and 6.0 prerelease builds before the fixed release. - **Patched versions tested:** SimpleHelp 5.5.16 (`SimpleHelp-linux-amd64.tar.gz`, SHA256 `9360af980277e1ef4330eb1ed08d981c9dfdcc4e25d87ed0552a47f5ebd5161a`). - **Risk level and consequences:** Critical. A remote unauthenticated attacker can authenticate as a group-authenticated technician using forged identity claims. A technician account can access the SimpleHelp technician console and, depending on group permissions and deployment, remote support / remote access capabilities. ## Impact Parity - **Disclosed/claimed maximum impact:** Remote authentication/authorization bypass via forged OIDC token, yielding an authenticated technician session and potential MFA bypass. - **Reproduced impact from this run:** Full remote API/OIDC authentication bypass on the real SimpleHelp 5.5.15 server. The script obtains a legitimate pending OIDC state from the product API, submits a forged ID token through the genuine `/oidc` callback, and observes `FULLY_AUTHENTICATED` status for the attacker-controlled technician identity. - **Parity:** `full` - **Not demonstrated:** Post-auth remote-control actions against managed endpoints were not performed; the reproduced impact stops at a concrete authenticated technician session and technician-console page access. ## Root Cause The vulnerable SimpleHelp OIDC implementation parses JWT claims from the ID token but does not cryptographically verify the token signature before using those claims for technician authentication. Runtime/class evidence shows that SimpleHelp 5.5.15 includes `utils/oauth/oidc/IDToken.class` and OIDC callback classes, but no `IDTokenVerifier` class. The patched 5.5.16 build adds `utils/oauth/oidc/IDTokenVerifier.class` and related JWKS caching classes, and its callback rejects the same forged token. The key behavioral difference is: - **5.5.15 vulnerable:** The forged token reaches `OIDCAuthenticator`, is parsed into an `IDToken`, passes group-authentication logic, registers a new anonymous/group-authenticated technician, and registers a session token. - **5.5.16 patched:** The same forged token causes the callback to fail closed; the status endpoint remains `UNAUTHENTICATED`. No public fix commit hash was provided in the ticket because SimpleHelp is a commercial binary distribution; the script anchors the negative control to the vendor fixed 5.5.16 release identified in the advisory. ## Reproduction Steps 1. Run `bundle/repro/reproduction_steps.sh`. 2. The script: - Verifies/downloads the official SimpleHelp 5.5.15 and 5.5.16 Linux server tarballs. - Extracts clean vulnerable and patched server instances. - Initializes each real SimpleHelp server through the first-launch path. - Configures a real OIDC authentication provider and a non-admin `Technicians` technician group that allows group-authenticated/OIDC-created logins. - Starts a local fake OIDC IdP that returns a JWT with `alg: none` and a bogus signature segment. - Requests a real OIDC authorization URL from `https://127.0.0.1/auth/v1/account/oidc_get`, preserving the server-issued `state`. - Delivers the forged token through the genuine `https://127.0.0.1/oidc?code=...&state=...` callback. - Checks `https://127.0.0.1/auth/v1/account/status` as the post-login authorization proof. - Repeats the same flow against patched 5.5.16 as the negative control. 3. Expected evidence: - Vulnerable flow: `status_after_body` contains `"state":"FULLY_AUTHENTICATED"` and the forged identity (`Forged Attacker`, `attacker`, `attacker@example.com`). - Patched flow: callback contains `Login Failed` and status remains `"state":"UNAUTHENTICATED"`. ## Evidence Primary evidence files: - `bundle/logs/reproduction_steps.log` — full script stdout/stderr for the successful run. - `bundle/logs/vuln_flow.json` — vulnerable HTTP/API/OIDC flow result. - `bundle/logs/patched_flow.json` — patched negative-control flow result. - `bundle/logs/vuln_idp.log` — fake IdP requests and the forged ID token returned to the product. - `bundle/logs/patched_idp.log` — same forged-token IdP interaction for patched version. - `bundle/logs/vuln_runtime_tail.log` — vulnerable server runtime log excerpts. - `bundle/logs/patched_runtime_tail.log` — patched server runtime log excerpts. - `bundle/logs/class_comparison.log` — class-level fix comparison showing `IDTokenVerifier` absent in 5.5.15 and present in 5.5.16. - `bundle/repro/runtime_manifest.json` — runtime evidence manifest written by the reproduction script. Key excerpts from the successful run: ```json // bundle/logs/vuln_flow.json "status_after_body": "{\"state\":\"FULLY_AUTHENTICATED\",\"user\":{\"uniqueID\":480346,\"displayName\":\"Forged Attacker\",\"username\":\"attacker\",\"emailAddress\":\"attacker@example.com\",\"isOnline\":true},\"code\":1}" ``` ```json // bundle/logs/patched_flow.json "callback_contains_login_failed": true, "status_after_body": "{\"state\":\"UNAUTHENTICATED\",\"code\":0}" ``` ```text // bundle/logs/vuln_runtime_tail.log [OIDCAuthenticator] Received OIDC response (...) [ProxyServerAuthentication] Group authenticated technician via group 'Technicians' [ServerConfig] Registering technician login for attacker / (Technicians) [Server Config] Configuration save requested (Forged Attacker - attacker [(Technicians)] [New Anon]) [ProxyServerAuthentication] Registering session token for Forged Attacker - attacker [(Technicians)] (...) ``` ```text // bundle/logs/class_comparison.log [*] Vulnerable OIDC classes 7852 ... utils/oauth/oidc/IDToken.class 6340 ... com/aem/shelp/proxy/wds/OIDCCallbackManager.class [*] Patched OIDC classes 8796 ... utils/oauth/oidc/IDToken.class 252 ... utils/oauth/oidc/IDTokenVerifier$1.class 1660 ... utils/oauth/oidc/IDTokenVerifier$CachedJwks.class 17996 ... utils/oauth/oidc/IDTokenVerifier.class ``` Environment details captured in logs include SimpleHelp server version/build (`5.5.15` build `20260326-092709`, patched `5.5.16` build `20260526-203544`), bundled JRE versions, HTTPS listener startup, and the exact API/callback URLs exercised. ## Recommendations / Next Steps - Upgrade SimpleHelp servers to 5.5.16 or later, or to the fixed 6.0 release/RC identified by the vendor. - Ensure OIDC ID tokens are validated using issuer metadata/JWKS before any claims are trusted: - Verify the JWT signature. - Reject `alg: none` or unsupported algorithms. - Validate `iss`, `aud`, `exp`, `iat`, and nonce/state binding. - Add regression tests that submit unsigned and incorrectly signed ID tokens through the real `/oidc` callback and assert rejection. - Audit existing SimpleHelp deployments for unexpected group-authenticated/anonymous technician accounts, especially identities created via OIDC. ## Additional Notes - The script was run successfully twice consecutively after the escaping/configuration fix. - The reproduction uses the real SimpleHelp server binaries and real HTTPS API/callback paths; the only test double is the OIDC identity provider, which is attacker-controlled by design for this class of vulnerability. - The script rewrites the IdP redirect host to `127.0.0.1` after preserving the SimpleHelp-issued callback path, `code`, and `state`, because the product derives a public hostname from its local environment. This keeps the callback on the genuine SimpleHelp `/oidc` endpoint while avoiding external DNS/network dependence. ## Reproduction Details Reproduced: 2026-07-04T07:12:55.570Z Duration: 5665 seconds Tool calls: 550 Turns: Unknown Handoffs: 4 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00222 pruva-verify CVE-2026-48558 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00222&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00222/artifacts/bundle/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-48558 - Source: https://nvd.nist.gov/vuln/detail/CVE-2026-48558 ## Artifacts - bundle/repro/rca_report.md (analysis, 8336 bytes) - bundle/vuln_variant/rca_report.md (analysis, 13229 bytes) - bundle/repro/reproduction_steps.sh (reproduction_script, 17868 bytes) - bundle/vuln_variant/reproduction_steps.sh (reproduction_script, 19340 bytes) - bundle/coding/proposed_fix.diff (patch, 24553 bytes) - bundle/ticket.md (ticket, 3301 bytes) - bundle/ticket.json (other, 4273 bytes) - bundle/logs/vuln_idp.log (log, 973 bytes) - bundle/logs/patched_idp.log (log, 1011 bytes) - bundle/logs/class_comparison.log (log, 1099 bytes) - bundle/logs/vuln_runtime_tail.log (log, 18609 bytes) - bundle/logs/patched_runtime_tail.log (log, 18242 bytes) - bundle/vuln_variant/patch_analysis.md (documentation, 7478 bytes) - bundle/coding/summary_report.md (documentation, 10229 bytes) - bundle/coding/verify_logs/fixed_idp.log (log, 372 bytes) - bundle/coding/src/FixAgent.java (other, 3972 bytes) - bundle/coding/fixagent.jar (other, 5923 bytes) - bundle/repro/runtime_manifest.json (other, 1035 bytes) - bundle/repro/validation_verdict.json (other, 740 bytes) - bundle/logs/reproduction_steps.log (log, 6019 bytes) - bundle/logs/flow_summary.json (other, 765 bytes) - bundle/logs/vuln_flow.json (other, 2498 bytes) - bundle/logs/patched_flow.json (other, 2341 bytes) - bundle/logs/forged_jwt.txt (other, 350 bytes) - bundle/vuln_variant/runtime_manifest.json (other, 965 bytes) - bundle/vuln_variant/validation_verdict.json (other, 2311 bytes) - bundle/vuln_variant/variant_manifest.json (other, 3914 bytes) - bundle/vuln_variant/root_cause_equivalence.json (other, 1484 bytes) - bundle/coding/verify_fix.sh (other, 17672 bytes) - bundle/coding/verify_logs/verify_result.json (other, 717 bytes) - bundle/coding/verify_logs/fix_evidence.log (log, 318 bytes) - bundle/coding/verify_logs/fixed_flow.json (other, 1090 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00222 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00222/artifacts/bundle/repro/reproduction_steps.sh - Web: https://pruva.dev/r/REPRO-2026-00222 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://pruva.dev