Timing exploits
Tot hier was het voor de meeste mensen nog wel gesneden koek...
Variabelen controleren, addslashes, post ipv get..
Maar nu, toen ik voor het eerst van deze exploit/hack hoorde,
kon ik eigenlijk niet geloven dat hier een stabiele exploit van gemaakt zou kunnen worden.
Ik heb het zelf een keer uitgetest, en het werkt inderdaad HEEL erg stabiel!
Het onderwerp kan misschien een beetje abstract zijn,
maar ik zal proberen het zo helder/simpel mogelijk uit te leggen.
stel je voor dat je een script, bank.php hebt.
dit script ziet er, versimpeld, zo uit:
2
3
4
5
6
7
8
9
10
$geld = get_geld_uit_database($user); //haal op hoeveel geld je hebt.
if ($geld<$input['verzend_geld']){ //kijk of je genoeg geld hebt om verzend_geld te kunnen betalen
echo "je hebt niet genoeg geld!";
quit();
}
$nieuwgeld = $geld-$input['verzend_geld'];
update_geld_in_database($nieuwgeld);
update_geld_van_ander_in_database($input['verzend_geld']);
echo "gelukt!";
als je deze code uitvoert zal het geld van allebei geupdate worden,
niks aan de hand, of toch wel?
jawel!
stel je nou voor, dat je het script 2 keer, op BIJNA hetzelfde moment uitvoert.
php is multi-threaded, dus hij zal dan om (ongeveer) iedere regel switchen tussen de verschillende scripts!
je krijgt nu zoiets (je begint zelf met 3000 euro, en je stuurt 3000 euro naar een vriend):
script#1 : get_geld -> 3000
script#2 : get_geld -> 3000
script#1 : if ($geld<$input['verzend_geld']) -> false
script#2 : if ($geld<$input['verzend_geld']) -> false
script#1 : $nieuwgeld = $geld-$input['verzend_geld']; -> 0
script#2 : $nieuwgeld = $geld-$input['verzend_geld']; -> 0
script#1 : update_geld_in_database($nieuwgeld); -> 0
script#2 : update_geld_in_database($nieuwgeld); -> 0
script#1 : update_geld_van_ander_in_database($input['verzend_geld']); -> 3000
script#2 : update_geld_van_ander_in_database($input['verzend_geld']); -> 6000
je vriend KRIJGT 6000, terwijl jij maar 3000 hebt gestuurd!
hoe los je dit op, waar zit hier de fout?
De fout zit hem erin, dat je php de berekening laat uitvoeren,
terwijl mysql dit in dit geval beter kan!
mysql heeft van zichzelf een locking mechanisme, om dit soort vervelende ongein te voorkomen!
het goede script ziet eruit:
2
3
4
5
6
7
8
update_geld_database_check($input['verzend_geld']); //een mysql query die EN update, EN checkt of je het geld wel hebt!
if(mysql_affected_rows() == 1){
echo "success!";
}
else{
sql_queries_om_fout_te_vinden();
}
ik hoop dat dit een beetje duidelijk is..