[PHP] Beveiling (POST)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Hoi,

Ik vraag me af hoe veilig een script is die input krijgt vanuit POST gegevens.
Ik bouw een web-app en 1 van de onderdelen die goed beveiligd moet zijn is het beoordelen.

Stel: een deelnemer die praktisch geen rechten heeft, weet alles wat hij moet weten:
De url voor het beoordelen en alle variabele die je nodig hebt. Normaliter kan een deelnemer hier niet achter komen, maar je weet het maar nooit (een andere gebruiker die zijn PC open laat staan)
Hij maakt een eigen formulier op zijn eigen webserver, en post het.

Nu zijn er een aantal dingen. Ten eerste gaat dit nog niet lukken, want hij is ingelogd met te weinig rechten om te mogen beoordelen, maar het baart me toch zorgen dat hij op die manier in het script kan komen. Een gebruiker met voldoende rechten kan zo wel dingen beoordelen die niet voor hem bedoeld zijn..
Hoe kan ik een form/referer van buitenaf blokkeren? Of nog beter: hoe kan ik enkel referers accepteren die ik wil? HTTP_REFERER staat niet op elke webserver aan namelijk.

Ten tweede: zijn SESSIONS te hacken? Daar in staat of, en hoe je ingelogd bent met welke rechten. Nu wordt er in die scripts opnieuw de inlog gecontroleerd, maar hij haalt dat toch echt uit de sessies.

Nu wordt alles gelogd, dus mocht het een keer iemand lukken, is dat te achterhalen. Maar ik ben benieuwd hoe mensen hier er over denken.

