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

Disseny segur

La seguretat ha de ser una preocupació, no una funcionalitat. Afegir-la a posteriori és costós i poc efectiu: les decisions de disseny preses al principi determinen la superfície d’atac de tot el sistema.

Aquest document s’organitza en cinc seccions progressives. Els criteris de disseny estableixen els principis fonamentals que han de guiar qualsevol decisió arquitectònica. Les pràctiques de codificació tradueixen aquests principis en hàbits concrets. La verificació del codi presenta les eines per detectar problemes. La taula OWASP Top 10 connecta riscos reals amb els controls que els prevenen. Finalment, la llista de verificació proporciona un checklist pràctic per auditar el codi abans de posar-lo en producció.

Els documents següents apliquen aquests principis en àrees específiques: Control d’accés desenvolupa el registre, l’autenticació i l’autorització d’usuaris, i Tecnologies, protocols i pràctiques cobreix les implementacions concretes de protocols i eines.

Criteris de disseny

Aquesta és una llista de possibles criteris a tenir en compte per a dissenyar codi segur:

  • El menor privilegi: una entitat només ha de tenir el conjunt necessari de permisos per realitzar les accions per a les quals estiguin autoritzades, i cap altre més (per exemple, una connexió de base de dades que només necessita llegir no hauria de tenir permisos d’escriptura o eliminació).
  • Fail-Safe per defecte: el nivell d’accés predeterminat d’un usuari a qualsevol recurs del sistema hauria de ser “denegat” a menys que se’ls concedís un “permís” explícitament (per exemple, un nou endpoint d’API hauria de requerir autenticació per defecte, no ser públic fins que algú recordi protegir-lo).
  • Economia del mecanisme: el disseny ha de ser el més simple possible. Això els fa més fàcils d’inspeccionar i confiar (per exemple, una sola funció centralitzada de comprovació de permisos és més segura que verificacions disperses pel codi).
  • Mediació completa: un sistema ha de validar els drets d’accés a tots i cadascun dels seus recursos (per exemple, comprovar permisos no només a la interfície sinó també a l’API i a la consulta SQL).
  • Disseny obert: els sistemes s’han de construir de forma oberta, sense secrets ni algorismes confidencials (per exemple, la seguretat ha de dependre de les claus, no de mantenir l’algorisme en secret — principi de Kerckhoffs).
  • Separació de privilegis: la concessió de permisos a una entitat ha de basar-se en múltiples condicions, no només una (per exemple, requerir MFA per a operacions crítiques, no només la contrasenya).
  • Mecanisme menys comú: qualsevol cosa que es comparteixi entre diferents components pot ser una via de comunicació i un potencial forat de seguretat, i per tant s’han de compartir les dades mínimes possibles (per exemple, microserveis amb bases de dades separades en lloc d’una base de dades compartida).
  • Acceptabilitat psicològica: els mecanismes de seguretat no haurien de fer més difícil l’accés al recurs que si no hi fossin (per exemple, passkeys que substitueixen contrasenyes oferint més seguretat amb menys fricció per a l’usuari).
  • Responsabilitat: el sistema ha de registrar qui és responsable d’utilitzar un privilegi. Si hi ha abús, podrem identificar el responsable (per exemple, logs d’auditoria que registren qui ha accedit a dades sensibles i quan).

Pràctiques de codificació

Aspectes tècnics que potencien la seguretat del codi:

  • Immutabilitat: ens podem estalviar problemes associats a la integritat i disponibilitat de les dades.
  • Disseny fail-fast per contractes: establint clarament quines són les precondicions i postcondicions perquè quelcom funcioni correctament.
  • Validació: validem l’origen, la mida, el context, la sintaxi i semàntica de les dades que interactuen amb el sistema. Existeixen llibreries de validació per a tots els llenguatges principals.
  • Redueix l’acoblament i la superfície d’API exposada: utilitza els mecanismes de visibilitat del llenguatge per exposar només el mínim necessari.
  • Evita mecanismes que eludeixen el sistema de tipus (serialització, reflection, introspection) tret que sigui estrictament necessari.
  • No exposis credencials o informació personal al codi font o a arxius de recursos: utilitza variables d’entorn o un gestor de secrets.
  • Utilitza llibreries conegudes i testades, segueix les vulnerabilitats de dependències de tercers i actualitza a l’última versió.
  • Utilitza sempre prepared statements per a accés a bases de dades (evita SQL injection).
  • No mostris informació de la implementació als missatges d’error.
  • Controla que l’entrada al sistema no causi ús desproporcionat de CPU, memòria i espai de disc.
  • Allibera els recursos sempre: fitxers, connexions, memòria, etc.
  • Preveu overflows aritmètics en operacions amb enters: utilitza les funcions de comprovació que ofereixi el teu llenguatge o llibreria estàndard.

Verificació del codi

Tenim eines dinàmiques (que executen el codi) i estàtiques (analitzen el codi sense executar-lo).

