From d3c28579b797074f0ef99c0d042d77812b9d33a9 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Tue, 6 Sep 2022 15:06:35 +1200 Subject: [PATCH] [CVE-2022-38462] Don't allow CRLF in header values --- src/Control/HTTPResponse.php | 10 +++++++++- tests/php/Control/HTTPResponseTest.php | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Control/HTTPResponse.php b/src/Control/HTTPResponse.php index 15eb80520..5f7dc5b4b 100644 --- a/src/Control/HTTPResponse.php +++ b/src/Control/HTTPResponse.php @@ -267,7 +267,7 @@ class HTTPResponse public function addHeader($header, $value) { $header = strtolower($header ?? ''); - $this->headers[$header] = $value; + $this->headers[$header] = $this->sanitiseHeader($value); return $this; } @@ -310,6 +310,14 @@ class HTTPResponse return $this; } + /** + * Sanitise header values to avoid possible XSS vectors + */ + private function sanitiseHeader(string $value): string + { + return preg_replace('/\v/', '', $value); + } + /** * @param string $dest * @param int $code diff --git a/tests/php/Control/HTTPResponseTest.php b/tests/php/Control/HTTPResponseTest.php index 18469ec62..88c1aaeeb 100644 --- a/tests/php/Control/HTTPResponseTest.php +++ b/tests/php/Control/HTTPResponseTest.php @@ -45,6 +45,26 @@ class HTTPResponseTest extends SapphireTest $this->assertEmpty($response->getHeader('X-Animal')); } + public function providerSanitiseHeaders() + { + return [ + 'plain text is retained' => ['some arbitrary value1', 'some arbitrary value1'], + 'special chars are retained' => ['`~!@#$%^&*()_+-=,./<>?;\':"[]{}\\|', '`~!@#$%^&*()_+-=,./<>?;\':"[]{}\\|'], + 'line breaks are removed' => ['no line breaks', "n\ro line \nbreaks\r\n"], + ]; + } + + /** + * @dataProvider providerSanitiseHeaders + */ + public function testSanitiseHeaders(string $expected, string $value) + { + $response = new HTTPResponse(); + + $response->addHeader('X-Sanitised', $value); + $this->assertSame($expected, $response->getHeader('X-Sanitised')); + } + public function providerTestValidStatusCodes() { return [