Skip to content

Heap UAF at ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_HANDLER #10169

Closed

Description

@Changochen

Description

The following code:

<?php
class A
{
    public string $prop = "";
}
class B
{
    public function __toString()
    {
        global $a;
        $a = $a->p = "";
        return "";
    }
}
$a = new A();
$a->prop = new B();
?>

Resulted in this output:

./php-fuzz-execute poc2.php.orig
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 18257342
INFO: Loaded 1 modules   (147832 inline 8-bit counters): 147832 [0x1d60c20, 0x1d84d98),
INFO: Loaded 1 PC tables (147832 PCs): 147832 [0x1d84d98,0x1fc6518),
./php-fuzz-execute: Running 1 inputs 1 time(s) each.
Running: poc2.php.orig
=================================================================
==2886385==ERROR: AddressSanitizer: heap-use-after-free on address 0x6060000121d1 at pc 0x0000012d7b10 bp 0x7fffffffd770 sp 0x7fffffffd768
READ of size 1 at 0x6060000121d1 thread T0

Git commit: ff42cb0

PHP Version

PHP 8.3.0-dev

Operating System

No response

Activity

  1. ndossche commented on Dec 26, 2022

    @ndossche
    Member

    What PHP configuration did you use to trigger this bug?
    I'm trying to reproduce this issue using ./sapi/cli/php with the binary compiled with ASAN. I tried both with opcache on and off.

  2. Changochen commented on Dec 27, 2022

    @Changochen
    Author

    Hi, thanks for the investigation.

    My config is:

    ./configure \
        --disable-all \
        --enable-debug-assertions \
        --enable-option-checking=fatal \
        --enable-fuzzer \
        --enable-exif \
        --enable-opcache \
        --without-pcre-jit \
        --disable-phpdbg \
        --disable-cgi \
        --with-pic --enable-address-sanitizer
    
  3. ndossche commented on Dec 27, 2022

    @ndossche
    Member

    Thanks for the additional info.
    I tried reproducing this in a variety of ways, but I still cannot. I tried it on 8.1.x, 8.2.x and the commit you referenced, but none worked.
    Is the php.ini file the default one, and does ./php-fuzz-execute do anything special (or where can I obtain it?)

  4. Changochen commented on Dec 28, 2022

    @Changochen
    Author

    Sorry for the confusion. With --enable-fuzzer, you will find ./php-fuzz-execute in sapi/fuzzer.

    I checked the above poc and found that it didn't crash the php binary. So I modified it a bit and got one that crashed php

    <?
    class d
    {
        public string $b;
    }
    class c
    {
        function __toString()
        {
            global $a;
            $a     = new d;
            $a->dd = "";
            return "";
        }
    }
    $a    = new d;
    $a->b = new c;

    This will trigger an invalid pointer deref in php and heap UAF write at php-fuzz-execute.

  5. ndossche commented on Dec 28, 2022

    @ndossche
    Member

    I can reproduce it as well now. Thanks.
    It seems that in zend_std_write_property, the conversion during zend_verify_property_type in the write_std_property: label path causes zobj to still refer to the old object instance instead of the new one.

  6. added a commit that references this issue on Feb 2, 2023
    5b21c16
  7. added a commit that references this issue on Jul 8, 2026
    47ed190
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions