Skip to content

BishopFox/CVE-2026-22557-check

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CVE-2026-22557 Vulnerability Assessment Tool

Safely detect whether a UniFi Network Application controller is vulnerable to CVE-2026-22557 without causing any disruption. See the full write-up at the Bishop Fox blog.

Description

CVE-2026-22557 is an unauthenticated path-traversal vulnerability in the UniFi Network Application's guest captive portal that allows remote attackers to read arbitrary files as the controller process user (CVSS 10.0). The vulnerability affects UniFi Network Application 10.1.85 and earlier on the 10.1.x branch, and corresponding earlier releases on the 10.2.x and 9.0.x branches. Ubiquiti shipped fixes in 10.1.89, 10.2.97, and 9.0.118 (SAB-062).

The guest portal's failure-page renderer reads the page_error request parameter and uses it verbatim as a relative path on the portal resource loader, with no validation. When portal_customized: true is set on the queried site (the configuration any branded captive portal, such as a hotel, retail, or café deployment, ends up with), the loader resolves that path against the on-disk portal directory, and the path can escape it.

This tool performs non-destructive vulnerability testing by:

  1. Reading the controller's reported version from /status and comparing it against the SAB-062 fix lines
  2. Confirming the guest portal is dispatched on the supplied URL
  3. Probing the page_error parameter on /guest/<site>/wechat/sign at ../ depths 1-8 against a dual-branch filename, to determine whether the traversal fires at all
  4. If the traversal fires, performing one additional read against a non-sensitive runtime catalog file (firmware.json) to determine whether the customized-portal filesystem branch is active

The tool requests only the runtime catalog file as a branch-active oracle. It does not read credentials, TLS material, database state, or backups, and does not write any file content to stdout or disk. Only the verdict is printed.

  • Vulnerable controllers with portal_customized: true on the queried site return the catalog file at the calibrated depth, confirming VULNERABLE.
  • Partially exposed controllers running a vulnerable build but with portal_customized: false on the queried site trigger the traversal at the calibration step but do not return disk content at the confirmation step → PARTIALLY EXPOSED. The application binary is still vulnerable; patching is required even though this site is not in the exploitable state.
  • Patched controllers (10.1.89+ / 10.2.97+ / 9.0.118+) reject the traversal at every depth → NOT VULNERABLE.
  • Unreachable sites or connectors yield NOT EXPOSED.

Installation

git clone https://github.com/BishopFox/CVE-2026-22557-check
cd CVE-2026-22557-check

Python 3.9+ is required. The tool uses only the Python standard library, so no pip install step is needed.

Usage

Test a UniFi Network Application controller at <TARGET>. Point the tool at whichever URL reaches the controller's web UI; the vulnerable handler is dispatched on the admin port (default 8443/TCP) as well as the dedicated guest-portal ports (8843, 8880).

python3 cve_2026_22557_check.py <BASE_URL> [--site NAME]

The default site slug is default. UniFi deployments with multiple sites configured should re-run the tool with --site <name> for each one. A controller is exploitable as soon as any one of its sites has portal_customized: true.

The examples below use --brief for a one-line-per-host result. Run without --brief to get the full banner, step-by-step progress, and a result block that includes recommended remediation actions.

Example: Vulnerable Controller

The controller is on a vulnerable build and the customized-portal precondition is active for the queried site, so the unauthenticated read path is reachable.

$ python3 cve_2026_22557_check.py https://192.168.1.100:8443 --brief
[VULNERABLE]        https://192.168.1.100:8443 site=default

Example: Partially Exposed Controller

The controller is on a vulnerable build, but the queried site does not have portal_customized: true enabled, so the disk-read precondition is not met for this site. The application binary still needs to be patched; another site on the same controller may still be in the exploitable state.

$ python3 cve_2026_22557_check.py https://192.168.1.100:8443 --brief
[PARTIAL]           https://192.168.1.100:8443 site=default

Example: Patched Controller

The controller is on a fixed build (10.1.89, 10.2.97, 9.0.118, or later), so the traversal does not fire on any queried depth.

$ python3 cve_2026_22557_check.py https://192.168.1.200:8443 --brief
[NOT VULNERABLE]    https://192.168.1.200:8443 site=default

Options

--site NAME       UniFi site slug to probe (default: "default")
--max-depth N     maximum ../ traversal depth to try (default: 8)
--no-tls-recon    skip TLS certificate subject/SAN display
--no-color        disable ANSI color output (also honored: NO_COLOR env var)
--timeout N       per-request timeout in seconds (default: 20)
--brief           print a single-line result, no banner or steps

Exit codes: 0 VULNERABLE, 1 partially exposed / not vulnerable / not exposed, 2 transport error.

Preconditions

The tool can only return a VULNERABLE verdict if the following conditions are met:

  • The target is running a vulnerable UniFi Network Application build (10.1.85 or earlier on the 10.1.x branch, or the equivalent earlier point releases on 10.2.x / 9.0.x).
  • The guest portal is reachable at the supplied URL. The /guest/* handler is dispatched on the admin port (8443) as well as the dedicated guest-portal ports (8843, 8880); the tool only probes the URL it is given.
  • The queried site has portal_customized: true in its guest_access setting, which is the precondition for the disk-read code path. A controller with multiple sites is exploitable if any of its sites has this enabled.

If any condition is not met, the tool falls through to a more conservative verdict. A PARTIALLY EXPOSED result still means the application is vulnerable and must be patched; the queried site simply happens not to expose the disk-read path.

Remediation

  1. Upgrade to UniFi Network Application 10.1.89, 10.2.97, 9.0.118, or later.
  2. If you cannot patch immediately, restrict network access to ports 8443 / 8843 / 8880 (and any reverse proxy fronting them) so they are reachable only from trusted management networks.
  3. After patching, rotate any credentials that may have been disclosed while the controller was reachable: administrator passwords, the SSH credential the controller pushes to managed devices, the controller's TLS keystore, RADIUS shared secrets, VPN / WireGuard keys, SSL-inspection CA material, SMTP relay passwords, and any payment-gateway keys.

Detection in your logs

The vulnerable request pattern is:

GET /guest/s/<site>/wechat/sign?page_error=<value>

Legitimate clients reach /guest/s/<site>/wechat/sign only via POST (which the dispatcher accepts without raising the failure-page renderer). Any GET of this endpoint carrying a page_error= query parameter, particularly one containing ../, %2e%2e, or a leading /, is anomalous and should be treated as an exploitation attempt. Tomcat's standard access log captures the full request line including the query string.

License

This code is distributed under an MIT license.

Legal Disclaimer

Usage of this tool for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state, and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program.

See Also

About

Safely detect whether a UniFi Network Application controller is vulnerable to CVE-2026-22557

Resources

License

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages