CVE-2023-51651 (published 2023-12-22T21:15Z)

AWS SDK for PHP is the Amazon Web Services software development kit for PHP. Within the scope of requests to S3 object keys and/or prefixes containing a Unix double-dot, a URI path traversal is possible. The issue exists in the `buildEndpoint` method in the RestSerializer component of the AWS SDK for PHP v3 prior to 3.288.1. The `buildEndpoint` method relies on the Guzzle Psr7 UriResolver utility, which strips dot segments from the request path in accordance with RFC 3986. Under certain conditions, this could lead to an arbitrary object being accessed. This issue has been patched in version 3.288.1.

CVSS v3 base score: 3.3, LOW (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/aws/aws-sdk-php
commit_details: repo_url: https://github.com/aws/aws-sdk-php
author: Sean O'Brien
author_date: 2023-11-22 14:30:39-05:00
msg: bugfix: dot segment handling (#2835)
repository: repo_url: https://github.com/aws/aws-sdk-php
repo_name: aws/aws-sdk-php
description: Official repository of the AWS SDK for PHP (@awsforphp)
repo_language: PHP
owner: aws
file_changes: filename: s3-dot-segment.json
change_type: ModificationType.ADD
diff: @@ -0,0 +1,7 @@
+[
+  {
+    "type": "bugfix",
+    "category": "s3",
+    "description": "Disables transformation of request URI paths with dot segments"
+  }
+]

programming_language: CoffeeScript
filename: RestSerializer.php
change_type: ModificationType.MODIFY
diff: @@ -242,14 +242,21 @@ abstract class RestSerializer
                 $path = rtrim($path, '/');
             }
             $relative = $path . $relative;
+
+            if (strpos($relative, '../') !== false) {
+                if ($relative[0] !== '/') {
+                    $relative = '/' . $relative;
+                }
+                return new Uri($this->endpoint . $relative);
+            }
         }
         // If endpoint has path, remove leading '/' to preserve URI resolution.
         if ($path && $relative[0] === '/') {
             $relative = substr($relative, 1);
         }
 
-        //Append path to endpoint when leading '//...' present
-        // as uri cannot be properly resolved
+        //Append path to endpoint when leading '//...'
+        // present as uri cannot be properly resolved
         if ($this->api->isModifiedModel()
             && strpos($relative, '//') === 0
         ) {

programming_language: PHP
filename: S3ClientTest.php
change_type: ModificationType.MODIFY
diff: @@ -2321,4 +2321,57 @@ EOXML;
         );
         $s3->execute($command);
     }
+
+    /**
+     * @dataProvider dotSegmentProvider
+     */
+    public function testHandlesDotSegmentsInKey($key, $expectedUri)
+    {
+        $s3 = $this->getTestClient('s3');
+        $this->addMockResults($s3, [[]]);
+        $command = $s3->getCommand('getObject', ['Bucket' => 'foo', 'Key' => $key]);
+        $command->getHandlerList()->appendSign(
+            Middleware::tap(function ($cmd, $req) use ($expectedUri) {
+                $this->assertSame($expectedUri, (string) $req->getUri());
+            })
+        );
+        $s3->execute($command);
+    }
+
+    public function dotSegmentProvider()
+    {
+        return [
+            ['../foo' , 'https://foo.s3.amazonaws.com/../foo'],
+            ['bar/../../foo', 'https://foo.s3.amazonaws.com/bar/../../foo'],
+            ['/../foo', 'https://foo.s3.amazonaws.com//../foo'],
+            ['foo/bar/../baz', 'https://foo.s3.amazonaws.com/foo/bar/../baz']
+        ];
+    }
+
+    /**
+     * @dataProvider dotSegmentPathStyleProvider
+     */
+    public function testHandlesDotSegmentsInKeyWithPathStyle($key, $expectedUri)
+    {
+        $s3 = $this->getTestClient('s3', ['use_path_style_endpoint' => true]);
+        $this->addMockResults($s3, [[]]);
+        $command = $s3->getCommand('getObject', ['Bucket' => 'foo', 'Key' => $key]);
+        $command->getHandlerList()->appendSign(
+            Middleware::tap(function ($cmd, $req) use ($expectedUri) {
+                $this->assertSame($expectedUri, (string) $req->getUri());
+            })
+        );
+        $s3->execute($command);
+    }
+
+    public function dotSegmentPathStyleProvider()
+    {
+        return [
+            ['../foo' , 'https://s3.amazonaws.com/foo/foo/../foo'],
+            ['bar/../../foo', 'https://s3.amazonaws.com/foo/foo/bar/../../foo'],
+            ['/../foo', 'https://s3.amazonaws.com/foo/foo//../foo'],
+            ['foo/bar/../baz', 'https://s3.amazonaws.com/foo/foo/foo/bar/../baz'],
+        ];
+    }
+
 }

programming_language: PHP