Beveiliging van mijn eigen CMS

Posted at January 19, 2012

You’ve found a dinosaur, this post is only here for archiving purposes. The content is outdated and is not applicable anymore.

In de post ga ik in op de beveiliging die ik heb toegepast op deze website. Ik verantwoord keuzes uit mijn ontwerp en leg uit hoe ik problemen heb opgelost. Graag rekening houden dat dit mijn eerste eigen PHP website is en ik alleen zaken heb beveiligd waarvan ik wist dat ze een mogelijk gat waren.

Data invoer

Dit is het meest voor de hand liggende punt probleem mbt. websites. Tot op heden heb ik er nog geen last van: Op het publieke deel van de website kan je geen informatie invoeren, op het admin kunnen blogposts aangemaakt en gewijzigd worden. In verband met het beoordelen van de website is het admin gedeelte nu openbaar, hierdoor wordt alle data invoer in het admin gedeelte (zodra de website live staat) niet weggeschreven.

Zodra de website beoordeeld is timmer ik het admin gedeelte dicht en kan niemand (behalve ik) data invoeren. Zodra iemand hier toch doorheen komt is mijn website compromised, het heeft dus geen zin om deze input verder te controleren.

Request forging

Als er een request binnenkomt en het geen request is voor een bestaande map of bestand wordt hij geroute naar index.php. Index.php handelt alleen requests af die ik zelf gedefinieerd heb.

Met alleen deze constructie is het dus mogelijk om core bestanden direct te requesten. Omdat 99% van mijn site OO, ofwel classes en omdat classes uitzichzelf bijzonder weinig doen (helemaal niks) ben ik al redelijk safe. Maar voor de zekerheid reroute ik alle requests van core files (en bijvoorbeeld cronjobs) naar mijn speciale pagina voor mensen die het toch proberen te slopen.

Dit doe ik met de onderstaande .htaccess code.

# prevent core files from being serverd or parsed
RewriteRule ^(core|views|import|libs|cron) sneaky [R,L]

Analytics

Ik heb mijn eigen analytics scripts geschreven in javascript. Alle data wordt via ajax overgepompt. Op mijn server aangekomen controleer ik de input door middel van regex.

Nu is dit onderdeel geen beveiligingsrisico omdat neppe requests alleen verwerkt worden in mijn database. Toch wil ik zeker weten dat mijn statistieken kloppen. Hiervoor wil ik nog een stapje verder gaan (dit is nog niet geschreven): Ik wil alle PHP sessie’s bijhouden zodra ze gemaakt worden, in een database stoppen en dit vergelijken met de requests. Zodra dit geen match is (of er een request wordt gedaan voor een verlopen PHP sessie) is het fake.

Bron code

Ik ben een fan van open data, ik heb dus gekozen om alle code achter deze website (op SQL wachtwoorden na) op Github te publiceren. Hier schuilt wel een gevaar aan: kwaadwillende kunnen zo supermakkelijk alles nalopen om gaten te zoeken. Ik ben bewust van dit gevaar, echter is deze website een leerervaring (en heb ik backups van alle data).

open data > maximale beveiliging

Admin gedeelte

Dit gedeelte is nu nog openbaar, zodra de website beoordeeld is timmer ik het dicht. Dat ga ik op de volgende manier aanpakken (nog niet geschreven):

  1. Ik ga bijhouden welke PHP sessie’s er op mijn website actief zijn (mede voor de zwaardere security in het analytics gedeelte).
  2. PHP slaat deze sessie op in een cookie.
  3. Ik sla op in een database zodra een sessie ingelogd is.
  4. Ik match de sessie uit het cookie met de ingelogde cookies uit de database.

Ik heb geen idee of dit ook echt veiliger is dan belangrijke data in een cookie opslaan. Maar los daarvan heb ik nu ook log met alle sessie’s (die ik kan matchen met tracking data) van iedereen die heeft ingelogd.