Blog: Hvordan implementeres autentificering korrekt?

Gennem tiden har jeg flere gange implementeret forskellige former for
autentificering. Nogle gange har jeg været bundet af forskellige
protokol-beslutninger og andre gange har jeg været mere frit stillet.

Derfor har jeg også haft mulighed for at samle mig en række ideer om hvordan
autentificering bør gøres rigtigt. De falder i 3 dele: 1) Forarbejdet på
klienten, 2) selve autentificerings-protokollen og 3) implementationen på
serveren.

Forarbejdet på klienten

Forarbejdet på klienten består i at tage brugerens input og omforme det til en
sekvens af bytes der kan bruges som det egentlige kodeord.

Tidligere viste man bare brugeren et password-felt og brugte hvadend brugeren
nu tastede. Hvis man i dag vil bruge kodeord skal man blandt andet forholde
sig til at i Unicode er et ‘Å’ ikke bare byte-sekvensen 0xC5, men kan skrives
på (mindst) to forskellige måder i Unicode og dernæst kan kodes i både UTF-8, UCS-2
og et par flere måder. Et godt udgangspunkt er
RFC 4013 (SASLprep).

Hvis man er mere eventyrlig kan man erstatte password-feltet med noget mere
visuelt. Eksempelvis man man lade brugeren tegne streger på et 16×16 grid af
ikoner og så omforme dette til en byte-sekvens. Jeg har set en del forslag til
hvodan dette skulle se ud, men ingen der rigtig har overbevist mig. Nogen der
har et rigtig godt eksempel på mere visuelle kodeord brugt i praksis?

Som det sidste skridt bør man vælge at obfuskere brugerens kodeord. Formålet
er første og frememst at beskytte brugere der vælger samme kodeord til
forskellige systemer; men det yder også en vis beskyttelse mod kodeord der kan
gættes via en ordbog. Forskellige muligheder er
PBKDFv2 eller
scrypt. I begge
tilfælde skal man vælge et salt som er specifikt for ens system.

Det er resultatet af det sidste skridt serveren skal kunne sikre sig at
brugeren kender (herefter kaldt kodeordet). Det vil sige at hvis man kender dette resultat, så kan man udgive sig for at være brugeren.

Selve autentificerings-protokollen

Den helt simple protokol er bare at sende hele kodordet til serveren, der så
kan slå op i brugerdatabasen for at tjekke om kodeordet er korrekt. Det
betyder at en angriber der kan lytte med kan opsnappe kodeordet og bruge det
senere. Det kan enten ske fordi man har glemt at bruge SSL, fordi SSL er noget
juks eller fordi brugeren forbinder sig til et forkert eller kompromiteret
server.

Det vi gerne vil opnå er at selvom det skulle lykkes en angriber at lytte med
på selve autentificeringen, så skal angriberen ikke senere kunne udgive sig
for brugeren. Det vil sige at man ikke må kunne gætte selve kodeordet ud fra
kommunikationen mellem klienten og serveren.

For at opnå dette kan man hashe kodeordet sammen med en vilkårlig streng som
serveren vælger og en streng som klienten vælger. Et godt udgangspunkt er at
se på RFC 5802 (SCRAM), men ideen er den
samme som HTTP Digest mode hvis man
anvender MD5-session metoden.

Denne slags challenge/response protokoller kræver dog at serveren har adgang
til brugerens kodeord og ikke bare en hash af kodeordet. Det stiller nogle
højere krav til opbevaringen af kodeord på serveren.

Implementationen på serveren

Oftest vil angreb være rettet mod at kompromitere selve serveren. Det mest
indlysende er at angriberen simpelthen kanhente en liste af brugernavne med
tilhørende kodeord i en eller anden form. Selv hvis kodeordene er salted og
hashet efter bedste evne giver det angriberen mulighed for kunne gætte kodeord
i ro og mag.

Et godt design vil derfor minimere mængden af kode der har adgang til hele
listen af kodeord. Derfor mener jeg man bør implementere autentificering som
en selvstændig service, der kan beskyttes uafhængigt af resten af
applikationen. Helt enkelt kan det gøres med en database hvor applikationen
ikke kan lave en ‘SELECT * FROM passwords’ men kun kan validere enkelte
passwords med en stored procedure ‘SELECT authentificate(username,salt,hash)’.

På denne måde vil et sikkerhedshul i et tilfældigt plugin til ens CMS ikke
længere kunne kompromitere hele listen af kodeord. Forsøg på at gætte kodeord
vil i hvert enkelt tilfælde kunne ses på autentificerings-servicen.

Med ovenstående seperation mellem adgang til kodord og resten af systemet
mener jeg at man får et mere sikkert system ved at have adgang til kodeord i
klartekst og bruge en challenge/response protokol end med et system hvor man
gemmer brugernes kodord i hashet form, men sender denne form over netværket.

Posted in computer.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>