Cookies zijn vereist voor de werking van deze website. Schakel cookies in om deze website op de juiste manier te kunnen gebruiken. Lees meer hier.

Beveiligde web server

Toegevoegd op 2019-01-13 15:56:00 UTC


Project op GitHub.

Samenvatting

De SecureWebServer is een .NET server applicatie die verschillende webpagina's beschikbaar stelt. De server luistert d.m.v. TCP sockets naar nieuwe HTTP verbindingen en handelt deze vervolgens af om de juiste pagina's te tonen en de interactie daarmee te verwerken. Hierbij zijn er verschillende maatregelen genomen om de server te beveiligen.

Het project is uitgevoerd voor de lessen die ik voor het vak Security heb gevolgd op mijn hbo-opleiding.

Inhoudsopgave

Functionaliteiten

Gebruikers kunnen de server benaderen via iedere browser. In eerste instantie komen ze op een homepage uit waar ze de mogelijkheid hebben om in te loggen. Hiermee krijgen ze toegang tot meer functionaliteit, afhankelijk van hun rechten.

Vanaf de homepage zijn verschillende pagina's beschikbaar. Zo is het mogelijk de configuratie van de server in te zien en te wijzigen. Daarnaast worden alle HTTP requests en responses gelogd en kan dit logbestand worden bekeken en gewist.

Hoewel er geen nieuwe gebruikers kunnen worden aangemaakt kunnen bestaande gebruikers en hun rechten wel worden gewijzigd.

Het is ook mogelijk om de mappenstructuur van de server door te bladeren, wanneer dit is ingeschakeld in de configuratie.

Configuratie

Bij het starten laadt de server een JSON configuratie bestand. Deze bevat de volgende instellingen:

  • Het poortnummer waarop de server luistert naar nieuwe verbindingen;
  • De hoofdmap waar alle HTML pagina's en overige bestanden in staan;
  • Een lijst aan standaard pagina's die als homepage gebruikt kunnen worden;
  • Of de bezoeker wel of niet door de mappenstructuur van de server mag navigeren.

Gebruikers kunnen de configuratie inzien en eventueel ook aanpassen, afhankelijk van hun rechten. Bij het aanpassen worden de nieuwe instellingen naar het JSON bestand weggeschreven. Wanneer de configuratie wijzigt wordt de RequestListener automatisch herstart met de nieuwe instellingen en wordt de gebruiker naar de hoofdpagina doorverwezen, eventueel met het nieuwe poortnummer in het geval dat deze is gewijzigd.

Componenten

Hieronder worden de belangrijkste componenten van de server omschreven.

RequestListener

De RequestListener luistert d.m.v. een TCP socket op een aparte thread naar nieuwe HTTP requests. Zodra er een nieuw request wordt gemaakt zal deze door de server op een nieuwe thread worden afgehandeld. De stream wordt uitgelezen en omgezet naar een RequestMessage, een object die alle uitgelezen gegevens van het HTTP request bevat. Het request zal vervolgens worden afgehandeld door de RequestHandler en wanneer daarbij een fout optreed zal dit worden afgehandeld door de ErrorHandler.

RequestHandler

De RequestHandler handelt alle HTTP requests af. Deze controleert eerst met behulp van de SecurityProvider of de gebruiker toegang heeft tot de aangeroepen URL, waarna er gezocht wordt naar een CommandHandler die verantwoordelijk is voor de afhandeling voor deze specifieke URL. Wanneer er geen CommandHandler gevonden kan worden zal de URL worden behandled als een pad naar een fysiek bestand of een map op de server. Uiteindelijk zal de RequestHandler een ResponseMessage object teruggeven aan de RequestListener zodat er een HTTP response naar de browser wordt teruggestuurd.

SecurityProvider

De SecurityProvider is verantwoordelijk voor de authenticatie en autorisatie van de gebruiker. Hieronder valt ook het in- en uitloggen van gebruikers en het instellen van een session cookie nadat de gebruiker met succes is ingelogd.

CommandHandlers

CommandHandlers zorgen voor de afhandeling van URL's waarbij niet simpelweg een statische pagina teruggegeven moet worden, maar waarbij er een speciale afhandeling voor nodig is. De server kent 7 aparte CommandHandlers.

  • IndexCommandHandler: Verantwoordelijk voor het tonen van de homepage. Bepaalde links op de pagina worden wel of niet getoond, afhankelijk van of de gebruiker is ingelogd en welke rechten deze heeft.
  • ConfigCommandHandler: Toont de configuratie van de server en geeft gebruikers met de juiste rechten de mogelijkheid om deze aan te passen. Bij het wijzigen van de configuratie wordt de gebruiker doorverwezen naar de homepagina met een nieuwe URL wanneer de poort ook verschilt.
  • LogCommandHandler: Toont de inhoud van het log4net log bestand waarin alle requests en responses worden bijgehouden. Gebruikers met de juiste rechten kunnen het logbestand ook leegmaken.
  • LoginCommandHandler: Handelt het inloggen van een gebruiker af.
  • LogoutCommandHandler: Handelt het uitloggen van een gebruiker af.
  • UserOverviewCommandHandler: Geeft een overzicht van alle gebruikers die op de server in kunnen loggen.
  • UserEditCommandHandler: Geeft de mogelijkheid om de informatie en de rechten van een gebruiker aan te passen.

ErrorHandler

Wanneer er een exception optreed in de applicatie en deze door de RequestListener afgevangen kan worden, zal deze worden doorgestuurd naar de ErrorHandler. Deze onderscheidt twee soorten exceptions.

  • RequestException: Dit is een exception die overal vanuit de code bewust kan worden veroorzaakt, waarbij er een HTTP status code meegegeven kan worden en eventueel ook een foutmelding voor de gebruiker.
  • Andere exceptions zorgen voor een Internal Server Error status code (500) en hierbij wordt er geen foutmelding aan de gebruiker getoond maar een statische pagina.

De ErrorHandler zorgt er vervolgens voor dat de gebruiker de juiste statische foutpagina te zien krijgt voor de desbetreffende status code. Als er geen statische foutpagina gevonden kon worden zal de foutmelding, indien meegegeven, als plain-text worden getoond aan de gebruiker.

Authenticatie

Authenticatie gebeurt d.m.v. een gebruikersnaam en wachtwoord. De server biedt niet de mogelijkheid om gebruikers aan te maken, maar wel om met bestaande gebruikers in te loggen die al aanwezig zijn in een SQL database.

Wachtwoorden zijn opgeslagen in de database als een SHA-512 hash waarbij een unieke salt is gebruikt.

Na succesvolle authenticatie wordt de gebruiker en zijn of haar rechten in-memory gecached met een sliding expiration van 20 minuten. Voor deze sessie wordt een token gegenereerd en als cookie mee teruggestuurd in de response headers.

Autorisatie

Bepaalde URL's of acties zijn niet beschikbaar voor gebruikers tenzij ze de juiste rechten hebben. De server kent hiervoor 2 gebruikersrollen.

  • Beheerders: Deze gebruikers mogen de server configuratie inzien en aanpassen. Ook kunnen ze het logbestand inzien en leegmaken. Tot slot kunnen ze ook gebruikers en hun rechten beheren.
  • Ondersteuners: Deze gebruikers kunnen ook de server configuratie inzien, maar niet aanpassen. Hetzelfde geldt voor het logbestand, die ze alleen maar kunnen bekijken. De gebruikers beheer en overzicht pagina's zijn helemaal niet beschikbaar.

De rechten die nodig zijn voor bepaalde URL's staan in de app.config van de webserver geconfigureerd.

Beveiliging

Om de server te beveiligen zijn er een aantal maatregelen genomen. Met name is er gekeken naar de OWASP Top 10 (2013). Vanwege o.a. tijdsgebrek en andere beperkingen zijn niet alle gewenste maatregelen toegepast.

Wel toegepast

  • SQL injection preventie: Variabele waarden in SQL queries worden als SQL parameters meegestuurd. Hierdoor wordt invoer niet klakkeloos in de query zelf geplaatst waarmee de kans op SQL injection wordt tegengegaan.
  • Wachtwoord hashing: Wachtwoorden worden met SHA-512 gehashed waarbij een unieke salt wordt gebruikt om de hash uniek te maken.
  • Sessie tokens als cookie: Sessie tokens worden niet in de URL meegegeven maar als cookie opgeslagen. Doordat de cookie geen expiration heeft zien browsers het ook als een session cookie en wordt deze opgeruimd zodra de browser wordt gesloten. Aan de kant van de server worden sessies weggegooid als er langer dan 20 minuten geen activiteit is geweest.
  • Gebruikersrollen: Voor sommige URL's en acties zijn bepaalde rechten nodig. Bij het uitvoeren hiervan wordt er gecontroleerd of de gebruiker de juiste rechten heeft door te kijken of deze in de juiste rol zit.
  • Geen directe verwijzingen: Er worden geen directe verwijzingen naar resources gedaan, zoals bijvoorbeeld ID's die in de database staan.
  • Geen stacktraces in foutmeldingen: Bij foutmeldingen worden statische pagina's getoond of een foutmeldingen die bewust is meegegeven. Er worden geen stacktraces in beeld getoond wanneer er bijvoorbeeld een Internal Server Error (status code 500) is opgetreden.
  • Cross-Site Scripting preventie: Cross-Site Scripting (XSS) wordt tegengegaan door bij wijzigingen de invoer te controleren op een geldig formaat. Ook wordt er gebruik gemaakt van de Content-Security-Policy en X-XSS-Protection response headers.

Niet toegepast

  • HTTPS: I.v.m. complexiteit en doordat de server alleen lokaal te draaien hoefde te zijn wordt er geen gebruik gemaakt van HTTPS.
  • Cross-Site Request Forgery preventie: Vanwege tijdsgebrek is er geen Cross-Site Request Forgery (CSRF) preventie toegepast.

Wesley Donker

Software Engineer

Nederland