DownUnderCTF 2023, Czyli Writeup Największego Australijskiego CTF!

securitybeztabu.pl 1 rok temu

Co to jest i dlaczego warto brać w nich udział

Turnieje CTF (ang. Capture the flag – zdobądź flagę) to popularny sposób na naukę przez zabawę w dziedzinie cyberbezpieczeństwa (i nie tylko). CTF-y polegają na rozwiązywaniu zadań z wielu różnych kategorii takich jak: OSINT, kryptografia, inżynieria wsteczna, eksploatacja binarna itd.

Dlaczego warto brać w nich udział?

  1. Możesz legalnie „pohackować” – z wyłączeniem oczywiście DDoS, bruteforce i innych technik przewidzianych przez regulaminy
  2. Nauka. CTF-y bardzo często składają się z zadań w kilku kategoriach, dzięki czemu każdy może znaleźć coś dla siebie. Znalazłem dwa cytaty, które doskonale to opisują:

„Nawet jeżeli w tasku nie dotrzesz do flagi, to nie ma siły, byś po drodze nie musiał czegoś poszukać i doczytać :)” – bl4de, artykuł na sekurak.pl

„Najmądrzejszy jest ten, który wie, czego nie wie…” – Sokrates

DownUnderCTF

DownUnderCTF to największy australijski CTF, organizowany corocznie od 2020 r. W tegorocznej edycji wzięło udział ponad 2000 drużyn i 4300 uczestników. Do rozwiązania było 68 zadań w 8 kategoriach: beginner, blockchain, crypto, misc, osint, pwn, rev i web.

Z założenia CTF przeznaczony był dla australijskich graczy, dlatego wraz z Cappybarą zaczęliśmy rozwiązywać zadania o 11.30, gdy w Sydney była już 19.30 J.

Wybrałem 7 najciekawszych zadań, które udało się nam rozwiązać.

Writeup

Poniżej znajdują się rozwiązania poszczególnych zadań, podzielone na kategorie.

Begginer

Proxed

Autor rozwiązania: Oskar

Zadanie składa się z dwóch części: linku do strony internetowej i archiwum z plikami.

Poniższy link prowadzi do strony internetowej, na której widnieje komunikat:


untrusted IP: 10.152.0.17

Przejdźmy w takim razie do analizy archiwum, które zostało dołączone do zadania. W katalogu cmd znajduje się katalog secret_server, a w nim plik main.go.

Analizując plik znaleźliśmy dość interesujący fragment:

Oznacza to, iż możemy otrzymać flagę, o ile zapytanie zostanie wysłane z adresu IP 31.33.33.7. Można to zrobić dzięki cURL i nagłówka http „X-Forwarded-For:[ip]” – być może uda się dzięki temu nabrać serwer, iż wysyłamy zapytanie z konkretnego adresu. Pora to sprawdzić.

Bingo! Mamy flagę J

Blinky Bill

Autor rozwiązania: Oskar

Zadanie składa się z pliku blinkybill.wav. W tle utworu można usłyszeć charakterystyczne sygnały, podobne do kodu Morse’a. Aby zobaczyć czy piosenka ma jakieś ukryte dno użyłem Audacity i opcji Spektogram.

Można zauważyć charakterystyczne dla kodu Morse’a sygnały. Odfiltrujmy je zmieniając zakres decybeli.

Udało się! Mamy widoczne krótkie i długie sygnały. Teraz pora je „przetłumaczyć” na litery.

Mamy sensowne zdanie! Flaga to DUCTF{BRINGBACKTHETREES}.

Randomly chosen

Autor rozwiązania: Cappybara

Zadanie składa się z dwóch plików: randomly-chosen.py i output.txt.

randomly-chosen.py generuje seed (liczbę) z przedziału od 0 do 1337, a następnie otwiera plik flag.txt. Następnie zmienna out dodaje losowy znak z pliku flag.txt pewną ilość razy. Jaka to ilość?

k = len(flag)*5))

Czyli – liczba dodanych losowo znaków jest 5 razy większa od liczby znaków flagi. Jak nam to może pomóc w dojściu do flagi?

Plik output.txt ma 305 znaków, czyli flaga ma 5 razy mniej znaków. Dzieląc 305 na 5 dostaniemy 61 – tyle znaków ma flaga!

Następnym krokiem jest stworzenie flagi pomocniczej o długości 61 znaków. Przykładową flagę zawierającą możliwe znaki flagi widać powyżej.

Aby dojść do flagi, należy znaleźć seed. Udało się Cappybarzewpaść na pomysł, aby porównać miejsca gdzie znajdują się znaki „{” i „}” w wybranych miejscach, ponieważ te miejsca są wspólne dla pliku output.txt i ciągu znaków wygenerowanego dzięki dobrego seedu dla pomocniczej flagi – zapisanego później jako output2.txt.

Udało się znaleźć seed, który wynosi 252.

Teraz pora na podmienienie znaków w pomocniczej fladze na znaki prawdziwej flagi. Potrzebne nam do tego są trzy pliki: flag.txt (flaga pomocnicza), output.txt i output2.txt.

Na podstawie tych trzech plików możemy dojść do prawdziwej flagi. Program zamienia literę w pomocniczej fladze na literę, która odpowiada jej na podstawie plików output.txt i output2.txt. Przykładowo – dla „a” będzie to litera „i” itd.

Zasada działania programu

Static file server

Autor rozwiązania: Cappybara

Zadanie składa się z archiwum i strony internetowej.

Po wejściu na stronę widać logo CTF i zakładkę not the flag.

Po wejściu w zakładkę zostajemy przekierowani na stronę o takim komunikacie. Spróbujmy więc wejść na /flag.txt.

Coś tu nie gra… Sprawdźmy pliki dołączone do zadania.

W pliku app.py widać odwołanie do lokalizacji /files, tak jakbyśmy byli zmuszeni do odwoływania się do niej podczas wysyłania zapytania.

Spróbujmy w takim razie wykonać atak path traversal, czyli dojścia do pliku inną ścieżką, obchodząc zabezpieczenia serwera. Można wykorzystać do tego BurpSuite.

Udało się! Doszliśmy do /flag.txt wykorzystując obowiązkowe odwołanie do /files.

OSINT

Monke bars

Autor rozwiązania: Oskar

Myślę, iż to najciekawsze zadanie tego CTF. Nie mamy dołączonego żadnego pliku do zadania.

Naszym celem jest znalezienie piosenki monke bars wraz z flagą. Zacznijmy więc poszukiwania!

Zacząłem poszukiwania od SoundClouda. Natknąłem się na piosenkę o identycznym tytule od nijakiego MC Fat Monke.

Próbowałem na początku kombinować z autorem piosenki jako flagą, ale gdy wsłuchałem się w treść piosenki, wyłapałem charakterystyczny prefiks flagi: DUCTF, a następnie bardzo szybką składankę kilku słów. Wyłapałem również słowo bracket (nawias) – od tego momentu wiedziałem, iż flaga jest podana wprost w piosence! Dość oryginalny zabieg jak na CTF.

Przez godzinę próbowałem różnych kombinacji zasłyszanych słów, po czym ukazał się komentarz od autora piosenki.

Dzięki temu udało mi się ustalić, iż flaga to DUCTF{smackithackitdropthatpacketcrackthistrack}. Piosenki można wysłuchać tutaj.

Faraday

Autor rozwiązania: Oskar

Dość nietypowe zadanie. Dostaliśmy numer telefonu kogoś nazywanego Faraday wraz z stroną internetową, która pozwala na znajdowanie urządzeń dzięki API. Wiemy również, iż nasz cel znajduje się w stanie Wiktoria w Australii, a to znacząco zawęża obszar poszukiwań w skali całej Ziemi J.

Wiktoria – na czerwono

Po wejściu na stronę widzimy dość ciekawą opcję – możliwość wysyłania zapytań do API telefonów. Oczywiście nie była to prawdziwa strona – działała tylko na spreparowany numer telefonu.

Przykładowe zapytanie wyglądało tak:

