-15% na nową książkę sekuraka: Wprowadzenie do bezpieczeństwa IT. Przy zamówieniu podaj kod: 10000

Wiesz gdzie prowadzi http://0/ ? Mogłeś zgarnąć ~50000 PLN od GitHuba

29 lipca 2017, 10:50 | Aktualności | komentarzy 7

Jak konkretnie?  Zobaczcie tutaj.

Jako wstęp do cytowanego tekstu można poczytać: RFC 3986 oraz nasz tekst o podatności Server Side Request Forgery. Można też obadać świeże mięso z BlackHata – tutaj. Dowiecie się  m.in. że URL:  http://2130706433/ prowadzi de facto do http://127.0.0.1/

Ale co z tym http://0/ ? To skrócona wersja http://0.0.0.0/ – a czy 0.0.0.0 prowadzi do 127.0.0.1 ? Prawie, w każdym razie np. na lokalną maszynę można dostać się tak:

sequraq$ ping 0
PING 0 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_req=1 ttl=64 time=0.042 ms
^C
--- 0 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.042/0.042/0.042/0.000 ms

Oczywiście nie można zapomnieć też o adresie ::

sequraq$ ping6 ::
PING ::(::) 56 data bytes
64 bytes from ::1: icmp_seq=1 ttl=64 time=0.034 ms
^C
--- :: ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.034/0.034/0.034/0.000 ms

Po tym wstępie możemy przejść do analizy zdalnego wykonania kodu w GitHub Enterprise.

Na początek z górki, bo filtr przeciwko SSRF (czyli zmuszenie serwera do wykonania konkretnego requestu HTTP) udało się ominąć, wstrzykując w odpowiednim miejscu taki request: http://0:9200/_shutdown/

Czyli serwer jest zmuszany do wykonania requestu HTTP na lokalną maszynę na port 9200, gdzie dostępne jest (bez uwierzytelnienia, a jak) API do ElasticSearch.

Ale ten SSRF był dość słaby (mała możliwość kreowania własnych requestów), udało się jednak dobić do portu wystawianego lokalnie przez Graphite, i tam znaleźć kolejny SSRF:

http://0:8000/composer/send_email? to=orange@nogg&url=http://orange.tw:12345/foo

Zbliżamy się już do końca. Parametr url w requeście powyżej (czy raczej jego obsługa w działającym pod spodem Pythonie) podatny jest na wstrzyknięcie znaków końca linii. Zatem możemy już sterować również request nagłówkami HTTP, czy nawet lepiej: gadać z dowolnymi protokołami które nie są HTTP.

Autor badania dobił się ostatecznie do lokalnego memcached (port 11211), gdzie wykorzystał błąd deserializacji, o którym pisaliśmy przy innych okazjach. Tym razem było to niebezpieczne użycie Marshal w Ruby.

Na koniec mieliśmy:

irb(main):008:0> GitHub.cache.get("nogg")
=> "uid=0(root) gid=0(root) groups=0(root)\n"

A cały poskładany payload wyglądał tak:

Github przyznał za buga + za najlepszy raport – 12500 USD nagrody.

PS
Jeśli chcecie znać takie sztuczki lub myślicie dopiero o wejściu w tę tematykę, zapraszamy na nasze nowe szkolenia z bezpieczeństwa aplikacji: podstawowe, zaawansowane i trzecie – dedykowane dla frontendowców.

–ms

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



Komentarze

  1. Łukasz

    Tekst bardzo przystępny, co jest dużą zaletą. Co do szkolenia umieszczonego w „zielonym” akapicie, to czy nie myśleliście o jakiejś książce? Jeżeli nie, to dlaczego? Wolałbym przeczytać dobrą książkę wprowadzająco w świat crybersecurity zamiast zaczynać od szkolenia.

    Odpowiedz
  2. Witam!

    Czy mogę prosić o podanie OS’a, na którym „ping 0” zwraca adres localhost’a?
    Na Windows’ie i Unix-Like nie zwracany jest ten adres, a tym samym powyższe wnioski nie mają zastosowania.
    Dziękuję.

    Odpowiedz
    • Piter

      Ubuntu…

      >$ ping 0
      PING 0 (127.0.0.1) 56(84) bytes of data.
      64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.043 ms
      64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.028 ms
      64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.037 ms

      Odpowiedz
  3. Kamil

    @IPTRACE ping 0 działa na większości Linuxów, nie działa np. na OpenBSD.

    Odpowiedz

Odpowiedz na Kamil