New issue
Advanced search Search tips
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
link

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

Comment 1 by kerrnel@chromium.org, Jul 20 2016

Owner: tsepez@chromium.org
This is in pdfium, Tom is this something you can take a look at?

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

Project Member
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

Comment 5 by kerrnel@chromium.org, Jul 22 2016

Labels: Security_Severity-High Security_Impact-Stable

Comment 6 by kerrnel@chromium.org, Jul 22 2016

Components: Internals>Plugins>PDF

Comment 7 by kerrnel@chromium.org, Jul 22 2016

Labels: OS-All

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

Project Member
Labels: M-52

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

Project Member
Labels: Pri-1

Comment 10 by ClusterFuzz, Jul 25 2016

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

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

Project Member

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

Comment 14 by och...@chromium.org, Jul 27 2016

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.

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

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

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

Project Member
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.

Comment 18 by gov...@chromium.org, Aug 1 2016

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?

Comment 19 by gov...@chromium.org, Aug 2 2016

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.

Comment 20 by gov...@chromium.org, Aug 2 2016

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.

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

Project Member

Comment 22 by och...@chromium.org, Aug 2 2016

Labels: -Merge-Approved-53 merge-merged-2785
Not sure why bugdroid didn't set the right labels.

Comment 23 by awhalley@chromium.org, Aug 24 2016

Labels: -reward-topanel reward-unpaid reward-5000

Comment 24 by awhalley@chromium.org, Aug 25 2016

Congratulations! The panel awarded $5,000 for this one.

Comment 25 by awhalley@chromium.org, Aug 26 2016

Labels: -reward-unpaid reward-inprocess

Comment 26 by awhalley@chromium.org, Aug 30 2016

Labels: -M-52 M-53 Release-0-M53

Comment 27 by awhalley@chromium.org, Sep 14 2016

Labels: CVE-2016-5152

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

Project Member
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

Comment 29 by awhalley@chromium.org, Apr 25 2018

Labels: CVE_description-submitted

Sign in to add a comment