VYPR
Moderate severityNVD Advisory· Published Oct 3, 2024· Updated Oct 8, 2024

Reflected XSS Vulnerability in Sulu Media Bundle

CVE-2024-47617

Description

Sulu is a PHP content management system. This vulnerability allows an attacker to inject arbitrary HTML/JavaScript code through the media download URL in Sulu CMS. It affects the SuluMediaBundle component. The vulnerability is a Reflected Cross-Site Scripting (XSS) issue, which could potentially allow attackers to steal sensitive information, manipulate the website's content, or perform actions on behalf of the victim. This vulnerability is fixed in 2.6.5 and 2.5.21.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
sulu/suluPackagist
>= 2.6.0, < 2.6.52.6.5
sulu/suluPackagist
>= 2.0.0, < 2.5.212.5.21

Affected products

1

Patches

2
eeacd14b6cf5

Merge commit from fork

https://github.com/sulu/suluJohannes WachterOct 2, 2024via ghsa
1 file changed · +1 1
  • src/Sulu/Bundle/MediaBundle/Controller/MediaStreamController.php+1 1 modified
    @@ -103,7 +103,7 @@ public function downloadAction(Request $request, $id, $slug)
                 }
     
                 if ($fileVersion->getName() !== $slug) {
    -                return new Response('Invalid file name "' . $slug . '" for media with ID "' . $id . '".', 404);
    +                return new Response('Invalid file name for media with ID "' . $id . '".', 404);
                 }
     
                 if ($this->securityChecker) {
    
a5a5ae555d28

Add forcing direct matching for media download urls (#7535)

https://github.com/sulu/suluAlexander SchranzJul 22, 2024via ghsa
3 files changed · +34 19
  • src/Sulu/Bundle/MediaBundle/Controller/MediaStreamController.php+7 2 modified
    @@ -81,10 +81,11 @@ public function getImageAction(Request $request)
     
         /**
          * @param int $id
    +     * @param string $slug
          *
          * @return Response
          */
    -    public function downloadAction(Request $request, $id)
    +    public function downloadAction(Request $request, $id, $slug)
         {
             try {
                 if (\ob_get_length()) {
    @@ -98,7 +99,11 @@ public function downloadAction(Request $request, $id)
                 $fileVersion = $this->getFileVersion($id, $version);
     
                 if (!$fileVersion) {
    -                return new Response(null, 404);
    +                return new Response('Invalid version "' . $version . '" for media with ID "' . $id . '".', 404);
    +            }
    +
    +            if ($fileVersion->getName() !== $slug) {
    +                return new Response('Invalid file name "' . $slug . '" for media with ID "' . $id . '".', 404);
                 }
     
                 if ($this->securityChecker) {
    
  • src/Sulu/Bundle/MediaBundle/Tests/Functional/Controller/MediaControllerTest.php+6 6 modified
    @@ -381,7 +381,7 @@ protected function setUpCollection(): void
          */
         public function test404ResponseHeader(): void
         {
    -        $this->client->jsonRequest(
    +        $this->client->request(
                 'GET',
                 '/uploads/media/50x50/1/0-photo.jpg'
             );
    @@ -399,9 +399,9 @@ public function testDownloadHeaderAttachment(): void
             $media = $this->createMedia('photo');
     
             \ob_start();
    -        $this->client->jsonRequest(
    +        $this->client->request(
                 'GET',
    -            '/media/' . $media->getId() . '/download/photo.jpg'
    +            '/media/' . $media->getId() . '/download/photo.jpeg'
             );
             \ob_end_clean();
             $this->assertEquals(
    @@ -418,9 +418,9 @@ public function testDownloadHeaderInline(): void
             $media = $this->createMedia('photo');
     
             \ob_start();
    -        $this->client->jsonRequest(
    +        $this->client->request(
                 'GET',
    -            '/media/' . $media->getId() . '/download/photo.jpg?inline=1'
    +            '/media/' . $media->getId() . '/download/photo.jpeg?inline=1'
             );
             \ob_end_clean();
             $this->assertEquals(
    @@ -437,7 +437,7 @@ public function testDownloadHeaderUmlauts(): void
             $media = $this->createMedia('wöchentlich');
     
             \ob_start();
    -        $this->client->jsonRequest(
    +        $this->client->request(
                 'GET',
                 '/media/' . $media->getId() . '/download/wöchentlich.jpeg?inline=1'
             );
    
  • src/Sulu/Bundle/MediaBundle/Tests/Functional/Controller/MediaStreamControllerTest.php+21 11 modified
    @@ -43,17 +43,27 @@ public function testDownloadAction(): void
             $filePath = $this->createMediaFile('test.jpg');
             $media = $this->createMedia($filePath, 'file-without-extension');
     
    -        $this->client->jsonRequest('GET', $media->getUrl());
    +        $this->client->request('GET', $media->getUrl());
             $response = $this->client->getResponse();
             $this->assertHttpStatusCode(200, $response);
         }
     
    +    public function testDownloadActionNotMatchingFileName(): void
    +    {
    +        $filePath = $this->createMediaFile('test.jpg');
    +        $media = $this->createMedia($filePath, 'test.jpg');
    +
    +        $this->client->request('GET', \str_replace('test.jpg', 'other.jpg', $media->getUrl()));
    +        $response = $this->client->getResponse();
    +        $this->assertHttpStatusCode(404, $response);
    +    }
    +
         public function testNotExistVersionDownloadAction(): void
         {
             $filePath = $this->createMediaFile('test.jpg');
             $media = $this->createMedia($filePath, 'file-without-extension');
     
    -        $this->client->jsonRequest('GET', \str_replace('v=1', 'v=99', $media->getUrl()));
    +        $this->client->request('GET', \str_replace('v=1', 'v=99', $media->getUrl()));
             $response = $this->client->getResponse();
             $this->assertHttpStatusCode(404, $response);
         }
    @@ -92,7 +102,7 @@ public function testDownloadWithoutExtensionAction(): void
             $filePath = $this->createMediaFile('file-without-extension');
             $media = $this->createMedia($filePath, 'File without Extension');
     
    -        $this->client->jsonRequest('GET', $media->getUrl());
    +        $this->client->request('GET', $media->getUrl());
             $response = $this->client->getResponse();
             $this->assertHttpStatusCode(200, $response);
         }
    @@ -102,7 +112,7 @@ public function testDownloadWithDotInName(): void
             $filePath = $this->createMediaFile('fitness-seasons.agency--C-&-C--Rodach,-Johannes');
             $media = $this->createMedia($filePath, 'fitness-seasons.agency--C-&-C--Rodach,-Johannes');
     
    -        $this->client->jsonRequest('GET', $media->getUrl());
    +        $this->client->request('GET', $media->getUrl());
             $response = $this->client->getResponse();
             $this->assertHttpStatusCode(200, $response);
     
    @@ -118,7 +128,7 @@ public function testDownloadWithDotInName(): void
     
         public function testGetImageActionForNonExistingMedia(): void
         {
    -        $this->client->jsonRequest('GET', '/uploads/media/sulu-400x400/01/test.jpg?v=1');
    +        $this->client->request('GET', '/uploads/media/sulu-400x400/01/test.jpg?v=1');
     
             $this->assertHttpStatusCode(404, $this->client->getResponse());
         }
    @@ -128,11 +138,11 @@ public function testGetImageAction(): void
             $filePath = $this->createMediaFile('test.jpg');
             $media = $this->createMedia($filePath, 'Test jpg');
     
    -        $this->client->jsonRequest('GET', $media->getFormats()['small-inset']);
    +        $this->client->request('GET', $media->getFormats()['small-inset']);
             $this->assertHttpStatusCode(200, $this->client->getResponse());
             $this->assertSame('image/jpeg', $this->client->getResponse()->headers->get('Content-Type'));
     
    -        $this->client->jsonRequest('GET', $media->getFormats()['small-inset.gif']);
    +        $this->client->request('GET', $media->getFormats()['small-inset.gif']);
             $this->assertHttpStatusCode(200, $this->client->getResponse());
             $this->assertSame('image/gif', $this->client->getResponse()->headers->get('Content-Type'));
         }
    @@ -142,11 +152,11 @@ public function testGetImageActionSvg(): void
             $filePath = $this->createMediaFile('test.svg', 'sulu.svg');
             $media = $this->createMedia($filePath, 'Test svg');
     
    -        $this->client->jsonRequest('GET', $media->getFormats()['small-inset']);
    +        $this->client->request('GET', $media->getFormats()['small-inset']);
             $this->assertHttpStatusCode(200, $this->client->getResponse());
             $this->assertSame('image/svg+xml', $this->client->getResponse()->headers->get('Content-Type'));
     
    -        $this->client->jsonRequest('GET', $media->getFormats()['small-inset.svg']);
    +        $this->client->request('GET', $media->getFormats()['small-inset.svg']);
             $this->assertHttpStatusCode(200, $this->client->getResponse());
             $this->assertSame('image/svg+xml', $this->client->getResponse()->headers->get('Content-Type'));
         }
    @@ -162,14 +172,14 @@ public function testGetImageActionSvgAsJpg(): void
             $filePath = $this->createMediaFile('test.svg', 'sulu.svg');
             $media = $this->createMedia($filePath, 'Test svg');
     
    -        $this->client->jsonRequest('GET', $media->getFormats()['small-inset.jpg']);
    +        $this->client->request('GET', $media->getFormats()['small-inset.jpg']);
             $this->assertHttpStatusCode(200, $this->client->getResponse());
             $this->assertSame('image/jpeg', $this->client->getResponse()->headers->get('Content-Type'));
         }
     
         public function testDownloadActionForNonExistingMedia(): void
         {
    -        $this->client->jsonRequest('GET', '/media/999/download/test.jpg?v=1');
    +        $this->client->request('GET', '/media/999/download/test.jpg?v=1');
     
             $this->assertHttpStatusCode(404, $this->client->getResponse());
         }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.