Przejdź do treści
Lekcja 16 z 117

Kurs › Moduł 1 › Lekcja 16

Uprawnienia specjalne i ACL

⏱ ok. 10 min czytania· moduł 1: Praca w powłoce

Po tej lekcji: kursant rozpoznaje i ustawia SUID, SGID i sticky bit, szuka ich przez find -perm, nadaje wyjątkowe uprawnienia przez ACL i blokuje plik przed zmianą przez chattr +i.

Wstęp

/etc/shadow z -rw-r-----, obok zwykły użytkownik wpisuje passwd i zmienia hasło

Twoje hasło leży w /etc/shadow. Ty nie masz prawa nawet tego pliku przeczytać. A jednak wpisujesz passwd, zmieniasz hasło i nowe hasło ląduje właśnie tam. Jak to możliwe, skoro z poprzedniej lekcji wynika, że to niemożliwe?

I druga sprawa z poprzedniej lekcji: Ania skasowała plik Eryka we wspólnym folderze, a jej nowe pliki dostały złą grupę. Dziś trzy specjalne bity to załatwią, a na deser plik, którego nie usunie nawet root.

SUID: przepustka na czas załatwiania sprawy

Wyobraź sobie archiwum w urzędzie. Petent nie ma tam wstępu. Ale jest okienko, w którym siedzi urzędnik z kluczem do archiwum. Podajesz wniosek „zmień moje hasło”, on idzie do archiwum, podmienia dokładnie jedną kartkę, Twoją, i wraca. Ty do archiwum nie wszedłeś ani na krok.

Tym urzędnikiem jest program passwd, a mechanizm nazywa się SUID, od „set user ID”. Program z SUID działa z uprawnieniami swojego właściciela, a nie osoby, która go uruchomiła. passwd należy do roota, więc działa jako root. Widać to, kiedy Eryk w drugim terminalu zostawi otwarte passwd:

ps -o pid,ruser,euser,cmd -C passwd
  PID RUSER    EUSER    CMD
19562 eryk     root     passwd

RUSER, prawdziwy użytkownik, to eryk. EUSER, użytkownik efektywny, czyli ten, którego jądro bierze pod uwagę przy sprawdzaniu kluczy, to root. A program passwd sam pilnuje, żebyś zmienił tylko swoje hasło.

W ls -l SUID to s w miejscu x właściciela, a cyfrowo dodatkowa czwórka z przodu: 4755. Ustawiasz go tak:

chmod u+s program
chmod 4755 program

Ale uwaga. SUID na programie roota to dziura, jeśli program da się namówić do czegoś innego niż jego jedno zadanie. Wyobraź sobie SUID na edytorze tekstu. Każdy użytkownik otwiera nim /etc/shadow jako root. Dlatego programów z SUID jest w systemie garstka i admin regularnie sprawdza, czy nikt nie dorzucił nowych.

SGID: wspólna szafa działu

SGID, „set group ID”, ma dwa zastosowania.

Na programie działa jak SUID, tylko dla grupy. Na przykład crontab na Ubuntu ma -rwxr-sr-x root crontab: działa z grupą crontab, żeby móc dopisać Twoje zadanie do wspólnego folderu.

Ale ważniejsze dla admina jest drugie zastosowanie: SGID na folderze. Wtedy każdy nowy plik w środku dostaje grupę folderu, a nie grupę osoby, która go zrobiła. To jak szafa działu księgowości z naklejką: cokolwiek tu włożysz, staje się własnością księgowości.

sudo mkdir /srv/ksiegowosc
sudo chgrp ksiegowosc /srv/ksiegowosc
sudo chmod 770 /srv/ksiegowosc

Ania tworzy plik, zanim włączymy SGID, i drugi po:

sudo chmod g+s /srv/ksiegowosc
ls -ld /srv/ksiegowosc
ls -l /srv/ksiegowosc
drwxrws--- 2 root ksiegowosc 4096 Nov  3 16:31 /srv/ksiegowosc
-rw-rw-r-- 1 ania ksiegowosc    2 Nov  3 16:31 po.txt
drwxrwsr-x 2 ania ksiegowosc 4096 Nov  3 16:31 podfolder
-rw-rw-r-- 1 ania ania          2 Nov  3 16:31 przed.txt

