php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #72519 imagegif/output out-of-bounds access
Submitted: 2016-06-30 04:10 UTC Modified: 2016-07-19 07:45 UTC
From: fernando at null-life dot com Assigned: stas (profile)
Status: Closed Package: GD related
PHP Version: 7.0.8 OS: *
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: fernando at null-life dot com
New email:
PHP Version: OS:

 

 [2016-06-30 04:10 UTC] fernando at null-life dot com
Description:
------------
output function from gd_gif_out.c causes out-of-bounds access of the masks array when ctx->cur_bits becomes a negative number.

Source code:

https://github.com/php/php-src/blob/master/ext/gd/libgd/gd_gif_out.c#L612

...
static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
                                  0x001F, 0x003F, 0x007F, 0x00FF,
                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };

static void
output(code_int code, GifCtx *ctx)
{
    ctx->cur_accum &= masks[ ctx->cur_bits ];               ## Read out of bounds

    if( ctx->cur_bits > 0 )
        ctx->cur_accum |= ((long)code << ctx->cur_bits);
    else
....


According to my research on libgd, this patch from May 14 fixes this problem, but it's not applied on PHP:

https://github.com/libgd/libgd/commit/82b80dcb70a7ca8986125ff412bceddafc896842


GDB output

gdb -q --args /home/user/php/php-70/sapi/cli/php -n poc.php
No symbol table is loaded.  Use the "file" command.
Breakpoint 1 (__asan_report_error) pending.
Reading symbols from /home/user/php/php-70/sapi/cli/php...done.
gdb-peda$ b gd_gif_out.c:612 if ctx->cur_bits < 0
Breakpoint 2 at 0x818a5b5: file /home/user/php/php-70/ext/gd/libgd/gd_gif_out.c, line 612.
gdb-peda$ r
Starting program: /home/user/php/php-70/sapi/cli/php -n poc.php
GIF87add,dd,[----------------------------------registers-----------------------------------]
EAX: 0x8b47000 --> 0x8b46db8 --> 0x1
EBX: 0x0
ECX: 0x4
EDX: 0xffff2814 --> 0x64 ('d')
ESI: 0x0
EDI: 0x0
EBP: 0xffff2778 --> 0xffff27b8 --> 0xffff9eb8 --> 0xffff9f28 --> 0xffff9f98 --> 0xffff9fc8 (--> ...)
ESP: 0xffff2770 --> 0x5
EIP: 0x818a5b5 (<output+17>:    mov    edx,DWORD PTR [ebp+0xc])
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x818a5a8 <output+4>:        sub    esp,0x4
   0x818a5ab <output+7>:        call   0x8076e59 <__x86.get_pc_thunk.ax>
   0x818a5b0 <output+12>:       add    eax,0x9bca50
=> 0x818a5b5 <output+17>:       mov    edx,DWORD PTR [ebp+0xc]
   0x818a5b8 <output+20>:       mov    ecx,DWORD PTR [edx+0x758c]
   0x818a5be <output+26>:       mov    edx,DWORD PTR [ebp+0xc]
   0x818a5c1 <output+29>:       mov    edx,DWORD PTR [edx+0x7590]
   0x818a5c7 <output+35>:       mov    eax,DWORD PTR [eax+edx*4+0x1e40]
[------------------------------------stack-------------------------------------]
0000| 0xffff2770 --> 0x5
0004| 0xffff2774 --> 0x0
0008| 0xffff2778 --> 0xffff27b8 --> 0xffff9eb8 --> 0xffff9f28 --> 0xffff9f98 --> 0xffff9fc8 (--> ...)
0012| 0xffff277c --> 0x818a4d9 (<compress+510>: add    esp,0x10)
0016| 0xffff2780 --> 0x0
0020| 0xffff2784 --> 0xffff2814 --> 0x64 ('d')
0024| 0xffff2788 --> 0xffff27b8 --> 0xffff9eb8 --> 0xffff9f28 --> 0xffff9f98 --> 0xffff9fc8 (--> ...)
0028| 0xffff278c --> 0x818a2e9 (<compress+14>:  add    eax,0x9bcd17)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, output (code=0x0, ctx=0xffff2814) at /home/user/php/php-70/ext/gd/libgd/gd_gif_out.c:612
612         ctx->cur_accum &= masks[ ctx->cur_bits ];
gdb-peda$ p ctx->cur_bits
$1 = 0xfffffffe                      ##  Out of bounds (negative value)


Test script:
---------------
<?php

$img = imagecreate(100, 100);
imagesetpixel($img, 0, 0, 5);
imagegif($img);


Expected result:
----------------
Valid gif file.

Actual result:
--------------
/ram/php-fuzz/phuzzer/php-70/sapi/cli/php -n poc.php


==8404==ERROR: AddressSanitizer: global-buffer-overflow on address 0x09f942f8 at pc 0x08663b24 bp 0xffbcb248 sp 0xffbcb238
READ of size 4 at 0x09f942f8 thread T0
    #0 0x8663b23 in output /home/user/php/php-70-asan/ext/gd/libgd/gd_gif_out.c:612
    #1 0x8664ca2 in compress /home/user/php/php-70-asan/ext/gd/libgd/gd_gif_out.c:566
    #2 0x8664ca2 in GIFEncode /home/user/php/php-70-asan/ext/gd/libgd/gd_gif_out.c:397
    #3 0x8668380 in php_gd_gdImageGifCtx /home/user/php/php-70-asan/ext/gd/libgd/gd_gif_out.c:134
    #4 0x85d3137 in _php_image_output_ctx /home/user/php/php-70-asan/ext/gd/gd_ctx.c:195
    #5 0x85d3137 in zif_imagegif /home/user/php/php-70-asan/ext/gd/gd.c:2662
    #6 0x9a388ac in ZEND_DO_ICALL_SPEC_HANDLER /home/user/php/php-70-asan/Zend/zend_vm_execute.h:586
    #7 0x980d06f in execute_ex /home/user/php/php-70-asan/Zend/zend_vm_execute.h:414
    #8 0x9b287c5 in zend_execute /home/user/php/php-70-asan/Zend/zend_vm_execute.h:458
    #9 0x95e4c3c in zend_execute_scripts /home/user/php/php-70-asan/Zend/zend.c:1427
    #10 0x932d58b in php_execute_script /home/user/php/php-70-asan/main/main.c:2494
    #11 0x9b31004 in do_cli /home/user/php/php-70-asan/sapi/cli/php_cli.c:974
    #12 0x80a6e78 in main /home/user/php/php-70-asan/sapi/cli/php_cli.c:1344
    #13 0xf6c9e636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
    #14 0x80a755a  (/ram/php-fuzz/phuzzer/php-70-asan/sapi/cli/php+0x80a755a)

0x09f942f8 is located 49 bytes to the right of global variable '*.LC3' defined in '/home/user/php/php-70-asan/ext/gd/libgd/gd_gif_out.c' (0x9f942c0) of size 7
  '*.LC3' is ascii string 'GIF89a'
0x09f942f8 is located 8 bytes to the left of global variable 'masks' defined in '/home/user/php/php-70-asan/ext/gd/libgd/gd_gif_out.c:604:22' (0x9f94300) of size 68
SUMMARY: AddressSanitizer: global-buffer-overflow /home/user/php/php-70-asan/ext/gd/libgd/gd_gif_out.c:612 output


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-07-13 06:30 UTC] stas@php.net
-Assigned To: +Assigned To: pajoye
 [2016-07-13 06:30 UTC] stas@php.net
