Hoofdcategorieën

Nieuwe reactie in topic: [Forumgame] Vind de kwetsbaarheid!

Let op:
  • Reageer ontopic, plaats geen onzinnige berichten en ga niet flamen of uitlokken (trollen).
  • Zie je iets dat niet door de beugel kan, attendeer dan een moderator via een topicreport maar post hierover niet in het topic, dat werkt alleen averechts. Zie ook de policy die wij op dit forum hanteren.
  • Lees je eigen bericht even door voor je het post.

Insert message
 

Let op! Het laatste bericht in deze discussie is meer dan 2 weken oud!

 

Smilies: :) :( ;) >:) :> :P :9 :o :*) :'( 8) :+ :D _/-\o_ :9~ O+ :O }:O :/ :| :X :? 8)7 |:( O-) :z ;( meer »

Page navigation

Laatste reacties:

 
row is leeg want $result bestaat ook al niet. ;) En dan gebeurd er niet veel, want al je users hebben een username.

Maar goed, het is een buggy versie van een security lek welke reeds in het begin van het topic langskwam. :P
 
 
Wie garandeert dat wat er in de users tabel staat correct is?

De fout is nu juist dat niemand hier kan vertellen of pietje geen username van : pietje" or 1=1 or name="pietje staat.

Username is nog steeds userinvoer, dat het eerst in een dbase heeft gestaan is niet relevant.

Zoals ik al zei kom ik wekelijks progjes tegen die ooit in een ver verleden geen inputcontroles deden / ergens een inputcontrole vergeten ( in een ver weg liggend form wat bijna niemand gebruikt ). Waardoor je nooit userinput moet vertrouwen, onafhankelijk van de bron ( formulier posten of dbase )

En ik zie nu dat ik toch beter moet opletten met posten, $res == $result....

Na 3x verbeteren nog deze fout laten zitten... Maarja, ik geloof dat het maar beter is als ik hier niet meer ga posten :)

Na 3x verbeteren nog meerdere fouten laten zitten... Ik moet geloof echt stoppen met posten in dit topic...
 
 
En laten we voor het gemak dan ook maar even vergeten dat mysql gaat vallen over die ; aan het eind van de eerste query ;)
 
 
Maar post dan een voorbeeld script dat relevant is, en niet een script en dan achteraf zeggen, oh maar pietje kan ook iets anders zijn, want dat kan het niet zijn in jou script. :?
 
 
quote:
Megamind schreef op dinsdag 20 mei 2008 @ 21:48:
Maar post dan een voorbeeld script dat relevant is, en niet een script en dan achteraf zeggen, oh maar pietje kan ook iets anders zijn, want dat kan het niet zijn in jou script. :?
username kan toch iets anders zijn als name?

Maar door de vele fouten van mijn post is het hele punt waardeloos geworden.

Maar vergelijk het eens met een willekeurig netwerk-systeem, name kan een korte code zijn om iemand aan te duiden ( id's houden de meeste mensen niet zo van, voelen ze zich zo'n nummertje ) terwijl username de voornaam van de gebruiker kan zijn.

Btw fout 1500, username en name moeten omdraaien. Op deze manier loopt het db-schema raar.
 
 
quote:
Gomez12 schreef op dinsdag 20 mei 2008 @ 21:54:
Btw fout 1500, username en name moeten omdraaien.
Die je zelf al maakt. Een username is namelijk juist typisch het ding waarmee je inlogt, en name het ding wat publiek weergegeven wordt om de de persoon aan te duiden. Maar idd, noem het dan loginname en displayname.
 
 
Laat ik er maar eens een stuk code posten. Voor het gemak weer in PHP. :)
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php

// Als voorbeeld definiëer ik dit lokaal, maar zou uit een DB moeten komen o.i.d..
$ThisUserID = 3// User ID van deze gebruiker.
$TargetUserID = 6// User ID van de begunstigde. (Dit getal mag niet gelijk zijn aan $ThisUserID en moet natuurlijk een bestaande gebruiker zijn.
$AccountThisUser = 600;    // Het bedrag wat deze gebruiker in bezit heeft.
$AccountTargetUser = 420// Het bedrag wat de andere gebruiker in bezit heeft.

if ( isset($_GET["Donate"]) )
{    
    if ( is_numeric($_GET["Donate"]) )
    {
        if ( is_intintval($_GET["Donate"]) ) )
        {
            $Donation = $_GET["Donate"];
            
            if ( $Donation <= $AccountThisUser )
            {
                $AccountThisUser = $AccountThisUser - $Donation;
                $AccountTargetUser = $AccountTargetUser + $Donation;
            }
            else
                die("You do not have enough money!");
        }
        else
            die("Error");
    }
    else
        die("Error");
}
else
    die("Error");