przed.txt ma grupę ania, więc reszta działu może go tylko czytać. po.txt ma ksiegowosc. A nowy podfolder dostał nie tylko grupę, ale też samo s, więc zasada idzie w dół całego drzewa. Cyfrowo SGID to dwójka z przodu: chmod 2770.

Sticky bit: wyrzucasz tylko swoje

Pamiętasz, jak Ania skasowała plik Eryka, bo miała w na folderze? W naszej szafie działu też tak jest:

ania$ rm -v /srv/ksiegowosc/eryka.txt
removed '/srv/ksiegowosc/eryka.txt'

Na to jest sticky bit, „lepki bit”. Na folderze znaczy: pliki może usuwać albo zmieniać im nazwy tylko ich właściciel, właściciel folderu i root. Jak lodówka w biurze, do której każdy może wstawić jogurt, ale wyrzucić wolno tylko swój. Teoretycznie. W prawdziwych biurach sticky bit nie działa.

sudo chmod +t /srv/ksiegowosc
ls -ld /srv/ksiegowosc
stat -c '%a' /srv/ksiegowosc
drwxrws--T 3 root ksiegowosc 4096 Nov  3 16:31 /srv/ksiegowosc
3770
ania$ rm /srv/ksiegowosc/eryka.txt
rm: cannot remove '/srv/ksiegowosc/eryka.txt': Operation not permitted

Cyfrowo sticky to jedynka z przodu. SGID 2 plus sticky 1 daje 3, stąd 3770. Najsłynniejszy folder ze sticky bitem znasz z lekcji 8:

ls -ld /tmp
drwxrwxrwt 13 root root 4096 Nov  3 16:30 /tmp

/tmp ma 1777: każdy może tam pisać, ale nikt nie skasuje cudzego pliku. Biurko na korytarzu z regułą „nie ruszaj cudzego”.

A czemu u mnie wyżej było duże T, a w /tmp małe t? Mała litera znaczy: bit specjalny plus zwykłe x pod spodem. Duża: bit specjalny bez x. To samo z s i S. Duże S na pliku to zwykle pomyłka, bo SUID bez prawa uruchomienia nic nie daje:

-rwSr-Sr-T 1 root root 0 Nov  3 16:31 x

find -perm: kto ma specjalne klucze

Lista wszystkich programów z SUID w systemie:

find / -xdev -perm -4000 -type f 2>/dev/null
/usr/bin/at
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/su
/usr/bin/sudo
/usr/bin/umount
...

-perm -4000 znaczy „musi mieć co najmniej ten bit”. -perm /6000 znaczy „którykolwiek z tych bitów”, czyli SUID albo SGID. -xdev nie wychodzi poza ten dysk, 2>/dev/null wycisza błędy, znasz z lekcji 6. Zapisz sobie tę listę na świeżym systemie i porównuj co jakiś czas. Nowy program z SUID, którego nikt nie instalował, to jeden z klasycznych śladów włamania.

ACL: wyjątek od reguły

Zwykłe uprawnienia mają jedno ograniczenie: jeden właściciel, jedna grupa. A przychodzi audytor i ma czytać budzet.txt, ale nie może być w grupie księgowości, bo wtedy zobaczyłby wszystko. Na to są ACL, Access Control Lists, listy kontroli dostępu. Lista gości na bramce: „oprócz pracowników wpuszczamy też pana Kowalskiego, tylko do sali B”.

sudo setfacl -m u:audytor:r /srv/ksiegowosc/budzet.txt
sudo setfacl -m u:audytor:x /srv/ksiegowosc
ls -l /srv/ksiegowosc/budzet.txt
getfacl /srv/ksiegowosc/budzet.txt
-rw-r-----+ 1 root ksiegowosc 10 Nov  3 16:31 budzet.txt
# file: budzet.txt
# owner: root
# group: ksiegowosc
user::rw-
user:audytor:r--
group::r--
mask::r--
other::---

-m to modify, dodaj albo zmień wpis. u:audytor:r to użytkownik, kto, co. Dla grupy piszesz g:nazwa:rx. Plus na końcu uprawnień w ls -l to sygnał: „tu są wyjątki, zajrzyj do getfacl”. Audytorowi dałem też x na folderze, bo bez przejścia przez drzwi pokoju nie dojdzie do biurka.

audytor$ cat /srv/ksiegowosc/budzet.txt
Q3: 1 mln
audytor$ echo hack >> /srv/ksiegowosc/budzet.txt
bash: /srv/ksiegowosc/budzet.txt: Permission denied

