Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book

Popularne dystrybucje Linuksa pozwalają podnieść uprawnienia lokalnemu atakującemu (pakiet needrestart i 10 lat podatności)

25 listopada 2024, 16:57 | W biegu | komentarze 4

Aktualizacja komponentów dystrybucji Linuksa może wymagać restartu całego systemu lub tylko określonych serwisów. Popularnym rozwiązaniem wspomagającym wykonywanie aktualizacji w tym zakresie jest needrestart dołączony do bardzo popularnych dystrybucji jak Ubuntu czy Debian.

TLDR:

  • Zespół badaczy Qualysa opublikował listę podatności, która pozwala lokalnemu atakującemu (z dostępem do systemu jako nieuprzywilejowany użytkownik) podnieść swoje uprawnienia do roota.
  • Luki bezpieczeństwa zostały wprowadzone w kwietniu 2014 roku (needrestart 0.8).
  • Do wykorzystania błędu nie jest potrzebna interakcja z użytkownikiem.
  • Źródłem problemu jest pakiet pakiet needrestart odpowiedzialny za wykrywanie usług przeznaczonych do restartu.
  • Dystrybucje takie jak Debian czy Ubuntu mają dostępne łatki w repozytoriach – zalecana jest szybka aktualizacja.

Badacze zidentyfikowali aż pięć podatności (w tym trzy kluczowe), pozwalających podnieść atakującemu (z dostępem do systemu) uprawnienia do użytkownika root. Podatności te zostały sklasyfikowane jako:

  • CVE-2024-48990 – uruchomienie interpretera Pythona przez wykorzystanie zmiennej środowiskowej PYTHONPATH oraz zmuszenie needrestart do skorzystania ze środowiska atakującego.
  • CVE-2024-48992 – podobna podatność do tej powyżej, tylko wykorzystująca interpreter języka Ruby, wskazywany przez zmienną środowiskową RUBYLIB.
  • CVE-2024-48991 – tym razem wykorzystano sytuację TOCTOU (time-of-check time-of-use), atakujący wygrywając wyścig (ang. race condition) i zmuszając podatny pakiet do uruchomienia podstawionego interpretera Pythona, zamiast tego systemowego.
  • CVE-2024-10224 – podatność bazuje na możliwości uruchamiania dowolnych komend powłoki w kontekście użytkownika root. Problemem jest tutaj moduł Perla – ScanDeps – zmuszając needrestart do otwarcia pliku o nazwie “komenda|” możliwe jest jej wywołanie. 
  • CVE-2024-11003 – dodatkowa podatność przypisana do modułu ScanDeps.

CVE-2024-48990 oraz CVE-2024-48992

W momencie gdy proces Pythona (lub Ruby) wymaga restartu w wyniku aktualizacji, needrestart pobiera zmienną środowiskową PYTHONPATH z pseudokatalogu /proc/<pid>/environ, która przechowuje zmienne środowiskowe dla każdego procesu.

Następnie proces restartujący ustawia własną zmienną środowiskową na tę odczytaną z environ, a następnie uruchamia Pythona, przekazując na wejście prosty skrypt:

