php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #72603 Out of bound read in exif_process_IFD_in_MAKERNOTE
Submitted: 2016-07-15 15:46 UTC Modified: 2016-07-25 15:18 UTC
From: nguyenvuhoang199321 at gmail dot com Assigned: stas (profile)
Status: Closed Package: EXIF related
PHP Version: 5.5.37 OS: *Nix
Private report: No CVE-ID: 2016-6291
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: nguyenvuhoang199321 at gmail dot com
New email:
PHP Version: OS:

 

 [2016-07-15 15:46 UTC] nguyenvuhoang199321 at gmail dot com
Description:
------------
I have found some vulnerable code that lacks check size of buffer may lead to memory out of read or write.

Take a look at : 
```
static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * value_ptr, int value_len, char *offset_base, size_t IFDlength, size_t displacement)
{
*****SNIP*******
	switch (maker_note->offset_mode) {
		case MN_OFFSET_MAKER:
			offset_base = value_ptr;
			break;
		case MN_OFFSET_GUESS:
			offset_diff = 2 + NumDirEntries*12 + 4 - php_ifd_get32u(dir_start+10, ImageInfo->motorola_intel);
#ifdef EXIF_DEBUG
			exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Using automatic offset correction: 0x%04X", ((int)dir_start-(int)offset_base+maker_note->offset+displacement) + offset_diff);
#endif
			offset_base = value_ptr + offset_diff;
			break;
		default:
		case MN_OFFSET_NORMAL:
			break;
	}

	if ((2+NumDirEntries*12) > value_len)
*****SNIP*******
}
```
As you can see this line while processing markernote of "Cannon"
```
offset_diff = 2 + NumDirEntries*12 + 4 - php_ifd_get32u(dir_start+10, ImageInfo->motorola_intel);
```
Because no checking the value return from php_ifd_get32u(dir_start+10, ImageInfo->motorola_intel); and weak check value of NumDirEntries, so attacker can control both value to make offset_diff may out of size offset_base.

That result may lead to information leak or memory corruption.

Here jpeg image link to lead to this problem : https://drive.google.com/file/d/0B0D1DYQpkA9UZmVOMzYwQlBnSGM/view?usp=sharing

Test script:
---------------
<?php
	$exif = exif_read_data('exif/gen.jpg');
	var_dump($exif);
?>

