Blogs

Blog #2: Pragmatische privacy voor programmeurs

In deel 1 van deze serie begonnen we met een eenvoudige aanpak om met privacy (AVG) om te gaan in een denkbeeldige Kitchen Sink app.

Uitkomst was een eenvoudige checklist voor elke feature, waarmee we kunnen zien of we alle privacy-vereisten naleven. Zelfs voor een simpele statische website moesten we een privacy-probleem oplossen, waarmee we uitkwamen op de volgende tabel:
 

Informatie over een persoon

Persoon identificeerbaar?

Ge-depersonaliseerd?

Plichten vervuld?

Rechten eigenaar voldaan?

Website-bezoek

Ja

Ja (Maskeren)✅

n.v.t.

n.v.t.

In deel twee gaan we aan de slag met een tweede increment voor Kitchen Sink.

Nog een beetje theorie

In deel 1 gaven we een korte definitie van privacy. Onderdeel daarvan was dat verwerkers* van persoonsgegevens bepaalde plichten moeten vervullen. Als we dat ook daadwerkelijk willen doen, moeten we natuurlijk weten wat die zijn.

(*) GDPR maakt onderscheid tussen de verantwoordelijkheden van verwerkers en verantwoordelijken. Voor het gemak gooien we die hier op één hoop.

Uitgaande van AVG zijn er zes principes (“beginselen”) voor het verwerken van persoonsgegevens:

  1. Rechtmatig, behoorlijk en transparant: een geldige reden hebben voor het verwerken van persoonsgegevens, die volgens verwachting gebruiken, en helder en open communiceren hierover.
  2. Doelbinding: gebruik persoonsgegevens alleen voor het gestelde doel
  3. Minimale gegevensverwerking: verzamel alleen persoonsgegevens die strikt noodzakelijk zijn
  4. Juistheid: draag er zorg voor dat persoonsgegevens correct zijn
  5. Opslagbeperking: bewaar de gegevens slechts zo lang als nodig is
  6. Integriteit en vertrouwelijkheid: bescherm persoonsgegevens tegen niet geautoriseerde inzage of wijziging
     

Dit zijn geen kant-en-klare plichten, maar ze helpen ons wel om de plichten die in AVG zijn uitgeschreven te plaatsen en groeperen. We kunnen ze dus goed gebruiken voor onze tabel.

IJverige lezers die de link naar AVG hebben gevolgd, is het wellicht opgevallen dat er nog een zevende principe wordt genoemd: verantwoordingsplicht. AVG noemt deze los van de rest, en het is een behoorlijk groot onderwerp, vandaar dat we dit in een apart artikel behandelen.

Increment 2: gootsteen-foto’s versturen

Om onze statische Kitchen Sink app wat “boeiender” te maken, gaan we nieuwe functionaliteit toevoegen: bezoekers kunnen een foto bestellen van een gootsteen (Kitchen Sink), en die sturen we per post op. Om dat te kunnen doen hoeven ze alleen maar hun adres te geven. We verwachten niet al te veel belangstelling, dus het versturen van de foto’s gaan we handmatig en gratis verzorgen.

Vanzelfsprekend hebben adresgegevens betrekking op een persoon, en een persoon kan zeker geïdentificeerd worden aan de hand van een adres. We voegen deze dus toe aan onze tabel:
 

Informatie over een persoon

Persoon identificeerbaar?

Ge-depersonaliseerd?

Plichten vervuld?

Rechten eigenaar voldaan?

Website-bezoek

Ja

Ja (Maskeren)✅

n.v.t.

n.v.t.

Adres

Ja

n.v.t.

n.v.t.

n.v.t.

Aangezien we zes plichten hebben, maken we daar ook weer een kleine tabel van:

Principe

Invulling

Controle

Rechtmatigheid

n.v.t.

n.v.t.

Doelbinding

n.v.t.

n.v.t.

Minimale gegevensverwerking

n.v.t.

n.v.t.

Juistheid

n.v.t.

n.v.t.

Opslagbeperking

n.v.t.

n.v.t.

Integriteit en vertrouwelijkheid

n.v.t.

n.v.t.

Rechtmatigheid

Het eerste principe is eigenlijk een groepje principes. Rechtmatigheid is de belangrijkste hiervan: hebben we een geldige reden voor het verwerken van persoonsgegevens. In ons geval hebben we een duidelijke functionele noodzaak: anders kunnen we de foto niet opsturen! AVG heeft zes geldige redenen voor verwerking van persoonsgegevens, en eentje daarvan is contractuele verplichting. Hoewel ons contract informeel is, is het wel van toepassing hier.

