Ik zie laatste tijd steeds meer PHP scripts die een CAPTCHA
validatie hebben. Met gebruik van GD wordt een random string
weergegeven op een afbeelding. Vervolgens wordt de random string in een
sessie variabel gestopt.
Op de volgende pagina, meestal na een POST request, wordt de controle gepleegd. Net daar is er iets goeds mis (soms ook bij random aanmaken van de string, maar dat terzijde).
<?PHP
session_start();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($_POST['input'] == $_SESSION['secret_string']) {
print 'YES!';
}
else {
print 'ERROR, WRONG!';
}
}
?>
Je
ziet vaak zo'n opzet, session_start() aanroepen en dan de strings
vergelijken. MAAR, de programmeur gaat ervan uit dat de sessie uit het
vorige formulier komt. Dat is nou wat zo dodelijk is. Spot je de fout
al? Wat nou als je in keer op de validatie script komt (je moet wel een
POST request aanmaken, dat kan makkelijk met cURL of met de juiste
headers aanmaken)? De sessie is dan onbekend. session_start() zal dan
een nieuwe sessie aanmaken, dus ook $_SESSION wordt opnieuw aangemaakt.
$_SESSION['secret_string'] is dan leeg en als je nou $_POST['input']
ook leeg houdt, dan is de uitkomst van die if() TRUE! OK, sommige
hebben nog een isset($_POST['input']), maar als $_POST['input'] leeg is
dan resulteert isset() ook nog als TRUE.
De oplossing:
if (isset($_POST['input']) AND isset($_SESSION['secret_string']) AND $_POST['input'] == $_SESSION['secret_string'])
Voor de grap keek ik nog even op phpfreakz.nl bij de Script Library. Happy hunting 
Wat ik ook zie, is het onjuiste gebruik van extract(). Deze bug komt wat minder voor.
Het gebruik van extract()
is voor luie programmeurs! Je haalt de keys uit een array dan ontstaan
er variabelen met de naam van de key. Voorbeeld van extract:
<?PHP
$koe = "moo!";
extract($_GET);
print $naam .' zei '. $koe;
?>
Zo moet je het aanroepen: ?naam=Tri
Output: Tri zei moo!
Uit $_GET wordt dus de key 'naam' eruit gehaald en ontstaat variabel $naam.
Nu de cruciale fout. Wat nou als we ?naam=Tri&koe=woef doen?
Output: Tri zei woef
Oops, we kunnen een variabele 'beheersen'. Dit is zeer ernstig. Vaak zie je het gebruik terug van extract() met $_POST, $_GET en database results. Wat nou als er een include($var .'header.php') wordt gebruikt? Juist....
Liever
gewoon keys gebruiken van de superglobals. Leest makkelijker en is ook
stukke duidelijker. Mocht je toch zo koppig zijn, gebruik dan bijv.
parameter EXTR_SKIP.
Een nieuwe idee kwam ik zojuist tegen bij Gmail. Na een eerste foute inlog, krijg je gewoon een melding. Na twee keer krijg je een CAPTCHA scherm. Dit voorkomt brute-force aanvallen. Wanneer je, na twee keer fout inloggen, een andere accountnaam gebrui
Tracked: Jan 04, 13:06