Actual result:
--------------
I will show you the variable of offset_diff, offset_base before and after hitting that code path.
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x18
RCX: 0x0
RDX: 0x7ffff3e7607e --> 0x29286fffffa92
RSI: 0x0
RDI: 0x7ffff3e7607e --> 0x29286fffffa92
RBP: 0x7fffffffa8a0 --> 0x7fffffffa9d0 --> 0x7fffffffaa30 --> 0x7fffffffab60 --> 0x7fffffffabc0 --> 0x7fffffffac00 --> 0x7fffffffac30 --> 0x7fffffffacd0 --> 0x7fffffffad10 --> 0x7fffffffadf0 --> 0x7fffffffb0d0 --> 0x7fffffffb100 --> 0x7fffffffb130 --> 0x7fffffffb170 --> 0x7fffffffb280 --> 0x7fffffffd580 --> 0x7fffffffe900 --> 0x7fffffffea50 --> 0xa15f90 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffa830 --> 0xc ('\x0c')
RIP: 0x613c3d (<exif_process_IFD_in_MAKERNOTE+489>:	call   0x610603 <php_ifd_get32u>)
R8 : 0x594
R9 : 0xc ('\x0c')
R10: 0x1c
R11: 0x206
R12: 0x42c170 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffeb30 --> 0x2
R14: 0x7ffff3e14030 --> 0x7ffff3e5fb80 --> 0x9a28f2 (<ZEND_DO_ICALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7ffff3e5fb80 --> 0x9a28f2 (<ZEND_DO_ICALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x613c34 <exif_process_IFD_in_MAKERNOTE+480>:	add    rdx,0xa
   0x613c38 <exif_process_IFD_in_MAKERNOTE+484>:	mov    esi,eax
   0x613c3a <exif_process_IFD_in_MAKERNOTE+486>:	mov    rdi,rdx
=> 0x613c3d <exif_process_IFD_in_MAKERNOTE+489>:	call   0x610603 <php_ifd_get32u>
   0x613c42 <exif_process_IFD_in_MAKERNOTE+494>:	sub    ebx,eax
   0x613c44 <exif_process_IFD_in_MAKERNOTE+496>:	mov    eax,ebx
   0x613c46 <exif_process_IFD_in_MAKERNOTE+498>:	add    eax,0x6
   0x613c49 <exif_process_IFD_in_MAKERNOTE+501>:	mov    DWORD PTR [rbp-0x24],eax
Guessed arguments:
arg[0]: 0x7ffff3e7607e --> 0x29286fffffa92
arg[1]: 0x0
arg[2]: 0x7ffff3e7607e --> 0x29286fffffa92
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa830 --> 0xc ('\x0c')
0008| 0x7fffffffa838 --> 0x594
0016| 0x7fffffffa840 --> 0x7ffff3e76008 --> 0x8002a4949
0024| 0x7fffffffa848 --> 0x1c006117bc
0032| 0x7fffffffa850 --> 0x7ffff3e76074 --> 0x1000202080002
0040| 0x7fffffffa858 --> 0x7fffffffae50 --> 0x7ffff3e5fa00 --> 0x12b9700 --> 0x8d43d1 (<php_stdiop_write>:	push   rbp)
0048| 0x7fffffffa860 --> 0x7fffffffa8a0 --> 0x7fffffffa9d0 --> 0x7fffffffaa30 --> 0x7fffffffab60 --> 0x7fffffffabc0 --> 0x7fffffffac00 --> 0x7fffffffac30 --> 0x7fffffffacd0 --> 0x7fffffffad10 --> 0x7fffffffadf0 --> 0x7fffffffb0d0 --> 0x7fffffffb100 --> 0x7fffffffb130 --> 0x7fffffffb170 --> 0x7fffffffb280 --> 0x7fffffffd580 --> 0x7fffffffe900 --> 0x7fffffffea50 --> 0xa15f90 (<__libc_csu_init>:	push   r15)
0056| 0x7fffffffa868 --> 0x5
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 5, 0x0000000000613c3d in exif_process_IFD_in_MAKERNOTE (
    ImageInfo=0x7fffffffae50, value_ptr=0x7ffff3e76074 "\002", value_len=0x1c,
    offset_base=0x7ffff3e76008 "II*", IFDlength=0x594, displacement=0xc)
    at /home/vagrant/Sources_Ext/audit/src/php7.0-7.0.4/ext/exif/exif.c:2754
2754				offset_diff = 2 + NumDirEntries*12 + 4 - php_ifd_get32u(dir_start+10, ImageInfo->motorola_intel);
gdb-peda$ x/80gx offset_base
0x7ffff3e76008:	0x00000008002a4949	0x00010005011a0002
0x7ffff3e76018:	0x8769000004000000	0x0022000000010004
0x7ffff3e76028:	0x0005829a00060000	0x0000041200000001
0x7ffff3e76038:	0x000000010005829d	0x0002928600000444
0x7ffff3e76048:	0x00000da6000000a8	0x0000002c00028298
0x7ffff3e76058:	0x0002010f00000e4e	0x00000e7a00000005
0x7ffff3e76068:	0x000000070004927c	0x020800020000006c
0x7ffff3e76078:	0xfa92000000010002	0x00ff00029286ffff
0x7ffff3e76088:	0x5252000000000000	0x5252525252525252
0x7ffff3e76098:	0x5252525252525252	0x5252525252525252
0x7ffff3e760a8:	0x5252525252525252	0x5252525252525252
0x7ffff3e760b8:	0x5252525252525252	0x5252525252525252
0x7ffff3e760c8:	0x5252525252525252	0x5252525252525252
0x7ffff3e760d8:	0x5252525252525252	0x5252525252525252
0x7ffff3e760e8:	0x5252525252525252	0x00f2525252525252
.....
0x7ffff3e76568:	0x5454545454545454	0x5454545454545454
0x7ffff3e76578:	0x5454545454545454	0x5454545454545454
0x7ffff3e76588:	0x5454545454545454	0x5454545454545454
0x7ffff3e76598:	0x00000000d9ff5454	0x0000000000000000
0x7ffff3e765a8:	0x0000000000000000	0x0000000000000000
0x7ffff3e765b8:	0x0000000000000000	0x0000000000000000
0x7ffff3e765c8:	0x0000000000000000	0x0000000000000000
0x7ffff3e765d8:	0x0000000000000000	0x000000000000059d
0x7ffff3e765e8:	0x0000000000b12b88	0x0000000000f774a0
0x7ffff3e765f8:	0x000009ce00000646	0x00007ffff3e76c00
As you see above at address 0x7ffff3e76598 is the end of offset_base.
Next i hit next to execute `offset_base = value_ptr + offset_diff;`
[----------------------------------registers-----------------------------------]
RAX: 0x7ffff3e76600 --> 0x7ffff3e76c00 --> 0x7ffff3e77200 --> 0x7ffff3e77800 --> 0x7ffff3e77e00 --> 0x7ffff3e78400 --> 0x7ffff3e78a00 --> 0x0
RBX: 0x586
RCX: 0x0
RDX: 0x58c
RSI: 0x0
RDI: 0x7ffff3e7607e --> 0x29286fffffa92
RBP: 0x7fffffffa8a0 --> 0x7fffffffa9d0 --> 0x7fffffffaa30 --> 0x7fffffffab60 --> 0x7fffffffabc0 --> 0x7fffffffac00 --> 0x7fffffffac30 --> 0x7fffffffacd0 --> 0x7fffffffad10 --> 0x7fffffffadf0 --> 0x7fffffffb0d0 --> 0x7fffffffb100 --> 0x7fffffffb130 --> 0x7fffffffb170 --> 0x7fffffffb280 --> 0x7fffffffd580 --> 0x7fffffffe900 --> 0x7fffffffea50 --> 0xa15f90 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffa830 --> 0xc ('\x0c')
RIP: 0x613c5d (<exif_process_IFD_in_MAKERNOTE+521>:	nop)
R8 : 0x594
R9 : 0xc ('\x0c')
R10: 0x1c
R11: 0x206
R12: 0x42c170 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffeb30 --> 0x2
R14: 0x7ffff3e14030 --> 0x7ffff3e5fb80 --> 0x9a28f2 (<ZEND_DO_ICALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7ffff3e5fb80 --> 0x9a28f2 (<ZEND_DO_ICALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x613c52 <exif_process_IFD_in_MAKERNOTE+510>:	mov    rax,QWORD PTR [rbp-0x50]
   0x613c56 <exif_process_IFD_in_MAKERNOTE+514>:	add    rax,rdx
   0x613c59 <exif_process_IFD_in_MAKERNOTE+517>:	mov    QWORD PTR [rbp-0x60],rax
=> 0x613c5d <exif_process_IFD_in_MAKERNOTE+521>:	nop
   0x613c5e <exif_process_IFD_in_MAKERNOTE+522>:	mov    edx,DWORD PTR [rbp-0x28]
   0x613c61 <exif_process_IFD_in_MAKERNOTE+525>:	mov    eax,edx
   0x613c63 <exif_process_IFD_in_MAKERNOTE+527>:	add    eax,eax
   0x613c65 <exif_process_IFD_in_MAKERNOTE+529>:	add    eax,edx
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa830 --> 0xc ('\x0c')
0008| 0x7fffffffa838 --> 0x594
0016| 0x7fffffffa840 --> 0x7ffff3e76600 --> 0x7ffff3e76c00 --> 0x7ffff3e77200 --> 0x7ffff3e77800 --> 0x7ffff3e77e00 --> 0x7ffff3e78400 --> 0x7ffff3e78a00 --> 0x0
0024| 0x7fffffffa848 --> 0x1c006117bc
0032| 0x7fffffffa850 --> 0x7ffff3e76074 --> 0x1000202080002
0040| 0x7fffffffa858 --> 0x7fffffffae50 --> 0x7ffff3e5fa00 --> 0x12b9700 --> 0x8d43d1 (<php_stdiop_write>:	push   rbp)
0048| 0x7fffffffa860 --> 0x7fffffffa8a0 --> 0x7fffffffa9d0 --> 0x7fffffffaa30 --> 0x7fffffffab60 --> 0x7fffffffabc0 --> 0x7fffffffac00 --> 0x7fffffffac30 --> 0x7fffffffacd0 --> 0x7fffffffad10 --> 0x7fffffffadf0 --> 0x7fffffffb0d0 --> 0x7fffffffb100 --> 0x7fffffffb130 --> 0x7fffffffb170 --> 0x7fffffffb280 --> 0x7fffffffd580 --> 0x7fffffffe900 --> 0x7fffffffea50 --> 0xa15f90 (<__libc_csu_init>:	push   r15)
0056| 0x7fffffffa868 --> 0x5
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
2759				break;
gdb-peda$ p offset_base
$86 = 0x7ffff3e76600 ""
gdb-peda$ x/40gx offset_base
0x7ffff3e76600:	0x00007ffff3e76c00	0x0000000000000000
0x7ffff3e76610:	0x0000000000000000	0x0000000000000000
0x7ffff3e76620:	0x0000000000000000	0x0000000000000000
After calculate offset_base, you can see that address is out of own buffer

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-07-17 23:25 UTC] stas@php.net
-Summary: Memory Out Of Bound +Summary: Out of bound read in exif_process_IFD_in_MAKERNOTE -PHP Version: 7.0.8 +PHP Version: 5.5.37
 [2016-07-17 23:36 UTC] stas@php.net
Fix in security repo as eebcbd5de38a0f1c2876035402cb770e37476519 and in https://gist.github.com/5226fbd757bbc5a01ca1064f099a285d
. Please verify.
 [2016-07-17 23:36 UTC] stas@php.net
-Assigned To: +Assigned To: stas
 [2016-07-18 07:06 UTC] nguyenvuhoang199321 at gmail dot com
Well this bug is fixed
 [2016-07-19 07:47 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=eebcbd5de38a0f1c2876035402cb770e37476519
Log: Fix bug #72603: Out of bound read in exif_process_IFD_in_MAKERNOTE
 [2016-07-19 07:47 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-07-19 07:53 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=eebcbd5de38a0f1c2876035402cb770e37476519
Log: Fix bug #72603: Out of bound read in exif_process_IFD_in_MAKERNOTE
 [2016-07-19 08:39 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=eebcbd5de38a0f1c2876035402cb770e37476519
Log: Fix bug #72603: Out of bound read in exif_process_IFD_in_MAKERNOTE
 [2016-07-19 08:55 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=eebcbd5de38a0f1c2876035402cb770e37476519
Log: Fix bug #72603: Out of bound read in exif_process_IFD_in_MAKERNOTE
 [2016-07-25 15:18 UTC] remi@php.net
-CVE-ID: +CVE-ID: 2016-6291
 [2016-10-17 10:11 UTC] bwoebi@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=eebcbd5de38a0f1c2876035402cb770e37476519
Log: Fix bug #72603: Out of bound read in exif_process_IFD_in_MAKERNOTE
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC