MySQL – tragikomiczna luka dająca dostęp do roota

22
2180
MySQL
MySQL

Sergei Golubchik, koordynator projektu MariaDB, odkrył bardzo poważny błąd bezpieczeństwa w bazie danych MySQL. Polega on na ominięciu autoryzacji i uzyskaniu bardzo łatwego dostępu do bazy danych z prawami administratora. Błąd o oznaczeniu CVE-2012-2122, pozwala atakującemu wykonać błędne logowanie ze złym hasłem i dać szansę dostępu. Szanse na zalogowanie się do bazy na konto root z błędnym hasłem wynoszą 1 na 256 prób. Aby się to udało, wystarczy wykonać odpowiednią przygotowaną pętle od 300 do 512 razy.

Firma Oracle załatała problem w serwerze MySQL (#64884) w wydaniach 5.1.63 i 5.5.24, które pojawiły się ponad 2 miesiące temu. Poprawki w dystrybucjach Linuksa powinny pojawić się niebawem.

Błąd polega na założeniu, że funkcja memcmp() zawsze zwraca wartość z przedziału -128 do 127. Na niektórych platformach z włączonymi optymalizacjami, funkcja ta potrafi zwrócić wartość z poza tego przedziału, co w efekcie powoduje, że funkcja porównująca zahashowane hasło, zwróci TRUE, w przypadku podania błędnego hasła.

Przykładowy exploit

$ for i in `seq 1 1000`; do mysql -u root --password=zlehaslo -h 127.0.0.1 2>/dev/null; done
mysql>

Systemy, które posiadają luki w serwerze bazy danych

  • Ubuntu Linux 64-bit ( 10.04, 10.10, 11.04, 11.10, 12.04 )
  • OpenSuSE 12.1 64-bit MySQL 5.5.23-log
  • Fedora 16 64-bit
  • Arch Linux

Systemy, które nie są podatne na atak

  • Oficjalne paczki MySQL oraz MariaDB (w tym wersje na Windows)
  • Red Hat Enterprise Linux, CentOS (32-bit and 64-bit) [ not conclusive ]
  • Ubuntu Linux 32-bit (10.04, 11.10, 12.04, likely all)
  • Debian Linux 6.0.3 64-bit (Version 14.14 Distrib 5.5.18)
  • Debian Linux lenny 32-bit 5.0.51a-24+lenny5 ( via @matthewbloch )
  • Debian Linux lenny 64-bit 5.0.51a-24+lenny5 ( via @matthewbloch )
  • Debian Linux lenny 64-bit 5.1.51-1-log ( via @matthewbloch )
  • Debian Linux squeeze 64-bit 5.1.49-3-log ( via @matthewbloch )
  • Debian Linux squeeze 32-bit 5.1.61-0+squeeze1 ( via @matthewbloch )
  • Debian Linux squeeze 64-bit 5.1.61-0+squeeze1 ( via @matthewbloch )
  • Gentoo 64-bit 5.1.62-r1 ( via @twit4c )
  • SuSE 9.3 i586 MySQL 4.1.10a ( via @twit4c )
Poprzedni artykułRaspberry Pi – obudowa dla maliny
Następny artykułGNU Emacs 24.1

22 KOMENTARZE

  1. Wyjaśnienie błędu zupełnie nie trafia do mnie. Funkcja memcmp zwraca 0 oznaczające prawdę lub inną wartość integer o znaku zależnym od tego, który ciąg bajtów jest większy. To z jakiego przedziału jest liczba nie ma znaczenia, byle mieściła się w integer.
    Być może problem polega na tym, że na różnych systemach int ma różny rozmiar, ale na wszystkich 32bitowych ma zawsze 32bity. Nie wiem czy istniały systemy z 8bitowym int (albo być może memcmp miała kiedyś inną sygnaturę, czyli może zwracała char – ale nawet gdyby to górna granica to 128, a nie 127 :) )

    A tak poza tym dobrze, że nie używam MySQL :)

    • Archi Linux jest rolling release, więc ciężko tu o nim pisać. Poza tym ja widzę, że jest dodany.

    • Poza tym to nie Sergei sprawdzał czy są luki wszędzie a różni ludzie i nadysłali o tym info.

    • Nie. Mieliśmy z innymi devami i TU niewątpliwą przyjemność przetestowania MySQL i MariaDB na różnych maszynach, nie tylko będących w naszych domach. memcmp() rzeczywiście zwraca wartości spoza podanego przedziału, ale w repozytorium dostępne są tylko najnowsze stabilne wersje oprogramowania, a więc załatane wydania MySQL.

  2. Cóż twórcy MySQL się nie popisali. Błąd polega na nieprawidłowym castingu zwracanej wartości przez memcmp. Normalnie funkcja zwraca wartości 0, 1 lub -1, ale jest to ogólnie niezdefiniowane zachowanie, nie należy przyjmować, że tak musi być. Jest powiedziane, że funkcja zwraca 0 gdy ciągi są identyczne, liczbę dodatnią gdy ciąg pierwszy jest większy od drugiego i ujemną w przeciwnym wypadku. Liczenie, że będzie tam jakaś konkretna wartość w jakiś przedziale to wróżenie z fusów.

    • Jesteś w błędzie bo to wina bilbioteki memcmp. Skoro dokumentacja mówi, jakie wartości ona zwraca – to takie powinna zwracać. To nie jest liczenie, że będzie tam konkretna wartość tylko ona tam powinna być i tyle.

      Jak korzystasz z bibliteki innej, i ona zwraca błędne wartości to błąd jest nadal po stronie bibliteki – ale pojawia się w Twojej aplikacji.

      Jeżeli uważasz, że twórcy MySQLa i MariaDB się nie popisali to nadal jesteś w błędzie, bo Oracle załatało TĘ LUKĘ PONAD 2 MIESIĄCE TEMU. To nie popisali się paczkujący w dystrybucjach.

    • Nie ma czegoś takiego jak biblioteka mamcmp. Jest standardowa biblioteka C, w której znajdziesz implementację oraz nagłówki funkcji memcmp(). Jeśli ktoś nie potrafi jej używać to jego problem.

    • @Antek, funkcja porównuje size pierwszych bajtów napisów s1 i s2. Funkcja zwraca liczbę mniejszą od zera, gdy s1 < s2, 0 gdy s1 jest taki sam jak s2 oraz liczbę większą od zera gdy s1 > s2.

      Nigdzie nie jest napisane z jakiego przedziału zwraca ona liczbę. Błąd po stronie MySQLa, który źle skorzystał z funkcji.

    • "Jesteś w błędzie bo to wina bilbioteki memcmp."
      To jakaś miejska biblioteka publiczna? :)

      "Skoro dokumentacja mówi, jakie wartości ona zwraca – to takie powinna zwracać. "
      Pokaż mi tę dokumentację która podaje że funkcja memcmp zwraca liczby z zakresu -128 do 127

      "Jak korzystasz z bibliteki innej, i ona zwraca błędne wartości to błąd jest nadal po stronie bibliteki – ale pojawia się w Twojej aplikacji. "
      Dlatego należy od każdej funkcji oczekiwać standardowego zachowania i nie oczekiwać niczego ponad to. Wtedy zmiana biblioteki nie spowoduje takich problemów.

      "Jeżeli uważasz, że twórcy MySQLa i MariaDB się nie popisali to nadal jesteś w błędzie, bo Oracle załatało TĘ LUKĘ PONAD 2 MIESIĄCE TEMU. To nie popisali się paczkujący w dystrybucjach. "
      Na pewno Oracle opisało, że nie wolno linkować z żadną inną biblioteką niż standardowa biblioteka C, a już w żadnym wypadku nie należy kompilować z wysoką optymalizacją :)
      Rzutowania do typów o mniejszym zakresie należy robić bardzo ostrożnie, zawodowcy powinni to wiedzieć. Do tego trzymać się standardów i rozumieć czym są zachowania niezdefiniowane.
      Czasami można znaleźć w kodzie programów kuriozalne błędy, które nie powodują wyłożenia kodu, ale działają tylko ze względu na specyfikę danego kompilatora. Wystarczy zmienić kompilator (czasami nawet tylko jego wersję), albo skompilować z inną flagą aby błąd się ujawnił.

ZOSTAW ODPOWIEDŹ

Proszę wpisać swój komentarz!
Proszę podać swoje imię tutaj