Pierre, could you please check that this fix is correct?
 [2016-07-14 02:16 UTC] pajoye@php.net
The fix is correct and can be applied in all branches as it is public already.

Will you do it? Or I can do it for 5.5+?
 [2016-07-14 04:49 UTC] stas@php.net
Pierre, if you could add it to the security repo into 5.5.38 branch, it'd be great.
 [2016-07-17 10:05 UTC] pajoye@php.net
Can you remind me which repository it is pls? I am not sure I have access to it either :) 

Btw when aer planned the next releases?
 [2016-07-17 23:39 UTC] stas@php.net
It's security repo. If you don't have access please send me the patch. The release is next week so it'd be nice to move it forward.
 [2016-07-17 23:40 UTC] stas@php.net
sorry, php-src-security repo.
 [2016-07-19 07:19 UTC] pajoye@php.net
-Assigned To: pajoye +Assigned To: stas
 [2016-07-19 07:19 UTC] pajoye@php.net
Merged into 5.6+

It seems 5.5 is closed now and I cannot push to it. Stas, that one should be in too.
 [2016-07-19 07:20 UTC] pajoye@php.net
While I was able to push another one earlier today, not sure if it was closed in the meantime or I made a mistake :/
 [2016-07-19 07:45 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-07-19 07:45 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2016-07-19 07:47 UTC] stas@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=8dc5ffa479f886fae235d4ff6391e14546a3fda9
Log: fix #72519, possible OOB using imagegif
 [2016-07-19 07:53 UTC] stas@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=8dc5ffa479f886fae235d4ff6391e14546a3fda9
Log: fix #72519, possible OOB using imagegif
 [2016-07-19 08:39 UTC] stas@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=8dc5ffa479f886fae235d4ff6391e14546a3fda9
Log: fix #72519, possible OOB using imagegif
 [2016-07-19 08:55 UTC] stas@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=8dc5ffa479f886fae235d4ff6391e14546a3fda9
Log: fix #72519, possible OOB using imagegif
 [2016-07-19 17:59 UTC] ab@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=55f7df261743c0fddc1ee6d4ace0848f946d36af
Log: fix #72519, possible OOB using imagegif
 [2016-07-21 00:27 UTC] tyrael@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=a48f64c403b05da244cfd30399bffd53e910a440
Log: fix #72519, possible OOB using imagegif
 [2016-10-17 10:10 UTC] bwoebi@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=8dc5ffa479f886fae235d4ff6391e14546a3fda9
Log: fix #72519, possible OOB using imagegif
 [2016-10-17 10:10 UTC] bwoebi@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=7b1572b1772dc92b2e73b7cf6d51dca88a60f411
Log: fix #72519, possible OOB using imagegif
 [2016-10-17 10:10 UTC] bwoebi@php.net
Automatic comment on behalf of pierre.php@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=2fbce5f51f4ba01e4d0de3b8592bb14773a98d4d
Log: fix #72519, possible OOB using imagegif
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC