Tutorials

Online php spel beveiligen

hoe beveilig ik mijn mmorpg, waar moet ik op letten?

Pagina 1

Inleiding

Omdat over het algemeen (99% van de gevallen) online php spellen, en dan mafia spellen in het bijzonder,
nogal lek van aard zijn, en ik talloze keren uit moet leggen hoe "die ene hack" ookalweer verholpen kon worden, heb ik besloten er dan maar een tutorial van te maken.

Voor wie is deze tutorial bedoelt?
Allereerst, niet ALLEEN voor mensen die zelf een online php spel hebben/maken/willen maken, maar ook voor iedereen die het interessant vind hier wat dieper over na te denken, en die kennis misschien over te brengen op andere takkken van het internet (denk aan fora, blogs, etc).

Hoeveel moet je van php weten om deze tutorial te snappen?
Nou, je hoeft absoluut geen php professional te zijn,
zolang je maar beschikt over een gezonde dosis verstand, en je iets afweet van hoe php werkt, en intern geregeld wordt. Maar daar kom ik later op terug.

Wat kan ik van deze tutorial leren? Maakt het me een meester hacker?
Nee, het zal je geen meester hacker maken, maar het zal je wel dieper doen nadenken over hoe je het beste een project als deze in elkaar kan zetten.
De kennis die ik hier deel is niet alleen nuttig voor een php spel, maar ook voor een winkelwagen script etc.

Genoeg gepraat, laten we beginnen!
Pagina 2

De absolute basis

Met de absolute basis bedoel ik de dingen waar je op moet letten,
en die voor iedere website gelden.
De meeste mensen weten dit allemaal wel, en kunnen rustig verder bladeren.

1)gebruikersinput:
Iedereen weet dat je alle input van een gebruiker ALTIJD moet controleren.
Vertrouw de gebruiker NOOIT. Check ook nooit alleen client-side, maar ook altijd server side.

2)quotes in sql:
Gebruik in mysql altijd quotes om de input, dus:
$sql = "SELECT * FROM table where field='".$input."'";

Dit in combinatie met addslashes/mysql_real_escape_string zorgt ervoor dat sql injetion in ieder geval niet mogelijk is.

pas op met includes:
Pas op met includes, include nooit een pagina waarvan de url gegeven is door de gebruiker.
Eigenlijk valt dit samen met punt een, maar ik vond hem toch het noemen wel waard.
Pagina 3

Het login systeem

Op iedere pagina heb je geaddslashed, of ge mysql_real_escaped,
dus je loginsysteem is veilig, toch?
Nee.

Een login systeem is op verschillende manieren te omzeilen.
Ten eerste: Session highjacking, hierbij steelt de aanvaller de sessie van de gebruiker, hierdoor kan php de gebruiker en de aanvaller niet uit elkaar houden,
en zal de aanvaller op het account van de gebruiker ingelogd zijn, zonder het wachtwoord te weten.

Ten tweede: md5 kraken. Het klinkt misschien stom, maar je wilt niet weten in hoeveel scripts je gewoon het wachtwoord (welliswaar gemd5'd) in de cookies ziet staan. MD5 IS NIET VEILIG!
het kost voor een aanvaller ongeveer 2 minuten om een wachtwoord te vinden wat dezelfde hash oplevert als jouw wachtwoord. hiermee kan de aanvaller dus gewoon inloggen.
(voor de mensen die denken: zo stom kan iemand niet zijn! de site waar je nu op zit is het levende voorbeeld!)


De oplossing voor het eerste probleem is opzich redelijk simpel:
zet het ip van de gebruiker in de sessie, controleer op iedere pagina of de ip's nog overeenkomen, zo nee, uitloggen die hap.
(en nu geen gezeur over dynamische ip's, die veranderen heus niet terwijl je OP internet zit, anders zou het hele nut van een ip weg zijn, namelijk dat een computer daarop te bereiken is.)

Het tweede punt is natuurlijk nog makkelijker te voorkomen.
Zet gewoon geen passwords in een cookie, klaar uit.
Pagina 4

Cross Page Command Execution

Cross Page Command Execution komt er in feite op neer,
dat je, omdat je de sessie niet kan/wil overnemen, de eigenaar van de sessie zelf het commando uit laat voeren.
wordt ook wel session riding genoemd.

Wat betekend dit nou?
stel je voor, ik heb een pagina ban.php.
ban.php checkt keurig of degene die de pagina oproept bevoegt is om de pagina te bekijken.
Omdat ban.php ook moet weten WIE hij moet bannen, geven we hem een parameter mee, doormiddel van een GET variabele.
om klaas te bannen moeten we, als admin zijnde, het volgende adres bezoeken:
ban.php?gebruiker=klaas

Opzich niks mis mee, zou je denken, ban check toch of de gebruiker wel admin is?
Klopt. maar het vervelende met sessies is: ze worden OVERAL meegegeven.
dus ook als de admin een plaatje opvraagt van de server, dan wordt zijn sessie meegegeven.

Hoe combineer ik die twee nou?
Nou, stel je voor, ik heb een forum, waar je plaatjes kan posten.
Als ik nu een plaatje post, met als url ban.php?gebruiker=vulmaarin
en de admin zou de pagina bekijken dan zal hij het plaatje ophalen,
en daarmee de gebruiker verbannen!

Hoe voorkom je dit?
Heel simpel, gewoon POST gebruiken voor al dit soort dingen.
alleen bij zoeken, of bekijken van een bepaalde pagina moet/mag je GET gebruiken.
Pagina 5

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:


$input = check_input($input);                  //check input, dus addslashes etc
$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:

$input = check_input($input);                  //check input, dus addslashes etc
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..
Pagina 6

xss

Bijna ieder online spel kent wel een profiel, of een forum, of private messages, of whatever, waarbij je de gebruiker graag in staat stelt om html te gebruiken.

Html is echter redelijk lastig xss vrij te parsen (zonder van htmlpurifier gebruik te maken), dus gebruiken veel fora ubb codes.

Veel van deze ubb parsers zijn (helaas) zelf ook niet helemaal xss vrij..
voor een mooi overzicht van een hele hoop xss vectors: ha.ckers.org/xss.html

Verder zou ik zeggen, als je zelf geen ervaring hebt met xss,
laat het dan even door iemand checken voor je hem online gooit,
er zullen namelijk altijd wel fouten in zitten, en een spel wat in 2 dagen gehacked heeft over het algemeen al snel geen goede naam meer.
Pagina 7

conclusie

Mijn conclusie is: ik heb weer veels te lang getypt, en ik moet echt gaan slapen, maar daar hebben jullie niet zoveel aan..

Conclusie #2:
De meeste technieken die gebruikt worden om een site te "hacken" zijn voor bijna iedere website gelijk, behalve de timing exploit..
Al moet ik erbij zeggen, die is natuurlijk ook heel wijd inzetbaar..
denk aan een voting script, of DOS attacks, etc.


Ik weet het, rotconclusie, maar maakt me niks uit!:P

Ik hoop dat jullie er wat aan hebben,

Huib

Reacties

0
Nog geen reacties.