New issue
Advanced search Search tips

Issue 629919 link

Starred by 2 users

Issue metadata

Status: Fixed
Owner:
Closed: Jul 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 1
Type: Bug-Security



Sign in to add a comment

Security: heap-buffer-overflow in opj_tcd_update_tile_data

Reported by gogil@stealien.com, Jul 20 2016

Issue description


VULNERABILITY DETAILS

A heap buffer overflow vulnerability is present in the openjpeg.


File libopenjpeg20/tcd.c, line 1145:
--------------------------------------------------------------------------------
OPJ_UINT32 opj_tcd_get_decoded_tile_size ( opj_tcd_t *p_tcd )
{
        OPJ_UINT32 i;
        OPJ_UINT32 l_data_size = 0;
        opj_image_comp_t * l_img_comp = 00;
        opj_tcd_tilecomp_t * l_tile_comp = 00;
        opj_tcd_resolution_t * l_res = 00;
        OPJ_UINT32 l_size_comp, l_remaining;

        l_tile_comp = p_tcd->tcd_image->tiles->comps;
        l_img_comp = p_tcd->image->comps;

        for (i=0;i<p_tcd->image->numcomps;++i) {    <--- `image->numcomps` is 0x10
                l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
                l_remaining = l_img_comp->prec & 7;  /* (%8) */

                if(l_remaining) {
                        ++l_size_comp;
                }

                if (l_size_comp == 3) {
                        l_size_comp = 4;
                }

                l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1;
                l_data_size += l_size_comp * (OPJ_UINT32)((l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0));    <--- 0x4 or 0x10 * (0x1064 * 0x1064)
                ++l_img_comp;
                ++l_tile_comp;
        }

        return l_data_size;    <--- This function will return 0xF3B40.
}
--------------------------------------------------------------------------------

To prove this vulnerability, I used the image as a following description.

	`image->numcomps` is 0x10
	One of the `l_size_comp` is 0x4, the others is 0x10.
	`l_res->x1 - l_res->x0` is 0x1064
	`l_res->y1 - l_res->y0` is 0x1064

	Therefore, (0x4 * 0x1064 * 1064) + ((0x10 * 0x1064 * 0x1064) * 0xF) = 0x1000F3B40 (Integer Overflow)

As a result, the function `opj_tcd_get_decoded_tile_size` will return 0xF3B40.



File libopenjpeg20/j2k.c, line 9562:
--------------------------------------------------------------------------------
static OPJ_BOOL opj_j2k_decode_tiles ( opj_j2k_t *p_j2k,
                                                            opj_stream_private_t *p_stream,
                                                            opj_event_mgr_t * p_manager)
{
        OPJ_BOOL l_go_on = OPJ_TRUE;
        OPJ_UINT32 l_current_tile_no;
        OPJ_UINT32 l_data_size,l_max_data_size;
        OPJ_INT32 l_tile_x0,l_tile_y0,l_tile_x1,l_tile_y1;
        OPJ_UINT32 l_nb_comps;
        OPJ_BYTE * l_current_data;
        OPJ_UINT32 nr_tiles = 0;

        l_current_data = (OPJ_BYTE*)opj_malloc(1000);    <--- The size of `l_current_data` is 1000.
        if (! l_current_data) {
                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tiles\n");
                return OPJ_FALSE;
        }
        l_max_data_size = 1000;

		for (;;) {
                if (! opj_j2k_read_tile_header( p_j2k,
                                        &l_current_tile_no,
                                        &l_data_size,           <--- `l_data_size` will be 0xF3B40. (It is the return value of `opj_tcd_get_decoded_tile_size`)
                                        &l_tile_x0, &l_tile_y0,
                                        &l_tile_x1, &l_tile_y1,
                                        &l_nb_comps,
                                        &l_go_on,
                                        p_stream,
                                        p_manager)) {
                        opj_free(l_current_data);
                        return OPJ_FALSE;
                }

                if (! l_go_on) {
                        break;
                }

                if (l_data_size > l_max_data_size) {
                        OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_data_size);    <--- `opj_realloc` will reallocate memory with size 0xF3B40.
                        if (! l_new_current_data) {
                                opj_free(l_current_data);
                                opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile %d/%d\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw);
                                return OPJ_FALSE;
                        }
                        l_current_data = l_new_current_data;
                        l_max_data_size = l_data_size;
                }
--------------------------------------------------------------------------------



