anedroid, Polish
@anedroid@wspanialy.eu avatar

Bardzo bym prosił o audyt mojego projektu "midutils". Są to 3 małe programy w Pythonie, których zadaniem jest ochrona plików przed nieuprzywilejowanymi procesami, np. plików cookies w Firefoxie, kluczy SSH, ważnych dokumentów. W szczególności zależy mi na ostatnim narzędziu "midlaunch" uruchamiającym aplikacje w kontenerach bwrap, które jest najbardziej złożone (407 linijek kodu). Wszystkie programy wymagają uprawnień root, więc niedopatrzenia mogą prowadzić do nieautoryzowanej eskalacji uprawnień.

Uważam, że w ekosystemie GNU/Linuxa brakuje tego typu narzędzi, więc zrobiłem własne. Chciałbym aby kiedyś trafiło do repozytoriów Arch, Ubuntu, Fedory i innych dystrybucji i pomogło poprawić bezpieczeństwo użytkowników desktopowego GNU/Linuxa. Niestety nie mam zbyt dużego doświadczenia w pracy nad średnimi i dużymi projektami, dlatego proszę was o pomoc.

Link do repozytorium git: https://git.disroot.org/anedroid/midutils

#python #linux #security

robryk,
@robryk@qoto.org avatar

@anedroid

@anedroid

Jest tam też chyba dość sporo sytuacji, gdzie dowolny użytkownik tego systemu może eskalować do roota wynikających z wyścigów na systemie plików.

Np. useradd nie jest zbyt ostrożny w tym jak tworzy katalog: https://github.com/shadow-maint/shadow/blob/master/src/useradd.c#L2293. Jeśli użytkownik (którego $HOME nie ma +t) odpali tworzenie użytkownika-cienia, i między między mkdir() z 2365 a chown() z 2387 zmieni nazwę .shadow-home, a na jego miejsce wsadz symlink dokądkolwiek ten chown zmieni właściciela tego symlinka.

Midlaunch odpala bwrapa jako root. W związku z tym bind mounty przezeń wykonywane będą używały uprawnień roota do trawersowania katalogów, więc pozwala użytkownikowi podmontować sobie w widocznym miejscu coś z katalogu, w którym on sam nie ma +x. Gdzieś wcześniej sprawdzasz czy właściwy użytkownik ma dostęp, no ale znowu to może być symlink który podmienię pomiędzy tym wywołaniem access a odpaleniem się bbwrapa. (Trochę nie rozumiem, czemu to nie uruchamia bwrapa jako użytkownik-cień.)

