security #cve-2020-15094 Remove headers with internal meaning from HttpClient responses (mpdude)

This PR was merged into the 4.4 branch.
This commit is contained in:
Fabien Potencier 2020-09-02 09:40:48 +02:00
commit d9910e0b33
3 changed files with 75 additions and 0 deletions

View File

@ -16,6 +16,7 @@ use Symfony\Component\HttpClient\CachingHttpClient;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Contracts\HttpClient\ResponseInterface;
class CachingHttpClientTest extends TestCase
{
@ -39,4 +40,71 @@ class CachingHttpClientTest extends TestCase
self::assertSame($response->getRequestOptions()['normalized_headers']['application-name'][0], 'Application-Name: test1234');
self::assertSame($response->getRequestOptions()['normalized_headers']['test-name-header'][0], 'Test-Name-Header: test12345');
}
public function testDoesNotEvaluateResponseBody()
{
$body = file_get_contents(__DIR__.'/Fixtures/assertion_failure.php');
$response = $this->runRequest(new MockResponse($body, ['response_headers' => ['X-Body-Eval' => true]]));
$headers = $response->getHeaders();
$this->assertSame($body, $response->getContent());
$this->assertArrayNotHasKey('x-body-eval', $headers);
}
public function testDoesNotIncludeFile()
{
$file = __DIR__.'/Fixtures/assertion_failure.php';
$response = $this->runRequest(new MockResponse(
'test', ['response_headers' => [
'X-Body-Eval' => true,
'X-Body-File' => $file,
]]
));
$headers = $response->getHeaders();
$this->assertSame('test', $response->getContent());
$this->assertArrayNotHasKey('x-body-eval', $headers);
$this->assertArrayNotHasKey('x-body-file', $headers);
}
public function testDoesNotReadFile()
{
$file = __DIR__.'/Fixtures/assertion_failure.php';
$response = $this->runRequest(new MockResponse(
'test', ['response_headers' => [
'X-Body-File' => $file,
]]
));
$headers = $response->getHeaders();
$this->assertSame('test', $response->getContent());
$this->assertArrayNotHasKey('x-body-file', $headers);
}
public function testRemovesXContentDigest()
{
$response = $this->runRequest(new MockResponse(
'test', [
'response_headers' => [
'X-Content-Digest' => 'some-hash',
]
]));
$headers = $response->getHeaders();
$this->assertArrayNotHasKey('x-content-digest', $headers);
}
private function runRequest(MockResponse $mockResponse): ResponseInterface
{
$mockClient = new MockHttpClient($mockResponse);
$store = new Store(sys_get_temp_dir() . '/sf_http_cache');
$client = new CachingHttpClient($mockClient, $store);
$response = $client->request('GET', 'http://test');
return $response;
}
}

View File

@ -0,0 +1,3 @@
<?php
throw new \PHPUnit\Framework\AssertionFailedError('Response body should not be evaluated.');

View File

@ -58,6 +58,10 @@ final class HttpClientKernel implements HttpKernelInterface
$response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch));
$response->headers->remove('X-Body-File');
$response->headers->remove('X-Body-Eval');
$response->headers->remove('X-Content-Digest');
$response->headers = new class($response->headers->all()) extends ResponseHeaderBag {
protected function computeCacheControlValue(): string
{