Programming FAQ: Beveiligen van websitesMet dank aan ACM.Inhoudsopgave
Beveiliging websites, de basisHet is voor webapplicaties erg belangrijk dat ze al vanaf het begin 'potdicht' geprogrammeerd worden. Na serverbugs lijkt het er op dat de meest voorkomende 'hacks' direct gerelateerd zijn aan 'gevaarlijk' of 'lui' programmeren. Veel sites worden door beginnende webprogrammeurs in elkaar gezet en zijn vaak een erg simpel doelwit voor een beetje geoefende hackers.Uiteraard is een bezoekje van een hacker niet zo heel erg, deze mensen hebben meestal het beste met iedereen voor en zullen dan ook over het algemeen na het vinden van de fout weinig ongein uithalen. Naast de hackers heb je ook nog de crackers, zij zullen zich niet gestopt zien door morele waarden en na het vinden van een gat in de beveiliging van de website nog flink nagenieten van het zo erg mogelijk pesten van de sitebeheerders. Bij grotere websites is het wat lastiger, hacks zijn nog steeds uit te voeren (er vanuit gaande dat software nooit bugvrij is). Maar het is wel te hopen dat het bij dergelijke sites toch wel erg moeilijk gemaakt is en/of wordt. Ook hier zijn de hackers niet 'al te erg', daar dezen de gevonden fouten (vaak met een oplossing) rapporteren. Helaas menen sitebeheerders dit soort meldingen in de praktijk nog wel eens te moeten negeren, het is echter verstandig zo veel mogelijk dat soort meldingen gewoon na te gaan en te controleren. Wat erger is in dit geval zijn de professionele crackers, deze zullen veel moeite doen om belangrijke gegevens te achterhalen (voor verkoop of uit opdracht) of de website flink te verpesten (mogelijk om klanten naar het eigen bedrijf te sturen, want een site die down is verliest snel zijn vaste bezoekers). Naast de 'gewone' hacks op systeem en software niveau zijn er ook nog de DoS aanvallen en dan tegenwoordig steeds vaker in gedistribueerde varianten (DDoS). Het grootste nadeel van een goed opgezette DoS is dat er vrijwel niets aan gedaan kan worden. De gevolgen van DoS aanvallen zijn legio, waarbij in het beste geval na een korte downtime de service weer in de lucht komt. In ergere gevallen kunnen DoS aanvallen dagen of zelfs weken duren en zal de service daar wellicht blijvende schade aan ondervinden of zelfs failliet gaan, aangezien de ISP waarschijnlijk ook een flinke rekening voor het vele dataverkeer zal opsturen terwijl er geen geld binnenkomt. Een DoS is eigenlijk niets anders dan het 'zo vaak opvragen van de service dat die service overbelast raakt', met als overduidelijk gevolg dat er geen services meer aan normale klanten geboden kan worden. DoS betekent dan ook 'Denial of Service'. Mocht een site zelf wel tegen een DoS bestand zijn, dan kan het ook nog voorkomen dat de stap daarvoor bezwijkt (veelal de ISP of een deel van diens services), ook in dat geval is het gewenste doel al bereikt. Sommige software bezwijkt onder hevige DoS aanvallen en kan in erge gevallen zelfs veiligheidsgaten openzetten. Al deze aanvallen kunnen er toe leiden dat er gegevens van en over de klanten bij derden bekend raken, dit is niet alleen zeer onwenselijk maar ook nog eens wettelijk verboden. Naast de klantgegevens zijn er natuurlijk ook nog eens allerlei andere gegevens die niet aan derden bekend mogen worden. Behalve beschikbaarheid van de gegevens is het ook mogelijk dat de gegevens wijzig- of verwijderbaar worden, wat nog weer een gradatie erger is (vooral omdat dan ook de gegevens beschikbaar zijn). Risico's in meer detail en het voorkomen ervanGeen informatie verstrekkenHoewel een hacker/cracker niets hoort te kunnen doen met de gevonden informatie, is het altijd beter dat hij niet meer informatie over een site heeft dan strikt noodzakelijk voor het gebruik van de site. Elk beetje informatie kan een veiligheidsgat blootleggen of de impact van een hack vergroten doordat de hacker veel beter weet wat hij allemaal kan uithalen. Weliswaar is dit dan een fout van de programmeur, maar de hacker zal daar alleen maar dankbaar voor zijn.Dit neemt niet weg dat het over het algemeen een goed idee kan zijn om anderen naar je code te laten kijken. Dit hoeft niet te betekenen dat je meteen je code opensourcet, maar vier ogen (of meer) zien meer dan twee. Als je aan grotere projecten werkt in grotere teams, is het niet ongebruikelijk dat er een veiligheidsexpert in dienst wordt genomen om de security kant van de code door te nemen. Wat sourcecode betreft betekent dit dus dat zelfs als een cracker/hacker jouw code niet kan zien, hij de veiligheidsgaten nog steeds kan vinden - het duurt hooguit wat langer! Oftewel, closed source code verandert niks aan het security principe, hier moet je altijd op letten! Closed source code is op zichzelf absoluut geen beveiliging, het kan slechts een toevoeging zijn op andere beveiligingsmethoden! DoS aanvallen afslaanZoals gezegd is er tegen de DoS aanvallen erg weinig te doen, de meeste bescherming ertegen zal door de ISP geboden moeten worden. Eventuele zaken die de downtime en DoS-werking kunnen verminderen zijn flinke overcapaciteit, maar zelfs sites als Yahoo!, ebay, microsoft.com en amazon zijn gevoelig voor DoS. Een DoS hoeft namelijk niet per se gericht te worden op de primaire webservers, maar kan ook heel goed de secundaire services uit de lucht halen, waardoor een site alsnog down gaat.Aangezien hier dus zo goed als niets aan te doen is, is het belangrijkste dat er in dergelijke gevallen niet te veel gelogd wordt (er komt toch elke keer hetzelfde), een volle harde schijf wil nog wel eens een server laten crashen. Daarnaast is het belangrijk dat de software nooit ofte nimmer onder hoge load mag bezwijken, een simpele controle op de belasting van het systeem zou gedaan kunnen worden om vervolgens de (zware) service te 'verbieden', waardoor de DoS al een stuk minder grote impact heeft. Het is uiteraard overduidelijk dat de software al helemaal geen steekjes mag laten vallen op het gebied van de beveiliging. Firewalls halen verder erg weinig uit tegen DoS aanvallen, behalve dat ze zo ingesteld kunnen worden dat ze het aantal requests op de webservers slechts 'gedeeltelijk' doorlaten, wat tot gevolg heeft dat een DoS gericht op de service (en niet op de bandbreedte) vrij effectief gestopt kan worden dmv goede firewalling en configuraties. ServersoftwareTegen de meeste andere aanvallen is wel vrij goed op te treden door de sitebeheerders.De bugs in de serversoftware zijn over het algemeen vrij snel door de leverancier gerepareerd, hoewel Microsoft er nog wel eens laks mee om leek te gaan in geval van IIS. Zij hebben ondertussen hun software strategie toch maar (flink) omgegooid en zijn zich veel meer op veiligheid gaan richten. Het devies is hier dus 'blijf op de hoogte' en zorg ervoor dat de nieuwste patches altijd geïnstalleerd worden (als deze veiligheidsgerelateerd zijn). Dit geldt zowel voor het operating system, de webserver software als alle andere gebruikte pakketten en tools. Naast bugs in de besturings systemen en de gebruikte software zijn er ook nog een heleboel andere instellingen die fout kunnen gaan. Zo moeten de rechten voor de 'webserver uitvoerende' gebruiker hooguit op "leesrechten" staan voor de php files (zodat deze niet gemodificeerd kunnen worden) en mag er in principe op geen enkele plek "schrijfrechten" gegeven worden. Ook mag die 'gebruiker' geen administrator/root rechten hebben, omdat dit te veel vrijheid geeft, wat (bijna) nooit nodig is. De server mag uiteraard ook niet door teveel mensen beheerd worden en (liefst) alleen door capabele beheerders. Aanvallen op de software zelfAlle aanvallen op de software van de website zelf (de PHP, JSP, ASP, etc. code) zijn in principe altijd te voorkomen. In die paar gevallen dat ze niet voorkomen kunnen worden moet er flink nagedacht worden of er niet een andere manier is om het gewenste resultaat te bereiken, in veel gevallen is er een andere oplossing of is het dusdanig moeilijker te maken dat het niet meer een 'major issue' kwa veiligheid.Spoofing, voor authenticatie en autorisatieEr zijn grofweg twee aanvalsmethoden te bedenken, spoofing van de gebruiker en invoeren van (bewust) foute waarden.De eerste varieert van het spoofen van ip-verkeer tot en met het zich voordoen van een andere gebruiker door 'achter diens PC te gaan zitten'. In de meeste gevallen is hier een goed sessie systeem nuttig met een korte sessielevensduur. SessieID's mogen ook niet voorspelbaar zijn, evenals automatisch gegenereerde wachtwoorden. De authenticatie/autorisatie van een user is over het algemeen veel beter te regelen dmv sessies. Echter kan een sessie geen bescherming bieden tegen het zgn. 'kapen van sessies' (het verkrijgen van het sessieID) en/of het afluisteren van verkeer. Wel kan je een sessie tot op zekere hoogte nog beschermen tegen het kapen, door ze te koppelen aan het (vaste) ip van de gebruiker. Sessies kunnen op allerlei wijzen gekaapt worden, een van de manieren is daarvoor het afluisteren van het verkeer en dat is gelukkig weer goed te voorkomen met encryptie van de communicatie. De standaardmethode hiervoor is de SSL-tunneling van HTTP, via HTTPS, dit biedt een behoorlijk goede beveiliging tegen allerlei vormen van afluisteren. Naast het moedwillig kapen is het ook mogelijk dat allerlei tussenliggende proxyservers pagina's in hun cache opslaan, die per gebruiker specifiek zouden moeten zijn. Een goede proxyserver zal de cache instellingen uit de headers aflezen en die respecteren. Voor dat soort zaken is het dus ook verstandig de cache-control headers altijd mee te sturen (oa voor 'private' cacheing), zodat niet twee gebruikers elkaars sessies etc kunnen krijgen. Gebruik van Challenge/Response bij authenticatieMet dank aan: curry684Challenge/response is een methode om de authenticiteit van een gebruiker die in wil loggen min of meer te garanderen en het aftappen van user/password combinaties te voorkomen. Het zit als volgt in elkaar: Stel: user heeft password Piet en username Karel:
Enige zwakke punten:
Bij password veranderen kun je wel combinatiehashes trekken op basis van vorige password waardoor er geen lekbare data over de lijn gaat. SSL gebruikenEr moet dan uiteraard wel goed gecontroleerd worden of HTTPS ook daadwerkelijk gebruik wordt, het liefst moet ook de 'inlogpagina' zelf al via HTTPS getransporteerd worden. Die controle is vrij eenvoudig uit te voeren met; if($_SERVER['HTTPS'] == 'on'), maar lastiger te 'forceren'. Je kunt een gebruiker tenslotte niet dwingen ineens een https verbinding te hebben, maar hem dat slechts als mogelijke opties tonen.Naast HTTPS/SSL voor de verbinding met de gebruiker kan er ook nog gedacht worden aan een SSL verbinding met de betalingsinstanties en/of andere resources op het internet die geraadpleegd moeten worden. Deze zullen nog een gevaarlijker plek zijn, wat hackers en crackers betreft. Verder kunnen SSL-certificaten gebruikt worden om de gebruiker zich te laten authenticeren bij de server, dit zal in de praktijk niet veel gebruikt worden, maar bij erg belangrijke applicaties is een dergelijke oplossing wel noodzakelijk. Foute invoer controlerenHet is, helaas, ook mogelijk dat gebruikers 'malicious' htmlcode kunnen plaatsen op een site (overal waar gebruikers berichten achter kunnen/mogen laten). In dat geval kunnen ze door middel van een simpel stukje javascript heel simpel alle inhoud uit de cookies en de GET/POST-aanroep krijgen. Hiertegen is verder geen bescherming te bieden door de aanbieder van de site, behalve door het tegengaan van javascript en html 'plaatsbaarheid'.De andere grote veiligheidsgaten trekker is het opgeven van foute waarden. Vaak gaan programmeurs er vanuit dat 'als het niet in het vakje past, kan het niet gestuurd worden'. Dat is helaas niet waar met http en ook op geen manier echt vast te leggen. Mocht er dus clientside door (bijv.) javascript de invoer gecontroleerd worden, dan dient deze altijd aan de serverside gecontroleerd te worden. Er zijn in de php-wereld twee klassieke voorbeelden: Stel er is een script met code: PHP:
Dit soort code laat het toe dat er (bijna altijd) willekeurige code uitgevoerd kan worden. Er wordt verder geen controle op de waarde van $_GET["include"] uitgevoerd, een voorbeeld exploit van deze fout is dan ook: code:
In dit geval zal de code van het script (of de scriptoutput) http://gevaar.nl/foutscript.php uitgevoerd worden op de doelserver. Dit is overigens heel eenvoudig te voorkomen. De ene manier is controleren of de waarde van $include wel toegestaan is, door bijvoorbeeld met de functie in_array() te controleren of deze in een bepaald array zit of door bijv dmv een switch/case boom de waarde $_GET["include"] nooit in een include te gebruiken. PHP:
of PHP:
Een variant hier op is het direct invoeren van waarden in allerlei queries. De 'zwaardere' databases kunnen prima overweg met meerdere queries in één statement, waardoor er een groot gevaar schuilt in het volgende: PHP:
Als nu via een GET-aanroep de variabele $naam een waarde als: PHP:
is het overduidelijk dat dit geen gewenst resultaat gaat geven. Het grote gevaar schuilt hem erin, dat de uiteindelijke query tekst het volgende wordt: PHP:
Wat natuurlijk perfect aan de eisen van de database voldoet, maar niet echt aan die van de gebruiker. Dit soort zaken is erg simpel op te lossen door de ' te 'escapen'. PHP biedt daar onder andere functies als addslashes(), mysql_string_escape(),pg_string_escape() voor. Gerelateerd hieraan is het opgeven van stukken tekst waar getallen verwacht worden (door allerlei functies te controleren) en het opgeven van verkeerde waarden voor de hidden-input velden. Het kan namelijk ook erg vervelende gevolgen hebben als blijkt dat een opgegeven getal 'niet 0' is en er mee gedeeld wordt (of het getal niet eens opgegeven is). GET en POST variabelen door elkaar gebruikenEen andere variant op deze aanvalsmethode is het opsturen van variabelen via GET terwijl deze door middel van POST gestuurd had moeten worden, bij veel sites die en geïntegreerde gebruikersadministratie interface hebben was het mogelijk om door middel van GET-variabelen statussen van gebruikers te wijzigen.Dit lijkt niet erg, totdat je diezelfde gebruikers plaatjes laat plaatsen. Als een gebruiker dan een plaatje opgeeft in de trant van: jouwserver.nl/admin/useradmin.php?action=maakadmin&userid=1234 kan er allerlei ergs gebeuren. Als in dit geval de variabele $action met de (valide) waarde 'maakadmin' uitgelezen wordt dan zal de gebruiker met userid 1234 ineens administratorrechten hebben gekregen nadat een al bestaande administrator toevallig dat 'plaatje' laadde. Een erg groot deel van de publiekelijk verkrijgbare forumsoftware pakketen was kwetsbaar voor deze variant. De oplossing hiervoor is ook weer redelijk eenvoudig, maar vereist wel wat meer inzicht in http en een strikter programmeermodel. Men moet zichzelf verplichten de 'automatisch globale' variabelen (alle sessie, cookie, post en get variabelen in de oudere php-versies) niet te gebruiken. PHP biedt de mogelijkheid de aanroep te veranderen in varianten als: $_POST['action'] waarmee gekeken wordt naar de bij de POST-request opgestuurde variabele met de naam 'action'. Hiermee wordt gegarandeerd dat de variabele altijd dmv een POST-request gestuurd was, een vergelijkbare mogelijkheid is er voor de SESSION, SERVER, GET en COOKIE variabelen (ook is er nog de FILES, voor gePOSTte files). Strict gebruikmaken van deze array's is dus erg aan te raden en zou verplicht moeten zijn. Om dit 'verplicht' strikt te maken kan de optie 'register_globals' op Off gezet worden om het zelfs niet meer mogelijk te maken dat het anders werkt. Code testen en debuggenHet is natuurlijk altijd de bedoeling dat code goed gedebugged en getest wordt, bij PHP is het vrij eenvoudig om flinke fouten te maken omdat een variabele gebruikt wordt die helemaal niet bestaat. Mocht dat bekend worden bij hackers, dan is het zelfs mogelijk dat zij een waarde meegeven waardoor er ernstige problemen kunnen ontstaan. Om deze fouten tegen te gaan is het raadzaam dat de code geen waarschuwingen oplevert indien de foutmeldingniveau's op het laagst mogelijk gezet zijn. Dit is in te stellen dmv: error_reporting(E_ALL)Rechten altijd controlerenZowel bij het aanbieden als het uitvoeren van een bepaalde functionaliteit moet er gecontroleerd worden of de gebruiker wel recht heeft dat te doen. Bijvoorbeeld het recht op het bekijken van de backend en het daar wijzigen van teksten.Daar bovenop kan nog eens gecontroleerd worden of die gebruiker het recht heeft 'artikelen van anderen' te wijzigen en ga zo maar door. Aangezien HTTP stateless is, moet er bij elke actie gecontroleerd worden waar de gebruiker is in het stadium van een actie (hiervoor zijn sessies bedacht) en moet er dus ook altijd gecontroleerd worden of de rechten wel valide zijn. Anders zou iemand 'voorbij de eerste stap' in kunnen stappen en dan ineens wel toegelaten worden. Ook is het erg raadzaam bij 'belangrijke taken' de veiligheidsopties nog strakker aan te trekken. Het is bijvoorbeeld mogelijk om in zulk soort gevallen altijd opnieuw om het password te vragen. Bijvoorbeeld bij het wijzigen van gegevens of rechten van andere gebruikers. Naast het opgeven van passwords moeten deze passwords ook altijd 'moeilijk' zijn, zowel niet raadbaar als niet berekenbaar. En het is helemaal 'veilig' als deze passwords ook nog eens om de X uur (automatisch) te laten veranderen (bijvoorbeeld elke 2 weken). Goede password policies stellen normaliter als eis dat het password bestaat uit een variërende reeks tekens van minimaal 6 tekens, liefst met getallen, leestekens, hoofdletters en gewone letters door elkaar. Dit maakt het password niet raadbaar en nauwelijks 'brute forceerbaar'. Een password als 'jansen' is natuurlijk erg makkelijk te raden als de gebruiker zelf 'Jan Jansen' heet, echter zal 'gsa-3$@sfa' nooit geraden worden. Het grootste nadeel is dat het password niet makkelijk te onthouden is en daardoor nog wel eens op het scherm geplakt wordt met een post-it, dan is natuurlijk al het nut van een moeilijk password verdwenen. Firewalls en 'hard' afschermenSommige delen van de site worden maar door een bepaald aantal mensen gebruikt, dan is het in principe niet nodig dat andere mensen daarbij kunnen komen. En vaak is het dan raadzaam dat dat door middel van een goede firewall afgeschermd wordt. Ook kan de meeste webserversoftware zo ingesteld worden dat mensen vanaf een bepaald ip-adres wel (of juist niet) ergens bij kunnen. Want wat een hacker niet kan zien, kan hij niet of nauwelijks hacken. Vergeet echter niet dat de hack op een van de zwakste schakels gebeurd, mocht de computer met het toegestane ip-adres makkelijk over te nemen zijn, dan heeft deze beveiliging geen effect meer.Intruder detectionEen belangrijke functionaliteit om (het slagen van) hackpogingen tegen te gaan is het zogenaamde intruder detection. Hiermee wordt geprobeerd de hacker op te sporen op het moment dat hij binnenkomt, een soort alarmsysteem dus. De meest gebruikte respons is dan een mailtje naar de beheerder, een regeltje in de logbestanden en/of het (tijdelijk) afsluiten van het ip-adres van de hacker.Als een hacker tijdig gedetecteerd kan worden zal de impact en kans van slagen van een hackpoging veel verkleinen. Zelfs als de hacker weet binnen te komen is het nog verstandig dat hij gedetecteerd wordt, zodat hij niet ongestoord zijn gang kan gaan. Een voorbeeld van intruder detectie is; Als de sessie van een gebruiker gekoppeld wordt aan zijn ip-adres, kan het ontdekt worden dat de sessie ineens van een ander ip komt. Bij mensen met een vast ip-adres betekent dat dan vrijwel zeker dat de sessie gekaapt is. Een verstandige respons is dan om de sessie te vernietigen en in de logfiles te vermelden dat dit heeft plaatsgevonden. Ook wijst het vaak op 'problemen' wanneer gebruikers meerdere sessies hebben lopen vanaf dezelfde computer (bijvoorbeeld voor gebruiker A en gebruiker B, C en D), er moet natuurlijk wel rekening mee gehouden worden dat proxyservers ook op zo'n manier over kunnen komen. Een ander punt is natuurlijk het 'te vaak' fout intikken van wachtwoorden. Loggen van foutenOm achteraf bewijsmateriaal te verzamelen en fouten in de software tijdens routine controles op te sporen is het verstandig dat er veel gelogd wordt. Natuurlijk heeft het geen nut tien keer hetzelfde te loggen, maar een intelligente logging van (vooral) de belangrijke stappen binnen het gebruik van de site werpt zeker zijn vruchten af. Een van de standaard handelingen van een hacker is om de logfiles te verwijderen na en/of tijdens zijn werkzaamheden, het is dan ook verstandig de logfiles op een andere server te laten bijhouden, zodat de hacker daar niet (makkelijk) bij kan komen.Andere handelingen tijdens vermeende hackpogingenAls onderdeel van een DoS aanval kan het gebeuren dat een hacker/cracker zich honderden-duizenden keren probeert te registreren als gebruiker of andere handelingen verricht (bestellingen in een webshop), het is daarom raadzaam om in ieder geval dat deel van de site te kunnen uitschakelen. Vaak is het daarbij nog nuttig de site in 'onderhoudsmodus' te zetten, zodat niets meer werkt en de eventuele schade en/of fouten hersteld kunnen worden. Naast het kunnen uitschakelen van die opties met de hand, is het ook erg verstandig dit (deels) te automatiseren, waardoor de site zichzelf voor een deel en bijvoorbeeld alleen voor bepaalde ip-adressen deels of compleet uitschakelt. Veelal kan dit laatste gecombineerd worden met intruder detection.SlotwoordKritiek, op- en aanmerkingen kunnen hier: [RFC] Uitbreiding voor de FAQ, beveiliging website en hier [ALG] over de FAQ. Security: open source of niet? |
[ Voor 12% gewijzigd door NMe op 23-02-2012 23:17 ]
'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.