|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2012-01-06 10:08 UTC] vrana@php.net
Description: ------------ Setting 'user_agent' INI value to a string containing a newline causes sending a new header. This behavior is even documented: http://php.net/wrappers.http#wrappers.http.example.custom.headers It is wrong for two reasons: 1. 'user_agent' INI setting should be used only for setting a User-Agent header and not for anything else. 2. It is a potential security risk (header injection) similar to the one fixed in PHP 5.1.2 (but with low impact). (See also bug #52979 but I believe that I am providing a better reasoning.) Test script: --------------- <?php $_POST['user_agent'] = "Robot\r\nX-Command: delete-all"; ini_set('user_agent', $_POST['user_agent']); readfile('http://private/service.php'); ?> Expected result: ---------------- Sending just a User-Agent header, not X-Command header. Actual result: -------------- Sending User-Agent and X-Command headers. If http://private/service.php accepts connections only from trusted sources and parses its commands from headers then it will execute the malicious action. PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Dec 03 22:00:01 2025 UTC |
I'm disagree with "Not a bug". What kind of value we pass to 'user_agent' ini option? > > Define the user agent for PHP to send. > Nothing said. In fact, we pass piece of whole block of headers, not just a value. RFC2616 says: User-Agent = "User-Agent" ":" 1*( product | comment ) product = token ["/" product-version] product-version = token token = 1*<any CHAR except CTLs or separators> separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT comment = "(" *( ctext | quoted-pair | comment ) ")" ctext = <any TEXT excluding "(" and ")"> quoted-pair = "\" CHAR TEXT = <any OCTET except CTLs, but including LWS> LWS = [CRLF] 1*( SP | HT ) OCTET = <any 8-bit sequence of data> CHAR = <any US-ASCII character (octets 0 - 127)> CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)> Ok, looks like end programmer should to pass correct value. But only VALUE, not piece of headers. Yes, problem goes from end programmer, who pass wrong things to 'user_agent', who doesn't know about RFC2616. CRLF can be found in User-Agent definition only inside `ctext` and only as LWS. So, PHP can check, if 'user_agent' has CRLF without SPACE or TAB after it. PHP doesn't need to check it on every run. One check per run just before first use of 'user_agent' and when changing it with ini_set() is enough to throw a Notice, a Warning or do something else to say end programmer, that he is not right. PHP can even insert SPACE after CRLF in that case and use new value instead of incorrect value.