note-反序列化-00

java反序列化notice

现在理解的反序列大概就是传入一串字符,经java的处理变成能执行的语句,实现rec

序列化指的是将对象或数据结构转换为可存储或传输的格式的过程,实现的方法是writeObject();反序列化则反之,实现的方法是readObject(),可以简单地理解为将文件压缩和解压缩的过程。

与PHP中反序列互相触发魔法函数导致的漏洞成因不同,java反序列化漏洞的成因主要是由于java序列化和反序列化机制的设计特点所致,简单地讲,只要反序列化代码中含有危险的命令代码,且该代码的参数是可控的,那它就存在该漏洞。

漏洞原理在我今天这里不是重要的,我主要想记录的是该漏洞的利用方式。

通常在解题中如果你看到一段字符串以rO0AB开头,那它是java序列化后base64编码的数据;如果一段字符串以aced开头,那它是java序列化后十六进制的数据,碰到这两种情况都基本可以认定该题考点为java反序列化漏洞,如果有直接接受该字符串的输入点,就可以尝试用链子直接打。

原文链接:https://blog.csdn.net/m0_64893612/article/details/136378608

[SWPUCTF 2021 新生赛]no_wakeup 学习笔记:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php

header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");

class HaHaHa{


public $admin;
public $passwd;

public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}

public function __wakeup(){
$this->passwd = sha1($this->passwd);
}

public function __destruct(){
if($this->admin === "admin" && $this->passwd === "wllm"){
include("flag.php");
echo $flag;
}else{
echo $this->passwd;
echo "No wake up";
}
}
}

$Letmeseesee = $_GET['p'];
unserialize($Letmeseesee);
```

大概是get一个p参数,传给$Letmeseesee然后反序列化,可能p经过反序列化后会变成一个名为this的变量,里面包含有{admin,passwd},其中passwd经过sha1计算再赋值给原来的passwd,当this里的admin===admin,经过sha1计算的passwd===wllm时就会输出flag

KIMI:

你的审计思路基本正确,但有一些细节需要澄清:
反序列化后的对象状态:
当用户传入的p参数被反序列化后,如果它是一个HaHaHa类的对象,那么__wakeup()方法会被调用,此时$passwd的值会被更新为sha1($passwd)。
因此,$passwd的值在反序列化后会被哈希处理,而不是直接使用传入的值。
条件判断:
在析构方法中,判断条件是$admin === “admin”且$passwd === “wllm”。
因此,攻击者需要构造一个对象,使得反序列化后$admin为”admin”,并且$passwd在经过sha1()哈希后等于”wllm”。

然而怎么可能会有在经过sha1处理后的到wllm的值。
所以要绕过这个__wakeup()

__wakeup() 的作用
反序列化时的初始化:
当一个对象被序列化后,其状态会被保存为字符串。在反序列化时,对象的状态会被恢复,但某些资源(如数据库连接)可能无法直接序列化,因此需要在反序列化后重新初始化这些资源。
__wakeup() 方法正是为此设计的,它允许你在对象恢复后执行一些必要的操作。
数据处理:
在反序列化后,你可能需要对对象的某些属性进行处理。例如,对敏感数据进行解密,或者对某些属性进行格式转换。

所以大概就是当触发反序列化时__wakeup就会调用这个sha1.

网上正确的payload:

1
?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

学习notice:

1
2
3
4
5
O:表示这是一个对象(Object)。  
O:6:"HaHaHa":表示这是一个类名为HaHaHa的对象,类名长度为6
3:表示对象有3个属性。
s:5:"admin";s:5:"admin";:第一个属性名为admin,值为admin。
s:6:"passwd";s:4:"wllm";:第二个属性名为passwd,值为wllm。

这个payload能够绕过__wakeup()方法的原因可能与PHP反序列化过程中的一些特性或漏洞有关,比如属性个数不匹配(CVE-2016-7124)。
在这个漏洞中,如果序列化字符串中指定的属性个数比实际类中定义的属性个数多,PHP在反序列化时可能会绕过__wakeup()方法的执行。

绕过原理
由于修改了属性个数,PHP在反序列化时会跳过__wakeup()方法的执行。因此,passwd属性的值不会被SHA-1哈希处理,而是直接保留为wllm。当对象被销毁时,__destruct()方法会检查admin和passwd的值,发现它们满足条件,从而包含flag.php并输出flag。
通过这种方式,攻击者成功绕过了__wakeup()方法,直接设置了所需的属性值,触发了敏感文件的包含。

我的理解就是:
构造一个被java序列化后的数值来满足条件,并且使用定义与实际的的属性个数不同来绕过wakeup(),因为wakeup根本就是不想让你过的

O:6:”HaHaHa”:2:{s:5:”admin”;s:5:”admin”;s:6:”passwd”;s:10:”wllm”;}
其中s是字符串长度,2代表里面有两个元素:admin=admin,passwd=wllm。
吧2改成其它超过实际元素的值即可绕过wakeup()
就是要大过2,不知道为什么不能小于2


note-反序列化-00
https://aidemofashi.github.io/2025/03/18/note-反序列化-00/
作者
aidemofashi
发布于
2025年3月18日
许可协议