Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book

Case study: błąd w wyrażeniu regularnym weryfikującym nazwę domeny w Google

18 marca 2020, 09:24 | W biegu | komentarze 2

W dzisiejszym odcinku z serii #vulnz omówimy ciekawy błąd znaleziony przez @xdavidhu (David Schütz) w pewnym wyrażeniu regularnym, które weryfikowało poprawność nazwy domeny w wielu usługach Google.

Wszystko zaczęło się od tego, że David natrafił na stronę pod następującym adresem URL:

https://console.developers.google.com/henhouse/?pb=["hh-0","gmail",null,[],"https://developers.google.com",null,[],null,"Create API key",0,null,[],false,false,null,null,null,null,false,null,false,false,null,null,null,null,null,"Quickstart",true,"Quickstart",null,null,false]

Dalej będziemy tę stronę nazywać henhouse (jak pierwsza część ścieżki). Strona ta była umieszczona w elemencie iframe w innej domenie. Była ona wykorzystywana do tego, by ramki rodzica wysłać wiadomość przez postMessage z tokenem OAuth. Jak widać w adresie URL, jednym z parametrów jest nazwa domeny, do której token ma zostać wysłany (w powyższym przykładzie jest to https://developers.google.com).

Henhouse podejmował decyzję, czy chce wysłać token OAuth do tej domeny, jej nazwę z adresu URL pewnym magicznym wyrażeniem regularnym, a następnie weryfikował, czy nazwa domeny kończy się na .corp.google.com lub .c.googlers.com lub jest to jedna z dopuszczonych domen na białej liście. Zobaczmy to na prostych przykładach:

  • W parametrze podajemy URL: https://abc.corp.google.com/test123. Za pomocą regeksa wyciągana jest nazwa domeny (abc.corp.google.com), która kończy się na .corp.google.com więc do niej zostanie wysłany token OAuth.
  • W parametrze podajemy URL: https://test123.c.googlers.com.pl#magic. Nazwa domeny wyciągnięta regeksem to test123.c.googlers.com.pl, która nie kończy się na żadną z oczekiwanych nazw, więc do niej token OAuth nie będzie wysłany.

Wyrażenie regularne wydobywające nazwę domeny z adresu URL wyglądało dość magicznie:

^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#([\s\S]*))?$

Aby lepiej je zrozumieć, David posłużył się narzędziem Debuggex (choć ja sam preferuję Regexper), które pozwala na rozrysowanie wyrażenie regularne do czytelniejszej formy (patrz: rysunek 1).

Wyrażenie regularne rozrysowane w narzędziu Regexper

Rys 1. Wyrażenie regularne rozrysowane w narzędziu Regexper

Na podstawie tak rozrysowanego regeksa, David zauważył, że wynika z niego, że znakami, które kończą nazwę domeny w adresie URL są: /, ? oraz #. Jest to dość naturalny wniosek , bowiem w każdym z poniższych adresów URL, nazwą domeny jest sekurak.pl:

  • https://sekurak.pl/test123
  • https://sekurak.pl?parametr=1
  • https://sekurak.pl#cos-po-hashu

W tym momencie zasadne jest jednak pytanie, czy tylko te trzy znaki mogą kończyć nazwę domeny w adresie URL? David napisał prosty skrypt w JS, który ujawnił, że dla przeglądarek istnieje jeszcze jeden znak: \.

Oznacza to, że jeśli przygotujemy adres podobny do następującego: https://zlosliwa-domena.pl\abc.corp.google.com, to googlowy regex uzna, że jest to poddomena corp.google.com, jednak gdy później ten sam adres URL zostanie sparsowany przez przeglądarkę, dla niej nazwa domeny to tylko zlosliwa-domena.pl, dzięki czemu tokeny OAuth mogły wyciekać do zewnętrznych domen.

Okazało się, że David zidentyfikował błąd w popularnej bibliotece używanej przez Google, o nazwie Closure. W repozytorium można znaleźć commit, który naprawia ten błąd. Za zgłoszenie błędu, Google wypłaciło bounty w wysokości 6000 USD.

Regeksowa zagadka

Dawno temu, w starej wersji serwisu rozwal.to, przygotowałem zadanie, które też wymagało nieco zabawy z regeksami i użyciem narzedzie typu Debuggex czy Regexper. Zadanie jest nadal dostępne, więc jeśli ktoś ma ochotę przećwiczyć użycie regeksów, serdecznie zachęcam do zmierzenia się z nim.

W zadaniu należy napisać adres email, który przechodzi sprawdzanie poprawności adresu email wbudowane w PHP, ale w taki sposób by zrobić z tego SQL Injection i wyciągnąć z bazy flagę w postaci ROZWAL_.... W PHP mail jest sprawdzany regeksem (do którego bezpośredni link tutaj), ale w jest w nim pewien błąd ;) Kluczem do rozwiązania zadania jest odkrycie tego błędu.

Link do zadania:

— Michał Bentkowski (@SecurityMB)

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

  1. rozwal.to za free

    Kiedy rozwal.to bedzie za free?

    Odpowiedz
    • jak się z tym odrobimy ;-) w czym covid nie pomaga.

      Odpowiedz

Odpowiedz