Skip to content

IPv6 ACL bypass in FastCGI listen.allowed_clients due to partial address comparison (memcmp 12 bytes)

Moderate
bukka published GHSA-62xp-839h-2637 Sep 24, 2026

Package

PHP-FPM (PHP)

Affected versions

<8.2.34
<8.3.35
<8.4.26
<8.5.11

Patched versions

8.2.34
8.3.35
8.4.26
8.5.11

Description

Summary

The IPv6 branch of the FastCGI client access check compares only the first 12 bytes of a 16-byte IPv6 address, so listen.allowed_clients matches on a /96 prefix instead of the exact address. An attacker who can source an address sharing the first 96 bits with an allowed one passes the check and reaches the FastCGI endpoint.

Details

fcgi_is_allowed() in main/fastcgi.c compares IPv6 client addresses with a hard-coded length of 12:

https://github.com/php/php-src/blob/php-8.5.10/main/fastcgi.c#L1334

An exact IPv6 comparison must cover all 16 bytes of struct in6_addr. The IPv4 branch above it compares its full 4 bytes correctly, and the IN6_IS_ADDR_V4MAPPED branch legitimately uses a 12-byte offset to reach the embedded IPv4 address, but that offset is not a valid length for a plain IPv6 comparison. Allowed addresses are parsed as full addresses with inet_pton(AF_INET6, ...), so the truncated comparison silently widens every configured entry to a /96 network.

The fix compares sizeof(client_sa.sa_inet6.sin6_addr) bytes.

PoC

Tested against a real php-fpm (fpm-fcgi), not a mock.

  1. Configure a pool:
listen = [::1]:19091
listen.allowed_clients = ::2
  1. Run php-fpm and send a FastCGI request from ::1 to [::1]:19091 for a test script.

  2. The request is accepted and the script executes, even though ::1 is not in listen.allowed_clients. Both addresses share the first 96 bits.

  3. Control test: set listen.allowed_clients = 2001:db8::2 and send the same request from ::1. The connection is denied as expected, because the first 96 bits differ.

Impact

This is an access control bypass in deployments that use FastCGI over IPv6 TCP and rely on listen.allowed_clients as a security boundary. An attacker with network reachability who can source an address within the same /96 as an allowed client bypasses the ACL and reaches the FastCGI endpoint, which in many deployments means executing PHP scripts in the FPM worker context.

Deployments using Unix sockets, IPv4 only, or an external firewall as the actual boundary are not affected.

Credit

This issue was originally reported in GHSA-r37j-mv37-rjpc. That advisory could not be used because the reporting account was deleted.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Adjacent
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

CVE ID

CVE-2026-91768

Weaknesses

No CWEs

Credits