Tot el marc de la lliçó anterior —subjectes, dominis, matriu d'accés, privilegi mínim— descansa sobre una paraula que encara no hem definit: identitat. Un domini de protecció s'assigna a un subjecte, i el subjecte s'identifica per un número. El nucli de Linux no coneix meteora, ni nuria, ni carlos: coneix el 990, el 1002 i el 1001. Tota la resta —el nom, la contrasenya, el grup, la shell— viu en fitxers de text de /etc que el nucli ni tan sols llegeix.
Això té una conseqüència que convé interioritzar des del primer minut: la identitat a UNIX és una convenció d'espai d'usuari sostinguda sobre un número. Si esborres la línia de meteora de /etc/passwd, els 17.280.000 bytes de 2026-08-31.dat continuen pertanyent a l'UID 990 i ls -l els mostra com a 990. Si crees un altre usuari amb el 990, aquell usuari és l'amo de les dades de Meteora sense haver tocat ni un sol fitxer. El número és la identitat; el nom és una etiqueta.
Aquesta lliçó recorre la cadena completa: els identificadors i per què cada procés porta tres UID —cosa que explica del tot el passwd setuid de 04-06—; els tres fitxers de /etc camp a camp; el cicle de vida d'un compte i el moment del qual surten més incidents, la baixa; l'autenticació en si, amb com es guarda una contrasenya, què significa el $y$j9T$... de /etc/shadow i quins atacs l'amenacen —descrits a nivell conceptual, per poder-se'n defensar—; PAM, la peça que decideix si entres i que gairebé ningú no entén fins que la trenca; l'autenticació per clau pública de SSH, que és la que faràs servir de debò a meteo-01; i l'elevació controlada amb sudo, amb el catàleg defensiu dels errors de configuració que converteixen un compte normal en root.
Contingut
- UID, GID i els tres identificadors d'un procés
- Grups suplementaris i la lectura d'
id,whoamiigroups /etc/passwd,/etc/shadowi/etc/groupcamp a camp- Comptes de sistema davant de comptes humans
- Gestió i cicle de vida d'un compte
- Autenticació: els tres factors
- Com s'emmagatzema una contrasenya
- Atacs a credencials i les seves contramesures
- PAM: l'arquitectura que decideix si entres
- Autenticació per clau pública amb SSH
- Elevació controlada de privilegis:
suisudo - Escalada de privilegis: catàleg defensiu i auditoria
UID, GID i els tres identificadors d'un procés
Cada procés porta un joc d'identificadors numèrics que el nucli consulta a cada comprovació d'accés. Els d'usuari són tres, i aquesta multiplicitat no és un caprici històric: resol un problema concret.
| Identificador | Abreviatura | Per a què serveix |
|---|---|---|
| UID real | ruid |
Qui ets: qui va llançar el procés. Comptabilitat, senyals, auditoria |
| UID efectiu | euid |
Què pots fer: és el que el nucli comprova a cada accés |
| UID desat | suid |
Què podries recuperar: còpia que permet baixar el privilegi i tornar-lo a apujar |
Recupera el passwd setuid de 04-06 i ara tindrà sentit complet. L'usuari joan (UID 1000) l'executa:
Abans de l'execve: ruid=1000 euid=1000 suid=1000
Després de l'execve: ruid=1000 euid=0 suid=0
↑ ↑
qui l'ha llançat privilegi amb
(per auditar) què actuaEl programa necessita les dues coses alhora: euid=0 per escriure a /etc/shadow, i ruid=1000 per saber de qui ha de canviar la contrasenya. Si només existís l'efectiu, passwd no tindria manera fiable de saber qui el va invocar i qualsevol podria canviar la contrasenya de qualsevol. Els tres identificadors existeixen, en resum, perquè autoritat i identitat puguin ser diferents i totes dues estiguin disponibles.
El desat habilita el patró més important per escriure serveis segurs: alliberar el privilegi.
/* L'ingestor obre el sòcol privilegiat i baixa a UID 990 per sempre */
obrir_socket_estacions(); /* necessita privilegi */
if (setgroups(0, NULL) != 0) return 1; /* ORDRE CRÍTIC: */
if (setgid(990) != 0) return 1; /* grups → GID → UID */
if (setuid(990) != 0) return 1;
if (setuid(0) == 0) { fprintf(stderr, "FATAL: privilegi recuperable\n"); return 1; }
bucle_principal(); /* ja sense privilegi */Tres detalls dels quals depenen vulnerabilitats reals. L'ordre és obligatori: setgroups i setgid van abans de setuid, perquè després de perdre l'UID 0 ja no hi ha permís per canviar els grups i el procés conservaria els grups suplementaris de root. setuid() cridat per root canvia els tres identificadors alhora, i per això la baixada és irreversible; amb seteuid() el desat continuaria sent 0 i un atacant recuperaria root amb una crida. I la verificació final no és paranoia: comprova que la baixada va ser definitiva, i la seva absència ha causat escalades documentades en programari molt conegut. Amb els GID passa el mateix, i el bit setgid actua sobre l'efectiu igual que setuid sobre el seu.
Grups suplementaris i la lectura d'id, whoami i groups
Un procés pertany a un grup primari i a diversos suplementaris, i per a les comprovacions de 04-06 qualsevol d'ells serveix per entrar a la classe de grup.
$ id
uid=1001(carlos) gid=1001(carlos) grupos=1001(carlos),4(adm),27(sudo),990(meteora)
$ whoami # equival a `id -un`: el nom de l'UID EFECTIU
carlos
$ id meteora # consultar una altra identitat sense ser-la
uid=990(meteora) gid=990(meteora) grupos=990(meteora)uid=1001(carlos) és l'UID efectiu amb el nom traduït; gid=1001 és el grup primari, que s'assigna per defecte als fitxers que creï —tret que el directori tingui setgid, com ara /var/lib/meteora—; i la llista grupos= són tots els seus grups. Els tres de carlos són tres decisions de seguretat diferents i convé que ho siguin: adm li dona lectura dels registres, sudo li habilita l'elevació i meteora l'accés al grup del servei. És separació de privilegis de 05-01 aplicada a una persona.
Un detall que sorprèn: whoami informa de l'efectiu, no del real. Dins d'un procés setuid root diu root encara que el llancés joan. Per saber qui hi ha al darrere es fa servir id -ru o, en una sessió interactiva, who am i, que consulta el registre de sessions i sobreviu als su encadenats.
Els grups suplementaris es calculen en iniciar sessió i s'hereten per
fork. Unusermod -aG meteora carlosno afecta les sessions obertes ni els processos ja arrencats.idmostrarà el grup nou perquè rellegeix/etc/group, però el procés continuarà sense l'accés: el nucli fa servir les credencials que el procés porta a sobre, no el fitxer. Cal reiniciar la sessió o el servei.
La manera ràpida de distingir-ho: id llegeix el fitxer, i grep Groups /proc/<pid>/status mostra els grups reals del procés. Si difereixen, aquest és el problema.
/etc/passwd, /etc/shadow i /etc/group camp a camp
/etc/passwd: set camps separats per dos punts
root:x:0:0:root:/root:/bin/bash carlos:x:1001:1001:Carlos Ruiz,Sistemes,,:/home/carlos:/bin/bash meteora:x:990:990:Servei Meteora,,,:/var/lib/meteora:/usr/sbin/nologin
| # | Camp | Valor a meteora |
Què significa |
|---|---|---|---|
| 1 | Nom | meteora |
El nom d'inici de sessió. Únic |
| 2 | Contrasenya | x |
Marcador històric: el hash és a /etc/shadow |
| 3 | UID | 990 |
La identitat real davant del nucli |
| 4 | GID primari | 990 |
Grup per defecte dels fitxers que creï |
| 5 | GECOS | Servei Meteora,,, |
Camp lliure: nom, despatx, telèfons |
| 6 | Directori | /var/lib/meteora |
El $HOME del compte |
| 7 | Shell | /usr/sbin/nologin |
Programa que s'executa en iniciar sessió |
La x del camp 2 és història viva: fins a principis dels noranta el hash era allà mateix, en un fitxer llegible per tothom perquè molts programes necessiten traduir UID a nom. Quan la potència de còmput va fer viables els atacs per diccionari, els hashos es van moure a /etc/shadow, llegible només per root, i va quedar la x com a marca. És un exemple perfecte de reducció de superfície: la dada sensible se separa del fitxer que tothom necessita llegir.
El camp 7, /usr/sbin/nologin, és un programa real que imprimeix un avís i surt amb error; la diferència amb /bin/false és cosmètica, però deixar el camp buit sí que importa, perquè llavors es fa servir /bin/sh.
Per què
meteorano té shell. És privilegi mínim aplicat a la identitat: el compte existeix només per ser amo d'uns fitxers i ser la identitat d'uns processos que arrenca systemd. Si un atacant obté una credencial demeteora, no la pot fer servir per entrar per SSH ni per obrir sessió: només li serveix si ja és a dins. Una capa sencera de defensa per una paraula al camp 7.
/etc/shadow: nou camps, i el que importa és el segon
| # | Camp | Exemple | Significat |
|---|---|---|---|
| 1 | Nom | carlos |
Enllaça amb /etc/passwd |
| 2 | Hash | $y$j9T$... |
La contrasenya derivada (apartat 7) |
| 3 | Últim canvi | 20330 |
Dies des de l'1/1/1970 en què es va canviar |
| 4 | Dies mínims | 1 |
No la pot tornar a canviar abans d'1 dia |
| 5 | Dies màxims | 365 |
Caduca a l'any |
| 6 | Avís | 14 |
Avisa 14 dies abans de caducar |
| 7 | Inactivitat | 30 |
Dies de gràcia després de caducar abans de bloquejar |
| 8 | Caducitat | (buit) | Data absoluta d'expiració del compte |
| 9 | Reservat | (buit) | Sense ús |
Els quatre valors possibles del camp 2 es confonen constantment: $y$... és una contrasenya vàlida; ! o !hash és compte bloquejat (passwd -l), un bloqueig reversible perquè el hash es conserva al darrere i passwd -u el restaura; * significa que mai no ha tingut contrasenya ni en tindrà, el normal en comptes de paquets; i buit significa accés sense credencial, cosa que és una emergència. Per això meteora:!: és el correcte per a un compte de servei.
I un matís decisiu per a l'apartat 5: bloquejar la contrasenya no bloqueja l'accés per clau SSH, perquè són mecanismes d'autenticació diferents.
/etc/group: quatre camps
Nom, marcador de contrasenya, GID i llista de membres suplementaris. La subtilesa: els membres el grup primari dels quals és aquest NO apareixen a la llista. meteora:x:990: és buit i tanmateix l'usuari meteora pertany al grup, perquè el té com a primari a /etc/passwd. Per això id nuria és més fiable que llegir /etc/group: combina les dues fonts.
Dues regles en editar aquests fitxers. Fes servir vipw, vipw -s i vigr en lloc de l'editor a pèl: bloquegen contra edicions simultànies i validen la sintaxi —un /etc/passwd corrupte deixa el sistema sense poder resoldre cap nom d'usuari—. I valida amb pwck i grpck després de qualsevol canvi manual.
Comptes de sistema davant de comptes humans
| Compte de sistema | Compte humà | |
|---|---|---|
| Exemple | meteora (990), www-data (33) |
carlos (1001), nuria (1002) |
| Rang d'UID a Debian | 1–999 | 1000 en endavant |
| Shell | /usr/sbin/nologin |
/bin/bash |
| Contrasenya | Bloquejada (! o *) |
Hash vàlid |
| Directori | Funcional (/var/lib/meteora) o inexistent |
/home/usuari |
| Inici de sessió interactiu | Mai | Sí |
| Cicle de vida | El del servei | El de la relació laboral |
La separació per rang no és una regla del nucli: és una convenció que apliquen useradd i login llegint /etc/login.defs. El seu valor és operatiu: permet escriure auditories del tipus "tot compte amb UID ≥ 1000 ha de tenir segon factor" o "cap amb UID < 1000 no ha de tenir shell". Així es va crear meteora:
sudo groupadd --system --gid 990 meteora
sudo useradd --system --uid 990 --gid meteora --no-create-home \
--home-dir /var/lib/meteora --shell /usr/sbin/nologin \
--comment "Servei Meteora" meteora
sudo passwd -l meteora # bloquejar explícitament la contrasenyaCada opció és una decisió. --system situa l'UID al rang de serveis i evita crear un grup personal. --no-create-home és correcte perquè /var/lib/meteora el crea el paquet amb els permisos 2750 de 04-06, no useradd amb els seus. --shell /usr/sbin/nologin tanca l'inici de sessió. I passwd -l és explícit encara que useradd --system ja deixi el compte bloquejat: la seguretat es declara, no es pressuposa.
Gestió i cicle de vida d'un compte
# ALTA d'una persona
sudo useradd --create-home --shell /bin/bash --comment "Nuria Vidal,,," nuria
sudo passwd nuria && sudo chage -d 0 nuria # forçar canvi al primer accés
# CANVI DE ROL
sudo usermod -aG adm nuria # la -a és obligatòria!
sudo gpasswd -d nuria meteora # treure d'un grup
# CADUCITAT
sudo chage -M 365 -m 1 -W 14 -I 30 nuria # màx, mín, avís, inactivitat
sudo chage -E 2027-06-30 extern_temporal # data de fi d'un contracte
sudo chage -l nuria # consultar l'estatL'error clàssic és a la línia del canvi de rol: usermod -G sense la -a substitueix tota la llista de grups suplementaris. Un usermod -G adm carlos ben intencionat el deixa fora de sudo i de meteora, i l'efecte no es nota fins que algú necessita aquests accessos. La -a significa append, i la regla és no escriure mai -G sense ella.
graph LR
A["ALTA<br/>Compte i grups<br/>mínims"] --> B["OPERACIÓ<br/>Revisió periòdica<br/>d'accessos"]
B --> C["CANVI DE ROL<br/>Afegir el nou<br/><b>i TREURE el vell</b>"]
C --> B
B --> D["BAIXA<br/>Tancar TOTS els<br/>camins d'accés"]
D --> E["ARXIU<br/>Reassignar<br/>la propietat"]
Els incidents s'acumulen sempre als dos mateixos punts.
El canvi de rol i l'acumulació de privilegis. Quan algú canvia de lloc de treball se li afegeixen els accessos nous i gairebé mai no se li treuen els vells; al cap de cinc anys i tres equips acumula accés a mitja empresa sense que ningú ho hagi decidit. És la violació silenciosa del privilegi mínim, i l'única defensa és la revisió periòdica d'accessos: cada sis mesos, comprovar que cada grup i cada regla de sudo continuen justificats. És avorrit i funciona.
La baixa, que és el risc real més gran del cicle. Un compte viu després de la sortida d'una persona és una credencial vàlida sense amo ni supervisió. I l'error habitual no és oblidar la baixa, sinó fer-la a mitges. Té cinc blocs i cap no en substitueix un altre: tancar els quatre camins d'accés (contrasenya, shell, caducitat del compte i authorized_keys), retirar els privilegis (grups, regles de sudo, ACL, tasques de cron), tallar les sessions vives, inventariar i reassignar els fitxers, i rotar els secrets que aquella persona coneixia. El procediment complet amb les seves ordres és l'exercici 2.
El pas més oblidat és retirar les authorized_keys, i és demolidor: usermod -L bloqueja la contrasenya però no impedeix entrar amb clau pública, perquè SSH ni consulta el hash quan l'autenticació és per clau. El segon més oblidat és tallar sessions: bloquejar un compte no expulsa qui ja és a dins.
Sobre esborrar el compte amb userdel -r: fes-ho només després d'arxivar el que calgui. I aquí arriba l'advertència obligada: la retenció de dades de persones, els registres d'accés i els terminis de conservació tenen implicacions legals (RGPD i normativa laboral); abans de fixar una política d'esborrat, consulta-la amb el responsable de compliment normatiu o amb assessoria jurídica. No és una decisió tècnica.
Autenticació: els tres factors
Autenticar és demostrar que ets qui dius que ets, i tots els mètodes caben en tres famílies:
| Factor | Base | Exemples | Debilitat |
|---|---|---|---|
| Alguna cosa que saps | Coneixement | Contrasenya, PIN, frase de pas | S'endevina, es reutilitza, es comparteix, es filtra |
| Alguna cosa que tens | Possessió | Clau SSH, TOTP, clau FIDO2 | Es perd, es roba, es pot clonar segons el tipus |
| Alguna cosa que ets | Biometria | Empremta, cara, iris | No es pot canviar si es compromet |
L'autenticació multifactor (MFA) exigeix elements de dues famílies diferents: contrasenya més pregunta de seguretat no és MFA —totes dues són "alguna cosa que saps"—; contrasenya més codi TOTP sí. És la separació de privilegis de 05-01 aplicada a la identitat: dues condicions independents en comptes d'una.
La debilitat de la biometria mereix èmfasi perquè se sol vendre com la més forta: una empremta compromesa és un problema permanent. Pots canviar una contrasenya en deu segons; no pots canviar de dits. Per això es fa servir correctament com a factor local —desbloquejar un dispositiu que guarda la clau real— i no com a credencial que viatgi per la xarxa. Per a meteo-01 l'objectiu és clar: SSH amb clau pública (alguna cosa que tens) protegida per frase de pas (alguna cosa que saps), i segon factor per a l'accés des de fora de la xarxa de gestió.
Com s'emmagatzema una contrasenya
Regla sense excepcions: una contrasenya no es guarda mai, ni en clar ni xifrada de manera reversible. Es guarda el resultat de passar-la per una funció de derivació de clau (KDF), i en autenticar es repeteix l'operació i es comparen els resultats.
Per què no serveix SHA-256: perquè està dissenyat per ser ràpid, i aquesta velocitat juga a favor de l'atacant —una GPU en calcula milers de milions per segon—. Una KDF de contrasenyes es dissenya amb tres propietats oposades: sal única i aleatòria, que fa que dos usuaris amb la mateixa contrasenya produeixin hashos diferents i invalida les taules precalculades; cost de treball ajustable, per fer-la deliberadament lenta i apujar el cost a mesura que millora el maquinari; i cost en memòria, que anul·la l'avantatge de les GPU i els ASIC, amb molt de càlcul i poca memòria per unitat.
| Algorisme | Prefix | Cost en memòria | Veredicte |
|---|---|---|---|
| DES tradicional | (13 caràcters) | No | Obsolet: només 8 caràcters útils |
| MD5-crypt | $1$ |
No | Obsolet |
| SHA-256/512-crypt | $5$, $6$ |
No | Acceptable amb moltes rondes |
| bcrypt | $2b$ |
Poc | Bo, molt provat des de 1999 |
| yescrypt | $y$ |
Sí | Per defecte al Debian actual |
| Argon2id | $argon2id$ |
Sí | Recomanació actual per a desenvolupament nou |
I així es llegeix el camp real de /etc/shadow:
$y$j9T$FvB2kXqR8mNpL4wZ$3xKm9QvW7rT2yH5nB8cF4dG6jK1mP0sA9zX3vC7bN2e │ │ │ │ │ │ │ └─ HASH: resultat de la derivació │ │ └──────────────────────────────── SAL: aleatòria, diferent per usuari │ └───────────────────────────────────────── PARÀMETRES: cost de temps i memòria └──────────────────────────────────────────── ALGORISME: y = yescrypt
La sal es guarda en clar i està bé que sigui així: no és un secret, la seva funció és garantir que cada contrasenya s'ataqui per separat, i el sistema la necessita per repetir el càlcul. En autenticar, el sistema llegeix la línia, extreu algorisme, paràmetres i sal, recalcula amb exactament aquests valors i compara en temps constant, per no filtrar informació pel temps de resposta.
grep ENCRYPT_METHOD /etc/login.defs # ENCRYPT_METHOD YESCRYPT
grep YESCRYPT_COST /etc/login.defs # YESCRYPT_COST_FACTOR 5El factor de cost és la palanca que compensa l'avenç del maquinari: apujar-lo multiplica la feina de cada intent, per al sistema i per a l'atacant. El criteri pràctic és fixar-lo perquè verificar una contrasenya costi entre 100 i 500 mil·lisegons al maquinari de producció: imperceptible per a qui s'autentica una vegada, devastador per a qui en prova milions. Val igual per a qualsevol aplicació pròpia: no implementis mai el teu esquema, fes servir libxcrypt, bcrypt o argon2 amb paràmetres revisats.
Atacs a credencials i les seves contramesures
Descrits a nivell conceptual, per poder-se'n defensar. Aquí no hi ha instruccions ni eines ofensives: cada fila es tanca amb la contramesura, que és el que ens interessa.
| Atac | En què consisteix (concepte) | Contramesura a meteo-01 |
|---|---|---|
| Diccionari | Provar paraules i variacions habituals | Longitud mínima alta, comprovació contra llistes filtrades |
| Força bruta | Recórrer l'espai de combinacions | Longitud: cada caràcter multiplica l'espai |
| Taules precalculades | Consultar hashos calculats per endavant | La sal: les inutilitza completament |
| Reutilització | Provar credencials filtrades d'altres serveis | Gestor de contrasenyes, contrasenyes úniques, MFA |
| Polvorització | Una contrasenya molt comuna contra molts comptes | Detecció per origen, no només per compte; MFA |
| Interceptació | Capturar la credencial en trànsit | TLS i SSH sempre; mai protocols en clar |
| Enginyeria social | Aconseguir que la persona la lliuri | Formació, verificació, MFA resistent al phishing (FIDO2) |
La conclusió quantitativa que ordena mitja taula: la longitud venç la complexitat. Amb 95 caràcters imprimibles, cada caràcter addicional multiplica l'espai de cerca per 95, mentre que substituir una a per una @ el multiplica per menys de dos —i els diccionaris d'atac coneixen aquesta substitució des de fa dècades—. Una frase de pas de quatre paraules poc relacionades és més resistent i molt més memorable que P@ssw0rd!, que a més compleix formalment qualsevol política de complexitat. Per això les guies modernes recomanen exigir longitud, no complexitat, i eliminar la caducitat periòdica obligatòria, que només produeix increments predictibles: és l'acceptabilitat psicològica de 05-01 convertida en política.
sudo apt install libpam-pwquality
# /etc/security/pwquality.conf
minlen = 14 # longitud: la defensa principal
minclass = 3 # tres classes de caràcters, sense exigir les quatre
dictcheck = 1 # rebutja paraules de diccionari
usercheck = 1 # rebutja variacions del nom d'usuari
# /etc/security/faillock.conf
deny = 5 # 5 errades...
unlock_time = 900 # ...bloquegen 15 minuts
fail_interval = 900 # comptades en una finestra de 15 minuts
even_deny_root = 0 # ATENCIÓ: bloquejar root et pot deixar foraTres comentaris que eviten problemes reals. deny=5 amb unlock_time=900 converteix la força bruta en inviable: 480 intents al dia davant dels milions per segon que l'atac necessita. even_deny_root=0 és deliberat: si un atacant pot bloquejar root provant contrasenyes, ha aconseguit una denegació de servei contra l'administració justament quan més falta fa. I el desbloqueig temporal és preferible al permanent, perquè un bloqueig permanent converteix qualsevol polvorització en la paràlisi de tota l'organització. Es consulta amb faillock --user carlos i es neteja amb --reset.
PAM: l'arquitectura que decideix si entres
Abans de PAM, cada programa que autenticava —login, su, sshd, passwd— portava el seu propi codi, i afegir un mètode nou obligava a recompilar-los tots. PAM (Pluggable Authentication Modules) hi posa una indirecció: els programes criden la biblioteca, i aquesta consulta un fitxer que decideix quins mòduls executar i en quin ordre.
graph LR
A["sshd / login / sudo"] --> B["libpam"] --> C["/etc/pam.d/<servei>"]
C --> D["auth<br/>és qui diu que és?"]
C --> E["account<br/>pot entrar ARA?"]
C --> F["password<br/>canviar credencial"]
C --> G["session<br/>preparar i tancar"]
| Pila | Pregunta | Mòduls típics |
|---|---|---|
| auth | És qui diu que és? | pam_unix, pam_faillock, pam_u2f, TOTP |
| account | Sent qui és, pot entrar ara? | pam_nologin, pam_time, pam_access |
| password | Com es canvia la credencial? | pam_pwquality, pam_unix |
| session | Què cal preparar abans i netejar després? | pam_limits, pam_systemd, pam_mkhomedir |
La distinció entre auth i account és la que més costa i la més útil: un compte caducat s'autentica correctament —la contrasenya és vàlida— i tot i així no entra, perquè la pila account ho denega. Són dues decisions independents.
| Bandera | Si el mòdul falla | Si té èxit |
|---|---|---|
required |
La pila fallarà, però es continua executant fins al final | Continua |
requisite |
Talla immediatament i retorna la fallada | Continua |
sufficient |
S'ignora i es continua | Èxit immediat si cap required anterior no ha fallat |
optional |
S'ignora, tret que sigui l'únic mòdul | Continua |
required davant de requisite té una justificació elegant: required continua executant la pila encara que ja sàpiga que fallarà, perquè un atacant no dedueixi en quin punt va fallar mesurant el temps de resposta.
# /etc/pam.d/sshd — AUTENTICACIÓ auth required pam_faillock.so preauth silent # bloquejat per errades? auth [success=1 default=ignore] pam_unix.so # contrasenya UNIX auth required pam_faillock.so authfail # registra la fallada auth required pam_deny.so # denegació final auth required pam_permit.so # COMPTE account required pam_nologin.so # existeix /etc/nologin? ningú no entra account required pam_unix.so # caducat? bloquejat? account required pam_faillock.so # ha superat el llindar d'errades? # CONTRASENYA password requisite pam_pwquality.so retry=3 password required pam_unix.so obscure yescrypt shadow # SESSIÓ session required pam_limits.so # aplica /etc/security/limits.conf session required pam_unix.so # registra inici i fi a wtmp session optional pam_systemd.so # crea la sessió de systemd
La pila auth té truc. [success=1 default=ignore] significa "si pam_unix té èxit, salta 1 línia", amb la qual cosa se salta authfail i arriba a pam_permit.so, que concedeix l'accés. Si la contrasenya falla, no salta: executa authfail —que incrementa el comptador— i després pam_deny.so. És un salt condicional, i tan bon punt ho veus així qualsevol fitxer de PAM es llegeix sense dificultat. A account, pam_nologin implementa un mecanisme molt útil: si existeix /etc/nologin, ningú tret de root no inicia sessió i se'n mostra el contingut; és la manera estàndard de buidar un servidor abans d'una intervenció.
Un canvi de política d'exemple, restringir SSH a uns grups i a un horari:
# A /etc/pam.d/sshd, dins de la pila account: account required pam_access.so account required pam_time.so # /etc/security/access.conf — llista blanca, i denegació final + : root carlos (admins) : ALL - : ALL : ALL # /etc/security/time.conf — becaris, només en horari laboral sshd ; * ; becaris ; Wk0800-1900
access.conf es llegeix de dalt a baix i la primera línia que hi casa decideix: es permet explícitament root, carlos i el grup admins, i l'última denega tota la resta. És exactament el principi de valors per defecte segurs de 05-01.
Advertència pràctica. Un error a
/etc/pam.d/et pot deixar fora del sistema de manera irrecuperable, root inclòs. Mantén una sessió root oberta, obre'n una altra per verificar el canvi, i tingues a mà la consola física o el KVM. Si la nova falla, la que continua oberta et permet desfer-ho.
Autenticació per clau pública amb SSH
La criptografia asimètrica, en dos paràgrafs. Es generen dues claus relacionades: una de privada, que no surt mai de la teva màquina, i una de pública, que pots repartir sense risc. El que es fa amb una només es desfà amb l'altra, i —això és l'essencial— conèixer la pública no permet deduir la privada.
Per autenticar, el servidor envia una dada aleatòria i demana que se signi amb la privada; qui la té produeix una signatura que el servidor verifica amb la pública que ja guarda. La clau privada no viatja mai per la xarxa, ni tan sols xifrada. Compara-ho amb una contrasenya, que sí que viatja —protegida pel canal, però viatja— i que el servidor ha de processar: si el servidor està compromès, la teva contrasenya es filtra; la teva clau privada, no.
# 1. Generar el parell (a LA TEVA màquina, mai al servidor)
ssh-keygen -t ed25519 -a 100 -C "carlos@portatil-2026" -f ~/.ssh/id_meteo01
# -a 100 : rondes que protegeixen la clau amb la frase de pas. Posa-la SEMPRE.
# -rw------- id_meteo01 ← PRIVADA: mode 600
# -rw-r--r-- id_meteo01.pub ← pública: es reparteix
# 2. Instal·lar-la al servidor i comprovar permisos (sshd els EXIGEIX)
ssh-copy-id -i ~/.ssh/id_meteo01.pub carlos@meteo-01
# drwx------ ~/.ssh -rw------- ~/.ssh/authorized_keys
# 3. L'agent: teclejar la frase de pas UNA vegada per sessió
eval "$(ssh-agent -s)" && ssh-add -t 8h ~/.ssh/id_meteo01Els punts que cal entendre. La clau es genera a la teva màquina: si la generes al servidor, la privada ha existit en un sistema que no controles del tot i ha passat pels seus discos i les seves còpies. La frase de pas la converteix de facto en un doble factor: qui robi el fitxer necessita a més conèixer-la. Els permisos són obligatoris, no una recomanació: sshd rebutja un authorized_keys, un ~/.ssh o fins i tot un $HOME massa oberts, perquè qui hi pogués escriure hi afegiria la seva pròpia clau. I l'agent existeix per acceptabilitat psicològica: sense ell, teclejar la frase cinquanta vegades al dia porta directament a eliminar-la; -t 8h limita el dany si algú es deixa la sessió oberta.
# /etc/ssh/sshd_config.d/99-meteora.conf PermitRootLogin no # mai root directe: entra i després sudo PasswordAuthentication no # NOMÉS claus públiques KbdInteractiveAuthentication no # tanca l'altra via de contrasenya AuthenticationMethods publickey AllowGroups admins # llista blanca de qui pot entrar MaxAuthTries 3 LoginGraceTime 30 AllowAgentForwarding no # evita reutilitzar el teu agent des del servidor ClientAliveInterval 300
Cada línia correspon a un principi de 05-01. PermitRootLogin no és separació de privilegis i traçabilitat: obliga a entrar amb el compte nominal i elevar amb sudo, de manera que cada acció queda atribuïda a una persona en lloc de a un root compartit. PasswordAuthentication no elimina de cop diccionari, força bruta, polvorització i reutilització: si no hi ha contrasenya per provar, no hi ha atac de contrasenya. AllowGroups és llista blanca. I AllowAgentForwarding no tanca un risc poc conegut: amb reenviament actiu, algú amb root al servidor pot fer servir el teu agent per saltar a altres màquines on la teva clau val.
Abans de tancar la sessió: valida amb
sudo sshd -t, recarrega ambsystemctl reload sshi obre una segona sessió per comprovar-ho sense tancar la primera. Deshabilitar les contrasenyes sense haver provat la clau és la manera més comuna de perdre l'accés a un servidor remot.
Elevació controlada de privilegis: su i sudo
Un administrador necessita privilegis de tant en tant, no tot el dia. Treballar sempre com a root viola el privilegi mínim de la pitjor manera: un rm -rf mal escrit i no hi ha xarxa de seguretat. Hi ha dues maneres de pujar, i són molt diferents.
su |
sudo |
|
|---|---|---|
| Contrasenya que demana | La de l'usuari destinació (la de root) | La teva pròpia |
| Granularitat | Tot o res: et converteixes en l'usuari | Per ordre, usuari i màquina |
| Durada | Una shell sencera | Una ordre (amb memòria cau de minuts) |
| Traçabilitat | "Algú va fer su"; la resta és anònim |
Cada ordre queda registrada amb qui la fa |
| Secret compartit | La contrasenya de root la coneix tot l'equip | Ningú no necessita conèixer-la |
| Revocar a una persona | Canviar la contrasenya de root i avisar tothom | Treure una línia de sudoers |
| Veredicte | Llegat; útil per a su - meteora en depurar |
La manera correcta |
La fila decisiva és la del secret compartit: amb su, la contrasenya de root la coneixen cinc persones i cap acció no és atribuïble; amb sudo, la contrasenya de root pot ni existir —a Debian està bloquejada per defecte— i retirar l'accés és esborrar una línia.
visudo no és opcional. Comprova la sintaxi abans de desar i es nega a escriure un fitxer no vàlid; un /etc/sudoers amb un error deixa el sistema sense sudo, i si a més PermitRootLogin no està actiu i root no té contrasenya, has perdut tota via d'administració tret de la consola física. La sintaxi d'una regla és qui on = (com a qui) quines ordres:
## --- Nivell 0: accés total (el grup sudo de Debian) ---
%sudo ALL=(ALL:ALL) ALL
## --- Nivell 1: només el que l'equip necessita ---
Cmnd_Alias METEORA_SVC = /usr/bin/systemctl start meteo-api, \
/usr/bin/systemctl stop meteo-api, \
/usr/bin/systemctl restart meteo-api
%meteora-ops ALL=(root) METEORA_SVC
## --- Nivell 2: sense contrasenya NOMÉS per al que és innocu i automatitzat ---
%monitoring ALL=(root) NOPASSWD: /usr/bin/systemctl status meteo-api
## --- Higiene general ---
Defaults env_reset, timestamp_timeout=5, passwd_tries=3
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults logfile="/var/log/sudo.log", log_input, log_outputEls quatre elements importants. Els Cmnd_Alias agrupen ordres i fan la política llegible, que és economia del mecanisme aplicada a la configuració. env_reset i secure_path són crítics: sense ells, un usuari podria manipular PATH o variables com ara LD_PRELOAD perquè l'ordre privilegiada carregui codi seu. timestamp_timeout=5 són els minuts de memòria cau de la contrasenya: 0 la demana sempre —segur i carregós, i ja saps on porta això— i valors alts deixen una finestra si algú deixa el terminal desatès. I log_input, log_output graven la sessió completa de les ordres elevades, valuosíssim en una investigació.
Sobre NOPASSWD: el seu risc no és teòric. Converteix qualsevol compromís del compte —una sessió oberta, una clau robada— en privilegi immediat sense cap barrera, eliminant el segon factor implícit de teclejar la contrasenya. Fes-lo servir només per a ordres de només lectura i sense arguments lliures, executades per automatismes que no poden teclejar, i mai amb ALL.
I la propietat que fa de sudo una eina de seguretat i no només de comoditat: tota elevació queda registrada, amb èxit i amb fracàs.
sep 01 11:42:17 meteo-01 sudo[4821]: carlos : TTY=pts/0 ; PWD=/home/carlos ;
USER=root ; COMMAND=/usr/bin/systemctl restart meteo-api
sep 01 11:45:03 meteo-01 sudo[4855]: nuria : 3 incorrect password attempts ;
TTY=pts/2 ; USER=root ; COMMAND=/usr/bin/cat /etc/shadowCada línia conté qui, des d'on, com a qui i què. La segona és justament l'esdeveniment que ha de disparar una alerta. Consulta els teus propis permisos amb sudo -l, els d'una altra persona amb sudo -l -U nuria, i oblida la contrasenya desada a la memòria cau amb sudo -k. El tractament sistemàtic d'aquests registres és Auditoria, Registres i Resposta a Incidents.
Escalada de privilegis: catàleg defensiu i auditoria
Escalada de privilegis és passar a un domini de protecció amb més autoritat —en el vocabulari de 05-01, un canvi de domini no previst—. La tractem exclusivament des de la defensa: quines configuracions la fan possible i com detectar-les. No es descriuen tècniques d'explotació.
| Categoria de fallada | Per què permet l'escalada | Com es detecta |
|---|---|---|
| Binaris setuid innecessaris | S'executen com el seu propietari: una errada seva és una errada amb privilegi | find / -perm -4000 contra una referència |
| Fitxers amb capabilities | Igual, i no es veuen a ls -l |
getcap -r /, amb referència |
Regles de sudo àmplies |
Moltes ordres permeten executar-ne d'altres o escriure fitxers arbitraris | sudo -l, revisió de sudoers.d/ |
| Comodins en rutes | Un * casa amb rutes no previstes, .. inclosos |
Revisió manual; evitar * |
| Scripts privilegiats escrivibles | Si pots editar el que root executa, executes com a root | find d'escrivibles per grup o altres |
| Tasques programades amb mals permisos | Un cron de root que executa un script editable |
Permisos de /etc/cron* |
| Rutes relatives en scripts privilegiats | El programa executat depèn del PATH |
Revisió de codi; rutes absolutes |
| Secrets a l'entorn o a l'historial | Una clau visible a ps, a environ o a .bash_history |
grep als historials |
| Serveis com a root sense necessitat | Una fallada del servei és una fallada amb UID 0 | ps -eo user,comm --sort user |
| Programari sense actualitzar | Vulnerabilitats conegudes del nucli o les biblioteques | apt list --upgradable |
#!/bin/bash
# auditoria-privilegis.sh — executar com a root, periòdicament
echo "[1] Comptes amb UID 0 (només hi ha de sortir root)"
awk -F: '($3==0){print " "$1}' /etc/passwd
echo "[2] Comptes SENSE contrasenya"
awk -F: '($2==""){print " CRÍTIC: "$1}' /etc/shadow
echo "[3] Comptes de sistema AMB shell interactiva"
awk -F: '($3<1000 && $3>0 && $7!~/nologin|false/){print " "$1" -> "$7}' /etc/passwd
echo "[4] setuid/setgid i [5] capabilities: per DIFERÈNCIA amb la referència"
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null | sort > /tmp/suid.now
getcap -r / 2>/dev/null | sort > /tmp/caps.now
diff /root/ref/suid.ref /tmp/suid.now | grep '^>' || echo " setuid: sense canvis"
diff /root/ref/caps.ref /tmp/caps.now | grep '^>' || echo " caps: sense canvis"
echo "[6] Regles de sudo amb NOPASSWD o comodins"
grep -rnE 'NOPASSWD|\*' /etc/sudoers /etc/sudoers.d/ 2>/dev/null | grep -v '^\s*#'
echo "[7] Tasques programades de root escrivibles per altres"
find /etc/cron* /var/spool/cron -type f \( -perm -0002 -o -perm -0020 \) -ls 2>/dev/null
echo "[8] Serveis executant-se com a root"
ps -eo user:16,comm --no-headers | awk '$1=="root"' | sort -u -k2 | head -30
echo "[9] Possibles secrets als historials de shell"
grep -rlE '(password|token|api[_-]?key|secret)=' /home/*/.bash_history 2>/dev/nullCom s'interpreta. Els blocs [1] a [3] han de tenir resultats fixos i coneguts; qualsevol novetat exigeix explicació, i un compte de sistema amb shell és justament el que un atacant crea per persistir. [4] i [5] són detecció per diferència: no importa la llista completa, sinó el que ha aparegut des de l'última vegada; el [5] és el que més s'oblida i menys soroll fa, perquè ls -l no mostra les capabilities. [6] no marca errors sinó coses per revisar: cada NOPASSWD i cada comodí necessita una justificació escrita. [7] busca el patró més rendible per a un atacant: un fitxer que ell pot escriure i que root executa tot sol. [8] ha de ser tan curt com sigui possible. I [9] recorda que un secret teclejat queda a l'historial en clar i per sempre, a més d'haver estat visible a ps mentre l'ordre s'executava.
Com es dissenya meteo-01 per contenir un compromís
| Decisió | Què impedeix si meteo-api cau |
|---|---|
meteora amb nologin i contrasenya bloquejada |
No serveix per iniciar sessió, ni per SSH ni localment |
| Configuració i binari propietat de root | No es pot reescriure a si mateix ni persistir així |
| Cap binari setuid propi del servei | No hi ha via de pujada a root al paquet |
/var/lib/meteora amb nosuid,nodev,noexec |
No pot executar un binari que hi dipositi |
NoNewPrivileges=yes a la unitat |
No guanya privilegi ni executant un setuid del sistema |
CapabilityBoundingSet= reduït |
No pot muntar, carregar mòduls ni depurar processos |
meteora no és a sudo ni té regles |
No hi ha cap regla que pugui invocar |
| Perfil d'AppArmor sense regles d'execució (05-01) | No aconsegueix una shell, primer pas de gairebé tot |
Registres amb grup adm i chattr +a |
No pot esborrar les seves petjades fàcilment |
Cap línia no basta tota sola. Juntes converteixen un compromís de l'aplicació en un incident acotat a l'aplicació, que és l'objectiu: no evitar totes les errades —impossible— sinó que una errada no es propagui.
Recordatori de responsabilitat. Tot l'anterior serveix per auditar i defensar sistemes propis. Qualsevol comprovació de seguretat sobre un sistema aliè requereix autorització expressa i per escrit del responsable; sense ella pot constituir un delicte amb independència de la intenció. I les decisions sobre comptes, registres d'accés i conservació de dades personals tenen implicacions d'RGPD i de normativa laboral: revisa-les amb compliment normatiu o assessoria jurídica.
Errors Habituals i Consells
Creure que passwd -l tanca un compte. Bloqueja la contrasenya i no toca l'autenticació per clau SSH. Una baixa completa exigeix quatre accions —contrasenya, nologin, caducitat i authorized_keys— més tallar les sessions vives.
Fer servir usermod -G sense -a. Substitueix tota la llista de grups suplementaris en lloc d'afegir-hi, i deixa la persona fora de sudo i del que tingués. L'efecte apareix dies després.
Esperar que un canvi de grup tingui efecte immediat. Els grups es fixen en iniciar sessió. id mostra el canvi perquè rellegeix el fitxer, però el procés conserva les seves credencials: compara amb /proc/<pid>/status i reinicia la sessió o el servei.
Editar /etc/sudoers sense visudo. Un error de sintaxi deixa el sistema sense sudo, i amb root sense contrasenya i sense accés SSH directe has perdut l'administració. Fes servir visudo i fitxers separats a /etc/sudoers.d/.
NOPASSWD: ALL "temporalment". Elimina l'única barrera davant d'una sessió segrestada. Si sudo molesta tant, apuja el timestamp_timeout; no eliminis la contrasenya.
Generar la clau SSH al servidor. La privada ha de néixer i morir a la teva màquina; si la generes allà, ha existit en un sistema que potser no controles i ha passat per les seves còpies de seguretat.
Deshabilitar PasswordAuthentication sense haver provat la clau. És la manera més habitual de quedar-se fora d'un servidor remot. Valida, recarrega i obre una segona sessió abans de tancar la primera. El mateix val per a qualsevol canvi a /etc/pam.d/.
Confondre les piles de PAM. auth respon a "és qui diu que és?" i account a "pot entrar ara?". Un compte caducat s'autentica bé i tot i així no entra.
Auditar setuid i oblidar getcap. Un binari amb cap_dac_override no mostra cap marca a ls -l. Mantén dues llistes de referència i compara-les periòdicament.
Consell: fes servir sudo -l com a reflex. Abans de suposar què pots fer, pregunta-ho; i com a administrador, sudo -l -U usuari és la manera més ràpida d'auditar els privilegis reals d'una persona, inclosos els que li arriben per grups que ja ningú no recorda.
Exercicis
Exercici 1: interpretar la identitat d'un sistema
Sobre la teva màquina o una màquina virtual de proves: (a) interpreta camp a camp la teva línia de /etc/passwd i la d'un compte de servei; (b) identifica l'algorisme, els paràmetres i la sal d'un hash real de /etc/shadow, i explica què signifiquen !, * i el camp buit; (c) localitza tots els comptes amb UID 0, els de sistema amb shell interactiva i els que no tenen contrasenya, explicant per què importa cada comprovació; (d) demostra empíricament que un usermod -aG no afecta una sessió oberta, comparant id amb /proc/$$/status.
Exercici 2: baixa segura d'un compte
L'analista nuria deixa l'empresa. Tenia compte amb shell, clau SSH instal·lada, pertinença a adm, una entrada d'ACL sobre /var/lib/meteora/lectures (04-06), una regla a /etc/sudoers.d/nuria, una tasca de cron diària, fitxers a /home/nuria i a /var/lib/meteora/export, i coneixia la clau d'API del proveïdor de dades. Escriu el procediment complet de baixa, ordenat, amb l'ordre exacta de cada pas, la justificació de què quedaria obert si s'ometés, la verificació final, i quines decisions s'han de consultar amb assessoria jurídica.
Exercici 3: dissenyar la política de sudo de l'equip
Dissenya /etc/sudoers.d/meteora per a tres perfils: %meteora-ops, que arrenca, atura, reinicia i consulta meteo-api, ingestor i agregador i llegeix els seus registres; %meteora-dba, que executa la còpia de seguretat i la restauració; i %monitoring, un compte automatitzat que només consulta l'estat, sense contrasenya. Justifica els Defaults. Després explica per què aquestes tres regles alternatives serien perilloses i què permetrien exactament:
%meteora-ops ALL=(root) NOPASSWD: /usr/bin/systemctl * %meteora-dba ALL=(root) /usr/bin/tar * %meteora-ops ALL=(root) /usr/bin/vim /etc/meteora/meteora.conf
Solucions
Solució 1
getent passwd $USER ; getent passwd www-data # (a)
sudo awk -F: '{print $1, substr($2,1,3)}' /etc/shadow # (b)
sudo awk -F: '($3==0){print "UID 0: "$1}' /etc/passwd # (c)
sudo awk -F: '($3<1000&&$3>0&&$7!~/nologin|false/){print "shell: "$1}' /etc/passwd
sudo awk -F: '($2==""){print "SENSE CONTRASENYA: "$1}' /etc/shadow(a) carlos:x:1001:1001:Carlos Ruiz,Sistemes,,:/home/carlos:/bin/bash és nom de sessió; x que remet a /etc/shadow; UID 1001, la identitat real davant del nucli; GID primari; GECOS descriptiu; $HOME; i shell interactiva. La de servei, www-data:x:33:33:...:/usr/sbin/nologin, difereix en tres punts decisius: UID per sota de 1000, directori funcional i nologin, que impedeix iniciar sessió encara que algú conegués una credencial.
(b) $y$j9T$FvB2kXqR8mNpL4wZ$3xKm... es descompon per $: y és yescrypt; j9T són els paràmetres de cost en temps i memòria; FvB2kXqR8mNpL4wZ és la sal, aleatòria per usuari i guardada en clar perquè no és un secret i el sistema la necessita per repetir el càlcul; la resta és el hash. ! és bloqueig reversible amb el hash conservat al darrere; * és "mai no en va tenir"; i buit és accés sense credencial.
(c) Les tres importen per raons diferents. Un segon compte amb UID 0 és root amb un altre nom —la identitat és el número—, i és una tècnica de persistència que no apareix en cap llista d'"administradors". Un compte de sistema amb shell és una via d'inici de sessió que no hauria d'existir i un patró habitual de porta del darrere. I un compte sense contrasenya entra sense credencial. En un sistema sa la primera retorna només root, la tercera res, i la segona només casos justificats com ara sync.
(d)
sudo groupadd provagrp && sudo usermod -aG provagrp $USER
id -Gn # ← SÍ que hi apareix provagrp (id rellegeix /etc/group)
grep Groups /proc/$$/status # ← NO hi apareix el seu GID (el procés no ha canviat)
sg provagrp -c 'grep Groups /proc/$$/status' # amb credencials noves, SÍ
sudo groupdel provagrpLa discrepància és la demostració: id consulta el fitxer, i el nucli fa servir les credencials que el procés porta a sobre des que es va crear. Els grups suplementaris es fixen en iniciar sessió i s'hereten per fork (02-01), així que només una sessió nova els incorpora. És l'explicació de "ja li he donat el grup i continua sense funcionar".
Solució 2
DATA=$(date +%F); mkdir -p /root/baixes/nuria-$DATA
# --- 0. INVENTARI PREVI (abans de tocar res) ---
sudo -l -U nuria > /root/baixes/nuria-$DATA/sudo.txt
sudo crontab -l -u nuria > /root/baixes/nuria-$DATA/cron.txt 2>/dev/null
sudo find / -xdev -user nuria -ls 2>/dev/null > /root/baixes/nuria-$DATA/fitxers.txt
# --- 1. TANCAR ELS QUATRE CAMINS D'ACCÉS ---
sudo usermod -L nuria # a) contrasenya
sudo usermod -s /usr/sbin/nologin nuria # b) shell
sudo chage -E 0 nuria # c) compte caducat
sudo mv /home/nuria/.ssh/authorized_keys \
/root/baixes/nuria-$DATA/authorized_keys.revocat # d) CLAUS SSH
# --- 2. RETIRAR PRIVILEGIS ---
sudo gpasswd -d nuria adm && sudo rm -f /etc/sudoers.d/nuria && sudo visudo -c
sudo setfacl -x u:nuria /var/lib/meteora/lectures
sudo setfacl -x d:u:nuria /var/lib/meteora/lectures # també l'ACL per defecte
sudo crontab -r -u nuria
# --- 3. TALLAR SESSIONS VIVES ---
sudo loginctl terminate-user nuria ; pgrep -u nuria && sudo pkill -KILL -u nuria
# --- 4. FITXERS: evitar orfes ---
sudo tar --acls -czf /root/baixes/nuria-$DATA/home.tar.gz /home/nuria
sudo chown -R carlos:meteora /var/lib/meteora/export/nuria-*
# --- 5. ROTAR SECRETS: clau d'API del proveïdor i contrasenyes compartides ---
sudo systemctl restart meteo-apiJustificació. El pas 0 va primer perquè si bloqueges abans d'inventariar perds la fotografia del que tenia, i aquesta fotografia és el punt de partida de qualsevol investigació posterior.
Al pas 1, els quatre subpassos tanquen camins independents: (a) l'autenticació per contrasenya; (b) l'obtenció de shell encara que sobrevisqui alguna via; (c) l'accés des de la pila account de PAM, amb independència de com s'autentiqui. I (d) és l'imprescindible i el més oblidat: sense ell, nuria continua entrant per SSH exactament igual que abans, perquè l'autenticació per clau pública no consulta el hash de la contrasenya.
El pas 2 existeix perquè els privilegis estan lligats al nom i a l'UID, no a la capacitat d'iniciar sessió: si l'UID 1002 es reassigna, la persona nova heretaria l'ACL, el grup i la regla de sudo. L'ACL per defecte és una entrada diferent de la normal i cal treure les dues, i una tasca de cron continuaria executant-se encara que el compte estigui bloquejat. El pas 3 és necessari perquè bloquejar no expulsa qui ja és a dins. El pas 4 evita els orfes de 04-06, que serien heretats pel pròxim UID 1002; --acls conserva les ACL que un tar normal perdria en silenci. I el pas 5 parteix que un secret conegut per algú que ja no hi és s'ha de considerar compromès: no es pot "desconèixer".
# --- VERIFICACIÓ ---
sudo chage -l nuria ; sudo -l -U nuria ; ls -l /home/nuria/.ssh/
getfacl /var/lib/meteora/lectures | grep nuria || echo "ACL neta"
who | grep nuria || echo "sense sessions"
grep -r nuria /etc/sudoers /etc/sudoers.d/ /etc/group || echo "sense referències"Assessoria jurídica. L'esborrat definitiu (userdel -r), el termini de conservació de l'arxiu de /home/nuria, el tractament del seu correu i la conservació dels registres d'accés que la identifiquen tenen implicacions d'RGPD i de normativa laboral, on les obligacions de conservació poden xocar amb la minimització de dades. S'han d'acordar amb compliment normatiu o assessoria jurídica abans d'executar-les, i el procediment les ha de recollir per escrit per no improvisar en cada cas.
Solució 3
# /etc/sudoers.d/meteora — editar SEMPRE amb: visudo -f /etc/sudoers.d/meteora
# Cada verb i cada unitat enumerats: RES de comodins
Cmnd_Alias METEO_CTL = /usr/bin/systemctl start meteo-api, /usr/bin/systemctl stop meteo-api, \
/usr/bin/systemctl restart meteo-api,/usr/bin/systemctl status meteo-api,\
/usr/bin/systemctl start ingestor, /usr/bin/systemctl stop ingestor, \
/usr/bin/systemctl restart ingestor, /usr/bin/systemctl status ingestor, \
/usr/bin/systemctl start agregador, /usr/bin/systemctl stop agregador, \
/usr/bin/systemctl restart agregador,/usr/bin/systemctl status agregador
Cmnd_Alias METEO_LOG = /usr/bin/journalctl -u meteo-api*, /usr/bin/journalctl -u ingestor*, \
/usr/bin/journalctl -u agregador*
Cmnd_Alias METEO_BAK = /usr/local/sbin/meteora-backup.sh, /usr/local/sbin/meteora-restore.sh
%meteora-ops ALL=(root) METEO_CTL, METEO_LOG
%meteora-dba ALL=(root) METEO_BAK
%monitoring ALL=(root) NOPASSWD: /usr/bin/systemctl status meteo-api
Defaults:%meteora-ops timestamp_timeout=5, log_input, log_output
Defaults:%meteora-dba timestamp_timeout=0
Defaults env_reset, passwd_tries=3, logfile="/var/log/sudo.log"
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"Els Defaults. env_reset i secure_path són els crítics: impedeixen manipular PATH, LD_PRELOAD o altres variables perquè l'ordre privilegiada carregui codi de l'usuari, cosa que convertiria qualsevol regla, per estreta que sigui, en execució arbitrària com a root. timestamp_timeout=5 dona cinc minuts de memòria cau a operacions freqüents, equilibri entre seguretat i acceptabilitat psicològica; per a %meteora-dba es posa a 0 perquè restaurar una còpia és destructiu i poc freqüent, i s'ha de confirmar sempre. log_input, log_output grava les sessions del grup que més toca el servei. I el NOPASSWD de %monitoring és acceptable només perquè l'ordre és única, de només lectura, sense arguments lliures i l'executa un automatisme que no pot teclejar.
Per què les tres alternatives són perilloses.
1. NOPASSWD: /usr/bin/systemctl *. El comodí cobreix tots els subcomandaments i totes les unitats del sistema, no només les de Meteora: inclou aturar el tallafocs, aturar auditd o deshabilitar SSH, i sobretot els subcomandaments que creen o editen unitats —qui pugui escriure una unitat fa que el sistema executi el que vulgui com a root a la pròxima arrencada—. Amb NOPASSWD, equival a concedir root sense cap barrera. Correcció: enumerar les ordres exactes amb la unitat inclosa, com a METEO_CTL.
2. /usr/bin/tar *. tar no es pot acotar amb un comodí, per dues raons independents. En extreure com a root, pot escriure a qualsevol ruta absoluta continguda a l'arxiu —/etc/sudoers.d/, /root/.ssh/authorized_keys, /etc/shadow— i el contingut de l'arxiu el controla qui el proporciona. I admet opcions que executen programes externs com a part del seu funcionament normal, que amb * queden permeses. Correcció: un script propi amb ruta fixa i paràmetres validats, com a METEO_BAK.
3. /usr/bin/vim /etc/meteora/meteora.conf. Sembla la més acotada i és igual de perillosa: els editors complets executen ordres del sistema i obren altres fitxers des de dins, així que un cop vim s'executa com a root la restricció de l'argument és irrellevant. El mateix val per a less, more, man, awk o find. Correcció: sudoedit (o sudo -e), que copia el fitxer a un temporal, l'edita amb els permisos de l'usuari i el retorna —l'editor no s'executa mai com a root—: %meteora-ops ALL=(root) sudoedit /etc/meteora/meteora.conf.
La lliçó general: una regla de sudo no acota el que l'usuari pot fer, sinó el que pot executar. Davant de qualsevol regla, pregunta't: pot aquesta ordre, amb aquests arguments, escriure un fitxer arbitrari o executar un altre programa?
Conclusió
La identitat a Linux és un número, l'UID; tota la resta viu en fitxers de /etc que el nucli ni tan sols llegeix, i d'aquí la conseqüència que ordena la lliçó: qui controla el número controla la identitat, per la qual cosa un segon compte amb UID 0 és root amb un altre nom. Cada procés porta tres UID —real, efectiu i desat— perquè autoritat i identitat han de poder ser diferents i totes dues estar disponibles: és el que permet a passwd escriure a /etc/shadow amb l'efectiu mentre fa servir el real per saber a qui ha de canviar la contrasenya. I alliberar privilegi —setgroups, setgid, setuid, en aquest ordre, i verificar que no es pot tornar enrere— és el privilegi mínim en el temps fet codi.
Els tres fitxers es llegeixen camp a camp. /etc/passwd en té set, amb la x que recorda per què els hashos es van treure d'un fitxer llegible per tothom, i un setè camp, nologin, que és tota una capa de defensa per a meteora. /etc/shadow en té nou, i el segon ho diu tot: $y$... és contrasenya vàlida, ! bloqueig reversible, * "mai no en va tenir" i buit és una emergència. /etc/group guarda només els membres suplementaris, per la qual cosa id és més fiable que llegir-lo. Al cicle de vida, els dos punts de risc són universals: l'acumulació de privilegis als canvis de rol, que només corregeixen les revisions periòdiques, i la baixa, que ha de tancar quatre camins —contrasenya, shell, caducitat i authorized_keys—, tallar sessions, reassignar fitxers i rotar secrets, perquè bloquejar la contrasenya no tanca l'accés per clau SSH.
En autenticació, els tres factors i la regla que MFA exigeix dues famílies diferents. Les contrasenyes no es guarden: es deriven amb una KDF que aporta sal única, cost de treball i cost en memòria, i per això el $y$j9T$sal$hash de Debian es llegeix com a algorisme, paràmetres, sal i resultat, amb la sal en clar perquè no és un secret. Davant de diccionari, força bruta, taules precalculades, reutilització i polvorització, les contramesures són concretes: longitud abans que complexitat, pam_pwquality, pam_faillock amb desbloqueig temporal i, sobretot, MFA. PAM organitza tot això en quatre piles —auth, account, password, session—, amb banderes que es llegeixen sense dificultat tan bon punt entens que [success=1] és un salt condicional, i amb la distinció entre autenticar-se bé i poder entrar ara repartida en piles separades.
Per a meteo-01 la configuració correcta és clau pública amb frase de pas i agent, amb PermitRootLogin no i PasswordAuthentication no: si no hi ha contrasenya per provar desapareix tota una família d'atacs, i entrar amb el compte nominal fa que cada acció sigui atribuïble. L'elevació es fa amb sudo, no amb su: granularitat per ordre, sense compartir la contrasenya de root, revocable esborrant una línia i amb registre de cada elevació. Les seves trampes són NOPASSWD, els comodins i la més subtil: una regla de sudo no acota el que l'usuari pot fer, sinó el que pot executar, així que qualsevol ordre capaç de llançar altres programes o escriure rutes arbitràries concedeix root encara que la regla sembli estreta. I el catàleg defensiu d'escalada de privilegis —setuid innecessaris, capabilities invisibles a ls -l, regles àmplies, comodins, scripts escrivibles, tasques amb mals permisos, secrets a l'entorn, serveis com a root— s'audita amb detecció per diferència contra una línia base, perquè el que importa no és la llista completa sinó el que ha aparegut des de l'última revisió.
Ja tenim identitat i control d'accés. Però tot l'anterior suposa que l'atacant entra per la porta: que intenta autenticar-se, que abusa d'una regla, que fa servir una credencial. I si no ho fa? Què passa quan l'errada és al codi de meteo-api i no cal cap credencial per disparar-la? Quines classes d'error de programació ho permeten, quines defenses posa el sistema operatiu per sota —ASLR, pila no executable, canaris— i com es comprova que estan actives? I quines mesures concretes, en ordre i amb la seva justificació, converteixen un Debian acabat d'instal·lar en un servidor enfortit?
Això és Amenaces Habituals i Enfortiment del Sistema, on classificarem les amenaces d'un servidor real amb l'indici que cadascuna deixaria a meteo-01, construirem el model d'amenaces de Meteora, veurem les classes de vulnerabilitat de programa i les defenses del nucli, i muntarem l'enfortiment complet: tallafocs, aïllament amb systemd, xifratge, gestió de secrets i còpies de seguretat com a control de seguretat.
Fonaments de Sistemes Operatius
Mòdul 1: Introducció als Sistemes Operatius
- Conceptes Bàsics de Sistemes Operatius
- Història i Evolució dels Sistemes Operatius
- Tipus de Sistemes Operatius
- Funcions Principals d'un Sistema Operatiu
- Arquitectura del Nucli: Monolític, Microkernel i Híbrid
- Mode Usuari, Mode Nucli i Crides al Sistema
Mòdul 2: Gestió de Recursos
- Gestió de Processos
- Planificació de la CPU
- Gestió de Memòria
- Memòria Virtual i Paginació
- Gestió d'Emmagatzematge
- Gestió de Dispositius
- Controladors, Interrupcions i Operacions d'E/S
Mòdul 3: Concurrència
- Conceptes de Concurrència
- Fils i Processos
- Comunicació entre Processos (IPC)
- Sincronització i Exclusió Mútua
- Problemes Clàssics de Concurrència
- Interbloquejos: Prevenció, Detecció i Recuperació
Mòdul 4: Estructures de Fitxers
- Sistemes de Fitxers
- Estructures de Directoris
- Particions, Muntatge i Sistema de Fitxers Virtual
- Gestió de Fitxers
- Assignació d'Espai, Journaling i Integritat
- Seguretat i Permisos de Fitxers
Mòdul 5: Protecció i Seguretat del Sistema
- Principis de Protecció i Control d'Accés
- Usuaris, Autenticació i Escalada de Privilegis
- Amenaces Habituals i Enfortiment del Sistema
- Auditoria, Registres i Resposta a Incidents
Mòdul 6: Virtualització i Contenidors
- Virtualització: Hipervisors i Màquines Virtuals
- Contenidors: Namespaces i cgroups
- El Sistema Operatiu al Núvol
- Sistemes Operatius Mòbils i de Temps Real
