Bug #69971 [Opn]: Use-after-free in sqlite3 when destroying statement object

From: Date: Mon, 15 Oct 2018 22:36:25 +0000
Subject: Bug #69971 [Opn]: Use-after-free in sqlite3 when destroying statement object
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-217583@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69971&edit=1

 ID:                 69971
 Updated by:         cmb@php.net
 Reported by:        s dot paraschoudis at gmail dot com
 Summary:            Use-after-free in sqlite3 when destroying statement
                     object
 Status:             Open
 Type:               Bug
-Package:            Reproducible crash
+Package:            SQLite related
 Operating System:   Ubuntu 14.04.1 LTS (32 bit)
 PHP Version:        5.6.10
 Block user comment: N
 Private report:     Y

 New Comment:

On a quick glance this looks like a duplicate of bug #53626.
Therefore I'm changing the package to “SQLite related” to better
track the issue.


Previous Comments:
------------------------------------------------------------------------
[2015-07-05 04:25:17] stas@php.net

Looks like this happens because php_sqlite3_db_object is destroyed before php_sqlite3_stmt by
shutdown handler, but stmt object tries to access intern->db_obj->free_list, which is in
memory already freed when destroying db_object. I'd advise SQL maintainer to take a look,
though it doesn't look like a security issue.

------------------------------------------------------------------------
[2015-06-30 15:17:30] s dot paraschoudis at gmail dot com

Description:
------------
PoC
==============
<?php
$conn = new sqlite3(':memory:');
$conn->query('CREATE TABLE users (id INTEGER NOT NULL, PRIMARY KEY(id))');
$stmt = $conn->prepare('insert into users (id) values (:id)') +
$stmt->execute();
?>

Running the following PoC we get:

user@ubuntuvm:~/Desktop$ USE_ZEND_ALLOC=0 ~/Desktop/php-5.6.10/sapi/cli/php
zend_llist_del_element_uaf.php

Notice: Undefined variable: stmt in /home/user/Desktop/zend_llist_del_element_uaf.php on line 5
PHP Fatal error:  Call to a member function execute() on null in
/home/user/Desktop/zend_llist_del_element_uaf.php on line 5
=================================================================
==3455== ERROR: AddressSanitizer: heap-use-after-free on address 0xb521d0e4 at pc 0x8aac792 bp
0xbfe425d8 sp 0xbfe425cc
READ of size 4 at 0xb521d0e4 thread T0
    #0 0x8aac791 in zend_llist_del_element zend_llist.c:93
    #1 0x821d4e5 in php_sqlite3_stmt_object_free_storage sqlite3.c:2138
    #2 0x8b88c26 in zend_objects_store_free_object_storage zend_objects_API.c:97
    #3 0x8a9e392 in shutdown_executor zend_execute_API.c:290
    #4 0x8adbb54 in zend_deactivate zend.c:960
    #5 0x894a998 in php_request_shutdown main.c:1883
    #6 0x8d15e80 in do_cli php_cli.c:1177
    #7 0x8d172c0 in main php_cli.c:1378
    #8 0xb5dd5a82 in __libc_start_main libc-start.c:287
    #9 0x80628b0 in _start ??:?
0xb521d0e4 is located 36 bytes inside of 64-byte region [0xb521d0c0,0xb521d100)
freed by thread T0 here:
    #0 0xb617b774 in __interceptor_free ??:?
    #1 0x8a2de51 in _efree zend_alloc.c:2437
    #2 0x821d306 in php_sqlite3_object_free_storage sqlite3.c:2119
    #3 0x8b88c26 in zend_objects_store_free_object_storage zend_objects_API.c:97
    #4 0x8a9e392 in shutdown_executor zend_execute_API.c:290
    #5 0x8adbb54 in zend_deactivate zend.c:960
    #6 0x894a998 in php_request_shutdown main.c:1883
    #7 0x8d15e80 in do_cli php_cli.c:1177
    #8 0x8d172c0 in main php_cli.c:1378
    #9 0xb5dd5a82 in __libc_start_main libc-start.c:287
previously allocated by thread T0 here:
    #0 0xb617b854 in malloc ??:?
    #1 0x8a2dd20 in _emalloc zend_alloc.c:2427
    #2 0x821d8ce in php_sqlite3_object_new sqlite3.c:2183
    #3 0x8ae97e7 in _object_and_properties_init zend_API.c:1199
    #4 0x8ae984a in _object_init_ex zend_API.c:1207
    #5 0x8ba4383 in ZEND_NEW_SPEC_HANDLER zend_vm_execute.h:945
    #6 0x8b9d3d9 in execute_ex zend_vm_execute.h:363
    #7 0x8b9d4e4 in zend_execute zend_vm_execute.h:388
    #8 0x8ade628 in zend_execute_scripts zend.c:1341
    #9 0x894d95b in php_execute_script main.c:2597
    #10 0x8d14b83 in do_cli php_cli.c:994
    #11 0x8d172c0 in main php_cli.c:1378
    #12 0xb5dd5a82 in __libc_start_main libc-start.c:287
