Odwrócenie flagi wykonania w systemach Linux. Dlaczego to jest możliwe?

23

Podczas czytania tego znalazłem następujący exploit:

% cp /usr/bin/id ~
% chmod -x ~/id
% ls -al ~/id
-rw-r--r-- 1 edd edd 22020 2012-08-01 15:06 /home/edd/id
% ~/id
zsh: permission denied: /home/edd/id
% /lib/ld-linux.so.2 ~/id
uid=1001(edd) gid=1001(edd) groups=1001(edd),1002(wheel)

Ten fragment pokazuje, że możemy w trywialny sposób ominąć uprawnienia systemu plików do wykonywania jako normalny nieuprzywilejowany użytkownik. Uruchomiłem to na Ubuntu 12.04.

Podczas gdy moduł ładujący Linux jest obiektem współdzielonym zgodnie z plikiem (1), ma również punkt wejścia, który pozwala na jego bezpośrednie wykonanie. Po wykonaniu w ten sposób moduł ładujący systemu Linux działa jako interpreter dla plików binarnych ELF.

Jednak na moim komputerze OpenBSD ten exploit nie jest skuteczny, ponieważ nie możesz uruchomić programu ładującego jako programu. Strona podręcznika OpenBSD mówi: „Sam ld.so jest współdzielonym obiektem, który jest początkowo ładowany przez jądro.”.

Wypróbuj to na Solaris 9, a otrzymasz awarię. Nie jestem pewien, co dzieje się gdzie indziej.

Moje pytania są zatem:

  • Dlaczego moduł ładujący systemu Linux (gdy jest wykonywany bezpośrednio) nie sprawdza atrybutów systemu plików przed interpretacją pliku binarnego ELF?
  • Po co wdrażać mechanizm, który ma uniemożliwiać wykonywanie plików, jeśli jest tak trywialnie odsunięty? Czy coś przeoczyłem?
Edd Barrett
źródło
1
Nie ma dobrego powodu, ale jeśli kiedykolwiek udało ci się usunąć system libc(raz zrobiłem, uaktualniając Arch Archa), będziesz wdzięczny za to małe dziwactwo.
new123456
1
@ new123456 o Boże, kanał IRC po aktualizacji był bolesny.
Rob
To moduł ładujący , a nie linker.
Przestań krzywdzić Monikę

Odpowiedzi:

33

Celem executepozwolenia nie jest ogólne zapobieganie wykonaniu . Jest to (1), aby powiedzieć progamom, które pliki mają zostać wykonane, i (2), aby zapobiec wykonaniu jako użytkownik uprzywilejowany , gdy określony jest bit setuid (itp.).

Włamanie do linkera jest mniej ryzykowne niż się wydaje. Możesz wykonać dowolny plik wykonywalny, do którego odczytu masz uprawnienia, jeszcze łatwiej:

$ cp unexecutable_file ~/runme
$ chmod +x ~/runme
$ ~/runme

Zobacz tę dyskusję na forum Arch Linux .

W podsumowaniu:

Oznaczanie plików, które należy wykonać

Kiedy piszesz skrypt powłoki, możesz oznaczyć go jako wykonywalny przy pomocy chmod +x. Wskazuje to twojej powłoce, że zamierzasz być wykonywalny (w przeciwnym razie dla całej powłoki to tylko kolejny plik tekstowy). Powłoka może następnie wyświetlać ją w tabulatorze podczas pisania ./Tab.

Podobnie: something.dkatalogi (np. init.d) Zawierają skrypty powłoki startowej lub kontrolnej, które są zwykle wykonywane automatycznie przez demony. Możesz umieścić plik komentarza lub plik README w katalogu jako zwykły plik tekstowy. Lub możesz tymczasowo wyłączyć jeden ze skryptów. Możesz to zrobić, usuwając bit wykonania dla tego konkretnego pliku. Mówi to demonowi, aby go pominął.

Zapobieganie uprzywilejowanemu wykonaniu

Do setuidbit oznacza, że podczas wykonywania pliku, jest on wykonywany jako określonego użytkownika (na przykład root).

Wpis na forum dobrze to wyjaśnia:

Chcesz, aby plik wykonywalny był ustawiony jako setuid dla niektórych użytkowników, ale chcesz, aby ludzie z określonej grupy mogli go wykonywać jako setuid. Nadal mogą go wykonać, kopiując, ale flaga setuid gubi się, więc będą wykonywać ją sami, a nie użytkownik, który był właścicielem oryginalnego pliku.

Ślimak mechaniczny
źródło
2
Dzięki - przeoczyłem fakt, że użytkownik może skopiować dowolny plik, który może odczytać, a zatem wybrać dowolne uprawnienia.
Edd Barrett
co z plikami z uprawnieniami do wykonywania, ale bez uprawnień do odczytu?
Lie Ryan
@LieRyan Co z nimi?
Przywróć Monikę
@BrendanLong: Oczywiście nie możesz ich skopiować, więc nie możesz zmienić ich uprawnień. (Ale dlaczego chcesz, nie mogę powiedzieć - jedyną rzeczą, którą możesz zrobić z kopią, jest upuszczenie zezwolenia na wykonanie)
MSalters
9

Jeśli masz dostęp do odczytu pliku, zawsze możesz wykonać jego kopię.

Jeśli możesz wykonać kopię osobistą, zawsze możesz zaznaczyć tę kopię jako wykonywalną.

To nie wyjaśnia zachowania ld-linuxa, ale wskazuje, że może nie być to bardzo przydatna luka bezpieczeństwa.

Jeśli chcesz ściślejszego bezpieczeństwa, rozważ SELinux

RedGrittyBrick
źródło
To jest najprawdziwsza prawda.
Edd Barrett
To było tylko pytanie koncepcyjne. Przypuszczam, że możesz ustawić nonexec również na systemy plików.
Edd Barrett
2

Patrząc na pytanie nieco inaczej: jak mówi Mechanical Snail, uprawnienie do wykonywania pliku nie ma na celu uniemożliwienia wykonania. Jednak opcja systemu plików „noexec” uniemożliwia wykonanie i nie jest tak łatwo ominięta (nie obsługiwana przez wszystkie systemy plików, ale z pewnością przez najpopularniejsze systemy Linux). Jeśli administrator chciałby uniemożliwić użytkownikom uruchamianie własnych programów, może określić opcję noexec w katalogach domowych i tmp oraz w innych, w których użytkownicy mogą tworzyć pliki.

$ mount -o noexec /dev/sdd1 /test
$ cd /test
$ cp /usr/bin/id .
$ ./id
-bash: ./id: Permission denied

Najwyraźniej można było obejść opcję noexec przy użyciu sztuczki ładującej wspomnianej w pytaniu, ale zostało to naprawione w jądrze kilka wersji wstecz.

Z http://linux.die.net/man/8/mount :

noexec

Nie zezwalaj na bezpośrednie wykonywanie jakichkolwiek plików binarnych w zamontowanym systemie plików. (Do niedawna można było mimo wszystko uruchamiać pliki binarne za pomocą polecenia takiego jak /lib/ld*.so / mnt / binary. Ta sztuczka kończy się niepowodzeniem od Linuksa 2.4.25 / 2.6.0.)

Randy Orrison
źródło