Autentificarea prin PAM poate reuși când rulezi clientul manual și poate eșua cu AUTH_FAILED imediat ce systemd pornește același profil. Parola nu se schimbă între acele rulări; ceea ce se schimbă este ansamblul de constrângeri din jurul procesului care îi pune întrebarea lui PAM. PAM răspunde printr-un helper a cărui capacitate de a-și schimba propriile credențiale este exact ceea ce elimină o unitate securizată. Găsește acel helper și granița de care are nevoie înainte de a atinge o listă de capabilități.

unix_chkpwd este binarul care răspunde la întrebarea PAM

Cu autentificare locală prin parolă, pam_unix citește rareori el însuși fișierul hash. Execută unix_chkpwd, pe care distribuțiile îl instalează setuid root sau setgid shadow, astfel încât o parolă să poată fi verificată în numele unui proces care nu ar trebui să citească /etc/shadow. Elimină capacitatea de a obține acea identitate și helperul nu mai poate încheia verificarea, așa că modulul returnează o simplă eroare de autentificare.

Eșecul arată atunci, în fiecare jurnal pe care clientul îl vede, ca o problemă de credențiale. Aceasta este capcana: clientul raportează ce i-a spus PAM, iar PAM raportează doar că stiva a spus nu. Rularea helperului manual ca root nu dovedește nici ea nimic, pentru că exersează o cale de privilegii pe care serviciul nu o folosește niciodată. Citește unitatea pe care systemd a încărcat-o de fapt, apoi citește jurnalul sistemului pentru încercarea făcută. Aceste două vederi separă o problemă de sandbox de o problemă de parolă greșită.

Citește unitatea înainte de jurnalul parolelor

O unitate împachetată poate purta un drop-in pe care nu l-ai scris, iar configurația efectivă este rezultatul îmbinării. Tipărește unitatea așa cum o vede systemd, împreună cu setările de sandbox care decid dacă helperul se poate ridica singur. Inspecția doar în citire este suficientă în această etapă.

systemctl cat [email protected]
systemctl show [email protected] -p User -p Group -p CapabilityBoundingSet -p AmbientCapabilities -p NoNewPrivileges
journalctl -u [email protected] -b

Prima comandă arată de unde vin unitatea și drop-in-urile ei, ceea ce contează pentru că o suprascriere adăugată acum luni trăiește mai mult decât memoria motivului pentru care există. A doua tipărește valorile de sandbox de care depind următoarele două secțiuni.

Compară ce vezi cu un gazdă funcțională cu aceeași distribuție și versiune. O diferență în User, CapabilityBoundingSet sau NoNewPrivileges este un indiciu concret; o diferență în comentarii de proză nu este. Notează valorile înainte de a schimba ceva, pentru că o comparație ulterioară cu o țintă în mișcare nu dovedește nimic. Dacă serviciul rulează ca un cont neprivilegiat cu un set de delimitare gol, helperul aproape nu are cu ce lucra.

Transformarea credențialelor, accesul la fișiere și politica sunt trei granițe

Începe cu ce se întâmplă în timpul exec. Un binar setuid sau un fișier cu file capabilities declanșează o transformare de credențiale, deci identitatea rezultată nu este o continuare a apelantului. Setul de delimitare limitează ce poate dobândi un astfel de binar, iar NoNewPrivileges blochează complet câștigurile setuid, setgid și file capabilities. Oricare dintre acestea trei poate opri helperul lăsând intactă orice altă funcție a serviciului.

Apoi separă ocolirea discreționară largă de accesul îngust de citire. CAP_DAC_OVERRIDE sare peste verificările discreționare aproape peste tot, în timp ce CAP_DAC_READ_SEARCH acoperă citirea și parcurgerea directoarelor cu propriile puteri suplimentare. Sunt instrumente diferite cu raze de acțiune diferite, iar niciunul nu este o formă de a scrie lasă PAM să citească fișierul shadow.

În final, întreabă dacă politica obligatorie permite acțiunea. O capabilitate Linux nu suprascrie SELinux, iar deținerea ei nu dovedește nimic despre o regulă de impunere a tipurilor. Tratează refuzul accesului la fișiere și refuzul unei capabilități ca dovezi diferite, pentru că numesc reparații diferite și adesea proprietari diferiți. Citește fiecare câmp al înregistrării, nu doar cuvântul denied. Ce executabil a făcut acțiunea, în ce domeniu rula, ce tip de țintă a atins, ce clasă de obiect a fost implicată și ce permisiune a refuzat politica - fiecare dintre acestea îngustează răspunsul altfel.

Scoate refuzul din jurnalul de audit

Pe un gazdă în modul enforcing, traseul de audit este singurul loc care înregistrează un refuz. Interoghează evenimentele recente și citește-le față de marcajul de timp al autentificării eșuate, nu față de ora la care ai început investigația.

ausearch -m AVC,USER_AVC -ts recent

Un rezultat gol nu este dovadă de nevinovăție. Înseamnă fie că auditul nu colectează, fie că fereastra ta a ratat încercarea, iar ambele posibilități trebuie excluse înainte de a exclude politica.

Ghidul Red Hat de depanare SELinux pune verificările de etichetă și configurație înaintea generării regulilor de permisiune, care este și ordinea corectă pentru această problemă. Un binar helper etichetat greșit și o lacună în politică produc refuzuri similare, dar necesită reparații diferite. Generarea unei reguli de permisiune pentru o greșeală de etichetare ascunde defectul și lasă următoarea actualizare de pachet să îl reintroducă. Confirmă eticheta pe helperul instalat înainte de a scrie orice politică.

Demonstrează schimbarea cu o autentificare acceptată și una respinsă

Schimbă doar granița pe care ai demonstrat-o, apoi testează ambele rezultate. Un cont care ar trebui să se autentifice trebuie să reușească, iar un cont cu parolă greșită trebuie să eșueze în continuare. O schimbare care face ca fiecare încercare să reușească a eliminat autentificarea în loc să o repare.

Rulează o încercare reală de conexiune și citește jurnalul imediat după. Linia care dovedește reparația este intrarea pam_unix(openvpn:auth) pentru acea încercare: ar trebui să spună succes de autentificare, iar nicio înregistrare AVC nu ar trebui să poarte aceeași secundă.

journalctl -u [email protected] -n 30 --no-pager
ss -tnp | grep openvpn

Un tunel funcțional are nevoie și de o reconectare, pentru că schimbările de sandbox strică a doua conexiune mai des decât pe prima. Verifică socketul stabilit după reconectare și confirmă că aceeași unitate îl deservește în continuare.

Articole similare