laruence / taint

Taint is a PHP extension, used for detecting XSS codes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

header() emits a warning, but there isnt a clear untaint function for this case

staabm opened this issue · comments

since 4fdfb3e 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

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.