Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 030396a

Browse files
committed
bug #32115 [SecurityBundle] don't validate IP addresses from env var placeholders (xabbuh)
This PR was merged into the 4.3 branch. Discussion ---------- [SecurityBundle] don't validate IP addresses from env var placeholders | Q | A | ------------- | --- | Branch? | 4.3 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #32108 | License | MIT | Doc PR | Commits ------- f23a7f6 don't validate IP addresses from env var placeholders
2 parents 0a1a885 + f23a7f6 commit 030396a

File tree

6 files changed

+54
-40
lines changed

6 files changed

+54
-40
lines changed

src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,6 @@ private function addAccessControlSection(ArrayNodeDefinition $rootNode)
143143
->integerNode('port')->defaultNull()->end()
144144
->arrayNode('ips')
145145
->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end()
146-
->beforeNormalization()->always()->then(function ($v) {
147-
foreach ($v as $ip) {
148-
if (false === $this->isValidIp($ip)) {
149-
throw new \LogicException(sprintf('The given "%s" value in the "access_control" config option is not a valid IP address.', $ip));
150-
}
151-
}
152-
153-
return $v;
154-
})->end()
155146
->prototype('scalar')->end()
156147
->end()
157148
->arrayNode('methods')
@@ -432,30 +423,4 @@ private function addEncodersSection(ArrayNodeDefinition $rootNode)
432423
->end()
433424
;
434425
}
435-
436-
private function isValidIp(string $cidr): bool
437-
{
438-
$cidrParts = explode('/', $cidr);
439-
440-
if (1 === \count($cidrParts)) {
441-
return false !== filter_var($cidrParts[0], FILTER_VALIDATE_IP);
442-
}
443-
444-
$ip = $cidrParts[0];
445-
$netmask = $cidrParts[1];
446-
447-
if (!ctype_digit($netmask)) {
448-
return false;
449-
}
450-
451-
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
452-
return $netmask <= 32;
453-
}
454-
455-
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
456-
return $netmask <= 128;
457-
}
458-
459-
return false;
460-
}
461426
}

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -731,20 +731,32 @@ private function createExpression($container, $expression)
731731
return $this->expressions[$id] = new Reference($id);
732732
}
733733

734-
private function createRequestMatcher($container, $path = null, $host = null, int $port = null, $methods = [], $ip = null, array $attributes = [])
734+
private function createRequestMatcher(ContainerBuilder $container, $path = null, $host = null, int $port = null, $methods = [], array $ips = null, array $attributes = [])
735735
{
736736
if ($methods) {
737737
$methods = array_map('strtoupper', (array) $methods);
738738
}
739739

740-
$id = '.security.request_matcher.'.ContainerBuilder::hash([$path, $host, $port, $methods, $ip, $attributes]);
740+
if (null !== $ips) {
741+
foreach ($ips as $ip) {
742+
$container->resolveEnvPlaceholders($ip, null, $usedEnvs);
743+
744+
if (!$usedEnvs && !$this->isValidIp($ip)) {
745+
throw new \LogicException(sprintf('The given value "%s" in the "security.access_control" config option is not a valid IP address.', $ip));
746+
}
747+
748+
$usedEnvs = null;
749+
}
750+
}
751+
752+
$id = '.security.request_matcher.'.ContainerBuilder::hash([$path, $host, $port, $methods, $ips, $attributes]);
741753

742754
if (isset($this->requestMatchers[$id])) {
743755
return $this->requestMatchers[$id];
744756
}
745757

746758
// only add arguments that are necessary
747-
$arguments = [$path, $host, $methods, $ip, $attributes, null, $port];
759+
$arguments = [$path, $host, $methods, $ips, $attributes, null, $port];
748760
while (\count($arguments) > 0 && !end($arguments)) {
749761
array_pop($arguments);
750762
}
@@ -788,4 +800,30 @@ public function getConfiguration(array $config, ContainerBuilder $container)
788800
// first assemble the factories
789801
return new MainConfiguration($this->factories, $this->userProviderFactories);
790802
}
803+
804+
private function isValidIp(string $cidr): bool
805+
{
806+
$cidrParts = explode('/', $cidr);
807+
808+
if (1 === \count($cidrParts)) {
809+
return false !== filter_var($cidrParts[0], FILTER_VALIDATE_IP);
810+
}
811+
812+
$ip = $cidrParts[0];
813+
$netmask = $cidrParts[1];
814+
815+
if (!ctype_digit($netmask)) {
816+
return false;
817+
}
818+
819+
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
820+
return $netmask <= 32;
821+
}
822+
823+
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
824+
return $netmask <= 128;
825+
}
826+
827+
return false;
828+
}
791829
}