Z dokumentacji dowiedziałem się, iż wartość promienia może zostać ustawiona maksymalnie na 200.000, dlatego ustawiłem taką wartość. W pole phoneNumber wpisałem numer telefonu podany w zadaniu.

Zapytanie wyglądało tak:

Dostałem odpowiedź, ale nie mówiła zbyt wiele.

Postanowiłem, iż skupię się bardziej na numerze telefonu. Wpisałem go w Google i dowiedziałem się, iż najprawdopodobniej pochodzi z Sydney.

Uznałem, iż w takim wypadku wybiorę do badań punkt bliżej Sydney. Kliknąłem na losowy punkt w Wiktorii stosunkowo blisko Sydney.

Źródło: Google Maps

Przepisałem jego współrzędne geograficzne: -36.869844, 147.578239.

Bingo! Wiemy, iż punkt znajduje się gdzieś w promieniu 200000 (prawdopodobnie metrów) od mojego losowo wybranego punktu. Próbowałem więc dalej szukać dokładniejszej lokalizacji, zmniejszając promień do 100000.

  • Zakres szerokości geograficznych dla parametru „TRUE”: od -35 do -38
  • Zakres długości geograficznych dla parametru „TRUE”: od 145 do 148
  • Średnia szerokość: -36,5
  • Średnia długość: 146,5

Wpisałem więc ten punkt i stopniowo zmniejszałem promień. Najmniejsza wartość promienia dla tego punktu, która dawała pozytywny rezultat to 9000.

Zawężając poszukiwania do 9 kilometrów od tego punktu, próbowałem wpisywać różne miasta i wsie jako flagi.

Źródło: Google Maps

Źródło: Google Maps

Podświetlony został przybliżony zasięg poszukiwań. Po kilku próbach okazało się, iż szukane miasto to Milawa.

DUCTF{milawa}

Web

Grades_grades_grades

Autor rozwiązania: Cappybara

Zadanie składa się z linku do strony internetowej i archiwum grades_grades_grades.tar.gz.

Po wejściu na stronę naszym oczom ukazuje się dość prosta strona, na której możemy się zalogować i zarejestrować nowe konto. Po utworzeniu nowego konta nie pojawiły się żadne cenne informacje – jedynie oceny.

W takim razie – sprawdźmy, czy nie zostało utworzone ciasteczko (cookie).

Mamy ciasteczko o nazwie auth_token i wartości zaczynającej się od ey, która jest charakterystyczna dla tokenów JWT zapisanych dzięki base64. W takim razie pora sprawdzić, czy nasze przypuszczenia są trafne.

Faktycznie jest to token JWT, ale nie ma w nim co zmieniać. W takim razie pora wrócić do dołączonego archiwum.

Przeglądając plik auth.py można zauważyć jak tworzone jest ciasteczko. Co ważne, każdy token tworzony przez użytkownika po dekodowaniu otrzymuje wartość „is_teacher”:”False”.

Stwórzmy więc token JWT z dopisaną wartością „is_teacher”:”True”. Co ważne – każda z wartości tokenu musi być zakodowana oddzielnie. Aby obejść fakt, iż HS256 jest jedynym przyjmowanym algorytmem, Cappybara dopisał „alg”:”none”

Niestety mimo tego token nie jest prawidłowy.

Pora przejść do BurpSuite. Utwórzmy więc nowy token i zobaczmy go w Burpie.

Spróbujmy dopisać is_teacher=true.

Serwer zwrócił prawidłowy token!

Użyjmy go w przeglądarce. Na stronie pojawiła się nowa zakładka – Grading Tool. Wejdźmy w nią.

Bingo! Mamy flagę J.

Podsumowanie

DownUnder CTF był ciekawym doświadczeniem – pozwolił na naukę w praktyce wielu tematów, których ciężko nauczyć się w innych warunkach. Z całego serca polecam branie udziału w CTF-ach – często rozgrywane są w weekendy. Writeupy i listę nadchodzących CTF-ów można zobaczyć na CTFTime.

Idź do oryginalnego materiału