web反序列化
serialize* - *unserialize
序列化的基本操作
首先序列化的意义在于利于储存和传递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
| <?php
class Kengwang { public $name = "kengwang"; public $age = 18; public $sex = true; public $route = LearningRoute::Web; public $tag = array("dino", "cdut", "chengdu"); public $girlFriend = null; private $pants = "red"; }
enum LearningRoute { case Web; case Pwn; case Misc; }
$kw = new Kengwang(); print_r(serialize($kw));
O:8:"Kengwang":7:{ s:4:"name";s:8:"kengwang"; s:3:"age";i:18; s:3:"sex";b:1; s:5:"route";E:17:"LearningRoute:Web"; s:3:"tag";a:3:{ i:0;s:4:"dino"; i:1;s:4:"cdut"; i:2;s:7:"chengdu"; } s:10:"girlFriend";N; s:15:" Kengwang pants";s:3:"red"; }
|
魔术方法
魔术方法
- __wakeup()方法
在执行反序列化的时候会检查是否存在此方法,若有则先执行此方法
- __sleep()方法
在执行序列化的时候会检查是否存在此方法,若有则限制性次方
- __construct()方法
PHP 允许开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法
执行顺序
序列化时会先调用 sleep 再调用 destruct, 故而完整的调用顺序为: sleep -> (变量存在) -> destruct
反序列化时如果有 __wakeup 则会调用 __wakeUp 而不是 __construct, 故而逻辑为 __wakeUp/__construct -> (变量存在)
绕过
__wakeup()
当反序列化时, 给出的字段个数的数字小于提供的字段个数, 将不会执行 __wakeup
不完整类绕过序列化检测
-2025WHUCTF新生赛
当我们尝试反序列化到一个不存在的类是, PHP 会使用 __PHP_Incomplete_Class_Name 这个追加的字段来进行存储
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
| class Cat { public $name = "咪酱"; } $cat = new Cat(); $str = serialize($cat);
unset($GLOBALS['Cat']);
$obj = unserialize($str);
echo get_class($obj);
print_r((array)$obj);
|
简单来讲就是下面四种情况:
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| <?php
?>
|
原生类
php本身存在的类,有些类会存在可调用的方法例如:Error、Exception等
参考网站博客: