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

Tecnologies

Introducció

Aquest document és una referència no exhaustiva de les tecnologies, protocols i pràctiques que permeten construir sistemes segurs.

Autenticació i Autorització

OAuth i OpenID Connect

OAuth 2.1 és el protocol estàndard per a autorització delegada en aplicacions modernes. Representa una evolució d’OAuth 2.0 que incorpora les millors pràctiques de seguretat apreses durant anys d’implementacions. El canvi més significatiu és que PKCE (Proof Key for Code Exchange) ja no és opcional sinó obligatori per a tots els fluxos d’autorització. Això protegeix contra atacs d’intercepció de codi d’autorització, especialment rellevant en aplicacions mòbils i Single Page Applications.

El flux principal és l’Authorization Code Flow amb PKCE. El client genera un verificador aleatori (code verifier) i envia el seu hash (code challenge) quan sol·licita autorització. Quan intercanvia el codi per un token, ha de proporcionar el verificador original. Això assegura que només el client que va iniciar el flux pugui completar-lo, fins i tot si un atacant intercepta el codi d’autorització.

Per a comunicació màquina a màquina, on no hi ha un usuari interactiu, s’utilitza el Client Credentials Flow. El client s’autentica directament amb les seves credencials (normalment un client ID i secret) i obté un token d’accés. És crucial que aquestes credencials es mantinguin segures i no s’incloguin mai en codi client públic.

OAuth 2.1 depreca explícitament l’Implicit Flow i el Password Grant. L’Implicit Flow retornava tokens directament a la URL, exposant-los a l’historial del navegador i logs de servidor. El Password Grant requeria que l’aplicació gestionés directament les contrasenyes dels usuaris, violant el principi de delegació d’OAuth.

OpenID Connect (OIDC) és una capa d’identitat construïda sobre OAuth 2.1. Mentre OAuth gestiona autorització (què pots fer), OIDC gestiona autenticació (qui ets). Afegeix un ID Token, que és un JWT signat que conté informació sobre l’usuari autenticat. Aquest token està pensat per al client, no per enviar-lo a APIs. Per obtenir més informació sobre l’usuari, els clients poden consultar el UserInfo endpoint.

OIDC també proporciona descobriment automàtic de configuració. Un provider publica la seva configuració en un endpoint conegut (/.well-known/openid-configuration), permetent als clients configurar-se automàticament amb els endpoints correctes, algoritmes suportats i altres metadades. Això simplifica la integració i permet actualitzacions del servidor sense canvis al client.

La gestió de sessions en OIDC permet als clients detectar quan un usuari ha tancat sessió al provider. Això és especialment important en aplicacions empresarials on el Single Sign-Out és un requisit.

JSON Web Tokens

Els JSON Web Tokens (JWT) són l’estàndard de facto per a tokens d’accés en APIs modernes. Un JWT té tres parts separades per punts: header, payload i signature. El header especifica el tipus de token i l’algoritme de signatura. El payload conté les claims (afirmacions) sobre l’usuari i el token. La signature assegura que el token no ha estat alterat.

Per a aplicacions on el client no pot mantenir secrets (SPAs, apps mòbils), s’han d’utilitzar algoritmes asimètrics com RS256 o ES256. El servidor signa amb la seva clau privada, i qualsevol pot verificar amb la clau pública. HS256, que utilitza una clau simètrica, només és apropiat per a comunicació servidor a servidor on ambdós extrems poden mantenir el secret de manera segura.

Les claims estàndard tenen significats específics: iss identifica qui ha emès el token, sub identifica el subjecte (usuari), aud especifica per a qui està destinat, exp marca quan expira, iat quan va ser emès i nbf abans de quina data no és vàlid. La validació estricta d’aquestes claims és fonamental per a la seguretat.

Una pràctica essencial és mantenir els tokens d’accés de curta durada, típicament entre 5 i 15 minuts. Això limita la finestra d’oportunitat si un token és compromès. Per evitar que l’usuari hagi de reautenticar-se constantment, s’utilitzen refresh tokens de llarga durada que permeten obtenir nous tokens d’accés. Els refresh tokens s’han de rotar cada vegada que s’utilitzen: quan el client utilitza un refresh token, rep un nou token d’accés i un nou refresh token, invalidant l’anterior. Si un refresh token robat s’utilitza, el servidor detecta la reutilització i pot revocar tota la cadena de tokens.

L’emmagatzematge de tokens al navegador és un tema complex. Les cookies amb flags HttpOnly, Secure i SameSite=Strict són generalment més segures que localStorage perquè no són accessibles des de JavaScript, protegint contra XSS. Tanmateix, són vulnerables a CSRF si no es protegeixen adequadament. localStorage és vulnerable a XSS però immune a CSRF. En aplicacions crítiques, combinar ambdós enfocaments (token d’accés en memòria, refresh token en httpOnly cookie) ofereix el millor balanç.

Passkeys i WebAuthn

WebAuthn representa un canvi fonamental en l’autenticació web, movent-nos d’un model basat en secrets compartits (contrasenyes) a un model de criptografia de clau pública. Quan un usuari es registra, el navegador (o dispositiu) genera un parell de claus criptogràfiques. La clau pública s’envia al servidor, mentre que la clau privada mai surt del dispositiu de l’usuari.

Durant l’autenticació, el servidor envia un repte (challenge) aleatori. El dispositiu signa aquest repte amb la clau privada, i el servidor verifica la signatura amb la clau pública emmagatzemada. Això elimina completament els atacs de phishing tradicionals: no hi ha contrasenya per robar, i les credencials estan vinculades al domini específic.

FIDO2 és l’estàndard que permet als passkeys sincronitzar-se entre dispositius de l’usuari. Això resol el problema històric de l’autenticació sense contrasenya: què passa si perds el dispositiu? Els passkeys emmagatzemats al clauer d’Apple, Google Password Manager o Windows Hello es sincronitzen de manera xifrada, proporcionant tant seguretat com usabilitat.

La implementació requereix suport tant al client (navegador) com al servidor. El client utilitza l’API WebAuthn del navegador per crear credencials i generar assertions. El servidor ha de validar aquestes assertions, verificant signatures i comprovant que el repte, origen i altres paràmetres són correctes.

Els navegadors moderns suporten conditional UI (o passkey autofill), que mostra passkeys disponibles directament en el camp d’usuari, proporcionant una experiència similar a l’autocompletat de contrasenyes. L’autenticació cross-device permet utilitzar el telèfon per autenticar-se en un ordinador escanejant un codi QR, útil quan els passkeys no estan sincronitzats entre dispositius.

Gestió de Sessions

Les sessions tradicionals amb IDs de sessió emmagatzemats en cookies segueixen sent rellevants, especialment per a aplicacions web renderitzades al servidor. La seguretat comença amb les flags de les cookies: Secure assegura que només es transmetin per HTTPS, HttpOnly impedeix accés 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.

Multi-Factor Authentication

L’autenticació multifactor (MFA) afegeix capes addicionals de seguretat més enllà de la contrasenya. El model clàssic distingeix tres factors: quelcom que saps (contrasenya), quelcom que tens (telèfon, token), i quelcom que ets (biometria). L’MFA efectiu combina factors de categories diferents.

TOTP (Time-based One-Time Password) genera codis de 6 dígits que canvien cada 30 segons basant-se en un secret compartit i el temps actual. Les aplicacions autenticadores emmagatzemen aquest secret i generen codis localment, sense requerir connexió a internet. Durant el setup, el servidor mostra un codi QR que conté el secret, l’usuari l’escaneja amb la seva app, i a partir d’aquí ambdós poden generar els mateixos codis de manera independent. 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 com iPhones, aquestes dades romanen al Secure Enclave 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ó.

Seguretat Web

Cross-Origin Resource Sharing (CORS)

La Same-Origin Policy és una restricció fonamental dels navegadors: el JavaScript d’una pàgina només pot fer peticions a la mateixa origen (protocol, domini i port). Això protegeix contra molts atacs on un site maliciós intenta llegir dades d’un altre site on l’usuari ha iniciat sessió.

CORS relaxa aquesta restricció de manera controlada, permetent als servidors especificar quins origens poden accedir als seus recursos. Quan el JavaScript fa una petició cross-origin, el navegador primer pot enviar una petició OPTIONS (preflight) preguntant al servidor si permet aquesta petició. El servidor respon amb headers indicant què està permès.

L’header Access-Control-Allow-Origin especifica quins origens poden accedir al recurs. Pot ser un origen específic o el wildcard *. Tanmateix, si la petició inclou credencials (cookies), no es pot utilitzar *: s’ha d’especificar l’origen exacte. Access-Control-Allow-Methods i Access-Control-Allow-Headers controlen quins mètodes HTTP i headers personalitzats estan permesos.

Access-Control-Allow-Credentials: true permet que les peticions incloguin cookies i headers d’autorització. Això és perillós si es combina amb origens massa permissius. Un error comú és reflectir automàticament l’origen de la petició al header Access-Control-Allow-Origin quan s’accepten credencials, permetent efectivament qualsevol origin autenticar-se.

Les peticions simples (GET, HEAD, POST amb content-types específics i sense headers personalitzats) no requereixen preflight. Això pot ser sorprenent per a desenvolupadors que esperen que totes les peticions cross-origin es verifiquin primer. És important dissenyar APIs assumint que aquestes peticions simples poden arribar de qualsevol origen.

Cross-Site Scripting (XSS)

XSS és l’injecció de JavaScript maliciós en pàgines web vistes per altres usuaris. Hi ha tres tipus principals. El Reflected XSS injecta script en paràmetres de URL o formularis que es reflecteixen immediatament a la pàgina. El Stored XSS emmagatzema el script a la base de dades (per exemple, en comentaris) i l’executa cada vegada que es visualitza. El DOM-based XSS manipula el DOM del client sense involucrar el servidor.

La Content Security Policy (CSP) és la defensa més potent. És un header que especifica quines fonts de contingut són de confiança. script-src 'self' només permet scripts del mateix origen. script-src https://trusted-cdn.com permet scripts d’un CDN específic. Però el millor enfocament modern són els nonces: el servidor genera un valor aleatori per cada resposta i només executa scripts amb aquest nonce.

Content-Security-Policy: script-src 'nonce-r4nd0m123' <script nonce="r4nd0m123">...</script>

Això invalida completament XSS injectat perquè l’atacant no pot conèixer el nonce. La directiva strict-dynamic permet que scripts amb nonces creïn nous scripts dinàmicament, facilitant l’ús de frameworks moderns.

Els frameworks frontend moderns proporcionen escapament automàtic per defecte. Les expressions en templates s’escapen automàticament convertint caràcters perillosos com < en entitats HTML. Tanmateix, funcions que permeten inserir HTML “raw” desactiven aquesta protecció i només s’han d’utilitzar amb contingut de confiança.

La Trusted Types API força que l’assignació a sinks perillosos (innerHTML, eval, etc.) només accepti objectes Trusted Type. Això converteix XSS d’un problema de revisar tot el codi a un problema de revisar els punts específics on es creen aquests objectes de confiança.

La sanitització és necessària quan has de permetre HTML limitat (per exemple, formatació en comentaris). Les llibreries de sanitització eliminen elements i atributs perillosos mentre preserven el formatatge segur. Mai intentis implementar el teu propi sanititzador: és extremadament difícil fer-ho correctament.

Cross-Site Request Forgery (CSRF)

CSRF explota que els navegadors adjunten automàticament cookies a les peticions. Un site maliciós pot fer que el teu navegador enviï una petició al teu banc (amb les teves cookies de sessió) transferint diners a l’atacant. L’usuari està autenticat, la petició és vàlida tècnicament, però no intencionada.

SameSite cookies són la defensa més simple i efectiva. SameSite=Strict impedeix completament que la cookie s’enviï en peticions cross-site. SameSite=Lax permet-la en navegacions top-level (seguir enllaços) però no en formularis POST o fetch requests cross-site. Per a la majoria d’aplicacions, Lax proporciona un bon equilibri entre seguretat i usabilitat.

Els tokens CSRF són un enfocament més tradicional. El servidor inclou un token aleatori en formularis o el proporciona a l’aplicació. Quan el formulari es submits, el token s’inclou (típicament com a camp ocult o header). El servidor verifica que el token coincideix amb el de la sessió. Com que l’atacant no pot llegir el token (per Same-Origin Policy), no pot crear peticions vàlides.

El pattern Double Submit Cookie emmagatzema el token tant en una cookie com en un lloc accessible a JavaScript (localStorage o el DOM). Quan es fa una petició, JavaScript llegeix el token i l’envia com a header o paràmetre. El servidor verifica que coincideixin. Això funciona perquè un atacant no pot establir cookies per al teu domini ni llegir-les.

Per a APIs JSON, un header personalitzat com X-Requested-With: XMLHttpRequest pot ser suficient. Els navegadors no permeten que sites arbitraris afegeixin headers personalitzats en peticions cross-origin (sense CORS), així que la presència d’aquest header demostra que la petició es va originar des del JavaScript del teu site.

Injection Attacks

La SQL injection insereix SQL maliciós en queries, potencialment llegint, modificant o eliminant dades. El input ' OR '1'='1 en un camp d’usuari podria convertir SELECT * FROM users WHERE username='$input' en SELECT * FROM users WHERE username='' OR '1'='1', retornant tots els usuaris.

Les prepared statements (també anomenades parameterized queries) són la solució definitiva. En lloc de concatenar strings per construir SQL, utilitzes placeholders que el driver de base de dades tracta com a dades, mai com a codi:

cursor.execute("SELECT * FROM users WHERE username = ?", (user_input,))

El driver automàticament escapa el input apropiadament per al dialecte SQL específic. És impossible injectar SQL perquè el input mai s’interpreta com a codi.

Els ORMs (Object-Relational Mappers) construeixen queries utilitzant mètodes que internament usen prepared statements. Tanmateix, ofereixen “escape hatches” per a raw SQL que poden ser vulnerables si no s’utilitzen amb cura. Les funcions de l’ORM són segures, les raw queries requereixen la mateixa atenció que el SQL directe.

El principi de mínim privilegi s’aplica a les credencials de base de dades. L’aplicació no hauria de connectar-se amb un usuari que té permisos DROP TABLE o CREATE USER. Si l’aplicació només llegeix i escriu dades normals, les seves credencials haurien de reflectir només aquests permisos.

Command injection executa comandes del sistema operatiu. Si l’aplicació utilitza input d’usuari per construir comandes (per exemple, executant ping $userInput), un atacant pot injectar ;rm -rf /. La millor defensa és evitar completament l’execució de comandes del shell amb input d’usuari. Si és absolutament necessari, utilitza llibreries que accepten arguments com a llista en lloc de string, i valida estrictament l’input contra una whitelist.

LDAP, XML i NoSQL injection són anàlegs a SQL injection en altres llenguatges de query. Els principis són els mateixos: mai construir queries concatenant strings, utilitzar sempre APIs que separen codi de dades, i validar l’input.

Security Headers

Els headers de seguretat configuren proteccions del navegador. HTTP Strict Transport Security (HSTS) obliga els navegadors a utilitzar sempre HTTPS amb el teu site:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Després de rebre aquest header, el navegador converteix automàticament totes les peticions HTTP en HTTPS durant un any. includeSubDomains aplica això també als subdominis. preload permet incloure el teu domini en llistes hardcoded dels navegadors, protegint fins i tot la primera visita.

Content Security Policy ja s’ha discutit en XSS, però també controla altres recursos: img-src, style-src, connect-src, etc. upgrade-insecure-requests instrueix el navegador a carregar tots els recursos per HTTPS fins i tot si l’HTML especifica HTTP.

X-Frame-Options: DENY impedeix que la teva pàgina es carregui en un iframe, protegint contra clickjacking. SAMEORIGIN permet iframes del mateix origen. La directiva CSP frame-ancestors és més flexible i hauria de preferir-se si ja utilitzes CSP.

X-Content-Type-Options: nosniff impedeix que els navegadors “endevinin” el tipus MIME del contingut. Sense això, un navegador podria interpretar un arxiu JSON com a HTML si sembla contingut HTML, potencialment executant scripts.

Referrer-Policy controla quanta informació de la URL anterior s’inclou en la petició següent. strict-origin-when-cross-origin envia la URL completa per a peticions same-origin però només l’origen per a cross-origin, i res si baixa de HTTPS a HTTP.

Permissions-Policy (anteriorment Feature-Policy) controla l’accés a funcionalitats del navegador com la càmera, micròfon, geolocalització, etc. Permissions-Policy: camera=(), microphone=() desactiva completament aquestes funcionalitats.

Clickjacking i UI Redressing

El clickjacking superimposa contingut invisible sobre la teva pàgina, enganyant els usuaris perquè facin clic en coses que no veuen. Per exemple, un iframe invisible amb el teu site col·locat sobre un joc. L’usuari creu que està jugant però està fent clic en botons del teu site.

X-Frame-Options i la directiva CSP frame-ancestors són les defenses primàries. frame-ancestors 'none' és equivalent a X-Frame-Options: DENY. frame-ancestors 'self' https://trusted.com permet específicament iframes del teu site i un site de confiança.

Les tècniques JavaScript de “frame busting” (detectar si estàs en un iframe i sortir-ne) són menys fiables. Els atacants han trobat maneres de desactivar-les utilitzant l’atribut sandbox dels iframes o altres tècniques. Els headers del servidor són més robusts perquè el navegador els respecta abans de carregar qualsevol JavaScript.

Web Application Firewalls (WAF)

Un Web Application Firewall (WAF) és una capa de protecció que filtra, monitoritza i bloqueja tràfic HTTP maliciós entre internet i l’aplicació web. Opera a nivell 7 (capa d’aplicació) del model OSI, permetent inspeccionar el contingut de les peticions.

Els WAFs poden desplegar-se a l’edge (CDN/cloud) o a nivell d’aplicació. Els WAF gestionats pels proveïdors de CDN filtren tràfic abans que arribi a l’origen. També existeixen solucions open source que es poden integrar amb servidors web.

L’OWASP Core Rule Set (CRS) és un conjunt de regles genèriques que protegeix contra els atacs més comuns: SQL injection, XSS, LFI/RFI, i altres. Proporciona un punt de partida sòlid, però sovint requereix tuning per evitar falsos positius en aplicacions específiques.

Els WAFs moderns van més enllà de regles estàtiques, incorporant machine learning per detectar anomalies i rate limiting integrat. Tanmateix, no són una solució màgica: són una capa de defensa adicional, no un substitut de codi segur. Atacants sofisticats poden trobar maneres d’evadir regles WAF, especialment si el WAF no està correctament configurat.

Emmagatzematge al Client

Les aplicacions web modernes sovint necessiten emmagatzemar dades al navegador. Els mecanismes disponibles tenen implicacions de seguretat molt diferents.

localStorage i sessionStorage són simples i síncrons, fent-los atractius per a desenvolupadors. Tanmateix, són completament vulnerables a XSS. Qualsevol script que s’executi a la pàgina pot llegir i modificar tot el contingut. Això significa que emmagatzemar tokens d’accés o informació sensible en localStorage els exposa a qualsevol vulnerabilitat XSS.

sessionStorage té el mateix problema que localStorage però les dades s’esboren quan es tanca el tab. Això és una millora marginal de seguretat, però no protegeix contra XSS durant la sessió.

IndexedDB és una base de dades asíncrona al navegador, capaç d’emmagatzemar grans quantitats de dades estructurades. Té les mateixes vulnerabilitats que localStorage respecte a XSS. És útil per a aplicacions offline o caching, però no per a dades sensibles.

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.

Subresource Integrity

Els CDNs permeten carregar llibreries populars ràpidament des de servidors optimitzats. Tanmateix, això introdueix un punt de confiança extern. Si el CDN és compromès o alterat, scripts maliciosos es carreguen en el teu site.

Subresource Integrity (SRI) proporciona protecció calculant un hash criptogràfic del script o stylesheet esperat i incloent-lo en el tag:

<script src="https://cdn.example.com/library.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC" crossorigin="anonymous"></script>

El navegador descarrega l’arxiu, calcula el seu hash, i només l’executa si coincideix. Si el CDN serveix un arxiu diferent (maliciós o simplement una versió diferent), el navegador el bloqueja i llença un error. L’atribut crossorigin="anonymous" és necessari per permetre que el navegador llegeixi el contingut per validar-lo.

