php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #73805 header() may not actually set header
Submitted: 2016-12-23 04:39 UTC Modified: 2021-08-02 15:06 UTC
From: habte dot yibelo at gmail dot com Assigned:
Status: Closed Package: HTTP related
PHP Version: Irrelevant OS: Irrelevant
Private report: No CVE-ID: None
 [2016-12-23 04:39 UTC] habte dot yibelo at gmail dot com
Description:
------------
Hello,

In CVE-2011-1398, and later on CVE-2012-4388 there is an attempt to stop CRLF injections in sapi_header_op function in main/SAPI.c functions. however the fix created other vulnerabilities on the way.

so for instance, assume an application vulnerable for CRLF injection:

header("Location:".$_GET['to']);

Sending ?to=x%0ANew:header after the fix will result in PHP returning:

"Multiple headers detected." but what also happens is, the 302/301 redirection doesn't happen. later we realized PHP just drops the header if it sees the character instead of rendering it either encoded or alteast echo the first header. 

This creates other vulnerabilites when user-input is rendered back to browser-security headers, sometimes this creates even dangerous bugs depending on what kind of header it gets refelected back to. Example cases are presended in the next section.


Test script:
---------------
Example, assume an application doing Content-Disposition while delivering sensitive files (svg, html, php):

<?php
$file = $_GET['file'];  
header('Content-Disposition: attachment; filename="'.$file.'"');
?>
<img src=x onerror=alert(1)>

Normally a download would happen, with the filename, but in this case, the header gets dropped so the browser have no option but to render the content. thus creating stored-XSS in this case. I have found terrible cases on applications where this has led to a code execution and finally decided to report it as it seem to affect a lot of developers not knowing about it.

Obviously this is just an example but this could affect a lot of cases, recently I have found it affecting a PKP (Public-Key-Pinning) header making MiTM possible by dropping the header.



Expected result:
----------------
Expected result should be the header getting returned, encoded or atleast is semi-half that isn't user controlled. 

Actual result:
--------------
header gets dropped.

Thanks,

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-12-27 06:57 UTC] stas@php.net
-Type: Security +Type: Bug
 [2016-12-27 06:57 UTC] stas@php.net
Not a security issue since it requires application code to be already vulnerable.
 [2016-12-28 02:46 UTC] habte dot yibelo at gmail dot com
"Not a security issue since it requires application code to be already vulnerable."

> vulnerable to what? there isn't any security vulnerability here. it is creating one. returning user-provided info in header is considered safe after the fixes so there should be no excuse. but these vulnerabilities have a potential to cause more serious issues. revisit please.
 [2021-08-02 15:06 UTC] cmb@php.net
-Summary: Fix of CVE-2011-1398 creating other security issues +Summary: header() may not actually set header -Type: Bug +Type: Documentation Problem
 [2021-08-02 15:06 UTC] cmb@php.net
In my opinion, the only potential issue here is that header()
returns void (and never throws), i.e. it suggests that it is
infallible, while actually it is not.  This should be clarified in
the docs.

> Expected result should be the header getting returned, encoded
> or atleast is semi-half that isn't user controlled.

Automatically escaping "dangerous" characters in a header might
make the header() function susceptible to other attack vectors,
and it is not possible to set a header with its "semi-half that
isn't user controlled", because that would require to distinguish
between user and programmer controlled[1].

The only appropriate solution is to leave this to userland: always
validate all user input before processing.

[1] <https://wiki.php.net/rfc/is_literal>
 [2021-08-02 15:19 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/doc-en/commit/f32912d04f3da53ad720bd782ad5a2483a1d79a0
Log: Fix #73805: header() may not actually set header
 [2021-08-02 15:19 UTC] git@php.net
-Status: Open +Status: Closed
 [2021-08-03 01:32 UTC] git@php.net
Automatic comment on behalf of sy-records
Revision: https://github.com/php/doc-zh/commit/a32aced7eca72e56f27774c7554e3ed78cef7d6f
Log: Fix #73805: header() may not actually set header
 [2021-08-03 14:50 UTC] git@php.net
Automatic comment on behalf of mumumu
Revision: https://github.com/php/doc-ja/commit/114e3842a19ff968e32f43beb1626e915193af05
Log: Fix #73805: header() may not actually set header
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 03:01:27 2024 UTC