Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book
Joomla łata serię pięciu podatności
Ostatnio pisaliśmy o serii podatności w systemie zarządzania treścią (CMS) Joomla o różnym stopniu krytyczności. Właśnie powstały łatki. Jedna z podatności ma wysoki poziom krytyczności. Kolejna z nich niesie ryzyko poważnych konsekwencji – może skutkować zdalnym wykonaniem kodu (RCE).
Znalezione podatności to:
- CVE-2024-21722: Niepoprawne kończenie sesji użytkownika przy zmianie MFA
- CVE-2024-21723: Nieprawidłowe parsowanie URLi prowadzące do open redirect
- CVE-2024-21724: Niewystarczająca walidacja danych wejściowych dla pól wyboru mediów prowadąca do cross-site scripting (XSS) w różnych rozszerzeniach.
- CVE-2024-21725: Niewystarczające escape’owanie adresów mailowych prowadziło do XSS w różnych komponentach
- CVE-2024-21726: Niewystarczające filtrowanie treści powodujące podatności XSS w różnych komponentach
Najpoważniejsze są dwie ostatnie podatności. CVE-2024-21725 otrzymało wysoki poziom krytyczności połączony z wysokim prawdopodobieństwem wykorzystania. Możemy zatem wkrótce spodziewać się fali ataków z wykorzystaniem tej luki.
Z kolei CVE-2024-21726 może – zgodnie z opisem znalazcy – w przypadku niektórych instalacji Joomla, prowadzić do zdalnego wykonania kodu. Na szczęście aby do tego doszło, konieczna jest interakcja administratora CMS przez kliknięcie złośliwego linku. Nie zmniejsza to jednak skutków wykorzystania tej podatności.
CVE-2024-21726 – analiza techniczna
Podatność CVE-2024-21726 może być wykorzystana tylko na instalacjach Joomla działających na PHP w wersji niższej niż 8.3 oraz 8.4. Dzieje się tak, gdyż jej wykorzystanie wynika z niespójności działania pewnych funkcji PHP. Niespójność ta została naprawiona w wyżej wymienionych wersjach, ale poprawka błędu nie została przeniesiona do starszych wersji PHP, ponieważ błąd nie został tam uznany za błąd dotyczący bezpieczeństwa.
Framework Joomla posiada rozbudowane reguły mające zapobiegać XSS. W szczególności służy do tego metoda cleanTags. Do tej pory korzystała ona z StringHelper::strpos
do określenia pozycji tagu HTML oraz z StringHelper::substr
do pobrania go. Metody te są jednak jedynie wrapperami na funkcje PHP mb_strpos
oraz mb_substr
.
Przykładowo dla danych wejściowych:
some-text<script>alert(1)</script>
w założeniu zwrócony powinien być bezpieczny, gdyż pozbawiony tagów HTML, ciąg znaków:
some-textalert(1)
Jak widać, ciąg znaków następujący po otwarciu tagu, czyli znakiem <, a przed najbliższym jego domknięciem, czyli znakiem > (czyli w zwykłym przypadku tagi HTML) powinien zostać usunięty. Ilustruje to Rysunek 1:
Okazuje się, że na starszych wersjach PHP metody mb_strpos oraz mb_substr w różny sposób traktowały nieprawidłowe sekwencje UTF-8. Gdy mb_strpos napotykała bajt wiodący w formacie UTF-8, próbuje przeanalizować kolejne bajty kontynuacji, aż do odczytania pełnej sekwencji bajtów. Jeśli napotkany zostanie nieprawidłowy bajt, wszystkie poprzednio odczytane bajty zostaną uznane za jeden znak, a przetwarzanie rozpoczyna się od nowa od nieprawidłowego bajtu.
Natomiast mb_subst po napotkaniu bajtu wiodącego, po prostu pomijała kolejne bajty. Szczegółowe omówienie różnic działania tych funkcji znajdziemy w oryginalnym artykule, sami natomiast różnicę w działaniu tych funkcji w różnych wersjach PHP możemy sprawdzić w prosty sposób. Uruchomienie poniższego kodu:
<?php
$a = mb_strpos("\xf0\x9fAAA<BB", '<');
echo $a,"\n";
$b = mb_substr("\xf0\x9fAAA<BB", 0, 4);
echo $b,"\n";
?>
na PHP 8.3 daje wynik:
4
?AAA
Natomiast na PHP 7.3 otrzymamy:4
�AAA<B
W obu przypadkach najpierw szukaliśmy pozycji na której występuje znak <, służący do otwarcia tagu HTML i w obu otrzymaliśmy wartość 4. Następnie wykorzystaliśmy pobraną wartość do pobrania – w założeniu bezpiecznego, bo nie zawierającego tagów HTML – ciągu poprzedzający tę pozycję. Jak widać, w przypadku PHP 7.3 tak otrzymana wartość zawiera znak < i literę B następującą po niej, czyli potencjalnie fragment tagu HTML!
Powyższa niespójność pozwalała atakującemu na wstrzyknięcie wielu nieprawidłowych sekwencji UTF-8, co mogło powodować przesunięcie indeksu zwracanego przez StringHelper::strpos
daleko poza otwarcie tagu HTML, a w efekcie możliwość dołączenia dowolnej wartości do oczyszczonego wyniku. Filtrowanie stosowane przez Joomla stawało się w ten sposób bezużyteczne.
Do eskalacji powyższej podatności do zdalnego wykonania kodu mogło powstać, gdy XSS tego typu był wykorzystany do utworzenia złośliwego linka, którego kliknięcie przez administratora spowoduje modyfikację szablonu poprzez dodanie dowolnego kodu PHP, a w konsekwencji RCE.
Joomla naprawiła błąd przez zastąpienie funkcji PHP, które były dostosowane do sekwencji wielobajtowych (mbstring), zwykłymi funkcjami PHP do obsługi string (rysunek 2).
Błędy zostały już załatane przez autorów Joomla w wersjach 5.0.3 oraz 4.4.3 – jeśli korzystacie z tego CMS, zaktualizujcie go jak najszybciej do jednej z wymienionych wersji.
~Paweł „Róża” Różański
„działających na PHP w wersji niższej niż 8.3 oraz 8.4.” -> Czy tutaj nie chodziło przypadkiem o 7.4? Wersja 8.4 nie została jeszcze wydana.
„Natomiast mb_subst po napotkaniu bajtu wiodącego” – autor zgubił bajt kończący ;)