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
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: 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