30-10-2018 / Od 0 do pentestera

Reflected File Download

W jednym z poprzednich materiałów demonstrowałem CSV Injection - czyli możliwość wykonania zewnętrznego kodu z poziomu aplikacji, która otwiera pliki CSV.

Zastosowanie takiego ataku ogranicza się zatem do kilku programów.

Czy można rozszerzyć potencjalny wektor ataku na większą ilość aplikacji?

Dzisiaj o Reflected File Download.

Ten typ podatności występuje zazwyczaj w endpointach JSONP.

Co to jest JSONP?

Załóżmy, że posiadamy API, które zwraca bieżący czas.

<?php
header('Content-Type: application/json');
header("Content-Disposition: attachment");
echo json_encode(array('czas' => time()));

Chcemy pobrać te dane przy pomocy JavaScript.

Jeżeli API znajduje się w obrębie bieżącej domeny wszystko jest w porządku.

<script  src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script>
$.ajax({
	url: "http://another_domain.example/od0dopentestera/api.php"
	}).done(function(data) {
		alert(data.czas);
	});
</script>

Problem pojawia się jednak jeżeli API to należy do zewnętrznego serwisu.

Standardowo przeglądarki nie pozwalają na wysłanie żądania ajax do innej domeny.

Chroni przed tym mechanizm Same Origin Policy.

Jednym z rozwiązań tego problemu jest JSONP.

Obejście korzysta z faktu iż o ile nie można wysłać żądania ajax do zewnętrznej domeny to można przy pomocy tagu script załadować zewnętrzny kod JavaScript.

Robi tak spora część serwisów internetowych - gdzie kody JavaScript różnych bibliotek hostowane są na serwerach zewnętrznych usługodawców tzw. CDN.

<script  src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script>
function test(dane) {
	alert(dane.czas);
}
</script>
<script src="http://another_domain.example/od0dopentestera/api.php?callback=test"></script>

Nie możemy jednak załadować pliku w formacie json - ponieważ nie zostanie on rozpoznany przez przeglądarkę jako prawidłowy kod JS.

Ale jeśli treść pliku json opakujemy w wywołanie funkcji - interpreter JavaScript zrozumie to jako instrukcje wykonania danej funkcji a json zostanie tam przekazany jako parametr.

Zobaczmy to praktyce.

API zwraca wynik opakowany w nazwę funkcji podaną do niego jako parametr callback.

Na naszej stronie zawieramy takie wywołanie API w tag script.

Dzięki temu dane z API zostaną przekazane do wybranej przez nas funkcji JavaScript.

Większość deweloperów nie waliduje nazwy funkcji - to sprawia że endpoint ten jest podatny na dzisiejszy atak.

W ataku CSV Injection podawaliśmy funkcję, zaczynając od znaku równości.

Tym razem wykorzystamy format bat - tam komendy można oddzielić od siebie wykorzystując pipe.

Jeżeli jako callback podamy nazwę komendy, następnie pipe a całość zapiszemy do pliki bat, Windows będzie myślał że ma do czynienia z programem wsadowym bat.

Wykona więc podaną komendę a następnie dalszą część pliku.

Jedyne co stoi nam na przeszkodzie to nazwa pliku.

Obecnie bowiem jest on pobierany jako json.

Na pomoc przychodzi atrybut download, który możemy przekazać do tagu href.

Dzięki temu plik zostanie pobrany jako .bat.

Teraz wystarczy że niczego nieświadomy użytkownik uruchomi taki plik.

Warto pamiętać, że skuteczność takiego ataku w głównej mierze zależy od domeny, z której pobierany jest plik.

Dla przykładu standardowy użytkownik bowiem z większą chęcią kliknie na plik pobrany ze strony banku - ponieważ jest to podmiot któremu ufa.

W tym przykładzie wykorzystałem pliki bat oraz system Windows.

Nic jednak nie stoi na przeszkodzie aby podobny atak wykonać na plikach .sh pod Linuxem1.

Jak zabezpieczyć się przed tym atakiem?

Ustawić nagłówek Content-Disposition ze zdefiniowaną nazwą pliku oraz pozwalać jedynie na zdefiniowane nazwy callbacków.

Content-Disposition: attachment; filename="plik.png"