Closed staabm closed 7 years ago
Considering I've not needed to this in any of my projects so far, what type of tainted data are you including?
I don't think there is a PHP function that can help here, for many years I've been using:
function head($text) {
return str_replace(array("\r", "\n", "\0"), '', $text);
}
But this isn't necessary, as the newline problem was fixed in January 2006, with PHP 5.1.2:
Fixed possible header injection by limiting each header to a single line
<?php
$tainted_value = '1' . "\n" . 'B: 2';
header('A: ' . $tainted_value);
?>
Warning: Header may not contain more than a single header, new line detected...
So you might be able to use a function like this:
function head($text) {
$text = str_replace(array("\r", "\n", "\0"), '', $text);
if (function_exists('untaint')) {
$text = untaint($text);
}
return $text;
}
But it really depends on the header, as that might not be good enough:
header('Set-Cookie: name=' . head($tainted_value) . '; HttpOnly; SameSite=Strict');
Where the $tainted_value
could be set to something like "abc; Path=/something".
In this case you would need to use something that filtered the value with known-good characters, for example a regexp to only allow [a-z0-9] characters.
Now I suspect the amount of damage that can be done with Set-Cookie
(when using a tainted value) is going to be quite limited... but a tainted value in a Content Security Policy is going to be a lot more problematic.
Now I suspect the amount of damage that can be done with Set-Cookie (when using a tainted value) is going to be quite limited... but a tainted value in a Content Security Policy is going to be a lot more problematic.
thats exactly the point. I dont want to protect against header injections - as those are handled by php itself as like you already mentioned - but protect against header values which would e.g. weaken security policies or similar.
I dont want to add untaint
calls thru all my products/libs/frameworks therefore I am investigating how things could work at best. additionally I would need to code these function calls in a way that they work when the extension doesnt isnt loaded (like you already mentioned).
Do you have an example of where you have a tainted string that gets added to a header?
I find that values going to the header function aren't tainted anyway... which I worry about, e.g. nothing from the database is considered "tainted" by default.
As in, the websites I work on set several headers, and I can only think of one example where I had a problem with the taint extension.
That was when I had a script that created a download, where it took the mime type from a GET variable (to say it was application/csv
), and while it was checked against a whitelist, the taint extension wasn't happy. To fix I simply changed the GET query so it specified the value from the whitelist.
Do you have an example of where you have a tainted string that gets added to a header?
we use custom X-xyz
headers with domain-specific logic which sometimes get filled from COOKIE/GET values.
In my opinion best way to prevent being XSS is not using a function that to make an inputed string safe, but using a map to ensure that , like:
//Not: header(function_make_string_safe($taint_string));
//BUT:
switch ($taint_string) {
case "xxxx":
header("yyyy");
case "zzzz":
header("www");
}
the key point here is, try the best to make sure that all output are generated by yourself ....
that sounds like a good approach. I am still "developing my style" on how to use this extension without make the actual code-base aware of the mechanics and apis.
I will see if this kind of "construction" makes it work for me, thx.
since https://github.com/laruence/taint/commit/4fdfb3e3eeec1365cfed1399e2e4234153b415b5 the
header()
function also warns against tainted strings - which is great.when looking thru the list of functions[1] which drop the taint-mark, there isnt a candidate which fits for escaping before passing a string into
header()
.how to handle this case?
[1] http://php.net/manual/en/taint.detail.untaint.php