Dat betekent dat we moeten kunnen aantonen dat elk adres dat we opslaan gekoppeld is aan een contract. Een goede manier is – aangenomen dat we een relationele database gebruiken – om een één-op-één relatie aan te maken tussen de tabellen contracten en adressen, en deze af te dwingen met behulp van een foreign key constraint. Dit zorgt ervoor dat er geen adres kan worden opgeslagen zonder bijbehorend contract, en dat als het contract verdwijnt, het adres meegaat. (Als je een NoSQL-database hebt, of alle gegevens in contracten wilt opslaan moeten we zo’n check zelf schrijven.) De tabel ziet er nu zo uit:

Principe

Invulling

Controle

Rechtmatigheid

Contractuele verplichting

Contract (foreign key)

Het is vast opgevallen dat we “behoorlijk” en “transparant” hier onder het tapijt geschoven hebben. Beiden hebben niet echt verband met de soort plichten waar we hier naar kijken, maar eerder met de rechten van de eigenaar van de gegevens (zoals het recht op informatie). Daar kijken we in een toekomstig deel van deze reeks naar.

Doelbinding

We hebben gezegd dat we het adres gaan gebruiken voor het vervullen van een contract, namelijk het opsturen van een foto. Dat betekent dat we het nergens anders voor kunnen gebruiken, tenzij het “verenigbaar” is met dit oorspronkelijke doel. In ons geval is er niets anders waar we het voor willen gebruiken.

Dat betekent dat we wettelijk gezien deze adressen niet mogen gebruiken om, bij voorbeeld, iedereen kunnen aanmelden voor mijn nieuwe glossy Gootstenen. Maar onze applicatie werpt ook geen barrières op als we dat wel zouden willen doen. En als onszelf in de toekomst vertrouwen al lastig is, dat groeit alleen maar als er ook anderen bij betrokken zijn. Twee andere principes, opslagbeperking en minimale gegevensverwerking helpen hier al bij, maar we kunnen nog meer doen.

Zo zou eigenlijk niemand toegang mogen hebben tot de adresgegevens, behalve de personen (of processen) die dat echt nodig hebben. Dit valt onder het bredere principle of least privilege. In ons geval betekent dit dat de Kitchen Sink web app alleen schrijfrechten krijgt voor de adres-tabel, want het hoeft alleen nieuwe regels toe te voegen, maar deze niet uit te lezen, te wijzigen of verwijderen.

We kunnen de uitvoering hiervan testen door deze toegangsrechten in te lezen en te controleren dat alleen de gebruiker “post-verstuurder” toegang heeft tot de tabel adressen.

Principe

Invulling

Controle

Rechtmatigheid

Contractuele verplichting

Contract (foreign key)

Doelbinding

Toegangsbeperking

Test✅

Er is nog meer wat we zouden kunnen doen, zoals audit logging. Dat voorkomt weliswaar misbruik van adressen niet, maar kan dit wel helpen detecteren. Maar het opzetten van audit logging op een veilig en bruikbare manier is geen abc-tje, en voor onze eenvoudige app is dat een grote investering om een klein risico af te dekken. AVG staat dergelijke overwegingen toe voor beschermingsmaatregelen, en het is valide om een maatregel niet te nemen als er een acceptabel risico is.

Minimale gegevensverwerking

We mogen alleen persoonsgegevens verwerken die “toereikend, ter zake dienend en beperkt tot wat noodzakelijk is” zijn. We mogen dus geen informatie verzamelen die we niet nodig hebben voor het versturen van een brief, zoals een geboortedatum. Aan de andere kant hoeven we ook niet overdreven minimalistisch te zijn. Hoewel je in de praktijk een brief kunt versturen met alleen een huisnummer en postcode, zijn naam, straat en plaats wel degelijk relevant, en PostNL raadt het gebruik hiervan zelfs aan.

Als we niet naar het buitenland versturen, hebben we dus voldoende aan vier database-velden: naam, straatEnHuisnummer, postcode en plaats. Om te voorkomen dat er nog meer velden worden toegevoegd waar geen toestemming voor is, kunnen we een testje schrijven dat naar de kolomnamen van de adressen-tabel kijkt, en faalt als er een niet goedgekeurde kolom in staat.

Principe

Invulling

Controle

Rechtmatigheid

Contractuele verplichting