135 sub files {
136     my $self = shift;
137     my $pid = shift;
138     my $cache = shift;
139     my $ptable = nr_ptable_pid($pid);
...
193     my %e = nr_parse_env($pid);
194     local %ENV;
195     if(exists($e{PYTHONPATH})) {
196         $ENV{PYTHONPATH} = $e{PYTHONPATH};
197     }
...
203     my ($pyread, $pywrite) = nr_fork_pipe2($self->{debug}, $ptable->{exec}, '-');
204     print $pywrite "import sys\nprint(sys.path)\n";
205     close($pywrite);

Listing 1. Podatny fragment kodu uruchamiający interpreter Pythona zdefiniowany przez atakującego (źródło: qualys.com)

Atakujący może teraz w katalogu, do którego ma dostęp, umieścić bibliotekę współdzieloną, importlib/__init__.so, która zawierać będzie złośliwy kod. Następnym krokiem jest uruchomienie procesu Pythona, który będzie działał w tle (zespół Qualys wykorzystuje tutaj operację sleep()). Na koniec wystarczy zmienić zmienną środowiskową PYTHONPATH w taki sposób, aby wskazywała na katalog z biblioteką. W momencie gdy needrestart uruchomi proces Pythona i ustawi środowisko wykonania na to zdefiniowane przez atakującego – kod współdzielonej biblioteki zostanie wykonany jako root. 

Analogicznie działa eksploit z wykorzystaniem interpretera języka Ruby. 

CVE-2024-48991

W tej podatności dochodzi do sytuacji wyścigu – atakujący może “podmienić” interpreter, który zostanie wywołany z uprawnieniami użytkownika root. Problemem jest sytuacja TOCTOU, między sprawdzeniem a użyciem interpretera.

 520         my $exe = nr_readlink($pid);
 ...
 606             $restart++ if(needrestart_interp_check($nrconf{verbosity} > 1, $pid, $exe, $nrconf{blacklist_interp}, $opt_t));
------------------------------------------------------------------------
166 sub needrestart_interp_check($$$$$) {
167     my $debug = shift;
168     my $pid = shift;
169     my $bin = shift;
170     my $blacklist = shift;
171     my $tolerance = shift;
...
176         if($interp->isa($pid, $bin)) {
------------------------------------------------------------------------
 40 sub isa {
 41     my $self = shift;
 42     my $pid = shift;
 43     my $bin = shift;
 44 
 45     return 1 if($bin =~ m@^/usr/(local/)?bin/python([23][.\d]*)?$@);
 46 
 47     return 0;
 48 }

Listing 2. Podatny fragment kodu, pozwalający na podstawienie swojego interpretera (źródło: qualys.com)

Atakujący może uruchomić swój proces, który będzie czekał aż needrestart przeczyta pseudoplik /proc/pid/exe po raz pierwszy (zespół badaczy sugeruje użycie inotify do uzyskania informacji o odczycie pliku), a następnie dokonuje wywołania execve(). Dzięki temu sprawdzenie warunków ścieżki odbywa się na systemowym interpreterze, ale wykonywany jest złośliwy kod atakującego. Badacze zauważają, że podobna sytuacja może wystąpić z interpreterem Ruby. 

CVE-2024-10224 (oraz CVE-2024-11003)

Oprócz problemów z Pythonem oraz Ruby, podatności dotykają również Perla wykorzystywanego przez needrestart. W tym przypadku, chociaż interpreter nie jest wywoływany, to wykorzystywana jest funkcja scan_deps() z modułu ScanDeps, która przechodzi rekursywnie przez perlowy skrypt. 

Okazuje się, że Perl od dawna cierpi na pewną przypadłość – dwuargumentową funkcję open. Atakujący, który kontroluje nazwę otwieranego pliku, może wykonać dowolną komendę. 

 868 sub scan_file{
 869     my $file = shift;
 870     my %found;
 871     open my $fh, $file or die "Cannot open $file: $!";

Listing 3. Podatny fragment kodu, pozwalający na dodanie swojej komendy (źródło: qualys.com)

Wykorzystanie tej podatności jest trywialne – atakujący uruchamia skrypt o nazwie /home/jane/perl| (pipe na końcu nazwy), w wyniku czego traktowany jest on jako polecenie i uruchamiany jest plik wykonywalny /home/jane/perl

Przedstawione podatności są bardzo proste w eksploitacji i chociaż sam zespół nie publikuje eksploitów pozwalających na ich wykorzystanie, to z opisu podatności można wywnioskować, jakie kroki są niezbędne do zaatakowania systemu. Zauważyliśmy też PoCe (ang. Proof of Concepts) dostępne na portalu GitHub. 

To nie pierwszy raz, kiedy występują problemy z interpreterami w pakiecie needrestart, dlatego badacze sugerują skorzystanie z poprzednich porad w celu wyłączenia heurystyk skanowania w poszukiwaniu interpreterów:

 # Disable interpreter scanners.
 $nrconf{interpscan} = 0;

Zmiany należy dokonać w pliku konfiguracyjnym, który zwykle znajduje się w  /etc/needrestart/needrestart.conf

Szczegółowa analiza podatności znajduje się pod tym linkiem.

Qualysowi gratulujemy kolejnego dobrego znaleziska, a użytkownikom jak zwykle zalecamy błyskawiczną aktualizację.

~fc

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

  1. SeeM

    Mam mieszane uczucia nie tyle do needrestart, bo pomysł jest rewelacyjny, co do oprogramowania je olewającego. Nie ma jak zaktualizować sobie produkcyjnego Debiana, no bo przecież needrestart mnie upilnuje, żebym niczego krytycznego nie przekręcił. A tu BUM pakiety z różnych repo (ekhem clickhouse i dockerio) radośnie się złożą.

    Odpowiedz
  2. Adam

    Nie mam tej aplikacji domyślnie zainstalowanej w moim Debianie. W których systemach opartych na Linux ta aplikacja jest domyślnie zainstalowana?

    Liczę na listę tych popularnych dystrybucji.

    Odpowiedz
  3. Piotr

    Dlaczego skrypty perlowe opisujecie jako pytonowe?

    Odpowiedz
  4. Jan

    A Debian taki był bezpieczny, przetestowany… Wszędzie czai się błąd.

    Odpowiedz

Odpowiedz