SRI és especialment important per a scripts crítics com frameworks. Un React compromès podria capturar totes les interaccions de l’usuari. Molts CDNs proporcionen hashes SRI juntament amb les URLs dels recursos.

La limitació d’SRI és que requereix saber el hash exacte per endavant. Si el CDN actualitza l’arxiu (fins i tot per fixes de seguretat), el hash canvia i la teva pàgina es trenca. Això requereix processos per actualitzar hashes quan actualitzes dependències.

Third-Party Scripts

Els scripts de tercers (analytics, ads, chat widgets) s’executen amb els mateixos privilegis que el teu propi codi. Poden accedir a localStorage, fer peticions, modificar el DOM, i capturar inputs de l’usuari. Cada script de tercer és un risc potencial.

Content Security Policy ajuda limitant d’on es poden carregar scripts. Si només permets scripts del teu domini i CDNs específics de confiança, scripts arbitraris no poden injectar-se. Tanmateix, scripts permesos encara tenen accés complet.

Els sandbox iframes proporcionen aïllament més fort. Carregant un script de tercer en un iframe amb l’atribut sandbox, pots limitar què pot fer: sandbox="allow-scripts" permet scripts però impedeix navegació, formularis, modals, etc. Els iframes sandbox no poden accedir a localStorage del parent ni llegir cookies.

Tanmateix, molts scripts de tercers requereixen accés al DOM principal per funcionar (per exemple, un widget de chat), fent sandbox impracticable. En aquests casos, l’auditoria regular és essencial. Què fa realment aquest script? Envia dades a servidors externs? Compleix amb GDPR?

Les solucions de server-side tagging (com Google Tag Manager server-side) mouen l’execució de scripts de tercers al servidor. El client envia dades event al teu servidor, que després les forwarda als serveis de tercers. Això proporciona control sobre quines dades es comparteixen i elimina scripts de tercers del navegador.

Seguretat d’APIs

Autenticació d’APIs

Les APIs RESTful modernes típicament utilitzen Bearer tokens, específicament JWTs. El client inclou el token en l’header Authorization: Bearer <token> de cada petició. Això és stateless: el servidor pot validar el token sense consultar una base de dades de sessions, utilitzant només la signatura criptogràfica.

Les API keys identifiquen el client o projecte que fa peticions. A diferència dels tokens d’usuari, no representen un usuari específic sinó una aplicació. S’han de transmetre sempre en headers (com X-API-Key), mai en la URL, perquè les URLs es poden guardar en logs, historial de navegador, etc. Les API keys haurien de rotar-se periòdicament, i els sistemes haurien de permetre múltiples keys actives simultànies per facilitar la rotació sense downtime.

Mutual TLS (mTLS) proporciona autenticació bidireccional amb certificats. No només el client verifica la identitat del servidor (com en TLS normal), sinó que el servidor també verifica la identitat del client mitjançant el seu certificat. Això és comú en comunicació microserveis dins d’un clúster on cada servei té el seu propi certificat, sovint gestionat per una service mesh.

OAuth 2.1 Client Credentials Flow és ideal per a autenticació màquina-a-màquina. El client (servei) s’autentica directament amb l’authorization server utilitzant les seves credencials i obté un token d’accés. Aquest flow no involucra cap usuari; el token representa el servei mateix.

Rate Limiting i Throttling

El rate limiting protegeix les APIs contra abús, atacs DoS i usage excessiu que pot afectar altres usuaris. Els límits es poden aplicar per IP, per usuari autenticat, per API key, o combinacions d’aquests. Els límits típics són peticions per segon, per minut o per hora.

L’algoritme token bucket és popular: cada client té un “cubell” amb una capacitat màxima de tokens. Els tokens es regeneren a una taxa constant. Cada petició consumeix un token. Si el cubell està buit, la petició es rebutja o es posa en cua. Això permet bursts curts mentre manté una taxa promig.

L’algoritme sliding window manté un comptador per cada finestra de temps (per exemple, cada minut). Quan una petició arriba, es comprova el comptador de la finestra actual i possiblement la anterior. Això proporciona un límit més suau que fixed windows, que poden permetre el doble de peticions al voltant de límits de finestra.

Els headers de resposta comuniquen l’estat dels límits al client:

  • X-RateLimit-Limit: Màxim permès
  • X-RateLimit-Remaining: Quantes queden
  • X-RateLimit-Reset: Quan es restableix el límit
  • Retry-After: Quan tornar a intentar-ho després d’un 429

La implementació pot ser en middleware de l’aplicació, en un API gateway, o utilitzant un store compartit en memòria per a arquitectures distribuïdes. Els stores en memòria són populars perquè les seves operacions atòmiques i expiració automàtica de claus s’adapten perfectament a rate limiting.

Input Validation

La validació d’input és la primera línia de defensa contra molts atacs. El principi de whitelist és fonamental: defineix què és acceptable en lloc d’intentar detectar què és maliciós. Per exemple, si esperes un codi postal espanyol, valida que sigui exactament 5 dígits, no intentes detectar patterns d’atac.

JSON Schema i OpenAPI permeten definir l’estructura esperada de les peticions declarativament. Llibreries de validació poden automàticament rebutjar peticions que no compleixin l’schema. Això centralitza la validació i la fa consistent entre endpoints.

La verificació de tipus és especialment important en llenguatges dinàmics. Si esperes un número, converteix-lo explícitament i gestiona errors de conversió. No assumeixis que perquè un camp es diu age contindrà un número.

Establir límits és crucial: longitud màxima de strings (prevé buffer overflows i DoS), ranges numèrics, tamany màxim de payload (prevé DoS de memòria). Els valors fora d’aquests límits haurien de ser rebutjats immediatament amb errors 400 clars.

La validació hauria d’ocórrer el més aviat possible en el pipeline de petició, idealment en middleware abans d’arribar a la lògica de negoci. Això manté el codi de negoci net i assegura que la validació no s’oblidi accidentalment.

API Versioning

Les APIs evolucionen: es necessiten noves funcionalitats, alguns dissenys demostren ser poc pràctics. El versioning permet aquests canvis mentre es manté compatibilitat amb clients existents. Hi ha diverses estratègies:

URI versioning (/v1/users, /v2/users) és el més visible i fàcil de testejar. Cada versió és efectivament una API diferent. Header versioning (Accept: application/vnd.api+json; version=2) manté URLs netes però és menys visible. Query parameter versioning (/users?version=2) és un compromís.

La deprecació requereix comunicació clara. El header Sunset indica quan s’eliminarà un endpoint: Sunset: Sat, 31 Dec 2026 23:59:59 GMT. Els clients poden programàticament detectar endpoints deprecated i planificar migracions. Els headers Warning poden proporcionar informació addicional.

Mantenir versions antigues té cost: cada versió és codi addicional per mantenir, testejar i potencialment arreglar vulnerabilitats de seguretat. És temptador mantenir versions indefinidament per compatibilitat, però això pot convertir-se en un problema de seguretat si versions antigues contenen vulnerabilitats conegudes que els clients encara utilitzen.

Una estratègia razonable és mantenir N versions amb una política clara de suport. Per exemple: la versió actual i l’anterior estan completament suportades, dues versions enrere està en mode manteniment (només fixes crítics), versions més antigues són end-of-life. Això dona als clients temps per migrar mentre manté el burden de manteniment manejable.

GraphQL Security

GraphQL és potent però presenta desafiaments de seguretat únics. El problema més notable són les queries recursives profundes. Un atacant pot construir una query que demana usuari, que té posts, cada post té autor, que té posts, etc., generant exponencialment més treball per al servidor.

El depth limiting estableix una profunditat màxima de query. Si la query excedeix aquest límit, es rebutja abans d’executar-se. Això requereix analitzar l’AST de la query, però moltes llibreries GraphQL proporcionen això out-of-the-box.

El query cost analysis assigna un “cost” a cada camp basat en el treball computacional que requereix. Una query simple d’un usuari pot tenir cost 1, mentre que una llista de tots els posts amb comentaris pot tenir cost 1000. S’estableix un màxim per query, rebutjant queries que el superin.

La introspection és útil durant desenvolupament perquè permet eines com GraphiQL descobrir l’schema. En producció, però, revela tota l’estructura de la teva API a atacants potencials. Hauria de desactivar-se en entorns públics.

El rate limiting en GraphQL és més complex que en REST perquè totes les queries van al mateix endpoint. El rate limiting s’ha de basar en el contingut de la query (cost calculat) o operacions específiques, no simplement en el número de peticions a /graphql.

API Gateways

Un API gateway és un reverse proxy que se situa entre clients i serveis backend. Centralitza funcionalitat transversal que altrament hauria de duplicar-se en cada servei.

L’autenticació centralitzada permet validar tokens un cop al gateway en lloc de a cada microservei. El gateway pot verificar JWTs, consultar un servei d’autenticació, o gestionar OAuth flows. Després envia informació d’usuari als backends en headers de confiança.

El rate limiting al gateway protegeix tots els backends amb una sola configuració. Es poden definir polítiques globals i per endpoint, aplicades abans que les peticions arribin als serveis.

La validació de peticions al gateway pot verificar que les peticions compleixin contracts d’API (OpenAPI specs) abans de reenviar-les. Això protegeix els backends de rebre dades malformades i proporciona errors consistents als clients.

El logging i monitoring centralitzat al gateway proporciona visibilitat de tot el tràfic. Es poden detectar patrons sospitosos com intent de scanning de vulnerabilitats, abús de rate limits, o intents d’accés a endpoints no autoritzats.

Seguretat en el Desenvolupament Modern

Secrets Management

El problema dels secrets (contrasenyes, API keys, claus de xifratge) és que el codi s’ha de poder executar però no ha de contenir els secrets directament. Fer commit de secrets al repositori és perillós: el git history manté els secrets fins i tot si es eliminen després, i els repositoris privats poden esdevenir públics accidentalment o ser compromesos.

Per a desenvolupament local, les variables d’entorn són un primer pas raonable. Un arxiu .env (que està al .gitignore) conté els secrets, i l’aplicació els llegeix a l’inici. Això separa secrets del codi, però encara requereix distribuir els secrets als desenvolupadors de manera segura.

Els vaults (gestors de secrets centralitzats) van més enllà. En lloc d’emmagatzemar secrets en arxius o variables d’entorn, l’aplicació consulta el vault en runtime. Això proporciona diversos avantatges: auditoria completa de qui accedeix quins secrets, rotació automàtica de secrets sense redesplegar aplicacions, i control d’accés granular.

En entorns Kubernetes, els Secrets nadius xifren dades at-rest utilitzant la clau de xifratge del clúster. Tanmateix, per defecte aquesta clau està emmagatzemada en etcd sense xifratge addicional. La configuració d’encryption at rest és essencial per a clústers de producció. Solucions d’External Secrets permeten fer commit de secrets xifrats al repositori, que només poden ser desxifrats pel clúster.

Per xifrar arxius de configuració directament en git, existeixen eines que utilitzen claus de proveïdors cloud o xifratge modern (substituts de GPG). Això permet versionar configuració sensible de manera segura.

Les bones pràctiques inclouen mai fer commit de secrets (utilitzar hooks de git per detectar-los), rotar secrets regularment i automàticament quan és possible, i implementar accés basat en rols on només els serveis que necessiten un secret específic poden accedir-hi. Els secrets haurien de tenir scopes mínims: una API key per a un servei específic, no una master key que fa tot.

Dependency Security

El programari modern depèn de centenars o milers de paquets de tercers. Cada dependència és codi que no has escrit però que s’executa amb els mateixos privilegis que el teu. Els supply chain attacks exploten això comprometent dependències populars. L’atac a event-stream (2018) o ua-parser-js (2021) van injectar codi maliciós en paquets amb milions de descàrregues.

Les eines d’audit de dependències escanegen les dependències contra bases de dades de vulnerabilitats conegudes. Haurien d’executar-se regularment en CI/CD i bloquejar deployments si es troben vulnerabilitats crítiques. Tanmateix, aquestes eines només detecten vulnerabilitats publicades, no codi maliciós encara no descobert.

Les eines d’actualització automàtica de dependències van més enllà, creant automàticament pull requests per actualitzar dependències quan es publiquen fixes de seguretat. Això redueix el window de vulnerabilitat però requereix processos de test robusts per assegurar que les actualitzacions no trenquin funcionalitat.

Els lock files (package-lock.json, yarn.lock, pnpm-lock.json) són essencials per a seguretat reproducible. Sense ells, npm install podria instal·lar versions diferents cada vegada, potencialment incloent una versió compromesa publicada després del teu últim test. Els lock files asseguren que tothom (desenvolupadors, CI, producció) utilitza exactament les mateixes versions.

La verificació d’integritat va un pas més enllà. npm utilitza checksums SHA-512 per verificar que el paquet descarregat no ha estat alterat. Algunes organitzacions van més lluny, verificant signatures criptogràfiques de paquets quan estan disponibles.

El Software Bill of Materials (SBOM) és una llista completa de tots els components del teu programari, incloent dependències transitives. Formats com SPDX o CycloneDX permeten generar SBOMs automàticament. Això és cada vegada més un requisit de compliance i facilita respondre ràpidament quan es descobreix una vulnerabilitat: pots saber immediatament si estàs afectat.

El framework SLSA (Supply chain Levels for Software Artifacts) defineix nivells de maduresa per a la seguretat de la cadena de subministrament. Des del nivell 1 (documentació bàsica del build) fins al nivell 4 (builds hermètics amb verificació completa), proporciona un camí clar per millorar. L’ecosistema Sigstore implementa SLSA amb components per signar artefactes, emetre certificats efímers, i mantenir registres de transparència. Això permet verificar la procedència d’artefactes sense gestionar claus de llarga durada.

Container Security

Els containers empaqueten aplicacions amb les seves dependències, però això significa que també empaqueten vulnerabilitats. La imatge base és crítica: una imatge amb un sistema operatiu complet pot contenir centenars de paquets que no necessites, cada un una possible font de vulnerabilitats. Imatges mínimes com Alpine Linux o Distroless contenen només el mínim necessari per executar l’aplicació. Per a llenguatges compilats com Go o Rust, fins i tot es poden utilitzar imatges scratch (completament buides) amb només el binari estàtic.

L’escaneig de vulnerabilitats d’imatges hauria de ser part del pipeline CI/CD. Les eines d’escaneig analitzen imatges per vulnerabilitats conegudes en paquets del sistema i dependències de llenguatge. Poden configurar-se per bloquejar el build si es troben vulnerabilitats crítiques.

Els multi-stage builds milloren la seguretat minimitzant el que va a la imatge final. La primera stage compila el codi amb totes les build tools necessàries. L’stage final només copia el binari compilat i les dependencies runtime a una imatge mínima. Això elimina compiladors, build tools i codi font de la imatge de producció.

Executar containers com a root és perillós. Si un atacant aconsegueix escapar del container, tindrà privilegis de root a l’host. Els Dockerfiles haurien d’incloure USER nonroot o crear un usuari específic. Kubernetes permet enforçar això amb PodSecurityStandards que rebutgen pods que intenten executar com a root.

Els secrets mai haurien de formar part de la imatge. Construir una imatge amb secrets hardcoded significa que qualsevol amb accés a la imatge té els secrets. A més, els secrets queden en les capes de la imatge fins i tot si s’eliminen en capes posteriors. Els secrets han de muntar-se en runtime des de secrets de Kubernetes o un vault extern.

Les imatges haurien d’actualitzar-se regularment, no només quan es canvia l’aplicació. Una imatge construïda fa sis mesos pot contenir vulnerabilitats que s’han descobert des de llavors. Rebuilds periòdics utilitzant la imatge base més recent asseguren que els patches de seguretat s’apliquen.

La seguretat en runtime va més enllà de la imatge. El monitoratge de comportament sospitós del kernel detecta intents d’escriure en directoris inesperats, execució de shells en containers que no haurien de tenir-los, o canvis en arxius binaris. AppArmor i SELinux proporcionen Mandatory Access Control, limitant què poden fer els processos independentment dels permisos de l’usuari. Tecnologies basades en eBPF ofereixen observabilitat i seguretat de xarxa a nivell de kernel amb baix overhead.

TLS/HTTPS

TLS (Transport Layer Security) xifra les comunicacions entre client i servidor, protegint contra espionatge i man-in-the-middle attacks. TLS 1.3 és la versió actual, llançada el 2018. Elimina cipher suites i opcions insegures, redueix la latència del handshake, i xifra més parts de la negociació. TLS 1.2 és el mínim acceptable en 2025; TLS 1.0 i 1.1 estan deprecated i han estat eliminats dels navegadors principals des de 2020.

Let’s Encrypt va revolucionar l’adopció d’HTTPS proporcionant certificats gratuïts i automatitzats. El protocol ACME permet als servidors demanar i renovar certificats automàticament sense intervenció manual, gestionant tot el cicle de vida dels certificats.

La configuració del servidor TLS és crucial. Cipher suites modernes com TLS_AES_128_GCM_SHA256 proporcionen xifratge fort eficient. Suites antigues amb RC4 o DES són vulnerables i haurien de desactivar-se. Perfect Forward Secrecy (PFS) utilitza claus efímeres per a cada sessió, assegurant que fins i tot si la clau privada del servidor es compromet en el futur, sessions passades no es poden desxifrar.

OCSP Stapling millora performance i privacitat. Sense ell, el client ha de contactar l’autoritat de certificació per verificar que el certificat no ha estat revocat, afegint latència i permetent a la CA trackejar quins sites visita l’usuari. Amb stapling, el servidor consulta l’estat de revocació i l’inclou en el handshake TLS, eliminant aquesta round-trip.

Certificate pinning en aplicacions mòbils significa hardcodejar la clau pública esperada del servidor. Això protegeix contra CAs compromeses que podrien emetre certificats falsos per al teu domini. Tanmateix, és perillós: si necessites rotar certificats i no has planejat adequadament (incloent backup pins), pots deixar usuaris sense poder connectar. Per això, moltes organitzacions pinen claus intermèdies en lloc de leaf certificates, donant més flexibilitat.

CI/CD Security

El pipeline CI/CD té accés a codi font, secrets, i permisos de deploy. És un objectiu d’alt valor per atacants. El SolarWinds hack (2020) va comprometre el build system per injectar malware en actualitzacions de programari, afectant milers d’organitzacions.

SAST (Static Application Security Testing) analitza codi font buscant patrons vulnerables, detectant SQL injection, XSS, i altres vulnerabilitats comunes. Aquestes eines haurien d’executar-se en cada pull request, bloquejant merge si es troben vulnerabilitats crítiques.

DAST (Dynamic Application Security Testing) testeja l’aplicació en execució, escanejant l’aplicació desplegada i enviant inputs maliciosos per detectar vulnerabilitats. DAST detecta problemes que SAST pot perdre (configuracions incorrectes, vulnerabilitats en dependències binàries) però requereix un entorn de test funcional.

El secrets scanning en commits impedeix que secrets arribin al repositori. Eines automàtiques escanegen cada commit buscant patrons que semblen API keys, contrasenyes, o claus privades. Alguns s’integren com a pre-commit hooks, bloquejant el commit localment. Altres escanegen el repositori sencer periòdicament, detectant secrets que podrien haver-se esmunyit.

L’anàlisi de dependències s’ha discutit anteriorment, però val la pena destacar que hauria d’executar-se en cada build, no només periòdicament. Una dependència segura ahir pot tenir una vulnerabilitat publicada avui.

El container scanning verifica imatges abans de desplegar-les. Fins i tot si vas escannejar la imatge quan es va construir, val la pena tornar-ho a fer abans del deploy per detectar vulnerabilitats descobertes mentrestant.

Infrastructure as Code (IaC) com Terraform o CloudFormation també necessita escanejat. Eines d’anàlisi estàtica analitzen templates buscant configuracions insegures com buckets S3 públics, security groups massa permissius, o xifratge desactivat. Detectar això abans d’aplicar els canvis prevé incidents de seguretat.

Infrastructure as Code Security

