用解码的base64字符串替换受保护的成员

时间:2014-10-02 07:55:53

标签: php base64

假设我有一个这样的课程

class ClassA {
   public $publicMember;
   private $privateMember;
   protected $protected;
}

我将对象ClassA编码为:

$objectA = new ClassA();
$stringA = base64_encode(serialize($objectA));

我想替换所有受保护的成员,但我不知道如何。我试过这样的事:

$newString = str_replace('�*�', '', base64_decode($stringA));

对不起,这个问题很简单,但我真的不知道如何处理这个问题。谢谢!

2 个答案:

答案 0 :(得分:1)

属性名称前面有长度。

string(92) "O:6:"ClassA":3:{s:12:"publicMember";N;s:21:"\000ClassA\000privateMember";N;s:12:"\000*\000protected";N;}"
| property name length        ^                     ^                                    ^
| we will try to capture this part                                                      ^         ^    

如果要将受保护的内容“转换”为公共内容,您可以减少此长度。例如。

class ClassA
    {

    public $publicMember;
    private $privateMember;
    protected $protected;

    }

$objectA = new ClassA();
$stringA = serialize($objectA);
$converted = preg_replace_callback('@:(\d+):"\x00\*\x00@', function($match)
//                                     ^ catch the number
//                                           ^     ^    null symbols        
    {
    $property_name_length = $match[1];
    return ':' . ($property_name_length - 3) . ':"'; // reduce catched number and do not return \x00*\x00
    }, $stringA);
var_dump(unserialize($converted));

可生产

class ClassA#2 (4) {
  public $publicMember =>
  NULL
  private $privateMember =>
  NULL
  protected $protected =>
  NULL
  public $protected =>
  NULL
}

P.S。但是,当您开始将序列化的数据存储为成员值时,此代码将失败。

答案 1 :(得分:0)

让我们尝试另一种方式:

  1. 将序列化类转换为stdClass
  2. 解序列化
  3. 添加公共保护属性
  4. 序列化
  5. 将序列化的stdClass转换为原始的
  6. -

    class ClassA
        {
    
        public $publicMember;
        private $privateMember;
        protected $protected;
    
        }
    
    $objectA = new ClassA();
    $stringA = serialize($objectA);
    
    // 1. convert serialzed class to stdClass
    $stringA = preg_replace('/' . strlen('ClassA') . '/', strlen('stdClass'), $stringA, 1);
    $stringA = preg_replace('/ClassA/', 'stdClass', $stringA, 1);
    
    // 2. unserialize
    $object = unserialize($stringA);
    
    // 3. add public protected properties
    while (list($key, $value) = each($object)) // hack with each
        {
        if (strpos($key, "\x00*\x00") === 0)
            {
            $key = str_replace("\x00*\x00", '', $key);
            $object->$key = $value;
            }
        }
    
    // 4. serialize
    $stringB = serialize($object);
    
    // 5. convert serialized stdClass to original
    $stringB = preg_replace('/' . strlen('stdClass') . '/', strlen('ClassA'), $stringB, 1);
    $stringB = preg_replace('/stdClass/', 'ClassA', $stringB, 1);
    
    var_dump(unserialize($stringB));
    

    可生产

    class ClassA#3 (4) {
      public $publicMember =>
      NULL
      private $privateMember =>
      NULL
      protected $protected =>
      NULL
      public $protected =>
      NULL
    }
    

    P.S。它比第一个更安全,但......:)