Hoe $_SERVER['PHP_SELF'] een XSS probleem kan veroorzaken
In dit artikeltje keken we naar een paar standaard dingen die vaak fout gaan bij mensen die met PHP beginnen. In deze korte toevoeging kijken we even naar wat variabelen in $_SERVER en hoe je die zou moeten gebruiken.
Het blijkt namelijk dat een van de meest gebruikte elementen uit $_SERVER: $_SERVER['PHP_SELF'] in veel gevallen niet veilig is; in elk geval met het gebruik van Apache. Als er namelijk PathInfo wordt meegegeven aan de URL en je gebruikt $_SERVER['PHP_SELF'] om bijvoorbeeld forms terug te posten naar dezelfde pagina, wordt deze path info ook direct weergegeven!
voorbeeld.php:
-
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
-
</form>
Als je voorbeeld.php aanroept via:
-
http://localhost/voorbeeld.php/"><script>alert('hatzee');</script>
... heb je zomaar een Cross Site Scripting lek te pakken:
-
<form action="/voorbeeld.php"><script>alert('hatzee');</script>" method="post">
-
</form>
En dat is natuurlijk niet de bedoeling!
What to do?
Allereerst kun je dit probleem tijdelijk omzeilen door PathInfo uit te schakelen. Dit kun je doen door in een .htaccess file het volgende neer te zetten:
-
AcceptPathInfo off
Het enige vervelende daaraan is dat een url als /index.php/artikel/1 dan gegarandeerd niet meer werkt. Je zult simpelweg een 404 foutmelding krijgen.
Maar gelukkig zijn er nog wat andere alternatieven. Zo kun je bijvoorbeeld $_SERVER['SCRIPT_NAME'] of $_SERVER['REQUEST_URI'] gaan gebruiken maar deze laatste werkt alleen niet in IIS.
Je zou ook, via een stukje script of met de hand, de juiste URL kunnen samenstellen en weergeven:
Als laatste heb je nog de mogelijkheid tot het bewerken van $_SERVER['PHP_SELF']:
-
/* Optie 1 - HTML tags omzetten naar HTML entities: */
-
-
/* Optie 2 - HTML tags compleet verwijderen, met als safety-net toch nog HTML entities */
-
-
/* Optie 3 - PATH_INFO uit $_SERVER['PHP_SELF'] verwijderen: */
-
-
function getPHPSelf()
-
{
-
{
-
$_SERVER['PHP_SELF'],
-
0,
-
);
-
} else {
-
return $_SERVER['PHP_SELF'];
-
}
-
}
Conclusie
Hoewel $_SERVER vaak als een "veilige" variabele wordt gezien is dit helaas niet het geval. Bepaalde elementen, zoals $_SERVER['PHP_SELF'] kunnen door kleine omstandigheden (PathInfo ja/nee) in de omgeving toch omgetoverd worden tot een onveilige waarde.
Volg Scriptorama via RSS!
Reageer ook!
behalve dat de gebruiker zichzelf lastig kan vallen met javascript-gedoe, wat voor ander gevaar schuilt hier dan in?
Bovendien gaat dit alleen op als de magic_quotes uit staan; staan ze aan dat wordt je wel heel erg beperkt in het inserten van js-code.
Door marty
op 02.17.06 @ 11:02 am | Permalink
Daar vergis je je toch in. Met de functie String.fromCharCode() kun je een hele hoop doen. Op PHPFreakz was ook iemand die dat niet zo geloofde, lees het volgende topic maar eens:
http://phpfreakz.nl/forum.php?forum=6&iid=779261#id779274
Door Mathieu
op 02.17.06 @ 11:17 am | Permalink
@Matieu
Mooi/goed voorbeeld. Het lijkt zo eenvoudig, maar zo was bijv hotmail hier in zijn vroege jaren ook gevoelig voor. *Kijkt stiekum even naar eigen scripts*
Door Clock
op 02.18.06 @ 11:54 pm | Permalink
Matieu => Mathieu
Excuses :)
Door Clock
op 02.18.06 @ 11:55 pm | Permalink
Ik geloof eigenlijk niet, dat als je een veilig script met $_SERVER["PHP_SELF"] etc. gebruikt dat je dan zo'n groot lek zou hebben.
Volgens mij ligt het gewoon net aan hoe netjes jij omgaat met het schrijven van je PHP...
Door Jan Willem van der Veer
op 03.24.06 @ 6:21 pm | Permalink
.. probeer het maar es. Zie ook het PHPFReakz topic dat ik aanhaal in de comments..
Door Mathieu Kooiman
op 03.24.06 @ 6:24 pm | Permalink
Sorry maar even een vraag van een beginner ... waar moet je deze code dan plaatsen ?
Zou het zo lukken ?
echo htmlentities(strip_tags($_SERVER['PHP_SELF']));"?>
of moet je de code
echo htmlentities(strip_tags($_SERVER['PHP_SELF']));
in het eigenlijke PHP-gedeelte zetten ?
Door Michael
op 04.30.06 @ 6:51 pm | Permalink
Als je naar dezelfde pagina wilt posten kun je ook nog gewoon geen waarde voor het action attribuut opgeven.
Door Mathieu Kooiman
op 04.30.06 @ 7:03 pm | Permalink
[...] Zoals de term user input het al zegt, het is invoer van de gebruiker. Nu zullen heel veel ontwikkelaars alleen denken aan $_GET. Okay, er zijn nog slimme onder ons die ook nog denken aan $_POST. Echter het blijft niet beperkt tot deze super globals. Een ander belangrijke vector zijn HTTP headers. Deze data wordt doorgegeven aan super global $_SERVER. Zoals Mathieu in "Hoe $_SERVER[’PHP_SELF’] een XSS probleem kan veroorzaken" laat zien is $_SERVER niet heilig. Een vaak over het hoofd gezien vector is $_COOKIE, ja de koekjes. Deze zijn ook te manipuleren en is dus ook user input. In feite zijn cookie gegevens gewoon HTTP headers. Om kort te zijn, alle super globals in PHP zijn user input en ga er altijd vanuit de user input niet te vertrouwen is en valideer deze altijd. [...]
Door SQL crash course met Joomla | Scriptorama op 06.27.06 @ 11:42 am | Permalink
Als ik AcceptPathInfo off opneem in m'n .htaccess krijg ik een Internal Server Error op elke pagina... Kan dat aan m'n Apache installatie liggen?
Door Henk
op 07.17.07 @ 10:39 pm | Permalink
"alle super globals in PHP zijn user input "
Dus ook sessie's?
Door Bram
op 08.20.07 @ 3:30 pm | Permalink
Niet per definitie, Bram. Het ligt er een beetje aan hoe je omgaat met sessie variabelen ($_SESSION['test'] = $_GET['test']; blijft natuurlijk een potentieel gevaar) en in hoe verre je de host vertrouwt :)
Door Mathieu Kooiman
op 08.24.07 @ 5:59 pm | Permalink
bedankt, dat had ik nog nooit opgemerkt,
ik zal er voortaan op letten!
groet,
Roelof
Door roelof
op 06.09.08 @ 8:26 pm | Permalink
Gebruik gewoon "" als action. Werkt ook en is veilig.
Door Fred
op 03.19.09 @ 8:33 pm | Permalink
[...] be your script file name. (The reason why I didn’t use $_SERVER['PHP_SELF'] is because of this Dutch source about how this element can cause an XSS [...]
Door Patrick » Simple PHP SOAP example op 03.25.09 @ 12:14 pm | Permalink
Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>