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)
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