src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ secured-by-one-real-ip-with-mask:
4040
secured-by-one-real-ipv6:
4141
path: /secured-by-one-real-ipv6
4242

43+
secured-by-one-env-placeholder:
44+
path: /secured-by-one-env-placeholder
45+
46+
secured-by-one-env-placeholder-and-one-real-ip:
47+
path: /secured-by-one-env-placeholder-and-one-real-ip
48+
4349
form_logout:
4450
path: /logout_path
4551

src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function testSecurityConfigurationForExpression($config)
109109
public function testInvalidIpsInAccessControl()
110110
{
111111
$this->expectException(\LogicException::class);
112-
$this->expectExceptionMessage('The given "256.357.458.559" value in the "access_control" config option is not a valid IP address.');
112+
$this->expectExceptionMessage('The given value "256.357.458.559" in the "security.access_control" config option is not a valid IP address.');
113113

114114
$client = $this->createClient(['test_case' => 'StandardFormLogin', 'root_config' => 'invalid_ip_access_control.yml']);
115115
$client->request('GET', '/unprotected_resource');

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
imports:
22
- { resource: ./../config/default.yml }
33

4+
parameters:
5+
env(APP_IP): '127.0.0.1'
6+
47
security:
58
encoders:
69
Symfony\Component\Security\Core\User\User: plaintext
@@ -43,6 +46,8 @@ security:
4346
- { path: ^/secured-by-one-real-ip$, ips: 198.51.100.0, roles: IS_AUTHENTICATED_ANONYMOUSLY }
4447
- { path: ^/secured-by-one-real-ip-with-mask$, ips: '203.0.113.0/24', roles: IS_AUTHENTICATED_ANONYMOUSLY }
4548
- { path: ^/secured-by-one-real-ipv6$, ips: 0:0:0:0:0:ffff:c633:6400, roles: IS_AUTHENTICATED_ANONYMOUSLY }
49+
- { path: ^/secured-by-one-env-placeholder$, ips: '%env(APP_IP)%', roles: IS_AUTHENTICATED_ANONYMOUSLY }
50+
- { path: ^/secured-by-one-env-placeholder-and-one-real-ip$, ips: ['%env(APP_IP)%', 198.51.100.0], roles: IS_AUTHENTICATED_ANONYMOUSLY }
4651
- { path: ^/highly_protected_resource$, roles: IS_ADMIN }
4752
- { path: ^/protected-via-expression$, allow_if: "(is_anonymous() and request.headers.get('user-agent') matches '/Firefox/i') or is_granted('ROLE_USER')" }
4853
- { path: .*, roles: IS_AUTHENTICATED_FULLY }

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/invalid_ip_access_control.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ security:
1919

2020
access_control:
2121
# the '256.357.458.559' IP is wrong on purpose, to check invalid IP errors
22-
- { path: ^/unprotected_resource$, ips: [1.1.1.1, 256.357.458.559], roles: IS_AUTHENTICATED_ANONYMOUSLY }
22+
- { path: ^/unprotected_resource$, ips: [1.1.1.1, '%env(APP_IP)%', 256.357.458.559], roles: IS_AUTHENTICATED_ANONYMOUSLY }

0 commit comments

Comments
 (0)