IaC declara infraestructura en arxius versionats. Això és excel·lent per a reproducibilitat i auditoria, però errors de configuració en IaC es propagen ràpidament. Un template Terraform amb un security group obert a 0.0.0.0/0 pot crear desenes de recursos vulnerables.

Les bones pràctiques inclouen defaults segurs en els teus mòduls. Si crees un mòdul Terraform per bases de dades, el xifratge hauria d’estar activat per defecte, requerint que es desactivi explícitament (cosa que no hauria de permetre’s en producció). Els security groups haurien de tenir deny per defecte i requerir especificació explícita de què està permès.

L’escaneig estàtic de templates detecta configuracions perilloses amb centenars de regles per a AWS, Azure, GCP i Kubernetes. Aquestes eines s’integren en CI/CD, comentant en pull requests quan detecten problemes.

Policy as Code permet expressar polítiques de seguretat i compliance com a codi. En lloc de reviews manuals de cada canvi d’infraestructura, el sistema avalua automàticament si compleix les polítiques. Per exemple: “tots els buckets S3 han de tenir xifratge activat”, “els security groups no poden permetre SSH des d’internet”, “les bases de dades han d’estar en subnets privades”.

Les polítiques s’escriuen en llenguatges declaratius de propòsit específic. Poden evaluar Terraform plans abans d’aplicar-los, Kubernetes manifests abans de desplegar-los, o requests a APIs abans d’executar-los. Això converteix els requisits de seguretat en controls automatitzats que no es poden saltar.

Logging i Monitoring

Els logs de seguretat són essencials per detectar i investigar incidents. Haurien de capturar tots els esdeveniments rellevants per a seguretat: intents d’autenticació (especialment fallits), canvis en permisos o configuració, accés a recursos sensibles, i errors que podrien indicar atacs.

Els intents d’autenticació fallits poden indicar password spraying o credential stuffing. Múltiples fallades des de la mateixa IP o contra el mateix compte són sospitosos. Tanmateix, cal equilibri: bloquejar accounts després de poques fallades facilita denial of service contra usuaris legítims.

Els canvis de permisos són crítics. Si un usuari regular adquireix de sobte permisos d’admin, podria ser escalació de privilegis. Els canvis en configuració de seguretat (security groups, firewall rules) haurien de triggerejar alertes per a review.

L’accés a recursos sensibles hauria de loguejar-se amb detall suficient per auditoria: qui va accedir què i quan. Això és sovint un requisit de compliance (GDPR, HIPAA) i essencial per investigar data breaches.

La centralització de logs és necessària en arquitectures distribuïdes. Sistemes d’agregació de logs permeten cerques potents i visualitzen tendències, convertint terabytes de logs crus en insights accionables.

La detecció d’anomalies utilitza machine learning per aprendre el comportament normal i alertar sobre desviacions. Un usuari que normalment accedeix des d’Espanya i de sobte accedeix des de Xina és sospitós. Un servidor que normalment serveix 100 requests/minut i de sobte en serveix 10.000 podria estar sota atac.

La retenció de logs equilibra costos d’emmagatzematge amb necessitats d’auditoria i investigació. Les regulacions sovint requereixen períodes mínims de retenció. Una estratègia comuna és mantenir logs detallats per 30-90 dies en hot storage per investigació ràpida, després arxivar-los en cold storage més econòmic per al període de retenció complet.

Cloud Security

Els cloud providers ofereixen infraestructura segura, però la seguretat de les aplicacions és responsabilitat compartida. El provider assegura la infraestructura física, hypervisors i xarxa base. El client és responsable del sistema operatiu, aplicacions, dades i configuració.

IAM (Identity and Access Management) és fonamental. El principi de mínim privilegi s’aplica estrictament: cada usuari, servei o rol només hauria de tenir els permisos mínims necessaris. Els sistemes d’IAM dels cloud providers són extremadament granulars, permetent permisos a nivell de recurs individual i acció específica.

Els rols són preferibles als usuaris per a serveis. Una instància de servidor o funció serverless no hauria de tenir credencials hardcoded o en variables d’entorn. En canvi, se li assigna un rol IAM, i els SDKs automàticament obtenen credencials temporals d’aquest rol. Això elimina el risc de credencials filtrades i permet rotació automàtica.

MFA hauria de ser obligatori per a tots els usuaris humans, especialment els que tenen permisos elevats. La majoria de data breaches en cloud comencen amb credencials compromeses. MFA fa aquests atacs exponencialment més difícils.

La segmentació de xarxa és crucial. Les xarxes virtuals aïllen recursos, amb subnets per separar tiers (web, aplicació, base de dades). Els recursos públics van en subnets públiques amb accés a internet, mentre que recursos interns van en subnets privades sense ruta directa a internet. Els gateways NAT permeten que recursos privats iniciïn connexions sortints per updates sense acceptar connexions entrants.

Security Groups i altres mecanismes de seguretat de xarxa actuen com a firewalls a nivell d’instància. Haurien de configurar-se amb deny per defecte i permit explícit només del tràfic necessari. Un server web necessita 443 entrant des d’internet, però no SSH des de qualsevol ubicació. SSH hauria de limitar-se a IPs específiques o, millor encara, requerir VPN o bastion hosts.

Els private endpoints permeten accedir a serveis gestionats (emmagatzematge d’objectes, bases de dades) sense travessar internet públic. El tràfic roman dins la xarxa del provider, millorant seguretat i sovint performance. Per exemple, una instància accedint a emmagatzematge d’objectes via private endpoint no exposa tràfic a sniffing, i no consumeix bandwidth públic.

El xifratge hauria d’estar activat everywhere. At rest, utilitzar serveis de xifratge gestionats del provider. Aquests gestionen la rotació de claus, control d’accés granular i auditoria d’ús de claus. In transit, TLS entre tots els serveis. Molts serveis cloud ofereixen xifratge per defecte, però cal verificar i configurar explícitament.

Els serveis cloud-native (managed databases, serverless functions, managed Kubernetes) normalment tenen seguretat millor integrada que self-hosted. Els serveis de bases de dades gestionades gestionen patching, backups i alta disponibilitat. Les funcions serverless són efímeres, limitant el window per explotar vulnerabilitats. Els serveis Kubernetes gestionats gestionen el control plane i són patchejats automàticament.

Les service meshes proporcionen seguretat adicional en arquitectures de microserveis. Implementen mTLS automàtic entre tots els serveis, xifrant tot el tràfic intern sense canvis al codi. També ofereixen polítiques d’autorització declaratives per controlar quin servei pot comunicar-se amb quin altre, i observabilitat completa del tràfic entre serveis.

Zero Trust Architecture

El model Zero Trust es basa en el principi “mai confiar, sempre verificar”. A diferència del model tradicional de seguretat perimetral (on tot el que està dins la xarxa és de confiança), Zero Trust assumeix que qualsevol petició pot ser maliciosa, independentment d’on provingui.

