Uprawnienia specjalne i ACL
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 passwdRUSER, 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 programAle 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/ksiegowoscAnia tworzy plik, zanim włączymy SGID, i drugi po:
sudo chmod g+s /srv/ksiegowosc
ls -ld /srv/ksiegowosc
ls -l /srv/ksiegowoscdrwxrws--- 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.txtprzed.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/ksiegowoscdrwxrws--T 3 root ksiegowosc 4096 Nov 3 16:31 /srv/ksiegowosc
3770ania$ rm /srv/ksiegowosc/eryka.txt
rm: cannot remove '/srv/ksiegowosc/eryka.txt': Operation not permittedCyfrowo 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 /tmpdrwxrwxrwt 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 xfind -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 deniedCzyta, 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.txtI 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.txtuser::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.lognowa linia
tee: app.log: Operation not permitted
xUwaga 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
| Komenda | Flaga | Co robi |
|---|---|---|
chmod | u+s / 4xxx | SUID: program działa jako właściciel pliku |
chmod | g+s / 2xxx | SGID: na folderze nowe pliki dziedziczą grupę folderu |
chmod | +t / 1xxx | sticky: usuwać może tylko właściciel pliku |
find | -perm -4000 | pliki z SUID (musi mieć ten bit) |
find | -perm /6000 | pliki z SUID lub SGID (którykolwiek bit) |
getfacl | plik | pokazuje ACL |
getfacl | -c | bez nagłówka z nazwą i właścicielem |
setfacl | -m u:nazwa:rwx | dodaje lub zmienia wpis użytkownika (g: dla grupy) |
setfacl | -x u:nazwa | usuwa jeden wpis |
setfacl | -b | usuwa wszystkie wpisy ACL |
setfacl | -d -m ... | domyślne ACL na folderze, dziedziczone przez nowe pliki |
setfacl | -R | rekurencyjnie |
lsattr | plik | pokazuje atrybuty |
chattr | +i / -i | blokuje / odblokowuje plik całkowicie |
chattr | +a / -a | tylko 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.txtPlik 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/ksiegowoscPrzepis 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
- Utwórz grupę
projekti 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). - Daj trzeciemu kontu, spoza grupy, prawo tylko do czytania wszystkich obecnych i przyszłych plików w tym folderze przez ACL.
- Wypisz wszystkie pliki z SUID albo SGID w
/usr/bin. - 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/projektdrwxrws--T 2 root projekt 4096 Nov 3 22:18 /srv/projekt3770, 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.txtOba 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/projektPierwsza 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 deniedCzyta, 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.