Skip to content

Commit

Permalink
bug #50552 [Security] Allow custom scheme to be used as redirection U…
Browse files Browse the repository at this point in the history
…RIs (Spomky)

This PR was merged into the 5.4 branch.

Discussion
----------

[Security] Allow custom scheme to be used as redirection URIs

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Fix #50500
| License       | MIT
| Doc PR        | not needed

ping `@sdespont` and `@MatTheCat`

This PR aims at fixing the redirection issue where only URLs starting with `http` are allowed.
With the modified behavior, it is now allowed to use any URL scheme. It will be possible to redirect to `android-app://com.google.android.gm/`.

~In addition, it prevents the redirection to the following URLs:~

* ~With path traversal e.g. `https://example.com/foo/../../.htpasswd`~
* ~With protocol-relative e.g. `//malicious.app/foo/bar`~

Commits
-------

3a6969f [Security] Allow custom scheme to be used as redirection URIs
  • Loading branch information
nicolas-grekas committed Jul 13, 2023
2 parents bae6cd8 + 3a6969f commit 6eff7f0
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/Symfony/Component/Security/Http/HttpUtils.php
Expand Up @@ -148,7 +148,9 @@ public function checkRequestPath(Request $request, string $path)
*/
public function generateUri(Request $request, string $path)
{
if (str_starts_with($path, 'http') || !$path) {
$url = parse_url($path);

if ('' === $path || isset($url['scheme'], $url['host'])) {
return $path;
}

Expand Down
49 changes: 49 additions & 0 deletions src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php
Expand Up @@ -58,6 +58,54 @@ public function testCreateRedirectResponseWithRequestsDomain()
$this->assertTrue($response->isRedirect('http://localhost/blog'));
}

/**
* @dataProvider validRequestDomainUrls
*/
public function testCreateRedirectResponse(?string $domainRegexp, string $path, string $expectedRedirectUri)
{
$utils = new HttpUtils($this->getUrlGenerator(), null, $domainRegexp);
$response = $utils->createRedirectResponse($this->getRequest(), $path);

$this->assertTrue($response->isRedirect($expectedRedirectUri));
$this->assertEquals(302, $response->getStatusCode());
}

public static function validRequestDomainUrls()
{
return [
'/foobar' => [
null,
'/foobar',
'http://localhost/foobar',
],
'http://symfony.com/ without domain regex' => [
null,
'http://symfony.com/',
'http://symfony.com/',
],
'http://localhost/blog with #^https?://symfony\.com$#i' => [
'#^https?://symfony\.com$#i',
'http://symfony.com/blog',
'http://symfony.com/blog',
],
'http://localhost/blog with #^https?://%s$#i' => [
'#^https?://%s$#i',
'http://localhost/blog',
'http://localhost/blog',
],
'custom scheme' => [
null,
'android-app://com.google.android.gm/',
'android-app://com.google.android.gm/',
],
'custom scheme with all URL components' => [
null,
'android-app://foo:bar@www.example.com:8080/software/index.html?lite=true#section1',
'android-app://foo:bar@www.example.com:8080/software/index.html?lite=true#section1',
],
];
}

/**
* @dataProvider badRequestDomainUrls
*/
Expand All @@ -77,6 +125,7 @@ public static function badRequestDomainUrls()
['http:/\\pirate.net/foo'],
['http:\\/pirate.net/foo'],
['http://////pirate.net/foo'],
['http:///foo'],
];
}

Expand Down

0 comments on commit 6eff7f0

Please sign in to comment.