// En dit moet weer in de DB geschreven worden.
echo "Account this user: &euro; ".$AccountThisUser.",--<br>";
echo "Account target user: &euro; ".$AccountTargetUser.",--<br>";

 
 
Onbekend: je kan een negatieve waarde voor Donate meegeven waardoor je de huidige user zijn account ophoogt ten koste van de targetUser.
 
 
Haha, dat is nog is een mooi exploit voorbeeld.


Ik zou 'Account*' trouwens vervangen door 'Amount*'.
 
 
Da's snel! Hij was toch niet moeilijk hè? :P
Maar ik kom zoiets toch weleens vaker tegen. Gelukkig niet met geldbedragen. :)
 
 
Regel 13 geeft zo te zien ook altijd true terug.
 
 
quote:
The Fox NL schreef op dinsdag 20 mei 2008 @ 23:20:
Regel 13 geeft zo te zien ook altijd true terug.
Klopt.

Ik denk trouwens dat het enigszins belangrijk is om in dit topic even vast te stellen dat je duidelijk moet zijn over waar bepaalde waarden vandaan komen. Zoals Onbekend het doet is het prima, hij declareert daar simpelweg variabelen, maar zegt wel erbij waar ze normaliter vandaan zouden komen.

In het voorbeeld Gomez12 staat hardcoded "pietje" in de query, er kan daardoor in principe niets misgaan. Het was niet duidelijk dat die waarde van de gebruiker moest komen.

Dat hebben we al eerder gehad in dit topic, en het is natuurlijk niet onlogisch dat je daar over valt.
 
 
Ik blijf het trouwens suf vinden dat na al die jaren PHP nog altijd geen fatsoenlijke int of float validatie functies heeft. Voor int kom je dan nog weg met ctype_digit(), maar voor floats is de enige fatsoenlijke manier eigenlijk zelf een regex in elkaar flansen die hopelijk maar aan de regels van PHP voldoet.
 
 
quote:
The Fox NL schreef op dinsdag 20 mei 2008 @ 23:20:
Regel 13 geeft zo te zien ook altijd true terug.
Ja, dat heb je goed gezien. Ik had dit stukje code even snel gemaakt met de nadruk dat een integer negatieve waarden kan bevatten.

Is_int mag inderdaad vervallen omdat het door de functie intval al altijd een integer is geworden.
En ik zie hiermee dat er nog een foutje in de code kan ontstaan als iemand bijvoorbeeld "1e10" invoert.
Op regel 15 moet het volgende staan: $Donation = intval($_GET["Donate"]);
 
 
Dat deze niet idempotente actie via GET ipv POST aangeroepen wordt, is ook een security probleem. B)

En die fout zie ik nog véél vaker. :'( Dat hele volkstammen het verschil tussen GET en POST (idempotentie) niet kennen is echt een serieus probleem. Het betreft niet alleen PHP'ers, maar er zijn er wel relatief veel die echt geen snars snappen van HTTP.
 
 
Hmm.. dan moet ik nu zeker iets gaan verzinnen omdat ik het als eerst heb geraden? Als iemand anders al iets heeft: ga je gang ;)
offtopic:
Voutloos: Ik krijg regelmatig te maken met mensen die niet in staat zijn om een HTTP request te maken vanuit code en dan maar direct vragen of ze niet een XML doc via SOAP kunnen sturen :/
 
 
Wat is dan het security probleem?

Met GET kan ik via de adresbalk variablen meegeven, en bij POST moet ik dat via een formulier op de website doen. Het enige nadeel (soms voordeel) is dat je de inhoud van een variable gemakkelijk kan zien via GET. Maar ze bieden beiden securityproblemen. Meer verschillen dan dat ken ik niet.
 
 
@Onbekend: Zoals Voutloos al zegt: volgens RFC 2616 moet een GET request idempotent zijn. Dat wil zeggen dat hij geen veranderingen mag veroorzaken in de permanente staat van de applicatie en dat het dus geen kwaad mag kunnen wanneer die GET meerdere keren opgevraagd of van tevoren gecached wordt.

Dat probleem is pijnlijk duidelijk wanneer je sommige sites gebruikt met een zogenaamde internet versneller (plugin). Die laden de links op die pagina alvast in zodat je de volgende pagina sneller kan opvragen omdat je die al in de cache hebt staan. Wat nu als er op die pagina links staan naar "pagina.php?action=delete"?

