【第十九天 - PHP反序列化(1)】

Q1. 什麽是 php 反序列化?

  • 为了让程序中的物件可以在保存到 persistent database,或者能够传输到其他程序,程序可以将物件的属性与状态利用特定的规则编码,转为资料序列,这便称为序列化 (Serialize) ,是许多程序语言都具备的功能,而将被序列化的物件还原的过程就称为反序列化
  • 许多语言都有序列化的函数,例如PHP、Python、Java 等。

Q2. php 反序列化原理

  • PHP 序列化的基本表达式有下列几种 (序列中分号、冒号前後都不能有空格,此处为了易读性才加入空格)
    • boolean
      • <boolean(b)型态> : <值(0或1)>
      • e.g. b:0b:1
    • int
      • <interger(i)型态> : <值 -2147483648~2147483647>
      • e.g. i:666
    • string
      • <string(s)型态> : <名称长度> : <名称>
      • e.g. s:4:"Baba"
    • array
      • <array(a)型态> : <array 长度> : { key ; value ; key ; value .....}
      • e.g. a:2:{i:1;s:3:"iam",i:2;s:4:"Baba"}
      • e.g. ['A' => 123, 2 => 'aaa'] 会变为 a:2:{s:1:"A";i:123;i:2;s:3:"aaa";}
      • key 可以使用 int、string,value 则不限
    • object
      • Object (o) 型态 : <object 名称长度> : <properties 数量> : {key; value; key; value; ...},其中:

        • property 若为 public:则 Key 名称即等同 property 名称
        • property 若为 protected:则 Key 名称为%00*%00<property名称>
        • property 若为 private:则 Key 名称需在 property 名称前面加上 %00<class名称>%00<property名称>
      • Object 的 method 不会被序列化。

      • e.g.

        class Babaobject{
        	public $iam;
        	public $Baba = 666;
        	protected $not = "QAQ";
          private $you = True;
        }
        
        • 上述程序,序列化後是:
        O:10:"Babaobject":4:{s:3:"iam";N;s:4:"Baba";i:666;s:6:"%00*%00not";s:3:"QAQ";s:15:"%00Babaobject%00you";b:1;}
        
        • protected $not = "QAQ"; 序列化後,直接印出会看到 s:6:"*not";s:3:"QAQ" ;而 private $you = True; 序列化後,直接印出会看到 s:15:"Babaobjectyou";b:1; 。之所以会看不到 %00 ,是因为在 ascii 中 %00 为空字元,因此无法显示,但在计算长度时仍可看出其确实存在,因而会比显示的字元多 2 个字。(因此会看到 *not 的长度是 6)
    • NULL
      • <Null (n) 型态>
      • e.g. N
      • 当变数无赋值时,则会放N

Q3. 反序列化类型?

  • 常见型

    • 在 PHP 中,有许多 magic method 会在特定条件下自动执行,例如:

      • __wakeup :反序列化时触发
      • __sleep :序列化时触发
      • __destruct :物件删除时触发

      参考资料: https://www.php.net/manual/en/language.oop5.magic.php

    • 举例来说,如下的程序码收到 网址?data=O:4:"Flag":0:{} 时,会反序列化出 Flag 物件,并印出 flag。

      <?php
        require('secret.php');
        class Flag {
          function __wakeup() {
            global $flag;
            echo $flag;
          }
        }
        unserialize($_GET['data']);
      

      https://ithelp.ithome.com.tw/upload/images/20211003/201405922MymnlIoOg.png

    • 有些时候我们可以利用窜改资料来达成目的,例如下方的例子,可以看出正常情况下 Flag 物件中的属性 u 会是一个 User 实例,但我们反序列化时可以改成 Admin ,像是这样 O:4:"Flag":1:{s:1:"u";O:5:"Admin":0:{}} ,如此便能拿到 flag。

      <?php
      require('secret.php');
      class Flag {
          function __construct() {
              $this->u = new User();
          }
          function __destruct() {
              $this->u->flag();
          }
      }
      
      class User {
      	function flag() {
      		echo "No flag for ya~";
      	}
      }
      
      class Admin {
      	function flag() {
      		global $flag;		
      		echo "Here you go: {$flag}";
      	}
      }
      
      unserialize($_GET['data']);
      
  • 原生型

  • phar 型


<<:  [DAY 20] _前20天的结语(落摔判断流程)

>>:  [Day 20] Sass - Using @extend

Ubuntu巡航记(2) -- 在 Ubuntu 作业系统内安装 TensorFlow

前言 前一篇搞定 Ubuntu 作业系统的安装,接下来我们继续安装『机器学习』的相关软件及工具,包括...

R语言-正规化回归预测-ridge & lasso (ridge & lasso regression in r)

废话不多说,直接附上code 影片含有程序码详细解说,若有误再烦请告知,谢谢 library(glm...

Day16 - [丰收款] 取得PayToken的最後一哩路很慢长

昨天抱病撰文,终於在本机端将单笔资料透过ORM的方法,成功将新增的订单资料更新到Heroku Pos...

A First Set of Refactorings

本篇同步发文於个人网站: A First Set of Refactorings This arti...

# Day 10 Cache and TLB Flushing Under Linux (二)

那麽接续昨天的阅读,我们继续看下去~ 文件 文件原文:Cache and TLB Flushing ...