Czyta, ale nie zmienia. Usuwanie wpisu to -x, a -b usuwa wszystkie wyjątki naraz:

sudo setfacl -x u:audytor /srv/ksiegowosc/budzet.txt
sudo setfacl -b /srv/ksiegowosc/budzet.txt

I trzecia flaga, najbardziej praktyczna: -d, czyli domyślne ACL na folderze. Wtedy każdy nowy plik w środku dziedziczy wyjątek sam:

sudo setfacl -d -m u:audytor:r /srv/ksiegowosc
echo nowy > /srv/ksiegowosc/nowy.txt
getfacl -c /srv/ksiegowosc/nowy.txt
user::rw-
user:audytor:r--
group::rwx	#effective:rw-
mask::rw-
other::---

Nowy plik od razu ma audytora na liście.

Jak to działa pod spodem

Uprawnienia to 12 bitów. Dziewięć znasz: trzy trójki rwx. Trzy pozostałe to właśnie SUID, SGID i sticky. Stąd czwarta cyfra z przodu: 4, 2, 1, tak samo jak r, w, x.

Kiedy uruchamiasz program z SUID, jądro przy starcie procesu ustawia jego efektywny numer użytkownika na numer właściciela pliku. Tak jak widać było w ps: RUSER eryk, EUSER root.

ACL to osobne dane, doczepione do i-węzła jako atrybuty rozszerzone. Właśnie przez to działają na ext4 na Ubuntu i na XFS na RHEL bez dodatkowej konfiguracji. Jest jedna pułapka: maska. Przy pliku z ACL to, co ls -l pokazuje w trójce grupy, to już nie uprawnienia grupy, tylko maska, czyli sufit dla wszystkich wyjątków. Zrób na takim pliku chmod 600 i patrz:

user::rw-
user:audytor:r--	#effective:---
group::r--	#effective:---
mask::---
other::---

Audytor dalej jest na liście, ale #effective:---. Na bramce stoi z zaproszeniem, a ochroniarz zamknął całe skrzydło.

chattr: plik zabetonowany

Ostatni zamek działa pod uprawnieniami, na poziomie systemu plików. chattr zmienia atrybuty pliku, a lsattr je pokazuje.

sudo chattr +i dns.conf
lsattr dns.conf
sudo sh -c 'echo x >> dns.conf'
sudo rm dns.conf
----i---------e------- dns.conf
sh: 1: cannot create dns.conf: Operation not permitted
rm: cannot remove 'dns.conf': Operation not permitted

+i to immutable, niezmienny. Nie da się go zmienić, usunąć, przenieść, zrobić do niego twardego linku ani zmienić mu uprawnień. Nawet rootowi. Root musi najpierw świadomie zdjąć blokadę przez chattr -i. Pomnik z betonu: nie przestawisz, dopóki nie weźmiesz młota.

Po co? Na przykład żeby żaden program nie nadpisał ręcznie ustawionego pliku konfiguracyjnego. Jest też brat +a, append only: można tylko dopisywać na końcu, idealne dla logów.

sudo chattr +a app.log
echo "nowa linia" | sudo tee -a app.log
echo x | sudo tee app.log
nowa linia
tee: app.log: Operation not permitted
x

Uwaga na dwie rzeczy. Plik z +i potrafi doprowadzić do szaleństwa kogoś, kto o nim nie wie: root dostaje „Operation not permitted” i zaczyna podejrzewać wirusa, dysk i życiowe wybory. Jak coś dziwnie nie daje się usunąć, sprawdź lsattr. Po drugie: zwykły użytkownik nie ustawi +i nawet na własnym pliku, to zarezerwowane dla roota.

Ściąga flag

KomendaFlagaCo robi
chmodu+s / 4xxxSUID: program działa jako właściciel pliku
chmodg+s / 2xxxSGID: na folderze nowe pliki dziedziczą grupę folderu
chmod+t / 1xxxsticky: usuwać może tylko właściciel pliku
find-perm -4000pliki z SUID (musi mieć ten bit)
find-perm /6000pliki z SUID lub SGID (którykolwiek bit)
getfaclplikpokazuje ACL
getfacl-cbez nagłówka z nazwą i właścicielem
setfacl-m u:nazwa:rwxdodaje lub zmienia wpis użytkownika (g: dla grupy)
setfacl-x u:nazwausuwa jeden wpis
setfacl-busuwa wszystkie wpisy ACL
setfacl-d -m ...domyślne ACL na folderze, dziedziczone przez nowe pliki
setfacl-Rrekurencyjnie
lsattrplikpokazuje atrybuty
chattr+i / -iblokuje / odblokowuje plik całkowicie
chattr+a / -atylko dopisywanie / zdjęcie blokady