Daarom moeten acties die iets veranderen in de database (of in meer algemene zin, de staat van de applicatie/website) altijd met een POST request gedaan worden. Voor meer informatie, zie RFC 2616, section 9.

Daarnaast worden de parameters bij een GET request opgeslagen in web server logs, proxy logs, firewall logs en wat er allemaal nog meer tussen zit voor je request bij de server is. Dat kan op zichzelf al een beveiligingsrisico zijn.
 
 
Niet zozeer een security probleem meer een usability probleem.
Elke fatsoenlijke browser gaat niet zomaar post-waardes reposten bij een F5 ( oftewel als het te lang duurt drukt iemand nog eens op F5 en dan heeft hij 2x gedoneerd )

Geen enkele website versneller die ik ken gaat post waardes ook prefetchen.

Iemand kan niet per ongeluk een bookmark aanmaken die elke keer weer een donatie doet.

Post waardes voor dingen die iets doen, Get waardes om iets op te halen.
 
 
quote:
Onbekend schreef op dinsdag 20 mei 2008 @ 23:10:
Da's snel! Hij was toch niet moeilijk hè? :P
Maar ik kom zoiets toch weleens vaker tegen. Gelukkig niet met geldbedragen. :)
Veel webshops zijn er vatbaar voor. Kun je een negatief aantal artikelen bestellen. De factuur ziet er vervolgens veelbelovend uit ;)

@.oisyn
Wat is er mis met is_int(), is_float() en/of is_numeric() ?

@Voutloos
Dat zijn ook de mensen die topics openen dat ze het stom vinden dat je in PHP geen headers meer kunt verzenden na je output, of dat je een ander frame niet van locatie kan veranderen met header("Location") :X
 
 
quote:
Gerco schreef op woensdag 21 mei 2008 @ 08:43:
Wat nu als er op die pagina links staan naar "pagina.php?action=delete"?
Om het af te maken een voorbeeld voorkauwen:
Stel dat je op GoT deze donate actie via GET zou hebben. Dan hoef je enkel een dergelijke link als webicon op te geven en je krijgt bij elke pageview geld van degene die de pagina bekijkt *O*

Als je rekening houdt met idempotentie en daarom de keuze GET/POST maakt, zit je meestal ook meteen goed voor wat betreft deze aanvalmogelijkheid. :)
quote:
Gomez12 schreef op woensdag 21 mei 2008 @ 08:46:
Niet zozeer een security probleem meer een usability probleem.
Lees bovenstaand voorbeeld en durf dit dan nog eens te zeggen. >:) :>
 
 
quote:
Onbekend schreef op dinsdag 20 mei 2008 @ 23:03:
Laat ik er maar eens een stuk code posten. Voor het gemak weer in PHP. :)
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php

// Als voorbeeld definiëer ik dit lokaal, maar zou uit een DB moeten komen o.i.d..
$ThisUserID = 3// User ID van deze gebruiker.
$TargetUserID = 6// User ID van de begunstigde. (Dit getal mag niet gelijk zijn aan $ThisUserID en moet natuurlijk een bestaande gebruiker zijn.
$AccountThisUser = 600;    // Het bedrag wat deze gebruiker in bezit heeft.
$AccountTargetUser = 420// Het bedrag wat de andere gebruiker in bezit heeft.

if ( isset($_GET["Donate"]) )
{    
    if ( is_numeric($_GET["Donate"]) )
    {
        if ( is_intintval($_GET["Donate"]) ) )
        {
            $Donation = $_GET["Donate"];
            
            if ( $Donation <= $AccountThisUser )
            {
                $AccountThisUser = $AccountThisUser - $Donation;
                $AccountTargetUser = $AccountTargetUser + $Donation;
            }
            else
                die("You do not have enough money!");
        }
        else
            die("Error");
    }
    else
        die("Error");
}
else
    die("Error");

// En dit moet weer in de DB geschreven worden.
echo "Account this user: &euro; ".$AccountThisUser.",--<br>";
echo "Account target user: &euro; ".$AccountTargetUser.",--<br>";

Bbbbbaaaaahhhh, al die ifs zijn ten eerste redundant en ten tweede kunnen ze gecombineerd worden. Wat is er mis met
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

// Als voorbeeld definiëer ik dit lokaal, maar zou uit een DB moeten komen o.i.d..
$ThisUserID = 3; // User ID van deze gebruiker.
$TargetUserID = 6; // User ID van de begunstigde. (Dit getal mag niet gelijk zijn aan $ThisUserID en moet natuurlijk een bestaande gebruiker zijn.
$AccountThisUser = 600;    // Het bedrag wat deze gebruiker in bezit heeft.
$AccountTargetUser = 420; // Het bedrag wat de andere gebruiker in bezit heeft.