[ Voor 3% gewijzigd door Guillome op 31-07-2010 16:14 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Avalaxy
  • Registratie: Juni 2006
  • Laatst online: 14:31
Hoe ik het altijd doe:

Voor elke correct ingelogde user een session aanmaken, vervolgens op elke pagina checken of er wel een open session voor die user is, zo niet -> wegredirecten met PHP (niet met javascript!).

Tevens: elke keer als de user inlogt session_regenerate_id() gebruiken want sessions zijn, inderdaad, te capturen.

Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Avalaxy schreef op zaterdag 31 juli 2010 @ 16:33:
Tevens: elke keer als de user inlogt session_regenerate_id() gebruiken want sessions zijn, inderdaad, te capturen.
Let daarbij wel op eventuele request die gelijktijdig gaan, zoals bijvoorbeeld met plaatjes of "ajax"-requests, want dat gaat gewoon fout vroeg of laat.

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Die vat ik niet Erkens. Bij een aanroep van een PHP pagina wordt eerst de PHP afgehandeld, dus de sessie gecontroleerd. Dan pas naar de client, en dan pas afbeeldingen en ajax requests.
Ik snap sowieso niet waarom afbeelden hierbij gemoeid zijn, het gaat niet via .htaccess toch?

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Afbeeldingen zou je bijvoorbeeld via PHP kunnen aanroepen als je deze niet voor iedereen toegankelijk wilt hebben. De AJAX-request gaan toch ook via PHP? En zal je hoogst waarschijnlijk ook via eenzelfde check willen sturen.
Daarnaast zijn er ook steeds meer mensen die het gemak van meerdere tabs in de browser gebruiken waardoor je ook rekening moet houden met "oude" pagina's die verversen. (alleen van toepassing als je de sessies via de URL mee stuurd, cookies zullen zeer waarschijnlijk wel goed gaan dan).

Acties:
  • 0 Henk 'm!

  • Kalentum
  • Registratie: Juni 2004
  • Laatst online: 23:04
In de eerste plaats moet je je autorisatie goed hebben. Als gebruiker X pogingen doet om iets te beoordelen wat niet mag, bv door de url te wijzigen, dan moet je gewoon een foutmelding geven.

Verder kun je detecteren of de HTTP POST van een geldige bron komt:

De ING (inlog) gebruikt per sessie nieuwe namen voor formuliervelden. Open de inlog pagina maar in een browser en kijk hoe de namen zijn van de inputvakjes voor gebruikersnaam en wachtwoord. Als je een andere browser opent op diezelfde link dan zul je zien dat de inputvakjes andere namen hebben. Deze zijn gekoppeld aan de sessie van de gebruiker. Bij de ING in de sessie zal staan dat het veld 'username' binnenkomt als 'eygadcnakleu'. Klopt dat niet met de sessie, dan weet je dat de POST van een andere bron komt.

Een andere mogelijkheid is om elk HTML formulier een unieke random hash mee te geven in een hidden field. Die unieke hash plaats je ook in de sessie en laat je verlopen na een bepaalde tijd. Als je een formulier binnenkrijgt van de gebruiker en de unieke hash klopt niet met wat je in de sessie hebt staan, weet je dat het formulier vanaf een andere bron komt.
Zie bv http://www.codinghorror.c...srf-and-xsrf-attacks.html voor meer info.

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Ok dus dit zou veilig moeten zijn (nu nog met cookies, dat gaat straks een DB in, functie rand_str is als voorbeeld)

Formulier:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
  session_start();
  session_regenerate_id(); // na en enkel na het active inloggen
  setcookie("sid", session_id(), time()+3600); // gaat de database in: na en enkel na het active inloggen
  setcookie("check", ($check=rand_str()), time()+3600); // gaat ook de database in, in het session record
  
  function rand_str()
  {
    $s = "";
    for($x=0;$x<10;$x++)
      $s .= chr(rand(ord("a"), ord("z")));
    return $s;
  }
?>
<form method="post" action="hack2.php">
  <input name="user_ID" value="251" />
  <input name="ID" value="21" />
  <input name="beoordeling" value="2" />
  <input name="check" value="<?=$check;?>" />
  <input type="submit" />
</form>


En de ontvanger:
PHP:
1
2
3
4
5
6
7
8
9
<?php
  session_start();
  $h = getallheaders();
  $r = $h["Referer"];
  $d = $_SERVER["HTTP_HOST"];
  if (session_id() != $_COOKIE["sid"]) die("Foute sessie"); // haal uit DB, niet uit cookie
  if (!in_array($r, Array("http://$d/hack.php"))) die("Foute referer");
  if ($_POST["check"] != $_COOKIE["check"]) die ("Foute checksum"); // haal uit db. niet uit cookie
?>

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Feanathiel
  • Registratie: Juni 2007
  • Niet online

Feanathiel

Cup<Coffee>

Guillome schreef op zaterdag 31 juli 2010 @ 16:12:
Ten tweede: zijn SESSIONS te hacken? Daar in staat of, en hoe je ingelogd bent met welke rechten. Nu wordt er in die scripts opnieuw de inlog gecontroleerd, maar hij haalt dat toch echt uit de sessies.
Het ligt er maar net aan wat je onder hacken verstaat. De inhoud van een sessie is niet uit te lezen vanuit de client, tenzij je dat specifiek in een PHP script zet. Sessions zijn echter wel over te nemen. Stel dat jij op een website terrecht komt en daar een sessionnummer aangewezen krijgt, dan kan ik dit nummer overnemen en verder browsen onder jouw naam. Dit kan alleen als er geen maatregelen getroffen zijn.

Als je op een of andere manier het sessienummer kunt uitlezen, wat zeker mogelijk is, dan is het ook niet lastig om de 'checksum' uit te lezen. Deze wordt namelijk gewoonweg mee gestuurd als POST-parameter. Door slechts één (netwerk-)pakket uit te lezen, zou je toegang kunnen verkrijgen vanaf een pc van buiten af. In principe houdt je alleen de beginnende 'hacker' hier mee weg. Een beter alternatief zou zijn, om bijvoorbeeld op IP te gaan controleren, maar let hierbij ook op de nadelen hiervan. In ieder geval een gegeven dat niet door de gebruiker aangepast kan worden. Uiteraard helpt het HTTPS-protocol hier ook bij. Alleen een man-in-the-middle attack zou hierbij nog zin hebben (of je zou goed moeten kunnen gokken wat de combinatie van de checksum en het sessienummer is).

Acties:
  • 0 Henk 'm!

Verwijderd

@Guillome:

Zowel POST als COOKIE zijn 100% afhankelijk van de input van de client. Die controle is dus redelijk zinloos.

Ook de referer is onder de invloed van de client, het is de client die dit meestuurt en heeft dus niets met de server te maken. Daarnaast maak je het voor jezelf heel moelijk doordat je overal precies moet weten waar de gebruiker allemaal mogelijk vandaan moet komen. Een onderhoud nachtmerrie!

Helaas biedt je op deze manier dus geen goede beveiliging, je maakt het alleen zeer omslachtig waardoor het veiliger lijkt, maar feitelijk is dat het niet.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 22:57

crisp

Devver

Pixelated

rutgerw schreef op zaterdag 31 juli 2010 @ 17:12:
[...]
Een andere mogelijkheid is om elk HTML formulier een unieke random hash mee te geven in een hidden field. Die unieke hash plaats je ook in de sessie en laat je verlopen na een bepaalde tijd. Als je een formulier binnenkrijgt van de gebruiker en de unieke hash klopt niet met wat je in de sessie hebt staan, weet je dat het formulier vanaf een andere bron komt.
Zie bv http://www.codinghorror.c...srf-and-xsrf-attacks.html voor meer info.
Laatst nog een blogpost geschreven hoe wij gebruik maken van tokens hier op Tweakers.net: Crisp's blog: CSRF protection with 'self-validating' tokens

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Kalentum
  • Registratie: Juni 2004
  • Laatst online: 23:04
Verwijderd schreef op zaterdag 31 juli 2010 @ 20:49:
@Guillome:

Zowel POST als COOKIE zijn 100% afhankelijk van de input van de client. Die controle is dus redelijk zinloos.

Ook de referer is onder de invloed van de client, het is de client die dit meestuurt en heeft dus niets met de server te maken. Daarnaast maak je het voor jezelf heel moelijk doordat je overal precies moet weten waar de gebruiker allemaal mogelijk vandaan moet komen. Een onderhoud nachtmerrie!

Helaas biedt je op deze manier dus geen goede beveiliging, je maakt het alleen zeer omslachtig waardoor het veiliger lijkt, maar feitelijk is dat het niet.
Hij wil die cookies helemaal niet gebruiken, zie het commentaar in de code. Blijkbaar zullen die die in de database worden opgeslagen.

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Feanathiel schreef op zaterdag 31 juli 2010 @ 20:32:
[...]
Als je op een of andere manier het sessienummer kunt uitlezen, wat zeker mogelijk is, dan is het ook niet lastig om de 'checksum' uit te lezen. Deze wordt namelijk gewoonweg mee gestuurd als POST-parameter.
Dit kan toch niet? Dat ik vanaf mijn PC thuis een eigen formulier maak en erin kan?

In het pakket ben ik ingelogd als gebruiker met random rechten (maakt even niet uit), dan heb ik toch een sessie toegewezen gekregen welke in de database staat. Bij het beoordeelformulier wordt het checksum aangemaakt en in de DB gezet.

Als ik mijn eigen formuliertje wil verzenden weet ik toch niet welke checksum ik gebruiken moet? Als je de 'echte' pagina erbij pakt, kan je de checksum zien staan ja, maar dan nog klopt het sessie ID niet van de postrequest je eigen formuliertje.

Ik vind het lastig om te doorzien hoe je dit zou kunnen hacken. Ik ga de 2 genoemde links vandaag doorlezen

Edit:
Ik zie dat de referer idd zomaar gefaked kan worden, die optie valt dus af.
Edit2: al klopt de sessie_ID dan niet meer.....

[ Voor 7% gewijzigd door Guillome op 01-08-2010 11:29 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Feanathiel heeft het vooral over Man-in-the-Middle attacks, terwijl de rest het vooral over csrf heeft. Er worden hier goede oplossingen tegen csrf aangereikt, maar daarin zit niets dat voorkomt dat een authentieke request door een tussenschakel gewijzigd wordt. Voor bescherming tegen mitm heb je https (inc. certificate checks) nodig.

Deze 2 soorten aanvallen staan helemaal los van elkaar.

[ Voor 8% gewijzigd door Voutloos op 01-08-2010 11:34 ]

{signature}


Acties:
  • 0 Henk 'm!

  • Feanathiel
  • Registratie: Juni 2007
  • Niet online

Feanathiel

Cup<Coffee>

Voutloos schreef op zondag 01 augustus 2010 @ 11:31:
Deze 2 soorten aanvallen staan helemaal los van elkaar.
Daarom, het is maar net wat je onder een hack verstaat. Is het iemand extern of is het de persoon zelf? Er zijn meerdere soorten aanvallen waar je jouw website tegen zult moeten beschermen.

De MitM-attack kan trouwens ook worden doorgetrokken in de richting van de XSS (cross site scripting), waarbij de gegevens gewoonweg met behulp van AJAX wordt verstuurd naar een ongewenst persoon.

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Wat ik hier onder een hack versta is wanneer een gebruiker zonder rechten zichzelf of een ander een beoordeling kan geven

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • kevinkrs
  • Registratie: Juni 2010
  • Laatst online: 08-10 20:37
Als je de rechten nu in een sessie opslaat, en die mee post ben je er toch?

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Hoe bedoel je? Rechten staan al in de sessie, maar hoezo meeposten?

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Na meerdere keren het topic lezen mis ik nog steeds t probleem. Stel dat iemand die url heeft, zodra hij het op een of andere manier oproept (via browser danwel script) dan krijgt ie toch gewoon een keurige pagina te zien waarop staat dat ie gee rechten heeft?

Overigens staan mijn rechten in de database, niet in de sessie zelf. Sterker nog, ik gebruik geen sessies maar gewoon een cookie met een ID erin die matcht met een user via mijn session-tabel. Bij het inloggen staat het locken op IP automatisch al aan dus kopieren van het ID zal meestal niet lukken. Eventueel kun je nog checken op useragent.

Dat icm. crisp zijn oplossing voor CSRF lijkt het me vrij waterdicht.

Acties:
  • 0 Henk 'm!

  • Kalentum
  • Registratie: Juni 2004
  • Laatst online: 23:04
Cartman! schreef op zondag 01 augustus 2010 @ 20:04:
Overigens staan mijn rechten in de database, niet in de sessie zelf. Sterker nog, ik gebruik geen sessies maar gewoon een cookie met een ID erin die matcht met een user via mijn session-tabel. Bij het inloggen staat het locken op IP automatisch al aan dus kopieren van het ID zal meestal niet lukken. Eventueel kun je nog checken op useragent.
Wat is het grote verschil tussen PHP's sessie-implementatie en je eigen? En hoe hou je state bij? alles in de database?

Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Cartman! schreef op zondag 01 augustus 2010 @ 20:04:
Na meerdere keren het topic lezen mis ik nog steeds t probleem. Stel dat iemand die url heeft, zodra hij het op een of andere manier oproept (via browser danwel script) dan krijgt ie toch gewoon een keurige pagina te zien waarop staat dat ie gee rechten heeft?
Waarschijnlijk regelt de TS zijn beveiliging aan de clientside (door wel of niet bepaalde zaken in de HTML op te nemen), ipv aan serverside te controleren of de gebruiker wel de benodigde rechten heeft om een bepaalde actie uit te voeren.

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online
Waar baseer je dat nou op?
Een deelnemer met onjuiste rechten krijgt idd danwel de inlog pagina, danwel de foutmelding dat hij niet genoeg rechten heeft.
Maar een gebruiker met voldoende rechten kan via zijn eigen form acties uitvoeren die eigenlijk alleen via de site mogen gaan. Het baart me zorgen dat dat vanaf eigen formulieren kan gaan. Daar gaat mijn vraag over:
Hoe weet ik zeker dat een post-request door mijn site is gedaan.
Ik ga nu de aangeboden oplossingen doornemen

[ Voor 89% gewijzigd door Guillome op 02-08-2010 09:27 ]

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 20:49

Janoz

Moderator Devschuur®

!litemod

Remus schreef op maandag 02 augustus 2010 @ 09:10:
[...]


Waarschijnlijk regelt de TS zijn beveiliging aan de clientside (door wel of niet bepaalde zaken in de HTML op te nemen), ipv aan serverside te controleren of de gebruiker wel de benodigde rechten heeft om een bepaalde actie uit te voeren.
Nope. Topicstarter is bezig met zich te wapenen tegen CSRF. Iemand die wel de rechten heeft en ingelogd is naar een pagina lokken waarop je middels javascript verschillende POST request op de site afvuurt. Hierdoor kun je acties uithalen met het slachtoffer zijn rechtenset.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Guillome schreef op maandag 02 augustus 2010 @ 09:22:
Waar baseer je dat nou op?
Een deelnemer met onjuiste rechten krijgt idd danwel de inlog pagina, danwel de foutmelding dat hij niet genoeg rechten heeft.
Maar een gebruiker met voldoende rechten kan via zijn eigen form acties uitvoeren die eigenlijk alleen via de site mogen gaan. Het baart me zorgen dat dat vanaf eigen formulieren kan gaan. Daar gaat mijn vraag over:
Hoe weet ik zeker dat een post-request door mijn site is gedaan.
Ik ga nu de aangeboden oplossingen doornemen
Je weet dat HTTP stateless is toch? Technisch gezien bestaat er niet zoals als een post vanaf je eigen website. Een HTML formulier is niet anders dan een collectie van key/value waardes welke in de volgende request worden meegegeven. Je zou een random id kunnen genereren en dit id in zowel de sessie als formulier plaatsen. Bij de post kun je controleren of deze id's nog steeds kloppen en anders 400 status code (bad request) terug geven.

En als je bang bent dat iemand offline je formulier aanpast. Via browser extensies zoals greasemonkey zijn ook online formulieren te wijzigen bij jouw controle om. in het kort: Jij hebt geen controle of wat er gebeurt tussen het moment dat jij het formulier naar de browser stuurt en later weer terug komt. HTTP referer checks werken in de regel niet omdat veel security producten (zoals een anti-virus scanner zoals Norton Security) standaard de referer leegmaken uit privacy oogpunt.

Daarnaast als je een goede serversided validatie hebt om de inkomende velden, dan maakt het eigenlijk niet of iemand het formulier wel of niet wijzigd. Wat betreft het overnemen van sessies. Veel sessie providers bieden de mogelijkheid om sessies aan een IP te koppelen. Dit maakt het een erg stuk lastiger om sessies over te nemen, maar niet onmogelijk.

Tegenwoordig komt het overgrote deel van de hack pogingen vooral van scriptkiddies welke niets of weinig van de materie afweten. De hackers/crackers met voldoende kennis en mogelijkheden om man in the middle attacks te creëren zijn vooral geïnteresseerd in grote websites.

Als je frameworks zoals Joomla of WordPress is het vooral zaak om te zorgen dat je snel de updates installeert en vooral oplet met extensies voor dergelijke platformen. Veel van deze extensies zijn geschreven door beginnende programmeurs en zitten helaas vaak vol met exploits..

If it isn't broken, fix it until it is..

Pagina: 1