Cum folosesc capsh: încerc să rulez un ping fără privilegii, cu capacități minime
On februarie 13, 2021 by adminExperimentez capabilități, pe Debian Gnu / Linux.
Am copiat / bin / ping în directorul meu actual de lucru. Așa cum era de așteptat, nu funcționează, inițial a fost setuid root.
Apoi dau ping-ului meu capacitățile minime (nu root) făcând sudo /sbin/setcap cap_net_raw=ep ./ping
și ping-ul meu funcționează, așa cum era de așteptat.
Apoi sudo /sbin/setcap -r ./ping
pentru a revoca această capacitate. Acum nu funcționează așa cum era de așteptat.
Încerc acum să funcționez ping folosind capsh
.
capsh
nu are privilegii, așa că trebuie să-l rulez ca root, dar apoi să renunț la root și astfel la toate celelalte privilegii.
Cred că am nevoie și de secure-keep-caps
, acest lucru nu este documentat în capsh
, dar este în capacitate manual. Am primit numerele de biți de la /usr/include/linux/securebits.h
. Pare corecte, întrucât rezultatul --print
arată că acești biți sunt corecți.
Am jucat ore în șir, până acum am acest lucru.
sudo /sbin/capsh --keep=1 --secbits=0x10 --caps="cap_net_raw+epi" == --secbits=0x10 --user=${USER} --print -- -c "./ping localhost"
Cu toate acestea, ping
erori cu ping: icmp open socket: Operation not permitted
, asta se întâmplă atunci când nu are capacitatea. De asemenea, --print
arată Current: =p cap_net_raw+i
, acest lucru nu este suficient, avem nevoie de e
.
sudo /sbin/capsh --caps="cap_net_raw+epi" --print -- -c "./ping localhost"
va seta capacitatea la Current: = cap_net_raw+eip
acest lucru este corect, dar ne lasă ca root
.
Edit-1
Am încercat acum sudo /sbin/capsh --keep=1 --secbits=0x11 --caps=cap_net_raw+epi --print -- -c "touch zz; ./ping -c1 localhost;"
Acest lucru produce:
touch: cannot touch `zz": Permission denied ping: icmp open socket: Operation not permitted
Prima eroare este de așteptat ca secure-noroot: yes
Dar a doua nu este Current: = cap_net_raw+eip
Edit-2
Dacă pun ==
înainte de --print
, acum afișează Current: = cap_net_raw+i
, deci asta explică eroarea anterioară, dar nu de ce pierdem capacitatea când trecem din root, deși secure-keep-caps
ar trebui remediați acest lucru.
Edit-3
Din câte văd, pierd Efective (e) și Permise (p), când se apelează exec. Acest lucru este de așteptat, dar am crezut că securizarea-păstrarea-capacelor, ar trebui să oprească pierderea lor. Îmi lipsește ceva.
Edit-4
Am făcut mai multe cercetări și am citit manualul din nou. Se pare că în mod normal capacitățile e
și p
se pierd atunci când: comutați de la utilizator root
(sau aplicați secure-noroot
, făcând astfel root un utilizator normal), acest lucru poate fi suprascris cu secure-keep-caps
; când apelați exec
, din câte îmi dau seama, este un invariant.
Din câte îmi dau seama, funcționează conform manualului. Din câte îmi dau seama, nu există nicio modalitate de a face ceva util cu capsh
. Din câte îmi dau seama, pentru a utiliza capabilități, trebuie să: utilizați capabilități de fișiere sau să aveți un program care conține capacități, care să nu utilizeze exec
. Prin urmare, nu există nicio împachetare privilegiată.
Deci, acum întrebarea mea este ce îmi lipsește, pentru ce este capsh
.
Edit-5
Am adăugat un răspuns cu privire la capacitățile ambientale. Poate că capsh
poate fi folosit și cu capabilități moștenite, dar pentru a fi utile, acestea ar trebui setate pe fișierul executabil. Nu pot vedea cum capsh poate face ceva util fără capacități ambientale sau să permită capacități moștenite.
Versiuni:
-
capsh
din pachetullibcap2-bin
versiunea1:2.22-1.2
- înainte de edit-3 am luat cel mai recent
capsh
de lagit://git.debian.org/collab-maint/libcap2.git
și a început să îl folosesc. -
uname -a
Linux richard-laptop 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux
User-land are 32 de biți.
Comentarii
Răspuns
Capacitățile sunt proprietăți ale proceselor. În mod tradițional, există trei seturi:
- Capabilități permise ( p ): capabilități care pot fi „activat” în procesul curent.
- Capabilități eficiente ( e ): capabilități care sunt utilizabile în prezent în procesul actual.
- Capabilități ereditare ( i ): capabilități de fișier care pot fi moștenite.
Programele rulate ca root au întotdeauna capacități permise și eficiente, așa că „adăugarea” mai multor capabilități nu are niciun efect vizibil. (Setul de capabilități moștenite este în mod normal gol.) Cu setcap cap_net_raw+ep ping
activați aceste capacități în mod implicit pentru orice utilizator care rulează acest program.
Din păcate, aceste capacități sunt legate de fișierul executat și nu sunt reținute după executarea unui nou proces secundar. Linux 4.3 a introdus Capabilități ambientale care permite moștenirea capabilităților de procesele secundare. (Consultați și Transformarea capacităților în timpul executării () în capabilitățile (7) .)
În timp ce jucați cu capabilități, rețineți aceste capcane:
- Când schimbați utilizatorul de la rădăcină la non-rădăcină, capabilitățile eficiente și permise sunt șterse (consultați Efectul modificărilor ID utilizator asupra capacităților în capabilități (7) ). Puteți utiliza opțiunea
--keep=1
acapsh
pentru a evita ștergerea seturilor. - Setul de capacități ambientale este șters când schimbarea ID-urilor de utilizator sau de grup. Soluție: adăugați capabilitățile ambientale după schimbarea ID-ului de utilizator, dar înainte executarea unui proces secundar.
- O capacitate poate fi adăugată numai la capacitățile ambientale set dacă se află deja în setul de capacități permise și moștenite.
De la libcap 2.26, programul capsh
a câștigat capacitatea de a modifica capacitățile ambientale prin opțiuni precum --addamb
( commit ). Rețineți că ordinea opțiunilor este semnificativă. Exemplu de utilizare:
sudo capsh --caps="cap_net_raw+eip cap_setpcap,cap_setuid,cap_setgid+ep" \ --keep=1 --user=nobody --addamb=cap_net_raw -- \ -c "./ping -c1 127.0.0.1"
Sfat: puteți adăuga opțiunea --print
oriunde în capsh
linia de comandă și vedeți starea sa actuală a capacităților.
Notă: cap_setpcap
este necesar pentru --addamb
în timp ce cap_setuid,cap_setgid
sunt necesare pentru opțiunea --user
.
Comentarii
- Ce număr de versiune specifică a libcap de când au capsh –addamb? Notele de lansare 2.32 menționau noi caracteristici majuscule, dar cuvintele erau vagi.
- @ 把 友情 留 在 无 盐 Când răspunsul a fost scris inițial, doar git master l-a susținut. De atunci, libcap 2.26 a fost lansat cu suport pentru opțiunea
--addamb
. Am actualizat răspunsul în consecință. - Din păcate, aceste funcții sunt legate de fișierul executat și nu sunt păstrate după executarea unui nou proces secundar. – prin proces secundar În mod normal, mă gândesc la
fork(2)
, care moștenește capacitățile. Doarexecve(2)
nu ‘ nu moștenește capacitățile, dar nu ‘ nu creează un copil proces. Mă înșel? - Citat
man capabiltiies
: Un copil creat prinfork(2)
moștenește copii ale părintelui său ‘ seturi de capacități.
Răspuns
Răspunsul lui Lekensteyn pare corect și complet, dar voi încerca să ofer o altă explicație dintr-un unghi diferit, care va încerca să sublinieze problema pe care o rezolvă setul de capabilități ambientale.
Când rulați sudo capsh --user=<some_user> --
Există 2 apeluri de interes de sistem care determină recalcularea capacităților (și potențial renunțare):
-
setuid
: Conformman capabilities
:
SECBIT_KEEP_CAPS Setarea acestui flag permite un fir care are unul sau mai multe 0 UID-uri să-și păstreze capacitățile atunci când își comută toate UID-urile la o valoare diferită de zero. Dacă acest flag nu este setat, atunci un astfel de UIDswitch face ca firul să piardă toate capacitățile.
Cu alte cuvinte, în comanda capsh
de mai sus, trebuie să ne asigurăm că SECBIT_KEEP_CAPS este setat în timpul setuid
apel sistem. În caz contrar, toate capacitățile sunt pierdute. Aceasta este ceea ce face --keep=1
. Deci, acum comanda devine sudo capsh --user=<some_user> --keep=1 --
-
execve
: Dacă utilizați opțiunea--keep=1
, toate seturile de capacități (eficiente, permise, moștenibile) sunt păstrate până la apelul de sistemexecve
, totușiexecve
determină recalcularea capacităților (și pentru utilizatorii non-root) și în un mod nu atât de evident.Pe scurt, înainte de adăugarea setului de capabilități ambientale , pentru ca o capacitate să se afle într-un fir „s” permis ” setat după un apelexecve
, fie:- Fișierul trebuie să aibă acea capacitate în setul său „permis” . se poate face cu
setcap cap_net_raw+p /bin/bash
. A face acest lucru face ca întregul exercițiu să fie inutil, deoarece seturile de capabilități ale firului (altele decât setul de delimitare) nu mai au niciun efect. - Atât fișierul, cât și firul trebuie să aibă această capacitate în seturile lor „moștenite” . S-ar putea să credeți că
setcap cap_net_raw+i
ar face trucul, dar se dovedește căexecve
determină renunțarea la permisiunile ereditare ale unui fir atunci când este apelat de un utilizator neprivilegiat (care suntem în prezent datorităsetuid
). Deci nu există nicio modalitate de a satisface această condiție ca utilizator neprivilegiat.
- Fișierul trebuie să aibă acea capacitate în setul său „permis” . se poate face cu
Capabilitățile ambientale introduse în Linux 4.3 fac posibil ca un fir să își păstreze capacitățile chiar și după un setuid
unui utilizator neprivilegiat urmat de un execve
, fără a fi nevoie să vă bazați pe capacitățile fișierelor.
Răspuns
S-ar putea să existe o eroare / caracteristică în nucleu. Au existat unele discuții:
- https://bugzilla.altlinux.org/show_bug.cgi?id=16694
- http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-03/5224.html
Nu am idee, dacă a fost ceva d una, pentru a remedia problema.
Nu mă înțelegeți greșit – comportamentul actual este sigur. Dar este atât de sigur încât împiedică lucrurile care par să funcționeze.
Edit: Conform http://man7.org/linux/man-pages/man7/capabilities.7.html există un nou set de capabilități Ambient (de la Linux 4.3). Se pare că acest lucru va permite ceea ce este necesar.
Răspuns
O ușoară ajustare a răspunsului lui Lekensteyn produce o invocare mai scurtă pentru nucleele recente:
sudo /usr/sbin/capsh --keep=1 --user=$USER \ --inh=cap_net_raw --addamb=cap_net_raw -- \ -c "./ping -c1 localhost"
Notă: În funcție de fișierul sudoers, acest lucru poate face o mizerie a mediului dvs. (de exemplu, schimbarea HOME). capsh vă va schimba uidul, dar nu va face nimic pentru a reveni la modificările de mediu sudo.
Deci, ce se întâmplă aici? Să aruncăm o privire:
-
sudo /usr/sbin/capsh
: Începem ca root, care are toate capacitățile în seturile sale eficiente (poate face acest lucru) și permise (poate adăuga acest lucru la seturile eficiente), dar nimic în celelalte seturi . Vom acoperi acele alte seturi într-o clipă. -
--keep=1
: Din motive de securitate (citiți: moștenire), capabilitățile nu moștenesc în mod normal între root- > comutatoare de identificare non-root. Acest semnalizator activează o caracteristică, cunoscută sub numele deSECBIT_KEEP_CAPS
, care permite acest lucru. Merită remarcat faptul că este șters automat la execut , ceea ce este o idee bună. -
--user=$USER
: Acum, că nu vom pierde toate capacitățile noastre la schimbarea UID, vom renunța la rădăcină. DatorităSECBIT_KEEP_CAPS
, păstrăm privilegii asemănătoare cu rădăcina, ceea ce ne permite să ne deranjăm în continuare cu capacitățile noastre. -
--inh=cap_net_raw
: Aceasta adaugă capacitatea noastră țintă la setul moștenit, deoarece nu puteți crea o capacitate ambientală (consultați articolul următor) dacă nu este moștenită. -
--addamb=cap_net_raw
: Chiar dacă „am solicitatSECBIT_KEEP_CAPS
,execve
a unui binar neprivilegiat (fără setuid / setgid / setcap) va încă ștergeți-ne capacitățile, rezultând fără privilegii. Linux 4.3 a adăugat setul ambient, care este adăugat înapoi la seturile eficiente și permise atunci când executați binare neprivilegiate. Perfect! -
-- -c ...
: După ce am configurat totul, executăm bash cu aceste argumente. Seturile de capacități sunt șterse (deoarece bash este lipsit de privilegii), setul ambient este adăugat înapoi și voilă! Avem permisiunea necesară pentru a deschide raw sockets.
Puteți verifica acest lucru folosind argument pentru capsh, ceea ce îl determină să se execute cu restul liniei de comandă:
sudo /usr/sbin/capsh --keep=1 --user=$USER \ --inh=cap_net_raw --addamb=cap_net_raw == --print Current: = cap_net_raw+eip
Ceea ce înseamnă că avem cap_net_raw ca eficient (poate face acest lucru), moștenit (îl poate transmite proceselor copil) și este permis (este permis să îl obțină). Și nu există alte capacități în niciuna dintre acestea.
Pentru mai multe informații despre capabilități și modul în care acestea funcționează, cel mai bun pariu este pagina de manual pentru capabilități (7) . Mai exact titlul Transformation of capabilities during execve()
.
Comentarii
- Ce vrei să spui prin Acest lucru se face devreme, deoarece necesită o serie de capabilități suplimentare care nu pot ‘ să renunțe până după ce ‘ s-a terminat. ?În cazul dvs., executați ca ” root „, deci chiar și așa
--user
wasn ‘ nu s-a schimbat, ‘ mai aveți capabilitățile necesare mai târziu? - Vă mulțumim că ați subliniat acest lucru! O versiune anterioară a acestei linii de comandă a renunțat explicit la privări, deci a fost necesar să setuid înainte de aceasta. Acum că privările sunt renunțate implicit ca parte a executării, nu ‘ nu este necesar.
capsh
din colab-maint repo nu ți-ar fi dat „cel mai recent”capsh
, pachetul Debian încă nu acceptă capacități ambientale. În amonte 2.27 o face.capsh
, în absența mediului ambiant (așa cum era inițial). Ce îmi lipsește. Trebuie să aibă o utilizare.