File libopenjpeg20/tcd.c, line 1352:
--------------------------------------------------------------------------------
OPJ_BOOL opj_tcd_update_tile_data ( opj_tcd_t *p_tcd,
				    OPJ_BYTE * p_dest,
				    OPJ_UINT32 p_dest_length
				    )
{
	...
1372	for (i=0;i<p_tcd->image->numcomps;++i) {
		...
1388		switch (l_size_comp)
1389			{
			...
1440			case 4:
1441				{
1442					OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_dest;    <--- The size of `p_dest` is still 0xF3B40.
1443					OPJ_INT32 * l_src_ptr = l_tilec->data;
1444
1445					for (j=0;j<l_height;++j) {    <--- `l_height` is 0x1064.
1446						for (k=0;k<l_width;++k) {    <--- `l_width` is 0x1064.
1447							*(l_dest_ptr++) = (*(l_src_ptr++));    <--- out of bound write.
1448						}
1449						l_src_ptr += l_stride;
1450					}
1451
1452					p_dest = (OPJ_BYTE*) l_dest_ptr;
1453				}
1454				break;
1455		}
--------------------------------------------------------------------------------

I can control the `l_tilec->data` using `J2K_MS_MCT` block.




VERSION
Chrome Version: 51.0.2704.106 Stable / latest pdfium_test
Operating System: Windows 10 x64 / Ubuntu 16.04 x64




REPRODUCTION CASE
Attached as poc.pdf




FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION

Attached as pdfium_ASAN_trace.txt, chrome_windbg_trace.txt


(1f44.f7c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
chrome_child!opj_tcd_update_tile_data+0xca:
00007fff`a9a46d56 8907            mov     dword ptr [rdi],eax ds:00000215`b5c1e000=????????
0:000> r
rax=0000000000414141 rbx=00000215ca3dd318 rcx=00000215cbc69034
rdx=0000000000000000 rsi=00000215c7afdf50 rdi=00000215b5c1e000
rip=00007fffa9a46d56 rsp=0000001e5c71ac50 rbp=0000000000000000
 r8=0000000000001064  r9=0000000000000968 r10=0000000000001024
r11=00000215ca3e8000 r12=0000000000000004 r13=0000000000000000
r14=00000215b5b16010 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202
chrome_child!opj_tcd_update_tile_data+0xca:
00007fff`a9a46d56 8907            mov     dword ptr [rdi],eax ds:00000215`b5c1e000=????????
0:000> u
chrome_child!opj_tcd_update_tile_data+0xca [c:\b\build\slave\win64\build\src\third_party\pdfium\third_party\libopenjpeg20\tcd.c @ 1440]:
00007fff`a9a46d56 8907            mov     dword ptr [rdi],eax
00007fff`a9a46d58 4903fc          add     rdi,r12
00007fff`a9a46d5b 4983e901        sub     r9,1
00007fff`a9a46d5f 75f0            jne     chrome_child!opj_tcd_update_tile_data+0xc5 (00007fff`a9a46d51)
00007fff`a9a46d61 4803ca          add     rcx,rdx
00007fff`a9a46d64 4983ea01        sub     r10,1
00007fff`a9a46d68 75df            jne     chrome_child!opj_tcd_update_tile_data+0xbd (00007fff`a9a46d49)
00007fff`a9a46d6a e9e7000000      jmp     chrome_child!opj_tcd_update_tile_data+0x1ca (00007fff`a9a46e56)
0:000> dd rdi-32
00000215`b5c1dfce  41410041 41410041 41410041 41410041
00000215`b5c1dfde  41410041 41410041 41410041 41410041
00000215`b5c1dfee  41410041 41410041 41410041 41410041
00000215`b5c1dffe  ???????? ???????? ???????? ????????
00000215`b5c1e00e  ???????? ???????? ???????? ????????
00000215`b5c1e01e  ???????? ???????? ???????? ????????
00000215`b5c1e02e  ???????? ???????? ???????? ????????
00000215`b5c1e03e  ???????? ???????? ???????? ????????

 
poc.pdf
20.5 KB Download
pdfium_asan_trace.txt
9.0 KB View Download
chrome_windbg_trace.txt
15.0 KB View Download
Owner: tsepez@chromium.org
This is in pdfium, Tom is this something you can take a look at?
Project Member

Comment 2 by sheriffbot@chromium.org, Jul 21 2016

Status: Assigned (was: Unconfirmed)

Comment 3 by tsepez@chromium.org, Jul 21 2016

Owner: och...@chromium.org
Passing the buck.

Comment 4 by gogil@stealien.com, Jul 22 2016

* Fix Suggestion
patch.txt
2.4 KB View Download
Labels: Security_Severity-High Security_Impact-Stable
Components: Internals>Plugins>PDF
Labels: OS-All
Project Member

Comment 8 by sheriffbot@chromium.org, Jul 23 2016

Labels: M-52
Project Member

Comment 9 by sheriffbot@chromium.org, Jul 23 2016

Labels: Pri-1
Project Member

Comment 10 by ClusterFuzz, Jul 25 2016

ClusterFuzz is analyzing your testcase. Developers can follow the progress at https://cluster-fuzz.appspot.com/testcase?key=5675126008053760
Project Member

Comment 11 by bugdroid1@chromium.org, Jul 26 2016

Comment 12 by gogil@stealien.com, Jul 26 2016

ClusterFuzz does not work?

Comment 13 by gogil@stealien.com, Jul 26 2016

Reducing the Run-time.

Please check new attached file.

Moreover, I can control these registers. (Tested on Win10 + 52.0.2743.82 Stable)

(22c8.2038): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
chrome_child!opj_tcd_update_tile_data+0x72:
00007fff`a974f97e 448b4108        mov     r8d,dword ptr [rcx+8] ds:00414138`2d1df401=????????
0:000> r
rax=0000000000414104 rbx=0000018c963085f8 rcx=004141382d1df3f9   <-- `4141` is `J2K_MS_MCT` blocks.
rdx=000000000008281e rsi=0000018c92302860 rdi=0000018c963a6794
rip=00007fffa974f97e rsp=000000364892ac30 rbp=0000000000000001
 r8=0000000000000131  r9=00000000fffffffe r10=0000000000000000
r11=0000018c963286f0 r12=0000000000000004 r13=0000000000000000
r14=0000018c96307b80 r15=0000000000000000
iopl=0         nv up ei pl nz na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
chrome_child!opj_tcd_update_tile_data+0x72:
00007fff`a974f97e 448b4108        mov     r8d,dword ptr [rcx+8] ds:00414138`2d1df401=????????
poc2.pdf
28.1 KB Download
Labels: reward-topanel
Status: Fixed (was: Assigned)
Thanks for the pocs and suggested patch. I've made small modifications and landed it so it should be fixed now.
Project Member

Comment 15 by sheriffbot@chromium.org, Jul 28 2016

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify
Project Member

Comment 16 by sheriffbot@chromium.org, Jul 30 2016

Labels: Merge-Request-53

Comment 17 by dimu@chromium.org, Jul 30 2016

Labels: -Merge-Request-53 Merge-Review-53 Hotlist-Merge-Review
[Automated comment] DEPS changes referenced in bugdroid comments, needs manual review.
Cc: awhalley@chromium.org
Before we approve merge to M53, Could you please confirm whether this change is baked/verified in Canary and safe to merge?

Labels: -Merge-Review-53 Merge-Approved-53
Approving merge to M53 branch 2785 based on chat with awhalley@. Please merge ASAP if possible before 5:00 PM PT today so we can take it for tomorrow's beta release. Thank you.
We're cutting M53 Beta RC today for release tomorrow. Please try to merge your change to M53 branch 2785 before 5:30 PM PT today so we can take it for this week beta. Thank you.
Project Member

Comment 21 by bugdroid1@chromium.org, Aug 2 2016

The following revision refers to this bug:
  https://chrome-internal.googlesource.com/chrome/tools/buildspec/+/8b2094e9fb96be2e67bce39f13de425646e7d04d

commit 8b2094e9fb96be2e67bce39f13de425646e7d04d
Author: Oliver Chang <ochang@google.com>
Date: Tue Aug 02 22:43:59 2016

Labels: -Merge-Approved-53 merge-merged-2785
Not sure why bugdroid didn't set the right labels. 
Labels: -reward-topanel reward-unpaid reward-5000
Congratulations! The panel awarded $5,000 for this one.
Labels: -reward-unpaid reward-inprocess
Labels: -M-52 M-53 Release-0-M53
Labels: CVE-2016-5152
Project Member

Comment 28 by sheriffbot@chromium.org, Nov 3 2016

Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: CVE_description-submitted

Sign in to add a comment