Dinàmic — DAST (Dynamic Application Security Testing):

  • Proves d’integració i unitàries: cal dissenyar proves que verifiquin el comportament del codi. Cada llenguatge té els seus frameworks de test (JUnit, pytest, Jest, etc.).
  • Code coverage: eines que mesuren quin codi s’ha executat durant els tests i quins camins queden sense cobrir, ajudant a decidir on cal afegir test cases.

Estàtic — SAST (Static Application Security Testing):

  • Static code analysis: analitza el codi font sense executar-lo, detectant errors semàntics, patrons insegurs i vulnerabilitats. Eines com Semgrep o CodeQL són polivalents; la majoria de llenguatges tenen també eines específiques (SpotBugs per Java, Bandit per Python, clippy per Rust, etc.).

Per a una visió més completa de com integrar aquestes eines en pipelines CI/CD, vegeu la secció CI/CD Security.

OWASP Top 10

L’OWASP publica periòdicament el Top 10 de riscos de seguretat web i el Top 10 de controls proactius que tot desenvolupador hauria de conèixer. Són dues cares de la mateixa moneda: cada risc té un control que el prevé. La taula següent els relaciona i apunta a les seccions d’aquest curs on es desenvolupen en detall.

Risc (OWASP 2025)ControlDetall
Pèrdua del control d’accésControl d’accés granular, denegar per defecteAutorització, IDOR
Configuració incorrectaConfiguració segura per defecte, headers de seguretatSecurity Headers
Fallades en la cadena de subministramentAuditoria de dependències, SBOM, verificació d’integritatDependency Security, CI/CD Security
Fallades criptogràfiquesXifrar dades en trànsit i en repòs amb protocols establertsTLS/HTTPS, Secrets Management
InjeccióPrepared statements, validació d’entradesInjection Attacks, Input Validation
Disseny insegurIntegrar seguretat des del dissenyCriteris de disseny
Fallades d’autenticacióMFA, gestió segura de sessionsAutenticació, Factors combinats
Fallades d’integritatVerificació de dependències i pipelinesDependency Security, SRI, CI/CD Security
Logging i alertes insuficientsCentralització de logs, monitoratge i alertesLogging i Monitoring
Gestió incorrecta de condicions excepcionalsErrors segurs, IDs de correlació, no exposar informació internaGestió Segura d’Errors

Llista de verificació de seguretat

Aquesta llista és un punt de partida per a una revisió de seguretat abans de posar en producció una aplicació. No és exhaustiva, però cobreix els controls més crítics.

Autenticació i Gestió de Sessions

  • Les contrasenyes s’emmagatzemen amb un algorisme KDF (bcrypt, Argon2) amb salt
  • Les contrasenyes noves es comproven contra bases de dades de filtracions conegudes (HaveIBeenPwned)
  • Els missatges d’error d’autenticació són genèrics (no diferencien usuari inexistent de contrasenya incorrecta)
  • Les sessions es regeneren immediatament després del login
  • Les cookies de sessió tenen els flags HttpOnly, Secure i SameSite
  • Hi ha un idle timeout i un absolute timeout de sessió configurats
  • El logout invalida la sessió al servidor (no només elimina la cookie al client)
  • MFA disponible i recomanat per als usuaris

Control d’Accés i Autorització

  • Totes les peticions comproven autorització al backend, no al frontend
  • Les consultes a la base de dades filtren per l’usuari autenticat (prevenció d’IDOR)
  • Els rols i permisos es comproven al backend en cada petició
  • El principi de privilegi mínim s’aplica a rols d’usuari i credencials de base de dades
  • Cap camp sensible (rol, preu, estat) és modificable directament pel client (prevenció de mass assignment)

Validació d’Entrades i Sortides

  • Totes les entrades es validen per longitud, tipus i format (whitelist)
  • S’utilitzen prepared statements o ORMs per a totes les consultes SQL
  • Les sortides HTML s’escapen automàticament per prevenir XSS
  • Els fitxers pujats es validen pel contingut real (magic bytes), es renombren amb un UUID i s’emmagatzemen fora del web root

Gestió d’Errors i Logging

  • Els errors retornats a l’usuari no contenen stack traces ni informació interna
  • S’utilitzen IDs de correlació per relacionar errors d’usuari amb logs del servidor
  • Les pàgines d’error per defecte del framework estan desactivades en producció
  • S’enregistren els intents d’autenticació fallits, canvis de permisos i accés a recursos sensibles

Comunicació i Headers

  • HTTPS és obligatori i HSTS està activat
  • Les capçaleres de seguretat estan configurades: CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy
  • CORS no permet origens genèrics (*) quan hi ha credencials implicades
  • La protecció CSRF està activa (tokens CSRF o cookies SameSite)

Dependències i Configuració

  • Les dependències s’escanegen per vulnerabilitats en el CI/CD
  • Cap credencial ni secret està hardcoded al codi font ni al repositori
  • Els secrets es gestionen via variables d’entorn o un vault

APIs (si aplica)

  • El rate limiting protegeix els endpoints d’autenticació i les operacions costoses
  • Els errors d’API no exposen missatges interns de base de dades ni stack traces
  • La introspection de GraphQL està desactivada en producció