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

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

    przez -
    22 752
    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 )

    • Admn

      Tak się śmiejecie z Debiana a tu proszę. Nie podatny na atak :]

    • mikolajs

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

      • W postgresql ostatnio tez załatali trochę luk bezpieczeństwa :P

      • Greg

        W poprzednich wersjach postgresql domyślna konfiguracja m.in. pozwalała użytkownikom lokalnym na logowanie się bez podania hasła.

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

      • mikolajs

        PS. zakres to oczywiście -128 do 127

    • Arch Linux jak najbardziej nie jest podatny – jak widać ani OSWorld, ani Sergei Golubchik nie zweryfikowali informacji.

      • Greg

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

      • TomJ

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

      • @Barthalion, nie?

      • 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.

    • mikolajs

      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.

      • Antek

        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.

      • sbv

        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.

      • mikolajs

        "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ł.

    • Minter

      Ale wtopa. Wstyd i tyle :-)

      • mietek

        Właśnie wyszła poprawka dla ubuntu

    • Pingback: Największe wpadki Open Source w 2012 roku - Linux mint, centos, ubuntu - OSWorld.pl - mały świat wielkich systemów!()