php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69971 Use-after-free in sqlite3 when destroying statement object
Submitted: 2015-06-30 15:17 UTC Modified: 2019-01-21 13:49 UTC
From: s dot paraschoudis at gmail dot com Assigned: cmb (profile)
Status: Duplicate Package: SQLite related
PHP Version: 5.6.10 OS: Ubuntu 14.04.1 LTS (32 bit)
Private report: No CVE-ID: None
 [2015-06-30 15:17 UTC] 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.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-07-05 04:25 UTC] stas@php.net
-Assigned To: +Assigned To: scottmac
 [2015-07-05 04:25 UTC] 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-07-05 04:26 UTC] stas@php.net
-Summary: Use-after-free vulnerability in zend_llist_del_element() +Summary: Use-after-free in sqlite3 when destroying statement object
 [2015-07-05 04:26 UTC] stas@php.net
-Type: Security +Type: Bug
 [2017-10-24 06:10 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: scottmac +Assigned To:
 [2018-10-15 22:36 UTC] cmb@php.net
-Package: Reproducible crash +Package: SQLite related
 [2018-10-15 22:36 UTC] cmb@php.net
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.
 [2019-01-21 13:49 UTC] cmb@php.net
-Status: Open +Status: Duplicate -Assigned To: +Assigned To: cmb
 [2019-01-21 13:49 UTC] cmb@php.net
Indeed, this is a duplicate of bug #53626.  Since that ticket
isn't private, I'm publishing this one.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Sat Jan 18 10:01:23 2020 UTC