Skip to content

Commit d11c832

Browse files
authored
Merge pull request #54 from weierophinney/hotfix/uri-xss-double-slash-test
Modify multiple slash in URI path detection
2 parents f33b664 + 98fda81 commit d11c832

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
11
# Change Log
2+
3+
## Added
4+
5+
- Adds `UriIntegrationTest::testGetPathNormalizesMultipleLeadingSlashesToSingleSlashToPreventXSS()`, `UriIntegrationTest::testStringRepresentationWithMultipleSlashes(array $test)`, and `RequestIntegrationTest::testGetRequestTargetInOriginFormNormalizesUriWithMultipleLeadingSlashesInPath()`.
6+
These validate that a path containing multiple leading slashes is (a) represented with a single slash when calling `UriInterface::getPath()`, and (b) represented without changes when calling `UriInterface::__toString()`, including when calling `RequestInterface::getRequestTarget()` (which returns the path without the URI authority by default, to comply with origin-form).
7+
This is done to validate mitigations for [CVE-2015-3257](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3257).
8+
9+
## Changed
10+
11+
- Modifies `UriIntegrationTest::testPathWithMultipleSlashes()` to only validate multiple slashes in the middle of a path.
12+
Multiple leading slashes are covered with the newly introduced tests.

src/RequestIntegrationTest.php

+21
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,25 @@ public function testUriPreserveHost_Host_Host()
169169
$request2 = $request->withUri($this->buildUri('http://www.bar.com/foo'), true);
170170
$this->assertEquals($host, $request2->getHeaderLine('host'));
171171
}
172+
173+
/**
174+
* Tests that getRequestTarget(), when using the default behavior of
175+
* displaying the origin-form, normalizes multiple leading slashes in the
176+
* path to a single slash. This is done to prevent URL poisoning and/or XSS
177+
* issues.
178+
*
179+
* @see UriIntegrationTest::testGetPathNormalizesMultipleLeadingSlashesToSingleSlashToPreventXSS
180+
*/
181+
public function testGetRequestTargetInOriginFormNormalizesUriWithMultipleLeadingSlashesInPath()
182+
{
183+
if (isset($this->skippedTests[__FUNCTION__])) {
184+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
185+
}
186+
187+
$url = 'http://example.org//valid///path';
188+
$request = $this->request->withUri($this->buildUri($url));
189+
$requestTarget = $request->getRequestTarget();
190+
191+
$this->assertSame('/valid///path', $requestTarget);
192+
}
172193
}

src/UriIntegrationTest.php

+41-2
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,50 @@ public function testPathWithMultipleSlashes()
233233
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
234234
}
235235

236-
$expected = 'http://example.org//valid///path';
236+
$expected = 'http://example.org/valid///path';
237237
$uri = $this->createUri($expected);
238238

239239
$this->assertInstanceOf(UriInterface::class, $uri);
240+
$this->assertSame('/valid///path', $uri->getPath());
240241
$this->assertSame($expected, (string) $uri);
241-
$this->assertSame('//valid///path', $uri->getPath());
242+
}
243+
244+
/**
245+
* Tests that getPath() normalizes multiple leading slashes to a single
246+
* slash. This is done to ensure that when a path is used in isolation from
247+
* the authority, it will not cause URL poisoning and/or XSS issues.
248+
*
249+
* @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3257
250+
* @psalm-param array{expected: non-empty-string, uri: UriInterface} $test
251+
*/
252+
public function testGetPathNormalizesMultipleLeadingSlashesToSingleSlashToPreventXSS()
253+
{
254+
if (isset($this->skippedTests[__FUNCTION__])) {
255+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
256+
}
257+
258+
$expected = 'http://example.org//valid///path';
259+
$uri = $this->createUri($expected);
260+
261+
$this->assertInstanceOf(UriInterface::class, $uri);
262+
$this->assertSame('/valid///path', $uri->getPath());
263+
264+
return [
265+
'expected' => $expected,
266+
'uri' => $uri,
267+
];
268+
}
269+
270+
/**
271+
* Tests that the full string representation of a URI that includes multiple
272+
* leading slashes in the path is presented verbatim (in contrast to what is
273+
* provided when calling getPath()).
274+
*
275+
* @depends testGetPathNormalizesMultipleLeadingSlashesToSingleSlashToPreventXSS
276+
* @psalm-param array{expected: non-empty-string, uri: UriInterface} $test
277+
*/
278+
public function testStringRepresentationWithMultipleSlashes(array $test)
279+
{
280+
$this->assertSame($test['expected'], (string) $test['uri']);
242281
}
243282
}

0 commit comments

Comments
 (0)