CVE-2023-51651 (PHP, published 2023-12-22T21:15Z)
Description: value: 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.
Severity: nan (CVSS v3 base score: 3.3)
Weakness: CWE-22 \u2014 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
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.
Repository: https://github.com/aws/aws-sdk-php
Files changed:
.changes/nextrelease/s3-dot-segment.json
src/Api/Serializer/RestSerializer.php
tests/S3/S3ClientTest.php
Commit message: bugfix: dot segment handling (#2835)



Vulnerable code:
        //Append path to endpoint when leading '//...' present
        // as uri cannot be properly resolved

Fixed code:
[
  {
    "type": "bugfix",
    "category": "s3",
    "description": "Disables transformation of request URI paths with dot segments"
  }
]

            if (strpos($relative, '../') !== false) {
                if ($relative[0] !== '/') {
                    $relative = '/' . $relative;
                }
                return new Uri($this->endpoint . $relative);
            }
        //Append path to endpoint when leading '//...'
        // present as uri cannot be properly resolved

    /**
     * @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'],
        ];
    }