BeyondCorp de Google va ser una de les primeres implementacions públiques d’aquesta arquitectura. En lloc de confiar en VPNs per accedir a recursos interns, cada petició s’autentica i autoritza individualment. Els usuaris accedeixen a aplicacions internes de la mateixa manera que accedirien a aplicacions públiques: a través d’internet, amb autenticació forta.

Els components clau inclouen identity-aware proxies que verifiquen identitat i context abans de permetre accés, microsegmentació que limita el moviment lateral dins la xarxa, i verificació contínua que revalida l’accés durant la sessió, no només al principi.

La implementació pràctica requereix: autenticació forta per a tots els usuaris i serveis (MFA, certificats), xifratge de tot el tràfic (fins i tot intern), autorització granular basada en identitat i context (dispositiu, ubicació, hora), i logging complet per a auditoria i detecció. El document NIST SP 800-207 proporciona una guia detallada per implementar Zero Trust en organitzacions.

Seguretat en Aplicacions Mòbils

Secure Storage

Les aplicacions mòbils no poden confiar en que l’entorn és segur. Els dispositius poden ser rooted/jailbroken, permetent accés directe al filesystem. Les aplicacions necessiten protegir dades sensibles fins i tot en aquests escenaris.

En iOS, els Keychain Services són el mecanisme recomanat per emmagatzemar secrets. Està integrat amb el Secure Enclave del dispositiu, un coprocessador criptogràfic dedicat. Les dades al Keychain estan xifrades amb claus que mai surten del Secure Enclave. L’accés pot requerir autenticació biomètrica, assegurant que només el propietari del dispositiu pot accedir als secrets.

En Android, EncryptedSharedPreferences i Android Keystore proporcionen funcionalitat similar. EncryptedSharedPreferences xifra automàticament les dades utilitzant claus del Android Keystore. El Keystore hardware-backed (disponible en dispositius moderns) genera i emmagatzema claus en hardware dedicat, fent-les inaccessibles fins i tot amb root access.

Per a aplicacions cross-platform, llibreries com flutter_secure_storage o react-native-keychain proporcionen abstraccions sobre aquests mecanismes natius. Utilitzen Keychain en iOS i Keystore en Android, oferint una API consistent.

El que mai s’hauria de fer és emmagatzemar secrets en SharedPreferences normal (Android) o UserDefaults (iOS). Aquests arxius són plaintext (o fàcilment desxifrables) i accessibles amb root/jailbreak. Tampoc hauria d’emmagatzemar-se informació sensible en la base de dades SQLite de l’app sense xifratge, ja que aquests arxius són igualment accessibles.

Certificate Pinning

En connexions HTTPS normals, el dispositiu confia en certificats signats per qualsevol CA reconeguda. Si un atacant pot comprometre una CA o afegir una CA pròpia al trust store del dispositiu (comú en dispositius corporatius), poden executar man-in-the-middle attacks interceptant tràfic HTTPS.

Certificate pinning hardcodeja quins certificats o claus públiques són vàlides per al teu servidor. Durant el handshake TLS, l’app compara el certificat rebut amb els pins hardcodejats. Si no coincideix, la connexió és rebutjada, fins i tot si el certificat està correctament signat.

Hi ha dues aproximacions: pinar el leaf certificate (el certificat específic del teu servidor) o pinar la clau pública intermèdia. Pinar el leaf requereix actualitzar l’app cada vegada que renovis el certificat (normalment cada 3 mesos amb Let’s Encrypt). Pinar la clau intermèdia dona més flexibilitat ja que pots rotar leaf certificates mentre mantinguis la mateixa CA.

És crucial incloure backup pins. Si el teu certificat principal es compromet o necessites rotar-lo d’emergència, un backup pin permet la transició sense deixar usuaris amb versions antigues de l’app sense poder connectar. Aquests backups poden ser claus de CAs alternatives o certificats futurs que planeje utilitzar.

El risc amb pinning és que un error pot bloquejar tots els usuaris. Si el certificat expira i no has actualitzat l’app a temps, o si perds accés a les claus privades i has de canviar completament de CA, usuaris amb l’app instal·lada no podran actualitzar (ja que no poden connectar per descarregar l’update). Per això, algunes organitzacions eviten pinning o utilitzen periods de grace.

Code Obfuscation

El codi de les aplicacions mòbils resideix al dispositiu de l’usuari. Un atacant amb temps i eines pot fer reverse engineering per entendre com funciona l’app, extreure secrets hardcodejats, o trobar vulnerabilitats.

Eines d’ofuscació per Android minifiquen i ofusquen el codi Java/Kotlin. Renombren classes, mètodes i variables a noms sense sentit, eliminen codi no utilitzat, i apliquen optimitzacions que fan el bytecode més difícil de seguir. Tanmateix, el bytecode de la JVM és relativament fàcil de decompile, així que ofuscació no és una protecció completa.

En iOS, el compilador genera codi natiu (no bytecode interpretable), fent-lo inherentment més difícil de fer reverse engineering. Tanmateix, eines de desassemblat encara poden analitzar binaris i, amb esforç, reconstruir la lògica.

És important entendre que l’ofuscació només fa el reverse engineering més difícil i costós, no impossible. No és una substitució per a disseny segur. Secrets crítics (claus d’API, encryption keys) mai haurien d’estar hardcodejats en l’app, independentment de l’ofuscació. Aquests han de venir del backend o generar-se dinàmicament.

L’ofuscació també pot complicar el debugging de crashes en producció. Els stack traces contenen noms ofuscats, fent difícil identificar on va ocórrer l’error. Les mapping files (que relacionen noms ofuscats amb originals) han de mantenir-se segures i disponibles per desofuscar crash reports.

Biometric Authentication

L’autenticació biomètrica proporciona seguretat i usabilitat: és més difícil robar una empremta o cara que una contrasenya, i és més convenient per a l’usuari.

En iOS, el LocalAuthentication framework proporciona una API senzilla per sol·licitar autenticació. L’app mai accedeix a les dades biomètriques reals; simplement pregunta al sistema “aquest usuari s’ha autenticat correctament?” i rep un sí o no. Les dades biomètriques romanen al Secure Enclave i mai són accessibles a aplicacions.

Android ofereix la BiometricPrompt API, que proporciona una experiència consistent independentment del mètode biomètric disponible (empremta, face unlock, iris scan). Com iOS, les dades biomètriques estan protegides pel sistema i no accessibles a l’app.

Els fallbacks són essencials. No tots els dispositius tenen capacitats biomètriques, i les biomètriques poden fallar temporalment (mans mullades per empremtes, màscares per reconeixement facial). L’app hauria de permetre autenticació amb PIN o patró quan la biometria no està disponible o falla.

La biometria no hauria de ser l’única capa de seguretat per operacions crítiques. Per transaccions financeres o canvis de configuració sensibles, combinar biometria amb un segon factor (com OTP) proporciona defensa en profunditat.