Średnia

Shopware: SSRF in Media External-Link Endpoint Bypasses IP Validation

  • Ujawniono: 04.06.2026
  • Aktualizacja: 11.10.2026 10:22

Summary

The /api/_action/media/external-link endpoint allows authenticated admin users to make server-side HTTP HEAD requests to arbitrary internal IP addresses. While the parallel uploadFromURL flow validates target IPs against private/reserved ranges via FileUrlValidator, the linkURL flow only performs a URL format check (regex for http:// or https:// prefix), allowing SSRF to internal network services and cloud metadata endpoints.

Details

The vulnerability is an inconsistency between two URL-handling flows in MediaUploadService.

Vulnerable path (external-link):

MediaUploadV2Controller::externalLink() at src/Core/Content/Media/Api/MediaUploadV2Controller.php:66 takes a user-supplied url parameter and passes it to MediaUploadService::linkURL() at src/Core/Content/Media/Upload/MediaUploadService.php:134.

linkURL() calls getContentSizeFromValidExternalUrl($url) at line 159, which only validates via validateExternalUrl():

php
// src/Core/Content/Media/Upload/MediaUploadService.php:207-212
public static function validateExternalUrl(string $url): void
{
    if (!preg_match('/^https?:\/\/.+/', $url)) {
        throw MediaException::invalidUrl($url);
    }
}

Then makes a server-side HEAD request with no IP filtering:

php
// src/Core/Content/Media/Upload/MediaUploadService.php:292-300
private function getContentSizeFromValidExternalUrl(string $url): int
{
    $this->validateExternalUrl($url);

    $headers = $this->httpClient->request('HEAD', $url)->getHeaders();
    if (!\array_key_exists('content-length', $headers)) {
        throw MediaException::fileNotFound($url);
    }

    return (int) $headers['content-length'][0];
}

Protected path (upload_by_url):

In contrast, uploadFromURL uses FileFetcher::fetchFromURL() which calls FileUrlValidator::isValid():

php
// src/Core/Content/Media/File/FileFetcher.php:64
if ($this->enableUrlValidation && !$this->fileUrlValidator->isValid($url)) {
    throw MediaException::illegalUrl($url);
}

FileUrlValidator::isValid() resolves the hostname via gethostbyname() and validates the IP against private and reserved ranges using filter_var() with FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE. This protection is entirely absent from the linkURL flow.

Impact

An authenticated admin user can:

  1. Probe cloud metadata services — HEAD requests to 169.254.169.254 reveal whether cloud metadata endpoints exist and leak content-length values
  2. Scan internal networks — Differentiate open/closed/filtered ports on internal hosts (10.x, 172.16.x, 192.168.x) based on response timing and error types
  3. Leak internal service information — The fileSize field stored in the database reflects the content-length header from internal services
  4. Redirect-based escalation — Symfony HttpClient follows redirects by default (max_redirects=20), allowing an attacker-controlled external server to redirect the HEAD request to arbitrary internal destinations

Impact is limited to information disclosure via HEAD requests. The admin authentication requirement (PR:H) reduces exploitability, but in multi-tenant or compromised-credential scenarios this allows network reconnaissance from the server's perspective.

Recommended Fix

Apply FileUrlValidator to the linkURL flow, consistent with the uploadFromURL flow. In MediaUploadService:

php
// src/Core/Content/Media/Upload/MediaUploadService.php

// Add constructor dependency:
private readonly FileUrlValidatorInterface $fileUrlValidator;

// In getContentSizeFromValidExternalUrl(), add IP validation:
private function getContentSizeFromValidExternalUrl(string $url): int
{
    $this->validateExternalUrl($url);

    if (!$this->fileUrlValidator->isValid($url)) {
        throw MediaException::illegalUrl($url);
    }

    $headers = $this->httpClient->request('HEAD', $url)->getHeaders();
    if (!\array_key_exists('content-length', $headers)) {
        throw MediaException::fileNotFound($url);
    }

    return (int) $headers['content-length'][0];
}

Additionally, consider setting max_redirects: 0 on the HttpClient request to prevent redirect-based SSRF bypasses.

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka Composer shopware/core >= 6.7.0.0, < 6.7.10.1 6.7.10.1
Paczka Composer shopware/platform >= 6.7.0.0, < 6.7.10.1 6.7.10.1

Odnośniki

Ocena CVSS 4.1/10
Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:L/I:N/A:N
Słabość (CWE)
CWE-918
Platforma
Composer
Paczka
shopware/core, shopware/platform
Ujawniono
04.06.2026
Aktualizacja
11.10.2026 10:22

Źródła i licencje

OSV / GitHub Advisory Database - GHSA-gq96-5pfx-f4vc - CC BY 4.0

Historia podatności: shopware/core

Wszystkie opisane podatności tej paczki (Paczka Composer), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (65) w archiwum
Wszystkich wpisów
65
Pierwsza → ostatnia
09.2020 06.2026
Bez poprawki
0
Wykorzystywana w atakach
0

Rozkład istotności

  • Krytyczna 5
  • Wysoka 16
  • Średnia 31
  • Niska 13

Ujawnienia w latach

  1. 2020: 7
  2. 2021: 13
  3. 2022: 7
  4. 2023: 6
  5. 2024: 7
  6. 2025: 12
  7. 2026: 13
Istotność:
  1. Shopware: SSRF in Media External-Link Endpoint Bypasses IP Validation ten wpis
    Średnia · 4.1 CVE-2026-48013 >= 6.7.0.0, < 6.7.10.1 6.7.10.1
  2. Wysoka · 8.9 CVE-2026-31889 >= 6.7.0.0, < 6.7.8.1, < 6.6.10.15 6.7.8.1, 6.6.10.15
  3. Wysoka CVE-2026-31887 >= 6.7.0.0, < 6.7.8.1, < 6.6.10.15 6.7.8.1, 6.6.10.15
  4. Wysoka · 7.2 CVE-2026-23498 >= 6.7.0.0, < 6.7.6.1 6.7.6.1
  5. Wysoka · 8.8 ghsa-9v82-vcjx-m76j >= 6.7.0.0, < 6.7.2.1 6.7.2.1
  6. Wysoka · 7.3 CVE-2025-27892 >= 6.7.0.0-rc1, < 6.7.0.0-rc2, >= 6.6.0.0, < 6.6.10.3, < 6.5.8.18 6.7.0.0-rc2, 6.6.10.3, 6.5.8.18
  7. Wysoka · 7.5 CVE-2025-30151 >= 6.6.0.0, < 6.6.10.3, >= 6.7.0.0-rc1, < 6.7.0.0-rc2, < 6.5.8.17 6.6.10.3, 6.7.0.0-rc2, 6.5.8.17
  8. Wysoka · 8.3 CVE-2024-42356 < 6.5.8.13, >= 6.6.0.0, < 6.6.5.1 6.5.8.13, 6.6.5.1
  9. Wysoka · 8.3 CVE-2024-42355 < 6.5.8.13, >= 6.6.0.0, < 6.6.5.1 6.5.8.13, 6.6.5.1
  10. Krytyczna · 9.3 CVE-2024-22406 < 6.5.7.4 6.5.7.4
  11. Wysoka · 8.8 CVE-2023-2017 < 6.4.20.1 6.4.20.1
  12. Wysoka · 7.5 CVE-2020-13997 >= 6.0.0, < 6.2.3 6.2.3
  13. Wysoka · 8.1 CVE-2022-24872 < 6.4.10.1 6.4.10.1
  14. Wysoka · 7.2 CVE-2022-24871 < 6.4.10.1 6.4.10.1
  15. Krytyczna ghsa-r64m-qchj-hrjp < 6.4.6.1 6.4.6.1
  16. Wysoka · 8.8 CVE-2021-37708 < 6.4.3.1 6.4.3.1
  17. Wysoka · 8.0 CVE-2021-37710 < 6.4.3.1 6.4.3.1
  18. Wysoka · 8.8 CVE-2021-37711 < 6.4.3.1 6.4.3.1
  19. Wysoka · 7.5 CVE-2021-32717 < 6.4.1.1 6.4.1.1

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.