==3455== ABORTING

Running it under gdb:

gdb-peda$ r zend_llist_del_element_uaf.php 
Starting program: /home/user/Desktop/php5610/sapi/cli/php zend_llist_del_element_uaf.php
PHP Notice:  Undefined variable: stmt in /home/user/Desktop/zend_llist_del_element_uaf.php on line 5

Notice: Undefined variable: stmt in /home/user/Desktop/zend_llist_del_element_uaf.php on line 5
PHP Fatal error:  Call to a member function execute() on null in
/home/user/Desktop/zend_llist_del_element_uaf.php on line 5

Fatal error: Call to a member function execute() on null in
/home/user/Desktop/zend_llist_del_element_uaf.php on line 5

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x5a5a5a62 ('bZZZ')
EBX: 0x8000000 
ECX: 0x38 ('8')
EDX: 0x5a5a5a62 ('bZZZ')
ESI: 0x0 
EDI: 0x89bf1d8 --> 0x0 
EBP: 0xbfffda58 --> 0xbfffda98 --> 0xbfffdad8 --> 0xbfffdb08 --> 0xbfffdbf8 -->
0xbfffdcc8 --> 0xbfffddb8 --> 0xbfffefa8 --> 0xbffff0c8 --> 0x0 
ESP: 0xbfffda58 --> 0xbfffda98 --> 0xbfffdad8 --> 0xbfffdb08 --> 0xbfffdbf8 -->
0xbfffdcc8 --> 0xbfffddb8 --> 0xbfffefa8 --> 0xbffff0c8 --> 0x0 
EIP: 0x8110282 (<php_sqlite3_compare_stmt_free+6>:  mov    eax,DWORD PTR [eax])
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x811027c <php_sqlite3_compare_stmt_free>: push   ebp
   0x811027d <php_sqlite3_compare_stmt_free+1>: mov    ebp,esp
   0x811027f <php_sqlite3_compare_stmt_free+3>: mov    eax,DWORD PTR [ebp+0x8]
=> 0x8110282 <php_sqlite3_compare_stmt_free+6>: mov    eax,DWORD PTR [eax]
   0x8110284 <php_sqlite3_compare_stmt_free+8>: mov    eax,DWORD PTR [eax+0x4]
   0x8110287 <php_sqlite3_compare_stmt_free+11>:  mov    eax,DWORD PTR [eax+0x1c]
   0x811028a <php_sqlite3_compare_stmt_free+14>:  test   eax,eax
   0x811028c <php_sqlite3_compare_stmt_free+16>:  je     0x81102a5
<php_sqlite3_compare_stmt_free+41>
[------------------------------------stack-------------------------------------]
0000| 0xbfffda58 --> 0xbfffda98 --> 0xbfffdad8 --> 0xbfffdb08 --> 0xbfffdbf8 -->
0xbfffdcc8 --> 0xbfffddb8 --> 0xbfffefa8 --> 0xbffff0c8 --> 0x0 
0004| 0xbfffda5c --> 0x841944e (<zend_llist_del_element+40>:  test   eax,eax)
0008| 0xbfffda60
("bZZZ\330Ū\b\230\332\377\277\254\231?\b\360\361\233\bx\367\275\267\260\231Z\bG\b")
0012| 0xbfffda64 --> 0x8aac5d8 --> 0x8a9b188 --> 0x899e780 --> 0x3 
0016| 0xbfffda68 --> 0xbfffda98 --> 0xbfffdad8 --> 0xbfffdb08 --> 0xbfffdbf8 -->
0xbfffdcc8 --> 0xbfffddb8 --> 0xbfffefa8 --> 0xbffff0c8 --> 0x0 
0020| 0xbfffda6c --> 0x83f99ac (<_efree+91>:  leave)
0024| 0xbfffda70 --> 0x89bf1f0 --> 0x1 
0028| 0xbfffda74 --> 0xb7bdf778 ('Z' <repeats 64 times>,
"\204\243\034\263\364ZWh=")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x08110282 in php_sqlite3_compare_stmt_free (free_list=0x5a5a5a62, statement=0x8aac5d8) at
/home/user/Desktop/php5610/ext/sqlite3/sqlite3.c:2065
2065    return ((*free_list)->stmt_obj->initialised && statement ==
(*free_list)->stmt_obj->stmt);

gdb-peda$ print free_list
$1 = (php_sqlite3_free_list **) 0x5a5a5a62

gdb-peda$ print *free_list
Cannot access memory at address 0x5a5a5a62

gdb-peda$ ptype free_list
type = struct _php_sqlite3_free_list {
    zval *stmt_obj_zval;
    php_sqlite3_stmt *stmt_obj;
} **

As seen above, both EAX and EDX point to freed memory.

Regards,
Symeon.



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=69971&edit=1


Thread (1 message)

  • cmb@php.net
  • Unknown Message
    • cmb@php.net
« previous php.bugs (#217583) next »