Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit 86f8035

Browse files
committed
Merge branch 'hotfix/d8-2426489'
Fixes ZF2015-05.
2 parents 11d695b + d977244 commit 86f8035

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

CHANGELOG.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,27 @@
22

33
All notable changes to this project will be documented in this file, in reverse chronological order by release.
44

5-
## 1.0.4 - TBD
5+
## 1.0.4 - 2015-06-23
6+
7+
This is a security release.
8+
9+
A patch has been applied to `Zend\Diactoros\Uri::filterPath()` that ensures that
10+
paths can only begin with a single leading slash. This prevents the following
11+
potential security issues:
12+
13+
- XSS vectors. If the URI path is used for links or form targets, this prevents
14+
cases where the first segment of the path resembles a domain name, thus
15+
creating scheme-relative links such as `//example.com/foo`. With the patch,
16+
the leading double slash is reduced to a single slash, preventing the XSS
17+
vector.
18+
- Open redirects. If the URI path is used for `Location` or `Link` headers,
19+
without a scheme and authority, potential for open redirects exist if clients
20+
do not prepend the scheme and authority. Again, preventing a double slash
21+
corrects the vector.
22+
23+
If you are using `Zend\Diactoros\Uri` for creating links, form targets, or
24+
redirect paths, and only using the path segment, we recommend upgrading
25+
immediately.
626

727
### Added
828

@@ -39,6 +59,9 @@ All notable changes to this project will be documented in this file, in reverse
3959
- The request MUST return a `UriInterface` instance from `getUri()`; that
4060
instance CAN be empty. Previously, Diactoros would return `null`; now it
4161
lazy-instantiates an empty `Uri` instance on initialization.
62+
- [ZF2015-05](http://framework.zend.com/security/advisory/ZF2015-05) was
63+
addressed by altering `Uri::filterPath()` to prevent emitting a path prepended
64+
with multiple slashes.
4265

4366
## 1.0.3 - 2015-06-04
4467

src/Uri.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,11 +511,24 @@ private function filterScheme($scheme)
511511
*/
512512
private function filterPath($path)
513513
{
514-
return preg_replace_callback(
514+
$path = preg_replace_callback(
515515
'/(?:[^' . self::CHAR_UNRESERVED . ':@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/',
516516
[$this, 'urlEncodeChar'],
517517
$path
518518
);
519+
520+
if (empty($path)) {
521+
// No path
522+
return $path;
523+
}
524+
525+
if ($path[0] !== '/') {
526+
// Relative path
527+
return $path;
528+
}
529+
530+
// Ensure only one leading slash, to prevent XSS attempts.
531+
return '/' . ltrim($path, '/');
519532
}
520533

521534
/**

test/UriTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,4 +448,11 @@ public function testFragmentIsNotDoubleEncoded()
448448
$uri = (new Uri())->withFragment($expected);
449449
$this->assertEquals($expected, $uri->getFragment());
450450
}
451+
452+
public function testProperlyTrimsLeadingSlashesToPreventXSS()
453+
{
454+
$url = 'http://example.org//zend.com';
455+
$uri = new Uri($url);
456+
$this->assertEquals('http://example.org/zend.com', (string) $uri);
457+
}
451458
}

0 commit comments

Comments
 (0)