Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb8f4116

Browse files
security #cve-2024-50342 [HttpClient] Resolve hostnames in NoPrivateNetworkHttpClient (nicolas-grekas)
This PR was merged into the 5.4 branch.
2 parentscb19470 +b4bf5af commitb8f4116

File tree

11 files changed

+83
-18
lines changed

11 files changed

+83
-18
lines changed

‎src/Symfony/Component/HttpClient/HttpOptions.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ public function buffer(bool $buffer)
148148
}
149149

150150
/**
151+
* @param callable(int, int, array, \Closure|null=):void $callback
152+
*
151153
* @return $this
152154
*/
153155
publicfunctionsetOnProgress(callable$callback)

‎src/Symfony/Component/HttpClient/NativeHttpClient.php‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,15 @@ public function request(string $method, string $url, array $options = []): Respo
138138
// Memoize the last progress to ease calling the callback periodically when no network transfer happens
139139
$lastProgress = [0,0];
140140
$maxDuration =0 <$options['max_duration'] ?$options['max_duration'] : \INF;
141-
$onProgress =staticfunction (...$progress)use ($onProgress, &$lastProgress, &$info,$maxDuration) {
141+
$multi =$this->multi;
142+
$resolve =staticfunction (string$host, ?string$ip =null)use ($multi): ?string {
143+
if (null !==$ip) {
144+
$multi->dnsCache[$host] =$ip;
145+
}
146+
147+
return$multi->dnsCache[$host] ??null;
148+
};
149+
$onProgress =staticfunction (...$progress)use ($onProgress, &$lastProgress, &$info,$maxDuration,$resolve) {
142150
if ($info['total_time'] >=$maxDuration) {
143151
thrownewTransportException(sprintf('Max duration was reached for "%s".',implode('',$info['url'])));
144152
}
@@ -154,7 +162,7 @@ public function request(string $method, string $url, array $options = []): Respo
154162
$lastProgress =$progress ?:$lastProgress;
155163
}
156164

157-
$onProgress($lastProgress[0],$lastProgress[1],$progressInfo);
165+
$onProgress($lastProgress[0],$lastProgress[1],$progressInfo,$resolve);
158166
};
159167
}elseif (0 <$options['max_duration']) {
160168
$maxDuration =$options['max_duration'];

‎src/Symfony/Component/HttpClient/NoPrivateNetworkHttpClient.php‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,24 @@ public function request(string $method, string $url, array $options = []): Respo
8080
$lastUrl ='';
8181
$lastPrimaryIp ='';
8282

83-
$options['on_progress'] =function (int$dlNow,int$dlSize,array$info)use ($onProgress,$subnets, &$lastUrl, &$lastPrimaryIp):void {
83+
$options['on_progress'] =function (int$dlNow,int$dlSize,array$info, ?\Closure$resolve =null)use ($onProgress,$subnets, &$lastUrl, &$lastPrimaryIp):void {
8484
if ($info['url'] !==$lastUrl) {
8585
$host =trim(parse_url($info['url'],PHP_URL_HOST) ?:'','[]');
86+
$resolve ??=staticfn () =>null;
87+
88+
if (($ip =$host)
89+
&& !filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)
90+
&& !filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)
91+
&& !$ip =$resolve($host)
92+
) {
93+
if ($ip = @(dns_get_record($host, \DNS_A)[0]['ip'] ??null)) {
94+
$resolve($host,$ip);
95+
}elseif ($ip = @(dns_get_record($host, \DNS_AAAA)[0]['ipv6'] ??null)) {
96+
$resolve($host,'['.$ip.']');
97+
}
98+
}
8699

87-
if ($host && IpUtils::checkIp($host,$subnets ??self::PRIVATE_SUBNETS)) {
100+
if ($ip && IpUtils::checkIp($ip,$subnets ??self::PRIVATE_SUBNETS)) {
88101
thrownewTransportException(sprintf('Host "%s" is blocked for "%s".',$host,$info['url']));
89102
}
90103

‎src/Symfony/Component/HttpClient/Response/AmpResponse.php‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,17 @@ public function __construct(AmpClientState $multi, Request $request, array $opti
8989
$info['max_duration'] =$options['max_duration'];
9090
$info['debug'] ='';
9191

92+
$resolve =staticfunction (string$host, ?string$ip =null)use ($multi): ?string {
93+
if (null !==$ip) {
94+
$multi->dnsCache[$host] =$ip;
95+
}
96+
97+
return$multi->dnsCache[$host] ??null;
98+
};
9299
$onProgress =$options['on_progress'] ??staticfunction () {};
93-
$onProgress =$this->onProgress =staticfunction ()use (&$info,$onProgress) {
100+
$onProgress =$this->onProgress =staticfunction ()use (&$info,$onProgress,$resolve) {
94101
$info['total_time'] =microtime(true) -$info['start_time'];
95-
$onProgress((int)$info['size_download'], ((int) (1 +$info['download_content_length']) ?:1) -1, (array)$info);
102+
$onProgress((int)$info['size_download'], ((int) (1 +$info['download_content_length']) ?:1) -1, (array)$info,$resolve);
96103
};
97104

98105
$pauseDeferred =newDeferred();

‎src/Symfony/Component/HttpClient/Response/AsyncContext.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ public function replaceRequest(string $method, string $url, array $options = [])
156156
$this->info['previous_info'][] =$info =$this->response->getInfo();
157157
if (null !==$onProgress =$options['on_progress'] ??null) {
158158
$thisInfo = &$this->info;
159-
$options['on_progress'] =staticfunction (int$dlNow,int$dlSize,array$info)use (&$thisInfo,$onProgress) {
160-
$onProgress($dlNow,$dlSize,$thisInfo +$info);
159+
$options['on_progress'] =staticfunction (int$dlNow,int$dlSize,array$info, ?\Closure$resolve =null)use (&$thisInfo,$onProgress) {
160+
$onProgress($dlNow,$dlSize,$thisInfo +$info,$resolve);
161161
};
162162
}
163163
if (0 < ($info['max_duration'] ??0) &&0 < ($info['total_time'] ??0)) {

‎src/Symfony/Component/HttpClient/Response/AsyncResponse.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public function __construct(HttpClientInterface $client, string $method, string
5151

5252
if (null !==$onProgress =$options['on_progress'] ??null) {
5353
$thisInfo = &$this->info;
54-
$options['on_progress'] =staticfunction (int$dlNow,int$dlSize,array$info)use (&$thisInfo,$onProgress) {
55-
$onProgress($dlNow,$dlSize,$thisInfo +$info);
54+
$options['on_progress'] =staticfunction (int$dlNow,int$dlSize,array$info, ?\Closure$resolve =null)use (&$thisInfo,$onProgress) {
55+
$onProgress($dlNow,$dlSize,$thisInfo +$info,$resolve);
5656
};
5757
}
5858
$this->response =$client->request($method,$url, ['buffer' =>false] +$options);

‎src/Symfony/Component/HttpClient/Response/CurlResponse.php‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,20 @@ public function __construct(CurlClientState $multi, $ch, ?array $options = null,
115115
curl_pause($ch, \CURLPAUSE_CONT);
116116

117117
if ($onProgress =$options['on_progress']) {
118+
$resolve =staticfunction (string$host, ?string$ip =null)use ($multi): ?string {
119+
if (null !==$ip) {
120+
$multi->dnsCache->hostnames[$host] =$ip;
121+
}
122+
123+
return$multi->dnsCache->hostnames[$host] ??null;
124+
};
118125
$url =isset($info['url']) ? ['url' =>$info['url']] : [];
119126
curl_setopt($ch, \CURLOPT_NOPROGRESS,false);
120-
curl_setopt($ch, \CURLOPT_PROGRESSFUNCTION,staticfunction ($ch,$dlSize,$dlNow)use ($onProgress, &$info,$url,$multi,$debugBuffer) {
127+
curl_setopt($ch, \CURLOPT_PROGRESSFUNCTION,staticfunction ($ch,$dlSize,$dlNow)use ($onProgress, &$info,$url,$multi,$debugBuffer,$resolve) {
121128
try {
122129
rewind($debugBuffer);
123130
$debug = ['debug' =>stream_get_contents($debugBuffer)];
124-
$onProgress($dlNow,$dlSize,$url +curl_getinfo($ch) +$info +$debug);
131+
$onProgress($dlNow,$dlSize,$url +curl_getinfo($ch) +$info +$debug,$resolve);
125132
}catch (\Throwable$e) {
126133
$multi->handlesActivity[(int)$ch][] =null;
127134
$multi->handlesActivity[(int)$ch][] =$e;

‎src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
useSymfony\Component\HttpClient\Exception\InvalidArgumentException;
1717
useSymfony\Component\HttpClient\Exception\TransportException;
1818
useSymfony\Component\HttpClient\Internal\ClientState;
19+
useSymfony\Component\HttpClient\NoPrivateNetworkHttpClient;
1920
useSymfony\Component\HttpClient\Response\StreamWrapper;
2021
useSymfony\Component\Process\Exception\ProcessFailedException;
2122
useSymfony\Component\Process\Process;
@@ -466,4 +467,26 @@ public function testMisspelledScheme()
466467

467468
$httpClient->request('GET','http:/localhost:8057/');
468469
}
470+
471+
publicfunctiontestNoPrivateNetwork()
472+
{
473+
$client =$this->getHttpClient(__FUNCTION__);
474+
$client =newNoPrivateNetworkHttpClient($client);
475+
476+
$this->expectException(TransportException::class);
477+
$this->expectExceptionMessage('Host "localhost" is blocked');
478+
479+
$client->request('GET','http://localhost:8888');
480+
}
481+
482+
publicfunctiontestNoPrivateNetworkWithResolve()
483+
{
484+
$client =$this->getHttpClient(__FUNCTION__);
485+
$client =newNoPrivateNetworkHttpClient($client);
486+
487+
$this->expectException(TransportException::class);
488+
$this->expectExceptionMessage('Host "symfony.com" is blocked');
489+
490+
$client->request('GET','http://symfony.com', ['resolve' => ['symfony.com' =>'127.0.0.1']]);
491+
}
469492
}

‎src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,14 +304,17 @@ protected function getHttpClient(string $testCase): HttpClientInterface
304304

305305
switch ($testCase) {
306306
default:
307-
returnnewMockHttpClient(function (string$method,string$url,array$options)use ($client) {
307+
returnnewMockHttpClient(function (string$method,string$url,array$options)use ($client,$testCase) {
308308
try {
309309
// force the request to be completed so that we don't test side effects of the transport
310310
$response =$client->request($method,$url, ['buffer' =>false] +$options);
311311
$content =$response->getContent(false);
312312

313313
returnnewMockResponse($content,$response->getInfo());
314314
}catch (\Throwable$e) {
315+
if (str_starts_with($testCase,'testNoPrivateNetwork')) {
316+
throw$e;
317+
}
315318
$this->fail($e->getMessage());
316319
}
317320
});

‎src/Symfony/Component/HttpClient/TraceableHttpClient.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ public function request(string $method, string $url, array $options = []): Respo
5858
$content =false;
5959
}
6060

61-
$options['on_progress'] =function (int$dlNow,int$dlSize,array$info)use (&$traceInfo,$onProgress) {
61+
$options['on_progress'] =function (int$dlNow,int$dlSize,array$info, ?\Closure$resolve =null)use (&$traceInfo,$onProgress) {
6262
$traceInfo =$info;
6363

6464
if (null !==$onProgress) {
65-
$onProgress($dlNow,$dlSize,$info);
65+
$onProgress($dlNow,$dlSize,$info,$resolve);
6666
}
6767
};
6868

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp