Jump to content
  • Hello visitors, welcome to the Hacker World Forum!

    Red Team 1949  (formerly CHT Attack and Defense Team) In this rapidly changing Internet era, we maintain our original intention and create the best community to jointly exchange network technologies. You can obtain hacker attack and defense skills and knowledge in the forum, or you can join our Telegram communication group to discuss and communicate in real time. All kinds of advertisements are prohibited in the forum. Please register as a registered user to check our usage and privacy policy. Thank you for your cooperation.

    TheHackerWorld Official

代码审计-PHP反序列化漏洞

 Share


KaiWn

Recommended Posts

什么是序列化

序列化可以实现将对象压缩并格式化,方便数据的传输和存储。
为什么要序列化?
PHP 文件在执行结束时会把对象销毁,如果下次要引用这个对象的话就很麻烦,所以就有了对象序列化,实现对象的长久存储,对象序列化之后存储起来,下次调用时直接调出来反序列化之后就可以使用了。
学习序列化要了解的基本内容。
类(Class): 类的定义包含了数据的形式以及对数据的操作。
对象:对象是类的实例。
方法:类中定义的函数。

<?php
//创建一个类 Test
 class Test
 { //定义 3 个属性,最后序列化后看一下这 3 个属性序列化后的结果。
 private $a = "private";
 public $b = "public";
 protected $c = "protected";
 } 
//创建一个对象,对象是类的实例。
 $test = new Test();
//序列化 test 这个对象
 $data = serialize($test);
//打印序列化后的对象
 echo $data;
?>

展示结果(前提条件,php只有再apache下可以运行,之前我创建了txt,发现无法运行,避免踩坑)
序列化之后的结果,每个字符都具有具体含义
2955483-20220819171126667-1214939944.png
O:4:"Test":3: {s:7:"Testa";s:7:"private"; s:1:"b";s:6:"public"; s:4:"*c";s:9:"protected";}

O Object 对象
4 名字长度为 4 Test(对象名称)
3 表示对象中存在3个属性

s:7:"Testa"; 变量名字
s:7:"private"; 
  • s string 字符串
  • 7 变量名长度为7 private私有的,会在Testa前后添加\00 ,即\X00Test\X00a (因此长度为7)
  • s string 字符串
  • 7 变量的值长度为7 private 值
s:1:"b";
s:6:"public"
  • s string
  • 1 名字长度 1
  • b 变量名字
s:4:"*c";
s:9:"protected";
  • s string
  • 4 名字长度 4
  • *c 变量名字 \x00*\x00c

序列化的过程:
通过classTest创建一个对象,然后把这个对象进行序列化,打印出来

反序列化:

PHP 反序列化漏洞又叫做 PHP 对象注入漏洞,成因在于代码中的 unserialize() 接收的参数可控,从上面的例子看,这个函数的参数是一个序列化的对象,而序列化的对象只含有对象的属性,那我们就要利用对对象属性的篡改实现最终的攻击
代码如下:
(注意:Testa和*c的部分要留出空格来,与前面的的长度相符合)
输出要用var_dump而不是echo

<?php

$data = 'O:4:"test":3:{s:7:" Test a";s:7:"private";s:1:"b";s:6:"public";s:4:" * c";s:9:"protected";}';
$free = unserialize($data);
var_dump($free);
?>

结果如下:

object(__PHP_Incomplete_Class)#1 (4) {
  ["__PHP_Incomplete_Class_Name"]=>
  string(4) "test"
  [" Test a"]=>   //名字
  string(7) "private"  //值
  ["b"]=>  //名字
  string(6) "public"   //值
  [" * c"]=> //名字
  string(9) "protected"   //值
}

反序列化造成漏洞的原因:

  • 反序列化一般都是用户传递过来恶意代码,通过反序列化执行
  • 反序列化的字符串用户可以控制
  • 内容长度改变以后,前面的长度也需要跟着改变

序列化-魔术方法

魔术方法介绍:
方法:类中定义的函数。
上面我们演示了如何进行序列化和反序列化,但是我们仅使用了属性,也就是变量,变量我们可以当
做数据来看待,而编程就是对数据进行一些列的操作和处理,操作和处理数据的过程我们一般通过函数来
定义,函数在面向对象编程中我们一般称之为方法,所以后续如果老师说到方法就等于说的是函数功能。
特殊的方法-魔术方法。
PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法,这些都是 PHP 内置的方法。
__construct 当一个对象创建时被调用,
__destruct 当一个对象销毁时被调用,
__wakeup() 使用 unserialize 时触发
__sleep() 使用 serialize 时触发
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据
__set() 用于将数据写入不可访问的属性
__isset() 在不可访问的属性上调用 isset()或 empty()触发
__unset() 在不可访问的属性上使用 unset()时触发
__toString() 把类当作字符串使用时触发,返回值需要为字符串
__invoke() 当脚本尝试将对象作为函数调用时触发

Link to post
Link to comment
Share on other sites

 Share

discussion group

discussion group

    You don't have permission to chat.
    • Recently Browsing   0 members

      • No registered users viewing this page.
    ×
    ×
    • Create New...