WordPress Plugin Vulnerabilities

All-in-One Video Gallery < 4.9.2 - Subscriber+ Server-Side Request Forgery via 'vdl' Parameter

Description

All-in-One Video Gallery registers a public, unauthenticated file-download handler triggered by `?vdl=<post_id>` on any `aiovg_videos` post (`public/video.php`, `AIOVG_Public_Video::download_video()`), which reads the post's `mp4` meta value and streams that URL's response back to the requester.

Version 4.9.0 was released specifically to fix CVE-2026-12123 (SSRF via this same `vdl` parameter) by adding a new guard function, `aiovg_resolve_safe_url()`, which validates the target host — and every redirect hop — against `aiovg_is_safe_remote_url()`, a private/reserved-IP-range check. This report identifies TWO independent, live-confirmed ways to bypass that brand-new guard, both still present in 4.9.0.

**Bypass A — same-host allowlist ignores port.** `aiovg_resolve_safe_url()` skips the IP-range check entirely if `aiovg_is_same_host_url( $url )` returns true. That function (`includes/helpers/functions.php`) compares only `wp_parse_url( $url, PHP_URL_HOST )` against the site's own `home_url()`/`site_url()` host — it never compares the port. A URL using the site's own hostname on a different port (e.g. `http://<site-host>:<internal-port>/`) is therefore treated as fully trusted and reaches `get_headers()`/`fopen()` with no validation at all, even though it targets a completely different, potentially loopback-only service (a database admin panel, an internal API, a monitoring dashboard, or any other application colocated on the same host).

**Bypass B — DNS rebinding (validate-then-fetch-separately, no IP pinning).** The same `aiovg_resolve_safe_url()` function resolves a hostname via `gethostbynamel()`/`dns_get_record()` to validate it, then immediately calls `get_headers()` on the SAME URL string — a second, separate DNS resolution. The caller (`download_video()`) performs several more separate resolutions of the same hostname afterward (`get_headers()` twice more, `fopen()`). Nothing pins the connection to the specific IP address that was actually validated. An attacker who controls the target domain's DNS answers (a TTL=0 record that returns a safe public IP on the first query and a private/loopback IP on every subsequent query — the standard DNS-rebinding technique) passes validation on query #1 and is fetched from an internal address on every query after that. This bypass does NOT require the attacker's hostname to match the site's own host in any way, so it applies to any deployment regardless of domain.

Both bypasses were independently confirmed via full live reproduction (see PoC), each proven not to depend on the other (Bypass B's test hostname bears no relationship to the site's own host, ruling out any overlap with Bypass A's mechanism). A vendor fix addressing only one of the two leaves the plugin fully exploitable via the other — both need fixing together, e.g. by comparing the full host+port authority in `aiovg_is_same_host_url()`, AND by resolving a hostname to an IP once, validating that IP, then connecting to that specific pinned IP for every subsequent request rather than re-resolving by hostname string at each step.

Impact: full HTTP response-body disclosure of whatever service answers at the attacker-chosen internal target — not a blind/timing oracle, the actual content is streamed back verbatim in the download response. Repeated requests across ports also function as a reliable internal port scanner (distinguishable "not found" / "invalid file format" / actual content responses). On cloud-hosted deployments, Bypass B in particular could be aimed at the instance metadata service (169.254.169.254) to attempt credential exfiltration, since it does not require any relationship to the site's own hostname.

Precondition: a Subscriber-level (or above) account is required to plant the malicious URL in a video's `mp4` post meta — identical precondition to CVE-2026-12123 itself, since this plugin grants `edit_aiovg_videos` to the `subscriber` role by design (`includes/roles.php`). The `?vdl=` trigger endpoint itself requires no authentication at all.

Severity assessed as High (CVSS 3.1: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N, approx. 7.1) — PR:L for the Subscriber-level precondition (matching CVE-2026-12123's own basis), AC:L since both bypasses are fully deterministic (no timing race, no brute-force beyond an ordinary port number), C:H since the full response body of the targeted internal service is disclosed verbatim.

Suggested fix: in `aiovg_is_same_host_url()`, compare the full authority (host AND port, defaulting port from scheme when absent), not hostname alone. Separately, in `aiovg_resolve_safe_url()`, resolve the hostname to an IP once, validate that IP, then connect to that specific pinned IP for the actual request rather than re-resolving the hostname independently at each subsequent step — this closes the DNS-rebinding TOCTOU window regardless of how quickly an attacker's DNS answer changes.

Proof of Concept

Affects Plugins

References

Classification

Type
SSRF
OWASP top 10
CWE

Miscellaneous

Original Researcher
Mohammed Abd Alrahman
Submitter
Mohammed Abd Alrahman
Submitter website
Verified
Yes

Timeline

Publicly Published
2026-08-07 (about 3 days ago)
Added
2026-08-07 (about 2 days ago)
Last Updated
2026-08-07 (about 2 days ago)

Other