Contract (foreign key)

Doelbinding

Toegangsbeperking

Test✅

Minimale gegevensverwerking

PostNL adresvelden

Test✅

Juistheid

Als we persoonsgegevens verwerken, moeten we er zorg voor dragen dat die juist en actueel is en zo snel mogelijk wordt gecorrigeerd. Aangezien we de adressen maar bewaren tot we ze op een envelop hebben geschreven (zie opslagbeperking), hebben we geen proces nodig voor het bewerken of corrigeren van adressen. We moeten wel “redelijke” stappen nemen om zorgen dat wat we bewaren juist is.

Aangezien de impact van onjuiste gegevens in ons geval maar beperkt is, kunnen we wegkomen met wat simpele maatregelen. Invoer-validatie is een voor de hand liggende aanpak. Alle velden zijn in ons geval verplicht, en het formaat van de postcode moet correct zijn. We zouden een meer geavanceerde aanpak kunnen nemen, waarbij de postcode controleren tegen de straatnaam en postcode. Maar dergelijke diensten kosten geld, en dat is voor een gratis dienst als de onze te prijzig.

Naast de gebruikelijke unit tests voor de validatie-code zouden we ook naar de gegevens in de database kunnen kijken en dezelfde controles uitvoeren. Daarvoor moeten onze tests dan wel toegang hebben tot de database, en dat is niet ideaal. Beter is daarom deze vereisten als contract aan het datamodel toe te voegen, zoals bijvoorbeeld met checks in SQL-databases.

Principe

Invulling

Controle

Rechtmatigheid

Contractuele verplichting

Contract (foreign key)

Doelbinding

Toegangsbeperking

Test✅

Minimale gegevensverwerking

PostNL adresvelden

Test✅

Juistheid

Validatie gebruikersinvoer

Contract (kolomchecks)

Opslagbeperking

Als we persoonsgegevens niet meer nodig hebben voor de reden waarvoor we het verzameld hebben, moeten we ze verwijderen. In ons simplistische geval is dat zodra we het adres op de envelop hebben geschreven en deze in de brievenbus hebben gegooid. (In een iets realistischer situatie zouden we rekening willen houden met b.v. track-en-trace of retour-post.) Een eerste ingeving is om een adres handmatig te verwijderen zodra het is opgeschreven. Maar handwerk is gevoelig voor fouten en kan makkelijk worden vergeten, en dan blijven we wellicht zitten met gegevens die we niet zouden mogen bezitten.

Een geautomatiseerd proces is een robuustere oplossing. We zouden kunnen vastleggen wanneer de persoon die de post verstuurd het adres uitleest, en dan aan het einde van de dag een job uitvoeren die alle opgehaalde adressen verwijderen. We kunnen testen of dit goed werkt door het aantal opgehaalde adressen te tellen. (Dit heeft hetzelfde privilege-probleem als hierboven bij juistheid. Dit kan worden omzeild door een view te maken op de adressen-tabel).

Backups moeten we ook in overweging nemen. Database-backups zijn een goed idee, maar natuurlijk bevatten die dan ook persoonsgegevens. Aangezien we niet individuele adressen uit een backupbestand willen vissen, moeten we hier iets voor bedenken. In plaats daarvan kunnen we backups een beperkt aantal dagen (b.v. 30) bewaren en daarna weggooien. Dit is een vrij standaard aanpak, die ook wel rolling backups heet. Een test voor deze maatregel is te controleren dat de oudste backup file niet ouder dan 30 dagen is.

Principe

Invulling

Controle

Rechtmatigheid

Contractuele verplichting

Contract (foreign key)

Doelbinding

Toegangsbeperking

Test✅

Minimale gegevensverwerking

PostNL adresvelden

Test✅

Juistheid

Validatie gebruikersinvoer

Contract (kolomchecks)

Opslagbeperking

Automatisch verwijderen

Test✅

Opslagbeperking

Rolling backups

Test✅

Integriteit en vertrouwelijkheid

Dit is veruit het breedste en lastigste principe. Integriteit en vertrouwelijkheid zijn twee van de drie traditionele kernbegrippen uit de informatiebeveiliging, ook wel bekend als de CIA-triade. Het goed beveiligen van applicaties gaat ver buiten de scope van deze blogpost, maar gelukkig hebben vele anderen hier uitgebreid over geschreven (zie de lees-suggesties hieronder). Bovendien is ook het controleren van dergelijke maatregelen behoorlijk lastig. Zo heeft OWASP’s Application Security Verification Standard een kleine 200 controles die je zou moeten uitvoeren. Veel daarvan zijn lasting te automatiseren, kostbaar om uit te voeren, of allebei. Om toch een beeld te geven van wat je hier kunt doen, geef ik twee voorbeelden van maatregelen die we in Kitchen Sink treffen.

Om te beginnen kijken we naar HTTPS. Hoewel dit langzaamaan de standaard wordt, zijn er nog genoeg sites die het verkeer tussen browser en server niet beveiligen. Maar eigenlijk is er geen excuus meer hiervoor, zeker nu Let’s Encrypt gratis certificaten aanbiedt, en webservers als Caddy HTTPS standaard hebben aanstaan. Controleren of HTTPS goed is geconfigureerd is ook automatisch te testen met een gratis HTTPS-configuratie checker, zoals die van SSL Labs.

Een tweede beveiligingsprobleem, dat steeds gangbaarder wordt, zijn kwetsbaarheden in componenten van derden. Zelfs eenvoudige web apps zijn al afhankelijk van een web application framework, een programmeertaal, een webserver, een database, een operating system en diverse libraries om die allemaal aan elkaar te lijmen. Open source of niet, deze kunnen allemaal kwetsbaarheden bevatten, en die worden ook regelmatig ontdekt en misbruikt. De beste aanpak is om al je componenten regelmatig te controleren en te patchen, upgraden of vervangen. Dat is vaak nog een handmatig proces, maar gelukkig is er (gedeeltelijke) ondersteuning. Source control-gigant GitHub heeft ondersteuning voor detectie van kwetsbare libraries in sommige talen, evenals tools als Snyk of Dependabot.

Eerder spraken we al over het principle of least privilege, dat zorgt dat gebruikers minimale privileges hebben. Maar deze gebruikers-accounts moeten ook goed beveiligd zijn. Dat betekent dat er een wachtwoord of SSH-sleutel moet zijn, maar liefst ook een beperking in IP-adressen waarvandaan ze bereikt kunnen worden (zo is de database idealiter niet vanaf het hele internet bereikbaar). En bij gebruik van een SSH-sleutel of wachtwoord moeten die ook weer aan eisen voldoen, liefst afgedwongen door de database (zoals in MySQL met de password validation component). Helaas weet ik niet hoe je (makkelijk) zou kunnen nagaan of deze opzet goed werkt.

Principe

Invulling

Controle

Rechtmatigheid

Contractuele verplichting

Contract (foreign key)

Doelbinding

Toegangsbeperking

Test✅

Minimale gegevensverwerking

PostNL adresvelden

Test✅

Juistheid

Validatie gebruikersinvoer

Contract (kolomchecks)

Opslagbeperking

Automatisch verwijderen

Test✅

Opslagbeperking

Rolling backups

Test✅

Integriteit en vertrouwelijkheid

HTTPS

Test✅

Integriteit en vertrouwelijkheid

Veilige componenten

Test✅

Integriteit en vertrouwelijkheid

Sterke authenticatie

Dit laatste gat in de controle is typisch voor security. Hoewel er (kostbare) tools zijn die veel security-gaten kunnen detecteren is het uiteindelijk vaak nodig om zaken handmatig te controleren. Huur hiervoor bij voorkeur een professional in, maar wees niet bang om het eerst zelf te proberen.

Tot slot

Deze blog post is hiermee ten einde, maar de iteratie nog niet. We hebben nog steeds de kolom “Rechten eigenaar voldaan?” openstaan. In het volgende deel gaan we dat gat opvullen.

In de tussentijd kun je hier meer lezen over verwante onderwerpen:

  • Het Open Web Application Security Project heeft bergen informatie over beveiliging van web apps. De top 10 is het bekendste, maar slechts een klein deel van wat OWASP doet.
  • Het boek Software Security – Building Security In van security-veteraan Gary McGraw is al meer dan een decennium geleden uitgekomen, maar is nog altijd relevant (enkele op code gerichte stukken daargelaten)
  • De Australiër Troy Hunt schrijft en praat regelmatig over security, en heeft veel artikelen en videos geschikt voor beginners.

Reactie toevoegen

U kunt hier een reactie plaatsen. Ongepaste reacties worden niet geplaatst. Uw reactie mag maximaal 2000 karakters tellen.

Uw reactie mag maximaal 2000 karakters lang zijn.

Reacties

Er zijn nu geen reacties gepubliceerd.