Jeśli sysctl protected_hardlinks (https://www.kernel.org/doc/Documentation/sysctl/fs.txt) nie jest włączony, chmid pozwala kraść pliki: można podmienić plik na hardlink do cudzego pliku pomiędzy weryfikacją właściciela a chmodem.

No i jeśli midlaunchowi każe podmontować coś na /sbin/runuser, to on to bardzo chętnie mi odpali jako root.

robryk,
@robryk@qoto.org avatar

@anedroid

BTW. Przed kilkoma innymi uchroniło Cię to, że bwrap zawsze ustawia no_new_privs (https://man7.org/linux/man-pages/man2/prctl.2.html) nawet jak nie musi. To też powoduje, że w środku tego co zostanie odpalone przez midlaunch bity SUID i SGID oraz file capabilities nie są respektowane, więc np. ping nie będzie działał.

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Hmm, u mnie jakoś ping działa, ale sudo już nie. I ping nie ma u mnie cap_net_raw. Widziałem go natomiast na innej dystrybucji.

Wiem, że brak tej flagi przysporzyłby mi dodatkowych problemów. Jednocześnie, to zmusza mnie do uruchamiania bwrap jako root - nie widzę innego sposobu, jak potem przelogować się na primary user.

robryk,
@robryk@qoto.org avatar

@anedroid

TIL o pingu: https://unix.stackexchange.com/questions/592911/how-does-ping-work-on-fedora-without-setuid-and-capabilities

Ta flaga == no_new_privs?

Co najmniej dla rzeczy z run_as_shadow możesz zrobić to w odwrotnej kolejności. (Trochę nie rozumiem, do czego służa aplikacje bez run_as_shadow.)

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Run_as_shadow zostało dodane później. Oryginalnie miało być tak, że aplikacja uruchamia się jako primary user, ale ma pomontowane w sandboxie niektóre foldery z shadow home (de facto należące do primary user, ale primary user nie ma do nich dostępu bo blokuje brak uprawnień grupy dla .shadow-home. Dostęp przez sandboxowaną aplikację do innych katalogów nieustawionych w konfiguracji jest efektem niepożądanym. Innymi słowy, ustawienie run_as_shadow=true to odpowiednik midsu z customowym shellem.

robryk,
@robryk@qoto.org avatar

@anedroid A, czyli cała ochrona bazuje na pośrednim katalogu bez g+x, rozumiem.

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Bardzo dziękuję za sprawdzenie tych rzeczy. Wiele to dla mnie znaczy. Mam nadzieję, że uda mi się zaadresować wymienione problemy choć częściowo i mój projekt nie okaże się bezużyteczny.

robryk,
@robryk@qoto.org avatar

@anedroid

Możesz chcieć wiedzieć o istnieniu qubes (mimo że jest w zupełnie innym miejscu na skali kompromisu między utrudnianiem życia a tym przed czym chce chronić).

Na Twoim miejscu zastanawiałbym się nad zrobieniem czegoś prawie że odwrotnego. I tak w tym setupie który masz musisz bardzo dobrze rozumieć skąd każdy jeden kawałek środowiska graficznego/shella/... czyta swoją konfigurację. Może więc zamiast tego odpalać całe środowisko graficzne jako shadow user i je tak skonfigurować, żeby (a) bardzo łatwo było dostać shella jako normal user (b) wszystkie aplikacje odpalały się w jakichś mniejszych sandboxach?

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Zabawa z symlinkami i race condition. Tego nie przewidziałem. Czyli ograniczenie targetu do homedir (realpath) i coś jeszcze trzeba będzie wykombinować.

robryk,
@robryk@qoto.org avatar

@anedroid

Obawiam się, że może się nie dać. ZTCW nie da się spowodować, żeby mount() nie podążał za symlinkami w ścieżce do celu.

robryk,
@robryk@qoto.org avatar

@anedroid Ten konkretny problem możnaby rozwiązać bez tego, gdyby tylko dało się mieć pewną kopię /proc w tym kontenerze: wtedy otwierasz /sbin/runuser i dajesz bwrapowi jako dodatkowy fd, i każesz mu odpalić /proc/self/fd/numerek. No ale upewnienie się, że naprawdę masz procfs na /proc jest co najmniej trudne.

anedroid,
@anedroid@wspanialy.eu avatar
robryk,
@robryk@qoto.org avatar

@anedroid To nie pomaga: mount(2) podąża za symlinkami, więc target można podmienić pomiędzy momentem kiedy się wykona realpath a uruchomieniem bwrapa.

Poza tym te mounty się dzieją po kolei. Pierwszy z nich może podmontować $HOME/a pod $HOME/b, a drugi $costam pod $HOME/b/sbin/runas.

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Czy można zablokować plik tak, aby nie można było nic z nim zrobić dopóki proces nie zginie lub zdejmie blokadę? Można by wtedy zablokować plik przed sprawdzeniem uprawnień.

robryk,
@robryk@qoto.org avatar

@anedroid

Wydaje mi się, że chcesz naprawiać problemy przez postulowanie coraz bardziej skomplikowanych interfejsów. Bardzo rzadko jest to dobra droga.

Gdyby taki interfejs istniał, kto mógłby zablokować plik? Czego nie możnaby zrobić z plikiem gdy jest zablokowany? Czy zablokowany byłby inode, czy może wpis w katalogu (dentry)?

Polecam raczej popatrzenie na to co można zrobić na otwartym pliku za pomocą syscalli fcośtam oraz tego jak dziala open(O_PATH).

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Chmid już nie pozwala kraść plików. Nie uruchomi się, jeżeli fs.protected_hardlinks jest wyłączony.

https://git.disroot.org/anedroid/midutils/commit/4c93e3bfe0ce37cc46abbc743709943e3226603e

Wydaje mi się, że podobny mechanizm prewencyjny powinienem zaimplementować przy tworzeniu użytkownika.

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Albo mógłbym tymczasowo zmienić właściciela primary homedir na nobody i dać +t, a potem zmienić go na shadow usera. Myślisz, że to dobry pomysł?

robryk,
@robryk@qoto.org avatar

@anedroid

Na pierwszy rzut oka każdy proces który ma wiele faz jest złym pomysłem, bo jest znacznie więcej sytuacji brzegowych do rozważenia (chociażby z powodu obsługi błędów, jak i z powodu możliwych wyścigów między wieloma kopiami tego samego procesu).

Czemu w ogóle kazać useraddowi tworzyć katalog domowy? Czemu nie zrobić tego zawczasu?

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Która wersja midsu lepsza?

https://git.disroot.org/anedroid/midutils/commit/d7a58eb70a8a95a1d41a838c81512c65d2bbd885

https://git.disroot.org/anedroid/midutils/commit/c0bb74985a700c4c70657d8c3de848bc9893033b

W branch master najpierw zmieniam właściciela primary homedir i ustawiam +s, następnie kopiuję zawartość /etc/skel do .shadow_home. Z kolei w branch alt1 całkowicie przeniosłem homedir shadow usera do /home.

W obydwu wykorzystuję blokadę na pliku /etc/midsu, aby dwie wersje midsu nie mogły operować jednocześnie prowadząc do race condition.

robryk,
@robryk@qoto.org avatar

@anedroid opisz proszę przed jakimi napastnikami to ma chronić

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Cały system korzysta z dodatkowego konta użytkownika przypisanego do podstawowego - jest to tzn. "shadow user" i ma na celu ochronę wybranych plików przed dostępem przez inne programy uruchamiane jako "primary user" (podstawowe konto z którego korzysta się na co dzień).

Midlaunch uruchamia aplikacje w kontenerach bwrap. Użytkownik może skonfigurować punkty montowania wskazujące na pliki do których ma dostęp shadow user, niekoniecznie zaś primary user. W ten sposób wybrane aplikacje będą uruchamiane jako primary user, ale z dostępem do wybranych chronionych katalogów.

Midsu pozwala tymczasowo zalogować się jako shadow user, w celu zarządzania chronionymi plikami lub zmiany konfiguracji kontenerów.

Chmid jest poleceniem zmieniającym właściciela pliku.

Z wszystkich tych narzędzi można korzystać jako nieuprzywilejowany użytkownik. Nie trzeba nawet być w grupie sudo/wheel. O ile nie jest to zablokowane w /etc/midsu, wywołanie "midsu" powoduje automatyczne utworzenie shadow usera i powiązanie go z kontem, jeśli jeszcze nie istnieje.

robryk,
@robryk@qoto.org avatar

@anedroid nie chodzi mi o to jak działa, ale o opis tego skąd napastnik zaczyna i jakiego celu ma nie móc osiągnąć, który normalnie może.

Jeśli napastnik zaczyna z możliwości wykonywania kodu jako podstawowy użytkownik, to czemu np. nie może wsadzić do $PATH katalog ze złośliwym midsu, które następnym razem gdy je uruchomisz wyśle mu wszystkie dane z konta-cienia?

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Zakładamy, że napastnik uzyskuje dostęp do podstawowego użytkownika, nie ma jednak dostępu do konta root. To może się zdarzyć, gdy np. użytkownik uruchomi złośliwy AppImage. Zakładamy również, że midsu jest zainstalowany jako aplikacja systemowa, zatem użytkownik nie może bezpośrednio modyfikować skryptów w /usr/lib/midsu. Te skrypty uzyskują uprawnienia root uruchamiając same siebie z sudo, a konfiguracja sudoers pozwala każdemu użytkownikowi uruchamiać je jako root (przy midsu dodatkowo wymagane jest podanie hasła). Podmiana midsu w $PATH nie zadziałałaby, ponieważ midsu nie miałby jak uruchomić się jako root, a tym samym nie uzyskałby dostępu do chronionych danych.

Chyba, że użytkownik należy do grupy sudo/wheel, wtedy w momencie gdy fałszywy midsu uruchomi się z sudo, użytkownik poda hasło i da fałszywemu midsu dostęp do roota. Niestety nie widzę sposobu w jaki możnaby temu przeciwdziałać, tzn. aby użytkownik mógł rozróżnić fałszywy midsu od prawdziwego. Może jedynie sprawdzić $PATH lub uruchomić midsu po ścieżce /usr/bin/midsu.

Na szczęście midsu jest używany tylko do zarządzania kontenerami (jak su do zarządzania systemem). Pozostałe 2 komendy - chmid oraz najczęściej używany midlaunch, nie wymagają podania hasła. Monit o hasło powinien wzbudzić wątpliwości.

robryk,
@robryk@qoto.org avatar

@anedroid

echo > ~/midsu << EOF
#!/bin/bash
exec /usr/bin/midsu zrób_coś_złośliwego
EOF
chmod +x ~/midsu
echo 'export PATH=$HOME:$PATH' >> ~/.bashrc

robryk,
@robryk@qoto.org avatar

@anedroid I tego rodzaju rzeczom się nie da przeciwdziałać. Jeśli atakujący ma kontrolę nad tym kawałkiem środowiska, przez które dokonujesz wszystkich swoich interakcji, to może je dowolnie zmieniać i podglądać.

anedroid,
@anedroid@wspanialy.eu avatar

@robryk To nie zadziała. Midsu nie pozwala dostosować uruchamianego programu z poziomu linii poleceń. Użytkownik może zmienić domyślny program umieszczając plik wykonywalny .midsu w katalogu domowym shadow usera. Może również wstawić parametr --failsafe aby uruchomić /bin/bash.

robryk,
@robryk@qoto.org avatar

@anedroid

> Może również wstawić parametr --failsafe aby uruchomić /bin/bash.

No to atakujący też może to zrobić i poprzekierowywać stdio tego basha.

Jestem silnie przekonany, ze z midlaunch da sie zrobic cos moralnie ekwiwalentnego, ale bede mial czas dopiero wieczorem.

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Faktycznie, zadziałało. Myślę, że można by wyłączyć midsu z $PATH i wymusić wpisywanie /usr/bin/midsu, albo... ustawić .bashrc, .bash_profile i .profile jako read-only:

$ chmod 644 ~/.bashrc ~/.bash_profile ~/.profile
$ chmid upgrade ~/.bashrc ~/.bash_profile ~/.profile

W ten sposób atakujący nie będzie mógł manipulować zmiennymi środowiskowymi. Trzeba by podobnie zrobić z konfiguracją emulatora terminala, aby nie podmienić powłoki tam.

robryk,
@robryk@qoto.org avatar

@anedroid

A skad wiesz, ze odpalasz ten emulator terminala (ze nie podmienilem konfiguracji menu twojego srodowiska graficznego, zeby odpalal cos zlosliwego zamiast niego)? A skad wiesz, ze twoj caly window manager nie zostal podmieniony na cos zlosliwego (przez np. ~/.xsession)?

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Hmm, a jakie zabezpieczenia stosuje sudo?

robryk,
@robryk@qoto.org avatar

@anedroid Żadne skuteczne (cała zabawa w to, że wpisanie hasła jest "ważne" tylko w tym samym terminalu niewiele daje).

Model w którym wymaganie hasła w sudo w czymkolwiek pomaga to model, w którym ofiara jest nieaktywna (a więc sama nie używa sudo) po tym jak napastnik uzyskał dostęp (no i przed tym jak został wykryty).

anedroid,
@anedroid@wspanialy.eu avatar

@robryk Zaktualizowałem README o sekcję dotyczącą bezpiecznego uruchamiania midsu.

robryk,
@robryk@qoto.org avatar

@anedroid

Wydaje mi sie, ze to co robisz tym plikom nie zapobiega zrobieniu mv ~/.bashrc ~/.smietnik

anedroid,
@anedroid@wspanialy.eu avatar

@robryk A na to też znalazłem rozwiązanie:

$ chmod +t ~
$ chmid upgrade ~

Mój home dir należy do shadow usera i ma sticky bit. Nie mogę usuwać ani przenosić "niemoich" plików.

$ chmod 644 ~/.bashrc ...
$ chmid upgrade ~/.bashrc ...

robryk,
@robryk@qoto.org avatar

@anedroid

No ale teraz masz zatrzęsienie innych plików konfiguracyjnych, które intencjonalnie pozwalają na coś podobnego: .xsession pozwala uruchomić inny window manager (i normalnie nie istnieje), pliki konfigurujące twoje środowisko graficzne pozwalają zmienić to co się odpala jak klikniesz "terminal" (i raczej chcesz je móc edytować, bo typowe środowiska graficzne to robią).

Napastnik może też zostawić uruchomiony program, który będzie ptrace()ował twoje shelle albo który, gdy zostanie odpalony terminal, zabije go i odpali od razu złośliwy terminal.

anedroid,
@anedroid@wspanialy.eu avatar

Może @grzgrz, @to3k albo @m0bi13 będą mogli pomóc?

m0bi13,
@m0bi13@pol.social avatar

@anedroid Chętnie zrobię review, ale lista todo długa, nie mogę obiecać terminu. Interesujące 👍 @grzgrz @to3k

anedroid,
@anedroid@wspanialy.eu avatar

@m0bi13 @grzgrz @to3k Dzięki.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • python
  • khanakhh
  • magazineikmin
  • mdbf
  • GTA5RPClips
  • everett
  • rosin
  • Youngstown
  • tacticalgear
  • slotface
  • ngwrru68w68
  • kavyap
  • DreamBathrooms
  • thenastyranch
  • tester
  • JUstTest
  • ethstaker
  • cubers
  • osvaldo12
  • cisconetworking
  • Durango
  • InstantRegret
  • normalnudes
  • Leos
  • modclub
  • anitta
  • provamag3
  • megavids
  • lostlight
  • All magazines