$Donation = $_GET["Donate"];

if ( isset($Donation) && is_numeric($Donation) && is_int(intval($Donation)) && ( $Donation <= $AccountThisUser ))
{    
    $AccountThisUser = $AccountThisUser - $Donation;
    $AccountTargetUser = $AccountTargetUser + $Donation;
}
else
    die("Error");

// En dit moet weer in de DB geschreven worden.
echo "Account this user: &euro; ".$AccountThisUser.",--<br>";
echo "Account target user: &euro; ".$AccountTargetUser.",--<br>";

(bijvoorbeeld), en kunnen die driedubbele checks niet vervangen worden naar een enkele aanroep naar een of andere functie die alleen true geeft als de meegegeven waarde een int en niet null is? Maak desnoods een eigen functie oid.

Daar komt nog bij dat je op deze manier ook negatieve nummers mee kunt geven in je get, evenals de zooi die hierboven gepost is over posts gebruiken voor dit soort gegevens.
 
 
Ik zou het ook niet meteen een 'security' probleem durven noemen, maar ik ben het wel met je eens dat GET uitsluitend voor idempotent operaties gebruikt mag worden.

Wat eerder een security probleem kan zijn, lijkt me, is dat er via GET operaties bepaalde items opgehaald worden. Stel bijvoorbeeld: edit.htm?id=12

De gebruiker krijgt dan de details van item met id 12 te zien. Hier kan de gebruiker naar believen wijzigingen in aanbrengen (vb: edit.htm?id=1) en op die manier informatie bekomen die hij eigenlijk niet mag zien. Het blijft uiteraard een idempotent operatie, maar introduceert wel een security probleem.
 
 
quote:
-FoX- schreef op woensdag 21 mei 2008 @ 11:14:
Ik zou het ook niet meteen een 'security' probleem durven noemen, maar ik ben het wel met je eens dat GET uitsluitend voor idempotent operaties gebruikt mag worden.

Wat eerder een security probleem kan zijn, lijkt me, is dat er via GET operaties bepaalde items opgehaald worden. Stel bijvoorbeeld: edit.htm?id=12

De gebruiker krijgt dan de details van item met id 12 te zien. Hier kan de gebruiker naar believen wijzigingen in aanbrengen (vb: edit.htm?id=1) en op die manier informatie bekomen die hij eigenlijk niet mag zien. Het blijft uiteraard een idempotent operatie, maar introduceert wel een security probleem.
Je snapt dat dit net zo goed geld als voor POST he? Je moet GET hetzelfde beschouwen als POST wat het je applicatie betreft. Cookie gegevens beveilig je toch ook goed?
 
 
quote:
frickY schreef op woensdag 21 mei 2008 @ 09:22:
Wat is er mis met is_int(), is_float() en/of is_numeric() ?
Wat er mis is met is_int() en is_float() mag je zelf opzoeken in de documentatie 8)7
is_numeric() is dan wel weer handig voor floats. Ik dacht eerlijk gezegd dat deze ook true returnde bij een string als "10 apen", maar dat blijkt (gelukkig) niet zo te zijn. Nou de ints nog, want ctype_digit() geeft weer false voor negatieve (of expliciet positieve) ints.
quote:
-FoX- schreef op woensdag 21 mei 2008 @ 11:14:
Wat eerder een security probleem kan zijn, lijkt me, is dat er via GET operaties bepaalde items opgehaald worden. Stel bijvoorbeeld: edit.htm?id=12

De gebruiker krijgt dan de details van item met id 12 te zien. Hier kan de gebruiker naar believen wijzigingen in aanbrengen (vb: edit.htm?id=1) en op die manier informatie bekomen die hij eigenlijk niet mag zien. Het blijft uiteraard een idempotent operatie, maar introduceert wel een security probleem.
Over het algemeen is er niets mis mee om daar een GET te gebruiken. Je moet in de applicatie sowieso een check doen of de huidige gebruiker wel bij dat id mag komen. Dus als hij het id wil veranderen naar een ander id waar hij ook toegang tot heeft is daar niets mis mee.

Een uitzondering is bijvoorbeeld als je een wiki pagina wilt editten en daardoor de pagina lockt. Maar dat impliceert dat het niet meer idempotent is en moet je dus sowieso een POST gaan gebruiken.
 

VNU Media logo Powered by True

© 1998 - 2009 Tweakers.net - Alle rechten voorbehouden

Uitgever van: