Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Control d’accés

El control d’accés inclou les activitats de registre, autenticació i autorització d’usuaris. És una de les àrees on els errors de disseny tenen més impacte: un sistema amb criptografia excel·lent però amb una gestió de sessions deficient continua sent vulnerable.

Aquest document cobreix les tres fases seqüencialment: com emmagatzemar credencials de forma segura en el registre, com verificar la identitat de l’usuari en cada petició (incloent gestió de sessions, emmagatzematge d’identificadors i autenticació multifactor), i com determinar quins recursos pot accedir un cop autenticat. Les tecnologies i protocols concrets (OAuth, JWT, WebAuthn) es desenvolupen a Tecnologies, protocols i pràctiques.

Registre

El registre d’usuaris té associat l’emmagatzematge d’aquella informació necessària per poder autenticar-los posteriorment. És important evitar deixar la informació en clar en fitxers o bases de dades, per estalviar-nos problemes de seguretat. També, evitar encriptar els passwords.

Un esquema habitual és l’ús de resums o hash. Si guardem el hash a la BBDD, no sabrem quin és el password, però podem comparar el que entra l’usuari amb el hash guardat, i dir si és el mateix.

Això només té un problema: hi ha taules preconstruïdes per a cercar les correspondències entre hash i password. Això ens obliga a afegir un string random (salt) al costat del password, i llavors el hash de tot plegat no és sempre el mateix per al mateix password. Aquest salt no ha de ser privat, compleix l’objectiu de fer inútils les tàctiques habituals per esbrinar passwords, i per tant es pot guardar en clar a la BBDD.

A l’hora de fer l’autenticació només haurem de fer la comparació entre el hash emmagatzemat i el calculat:

hash(salt + password1) és igual a hash(salt + password2)?

Una tècnica per a generar resums més segurs és el key stretching, que fa que la seva generació sigui lenta per a fer més difícil un atac de força bruta. Els algorismes KDF (Key Derivation Function) són un exemple.

A l’hora de definir una política de contrasenyes, les recomanacions actuals (NIST SP 800-63B) s’allunyen de les regles de composició obligatòria (majúscules, símbols, números) perquè generen patrons predictables com Password1!. En canvi, s’emfatitza la longitud: un mínim pràctic de 12-15 caràcters és més efectiu que la complexitat. No s’ha d’imposar una longitud màxima que trunci contrasenyes, ja que això és un indicador de comparació en pla.

Un complement essencial és la detecció de filtracions: en el moment del registre i de cada canvi de contrasenya, cal comprovar si la nova contrasenya apareix en bases de dades de credencials filtrades (com HaveIBeenPwned). Això es fa amb el model de k-anonimitat: s’envia únicament els primers 5 caràcters del hash SHA-1 de la contrasenya a l’API, i es comprova localment si el sufix del hash apareix en la llista retornada. Així mai s’exposa la contrasenya ni el hash complet.

Respecte al bloqueig de compte, el bloqueig dur després de N intents fallits és en si mateix un vector de denegació de servei contra usuaris legítims. Les alternatives preferides són: retard exponencial entre intents, CAPTCHA a partir d’un cert llindar, limitació de taxa per IP i notificació a l’usuari. Si s’utilitza bloqueig, hauria de ser temporal (desbloqueig automàtic als 30 minuts) i no requerir intervenció manual.

Finalment, el restabliment de contrasenya és una porta d’entrada crítica: els tokens de restabliment han de ser d’un sol ús, de durada limitada (15-30 minuts), i enviats per un canal verificat (correu electrònic o SMS al número registrat).

Autenticació

L’autenticació implica, habitualment, recollir la identificació de l’usuari per tal de comprovar la seva autenticitat.

Un cop tenim l’usuari autenticat, aquest pot rebre un identificador generat pel servidor i que el client haurà de fer arribar cada petició al servidor per tal de confirmar que està autenticat.

Les aplicacions client / servidor es poden diferenciar en dos tipus: stateful i stateless: amb i sense estat. Això es refereix al fet que el servidor emmagatzemi o no dades associades a l’usuari autenticat, el que s’anomena sessió.

  • Stateful: amb sessió i dades emmagatzemades al servidor. L’identificador generat és el de la sessió. El servidor passa un ID al client, que utilitza cada cop que es comunica amb el servidor. El servidor l’utilitza per obtenir les dades que té associades.
  • Stateless: sense sessió i dades emmagatzemades al client. L’identificador generat es diu token. Pot ser simplement un ID aleatori generat, però habitualment contenen informació associada que ha estat signada criptogràficament.

Identificador al client

A les aplicacions web, si un client està autenticat cal que li faci saber al servidor mitjançant algun tipus d’identificador secret. El client podria ser un navegador, si és una aplicació web d’usuari, o una aplicació client.

Si el client és un navegador, hi ha bàsicament dos esquemes per guardar aquest identificador al client: cookies i web storage.

  • Les cookies són part del protocol HTTP. Permeten guardar galetes nom/valor mitjançant una capçalera “Set-Cookie” des del servidor (resposta), i informen el servidor de les galetes actuals mitjançant una capçalera “Cookie” des del navegador.
  • El web storage és un mecanisme activable des del client exclusivament, mitjançant scripting. Tenim dos objectes, sessionStorage i localStorage, que permeten accions del tipus setItem/getItem sobre parelles nom/valor. No és un mecanisme que directament substitueixi les cookies, tot i ser semblants.

Aquestes dues tecnologies podrien emmagatzemar identificacions per accedir a aplicacions. Les cookies envien la informació directament al servidor, mentre el web storage permet gestionar la informació al client, exclusivament.

Si es tracta d’una aplicació client, aquesta informació la pot guardar el programari corresponent, i enviar-la quan calgui al servidor.

En el cas que l’identificador no estigui xifrat, és important que no sigui fàcilment deduïble per evitar que es puguin construir maliciosament (ID aleatori i llarg). JWT proporciona l’opció de xifrar la informació d’accés i autorització.

Les implicacions de seguretat dels dos mecanismes són molt diferents. localStorage i sessionStorage són completament vulnerables a XSS: qualsevol script que s’executi a la pàgina pot llegir i modificar tot el contingut, exposant tokens d’accés o informació sensible. IndexedDB té les mateixes vulnerabilitats respecte a XSS.

Les cookies amb HttpOnly no són accessibles des de JavaScript, protegint contra XSS. La flag Secure assegura que només es transmetin per HTTPS. SameSite=Strict prevé CSRF. Això fa les cookies molt més segures per emmagatzemar tokens de sessió o refresh tokens.

La millor pràctica per a SPAs és mantenir tokens d’accés en memòria (variables JavaScript), mai en localStorage. El token es perd quan es tanca el tab, però això és acceptable si és de curta durada (minuts). Un refresh token de llarga durada es pot guardar en una httpOnly cookie. Quan el token d’accés expira, JavaScript fa una petició a un endpoint específic que llegeix la refresh cookie i retorna un nou access token.

Enviament de l’identificador

A continuació, es comenten alguns possibles mètodes per a enviar l’identificador al servidor.

  • HTTP Basic Authentication utilitza una capçalera del tipus:

    Authorization: Basic base64(username:password)

  • Les cookies són el mètode més clàssic, i permeten dos headers especials, un del servidor:

    Set-Cookie: sessionId=shakiaNg0Leechiequaifuo6Hoochoh; path=/; Secure; HttpOnly; SameSite

    i un altre des del client:

    Cookie: sessionId=shakiaNg0Leechiequaifuo6Hoochoh

  • Els tokens (bearer) es passen utilitzant una capçalera:

    Authorization: Bearer ujoomieHe2ZahC5b

    Els tokens solen tenir un límit de validesa, i s’utilitzen sovint amb aplicacions stateless.

  • Les firmes (signatures) signen i envien les dades significatives de la petició en format formulari. Per exemple: APIs de serveis cloud.

  • Els certificats de client TLS realitzen un handshake abans de cap petició HTTP.

Factors combinats

L’autenticació es pot fer a partir d’alguna cosa que l’usuari sap, té o és. Podem tenir un sol factor d’autenticació, o combinar-los. És habitual tenir un doble factor d’autenticació en serveis més segurs.

Un segon factor habitual és el One-Time Password (OTP). Es poden basar en sincronització de temps o algorismes matemàtics que generen cadenes. Hi ha dues implementacions: HOTP i TOTP. La diferència és què comparteixen per generar la contrasenya: un comptador o el temps.

  1. El servidor crea una clau secreta per a l’usuari, i la comparteix amb un codi QR sobre una sessió segura (HTTPS).
  2. Les dues parts generaran l’OTP utilitzant un secure hash (tipus HMAC), i el servidor haurà de validar si és l’esperat.

La generació es fa amb aquesta fòrmula:

  • hash (shared secret + counter) = HOTP
  • hash (shared secret + time) = TOTP

Aplicacions TOTP com FreeOTP o andOTP emmagatzemen el secret i generen codis localment, sense requerir connexió a internet. La validació al servidor ha d’acceptar codis del període actual i adjacent per compensar el clock skew.

SMS i email com a segon factor són còmodes però menys segurs. Els SMS són vulnerables a SIM swapping, on un atacant convenç l’operadora per transferir el número de la víctima a una SIM controlada per l’atacant. L’email és tan segur com el compte de correu, que sovint està protegit només per contrasenya. Malgrat això, són millor que res i més fàcils d’adoptar per usuaris no tècnics.

La biometria (empremtes, reconeixement facial) proporciona una experiència d’usuari excel·lent. És important entendre que els sistemes moderns no emmagatzemen imatges de la teva cara o empremta, sinó templates criptogràfics derivats. En dispositius moderns, aquestes dades romanen en un enclavament segur del hardware (TEE/TPM) i mai surten del dispositiu.

Els backup codes són essencials per a la recuperació d’accés. Són típicament 8-10 codis d’un sol ús que l’usuari ha de guardar de manera segura. Quan es queden sense dispositius MFA, poden utilitzar un d’aquests codis per accedir i reconfigurar l’autenticació.

Autenticació amb sessió

Seguretat de sessions

La seguretat de les sessions comença amb com es transmet i s’emmagatzema el ID. Les cookies de sessió han de tenir les flags Secure (només per HTTPS), HttpOnly (inaccessibles des de JavaScript, protegint contra XSS) i SameSite (controla quan s’envien en peticions cross-site).

SameSite=Strict és el més restrictiu: les cookies només s’envien en peticions same-site. Això protegeix fortament contra CSRF però pot trencar fluxos legítims, com seguir un enllaç d’email a la teva aplicació. SameSite=Lax és un bon compromís: les cookies s’envien en navegació top-level (GET) però no en peticions cross-site POST o XMLHttpRequest.

La fixació de sessió és un atac on un atacant estableix l’ID de sessió de la víctima a un valor conegut abans que s’autentiqui. Després del login, l’atacant pot utilitzar aquest ID per segrestar la sessió. La defensa és simple: regenerar l’ID de sessió immediatament després de qualsevol canvi en el nivell de privilegi, especialment després del login.

Els timeouts de sessió proporcionen dues proteccions diferents. L’idle timeout invalida sessions inactives, protegint contra l’ús d’una sessió abandonada. L’absolute timeout invalida sessions després d’un període màxim independentment de l’activitat, forçant reautenticació periòdica. Els valors apropiats depenen de la sensibilitat de l’aplicació.

Single Sign-On (SSO) permet als usuaris autenticar-se un cop i accedir a múltiples aplicacions. OAuth/OIDC són els protocols estàndard moderns per implementar SSO. Quan un usuari s’autentica al proveïdor d’identitat (IdP), cada aplicació pot obtenir els seus propis tokens sense requerir credencials addicionals. La gestió de Single Sign-Out, on tancar sessió en una aplicació tanca sessió en totes, requereix coordinació entre aplicacions i l’IdP.

L’error més comú és no regenerar l’ID de sessió immediatament després del login. Si el servidor reutilitza el mateix ID que tenia l’usuari abans d’autenticar-se, un atacant que conegués aquest ID pot accedir a la sessió ja autenticada (session fixation). La regeneració és una crida a una funció, però si s’oblida obre una porta crítica.

Autenticació amb token

Autorització

Un cop l’usuari ha estat autenticat, hi ha un nombre de permisos que se li assignen en funció del seu rol dins de l’aplicació. Hi ha diferents formes d’assignar-los:

  • Nivell: els usuaris i les tasques tenen nivells, un usuari pot fer les tasques amb nivell igual o menor al seu.
  • Usuari: es fan parelles usuari-tasca (many2many)
  • Grup: un usuari té un grup, es fan parelles grup-tasca
  • Responsabilitat: un usuari pot tenir diversos grups

Un cop assignats els permisos, és important fer-los efectius en cadascuna de les interaccions de l’usuari amb el sistema. Això pot fer-se tant stateless (exemple: autoritzacions dins de JWT) com stateful (emmagatzematge a la sessió del servidor).

La majoria de frameworks implementen el model RBAC (Role-Based Access Control): els permisos s’assignen a rols, i els rols als usuaris. Per a escenaris més granulars, s’utilitza ABAC (Attribute-Based Access Control), on la decisió depèn d’atributs de l’usuari, del recurs i del context (hora del dia, IP d’origen, etc.).

Un error comú és comprovar l’autorització únicament a la capa de presentació (la interfície d’usuari). L’autorització s’ha d’aplicar a totes les capes: al controlador o endpoint de l’API, i a nivell de consulta a la base de dades. En particular, cal verificar que l’usuari autenticat és propietari de l’objecte específic que sol·licita, no només que té el rol adequat — vegeu la secció IDOR i Falles de Lògica de Negoci per al patró concret d’implementació.