⚠ Typowy błąd

Wspólny folder działu ustawiony samym chmod 770 i grupą. Po tygodniu telefon: „nie mogę edytować pliku Ani”. Sprawdzasz:

-rw-rw-r-- 1 ania ania          2 Nov  3 16:31 przed.txt

Plik ma grupę ania, nie ksiegowosc. Folder był dobry, ale bez SGID każdy nowy plik dostaje grupę swojego autora. Naprawa w dwóch krokach. Najpierw na przyszłość SGID na folderze. Potem poprawka tego, co już powstało:

sudo chmod 2770 /srv/ksiegowosc
sudo chgrp -R ksiegowosc /srv/ksiegowosc

Przepis na porządny folder działu to więc: grupa, 2770, a jeśli ludzie mają nie kasować sobie nawzajem plików, jeszcze sticky, czyli 3770.

✎ Zadanie

  1. Utwórz grupę projekt i dwa konta testowe w tej grupie. Zrób folder /srv/projekt, w którym nowe pliki automatycznie dostają grupę projekt, a nikt nie może usunąć cudzego pliku. Sprawdź to, tworząc i usuwając pliki jako oba konta (su - nazwa).
  2. Daj trzeciemu kontu, spoza grupy, prawo tylko do czytania wszystkich obecnych i przyszłych plików w tym folderze przez ACL.
  3. Wypisz wszystkie pliki z SUID albo SGID w /usr/bin.
  4. Zablokuj jeden plik testowy chattr +i, spróbuj go usunąć jako root i odblokuj.
Pokaż rozwiązanie
sudo groupadd projekt
sudo useradd -m -s /bin/bash kasia
sudo useradd -m -s /bin/bash tomek
sudo useradd -m -s /bin/bash gosc
sudo usermod -aG projekt kasia
sudo usermod -aG projekt tomek
sudo mkdir /srv/projekt
sudo chgrp projekt /srv/projekt
sudo chmod 3770 /srv/projekt
ls -ld /srv/projekt
drwxrws--T 2 root projekt 4096 Nov  3 22:18 /srv/projekt

3770, czyli SGID i sticky naraz, plus pełne prawa dla właściciela i grupy. Test: Kasia robi plik, Tomek robi plik i próbuje usunąć plik Kasi.

rm: cannot remove '/srv/projekt/kasia.txt': Operation not permitted
-rw-rw-r-- 1 kasia projekt 7 Nov  3 22:18 kasia.txt
-rw-rw-r-- 1 tomek projekt 8 Nov  3 22:18 tomek.txt

Oba pliki mają grupę projekt, a Tomek odbił się od cudzego. Teraz gość:

sudo setfacl -R -m u:gosc:rX /srv/projekt
sudo setfacl -d -m u:gosc:rX /srv/projekt

Pierwsza linijka załatwia to, co już jest, druga to, co dopiero powstanie. Duże X z lekcji 15 daje przejście przez foldery, a plikom samo czytanie. Kasia robi nowy plik, gość próbuje:

nowy
-bash: line 1: /srv/projekt/nowy.txt: Permission denied

Czyta, nie pisze. A lista plików z SUID lub SGID w /usr/bin to find /usr/bin -perm /6000 -type f, u mnie 19 pozycji, między innymi passwd, sudo, su, crontab. Na koniec chattr +i, próba rm jako root kończy się Operation not permitted, chattr -i i dopiero wtedy plik znika. Jeśli komuś root się nie odbił, niech sprawdzi, czy na pewno dodał plus, a nie minus.

Co dalej

Cały czas pracujesz w Bashu takim, jaki dostałeś z pudełka. W następnej lekcji urządzamy go pod siebie: zmienne środowiskowe, PATH, czyli skąd Bash wie, gdzie szukać programów, .bashrc kontra .bash_profile, aliasy, kolorowy znak zachęty i historia, która nie zapomina.