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 | 0 komentarzy

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

Odpowiedz