前言
題目鏈接: http://natas25.natas.labs.overthewire.org
做這一題花了一些時間,也是由于自己知識點掌握不足,所以分享下解題程序,
題目分析
首先,登錄后看到以下界面,是一篇文章的內容,右上角,language的地方可以選擇語言,默認是英語,可以選擇德語,當選擇德語或英語后,可以看到URL請求會發送lang的引數,當我看到這里的時候先想到的是文章內容可能是讀取的網站的檔案內容,猜測通過目錄遍歷去直接查看/etc/natas_webpass/natas26的內容(此檔案存放了下一關的密碼),(這邊沒有嘗試,直接先查看了源代碼,當然此關沒這么簡單,嘗試結果也會是失敗的,)


點擊view sourcecode來解讀下源代碼,
可以看到一共有四個函式,分別是setLanguage、safeinclude、listFiles和logRequest,根據名稱含義及代碼大致猜測setlanguage是設定語言,safeinclude是檔案包含的安全設定,listfile是羅列檔案或查找檔案(此函式其實并未完全理解,但大致理解為用于查找lang引數傳入的檔案路徑),logrequest是用于寫入安全日志,
大致理了下邏輯關系,
<?php foreach(listFiles("language/") as $f) echo "<option>$f</option>"; ?>
1、頁面請求開始后,foreach函式會呼叫listfiles函式的回傳結果作為變數f并輸出,默認情況下就是我們一打開看到的英文文章,
<?php
session_start();
setLanguage();
echo "<h2>$__GREETING</h2>";
echo "<p align=\"justify\">$__MSG";
echo "<div align=\"right\"><h6>$__FOOTER</h6><div>";
?>
2、當頁面上選擇language后,呼叫setlanguage函式,之后就是幾個函式的相互呼叫,
function setLanguage(){
/* language setup */
if(array_key_exists("lang",$_REQUEST))
if(safeinclude("language/" . $_REQUEST["lang"] ))
return 1;
safeinclude("language/en");
}
3、Setlanguage函式將request中的lang引數丟給safeinclude函式,假如此時request中傳遞的lang引數為../../../../../etc/natas_webpass/natas25,經過拼接后傳遞給safeinclude函式的引數就變成了language/../../../../../etc/natas_webpass/natas25
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;
}
4、safeinclude函式將經過幾次判斷:
-
- 首先判斷檔案路徑中是否包含"../",若包含則通過str_replace函式將"../"全部替換為空,并通過logrequest函式記錄這次事件,這種過濾,如:將每個../替換為…/./,這種過濾是一次性的,不會對過濾的內再次校驗,…/./過濾后就變成了../,
- 然后判斷檔案路徑中是否包含了natas_webpass,若包含直接斷開連接,并記錄日志,這導致了直接訪問natas_webpass/natas26的方法不可行了,
- 最后的判斷則是包含檔案,并回傳內容了,
到此為止,我最開始的猜想證明錯誤了,這里我也卡了很久,畢竟剛開始學,知識匱乏(無奈,,,)
一開始我忽略了,logrequest函式記錄日志這一程序,因為沒看該函式內容前,一直以為日志記錄的只是固定的字串,但其實還有時間和requests請求中的user-agent欄位,卡了很久后,無奈Google了一番,確認了新思路,利用user-agent進行注入,將natas26檔案內容寫入日志后,再通過目錄遍歷查看日志檔案,
function logRequest($message){
$log="[". date("d.m.Y H::i:s",time()) ."]";#記錄時間
$log=$log . " " . $_SERVER['HTTP_USER_AGENT'];#通過user-agent去包含natas26檔案
$log=$log . " \"" . $message ."\"\n";
$fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a");#日志路徑,目錄遍歷時用,
fwrite($fd,$log);
fclose($fd);
}
logrequest函式中有兩個關鍵點:
$log=$log . " " . $_SERVER['HTTP_USER_AGENT'];
-
- 這條陳述句會將HTTP請求中的user-agent欄位的內容,拼接到日志資訊中,這里我采用了include函式去讀取natas26檔案內容,(這里并非只能用include,只要可以讀取檔案內容的方式應該都可以,)
$fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a");
-
- 日志存盤的路徑,以及日志檔案名的命名規則,
開始解題
我使用了burpsuite來抓包和改包,設定好代理后,抓到請求包,并發送給repeater,開始構造所需的請求包,
主要有兩處需要修改的地方:
-
- 構造lang引數去讀取日志檔案,
?lang=..././..././..././..././..././..././var/www/natas/natas25/logs/natas25_1hlck4sj7dasfhp0h05efhb9b1.log
?lang=..././logs/natas25_1hlck4sj7dasfhp0h05efhb9b1.log
這里,我列出了2種路勁,第一種路勁是回傳到根目錄,然后使用完整路徑訪問日志檔案,第二種路勁是猜測logs目錄和language目錄屬于同一級目錄,所以回傳至natas目錄,然后訪問logs目錄下的日志檔案,原理是一樣的,只是當不知道目錄之間的關系時,又知道完整路勁,就采用第一種方式,
-
- 構造user-agent引數去包含natas_webpass/natas26檔案內容,
User-Agent: <?php include('/etc/natas_webpass/natas26') ?>
如圖,其中PHPID也是關鍵,因為日志檔案的命名是用到了PHPID,
構造好資料包后,發送請求,獲得下一關的密碼,(圖片中密碼抹掉了幾位,建議動手嘗試)
(可以看到第一次請求由于輸錯了路勁,導致include失敗的資訊也是寫入了日志中,)
這里可以看到safeinclude函式,當"../"被替換后,會在日志中記錄"Directory traversal attempt! fixing request."
當直接嘗試訪問/etc/natas_webpass/natas26時,會斷開連接,沒有回傳內容,并會在日志中記錄"Illegal file access detected! Aborting!"
以上就是整個natas25的解題程序了,當時主要是在user-agent的注入上花了點時間學習,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/53223.html
標籤:其他
上一篇:byteCTF 2019
