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
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 `bwrap`a 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 Zabawa z symlinkami i race condition. Tego nie przewidziałem. Czyli ograniczenie targetu do homedir (realpath) i coś jeszcze trzeba będzie wykombinować.
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.
@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.
@robryk Ograniczyłem możliwość montowania poza homem.
https://git.disroot.org/anedroid/midutils/commit/3a347f3206513715b4a30ae17add7f7dfae522af
@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.
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).