php / php/php-src

Heap use-after-free in zend_object_is_lazy

オープン
#21,776 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

Bug Status: Needs Triage
主要言語
C
スター
40.4k
フォーク
8.1k
平均マージ
2日 13時間
マージ済み PR(30日)
96

説明

Description

The following code:

<?php
class C {
    function __isset($x) {
        $GLOBALS['o'] = 0;
        return true;
    }
}
$o = new C;
$o->a ?? 0;

Resulted in this output:

==14==ERROR: AddressSanitizer: heap-use-after-free on address 0x7bf52c2f022c at pc 0x556c44a42d3f bp 0x7ffc0bb4a590 sp 0x7ffc0bb4a588
READ of size 4 at 0x7bf52c2f022c thread T0
SCARINESS: 45 (4-byte-read-heap-use-after-free)
    #0 0x556c44a42d3e in zend_object_is_lazy /src/php-src/Zend/zend_lazy_objects.h:82:10
    #1 0x556c44a42d3e in zend_lazy_object_must_init /src/php-src/Zend/zend_lazy_objects.h:99:9
    #2 0x556c44a42d3e in zend_std_read_property /src/php-src/Zend/zend_object_handlers.c:984:6
    #3 0x556c446a3836 in ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER /src/php-src/Zend/zend_vm_execute.h:42445:12
    #4 0x556c44ace5fb in fuzzer_execute_ex /src/php-src/sapi/fuzzer/fuzzer-execute-common.h:65:12
    #5 0x556c445ca23d in zend_execute /src/php-src/Zend/zend_vm_execute.h:115542:2
    #6 0x556c44acf65f in fuzzer_do_request_from_buffer /src/php-src/sapi/fuzzer/fuzzer-sapi.c:293:5
    #7 0x556c44ace3e7 in LLVMFuzzerTestOneInput /src/php-src/sapi/fuzzer/fuzzer-execute.c:25:2
    #8 0x556c436269dd in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
    #9 0x556c43611752 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:329:6
    #10 0x556c43617620 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:865:9
    #11 0x556c43643152 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #12 0x7f952ce2c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d)
    #13 0x556c4360a83d in _start (/out/php-fuzz-execute+0xa0a83d)

DEDUP_TOKEN: zend_object_is_lazy--zend_lazy_object_must_init--zend_std_read_property
0x7bf52c2f022c is located 12 bytes inside of 56-byte region [0x7bf52c2f0220,0x7bf52c2f0258)
freed by thread T0 here:
    #0 0x556c43745096 in free /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:51:3
    #1 0x556c44a55fd4 in zend_objects_store_del /src/php-src/Zend/zend_objects_API.c:197:3
    #2 0x556c44a41c0c in zend_std_read_property /src/php-src/Zend/zend_object_handlers.c:940:4
    #3 0x556c446a3836 in ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER /src/php-src/Zend/zend_vm_execute.h:42445:12
    #4 0x556c44ace5fb in fuzzer_execute_ex /src/php-src/sapi/fuzzer/fuzzer-execute-common.h:65:12
    #5 0x556c445ca23d in zend_execute /src/php-src/Zend/zend_vm_execute.h:115542:2
    #6 0x556c44acf65f in fuzzer_do_request_from_buffer /src/php-src/sapi/fuzzer/fuzzer-sapi.c:293:5
    #7 0x556c44ace3e7 in LLVMFuzzerTestOneInput /src/php-src/sapi/fuzzer/fuzzer-execute.c:25:2
    #8 0x556c436269dd in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
    #9 0x556c43611752 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:329:6
    #10 0x556c43617620 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:865:9
    #11 0x556c43643152 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #12 0x7f952ce2c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d)

DEDUP_TOKEN: __interceptor_free--zend_objects_store_del--zend_std_read_property
previously allocated by thread T0 here:
    #0 0x556c43745334 in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:67:3
    #1 0x556c44456a01 in tracked_malloc /src/php-src/Zend/zend_alloc.c:3016:14
    #2 0x556c44a581dd in zend_objects_new /src/php-src/Zend/zend_objects.c:190:24
    #3 0x556c444767ad in _object_and_properties_init /src/php-src/Zend/zend_API.c:1819:22
    #4 0x556c4466c588 in ZEND_NEW_SPEC_CONST_UNUSED_HANDLER /src/php-src/Zend/zend_vm_execute.h:11366:6
    #5 0x556c44ace5fb in fuzzer_execute_ex /src/php-src/sapi/fuzzer/fuzzer-execute-common.h:65:12
    #6 0x556c445ca23d in zend_execute /src/php-src/Zend/zend_vm_execute.h:115542:2
    #7 0x556c44acf65f in fuzzer_do_request_from_buffer /src/php-src/sapi/fuzzer/fuzzer-sapi.c:293:5
    #8 0x556c44ace3e7 in LLVMFuzzerTestOneInput /src/php-src/sapi/fuzzer/fuzzer-execute.c:25:2
    #9 0x556c436269dd in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
    #10 0x556c43611752 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:329:6
    #11 0x556c43617620 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:865:9
    #12 0x556c43643152 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #13 0x7f952ce2c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d)

DEDUP_TOKEN: __interceptor_malloc--tracked_malloc--zend_objects_new
SUMMARY: AddressSanitizer: heap-use-after-free /src/php-src/Zend/zend_lazy_objects.h:82:10 in zend_object_is_lazy
Shadow bytes around the buggy address:
  0x7bf52c2eff80: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x7bf52c2f0000: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x7bf52c2f0080: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x7bf52c2f0100: 00 00 00 00 00 00 00 fa fa fa fa fa fd fd fd fd
  0x7bf52c2f0180: fd fd fd fd fa fa fa fa 00 00 00 00 00 00 00 fa
=>0x7bf52c2f0200: fa fa fa fa fd[fd]fd fd fd fd fd fa fa fa fa fa
  0x7bf52c2f0280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7bf52c2f0300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7bf52c2f0380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7bf52c2f0400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7bf52c2f0480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==14==ABORTING
PHP Version
PHP 8.5
Operating System

No response

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず、AddressSanitizer ビルドで PHP スニペットを再現し、次に Zend/zend_lazy_objects.h と Zend/zend_object_handlers.c の zend_object_is_lazy、zend_lazy_object_must_init、zend_std_read_property 周辺を調べてください。示されている __isset コールバックを通じてオブジェクトのライフタイムを追跡し、同じ再現手順で修正によって heap-use-after-free が解消されることを確認してください。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
c, php
領域
backend, security
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
42/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。