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