|
|
Adobe Flash stack corruption when decoding JPEG-XR image | ||||
| Project Member Reported by scvitti@google.com, Mar 16 2015 | Back to list | ||||
Adobe Flash supports decoding of JPEG-XR images. This functionality is enabled by default. Diving into the function _jxr_r_MB_LP there is a stack overflow when indexing into an integer array. The flash code for this appears to closely match the ITU reference implementation (http://www.itu.int/rec/T-REC-T.835-201201-I/en) so I will reference that C code here to show the vulnerability: file r_parse.c in function _jxr_r_MB_LP: 0 int RLCoeffs[32] = {0}; 1 ... 2 int num_nonzero = 0; 3 ... 4 num_nonzero = r_DECODE_BLOCK(image, str, 5 chroma_flag, RLCoeffs, 1/*LP*/, location); 6 7 DEBUG(" : num_nonzero = %d\n", num_nonzero); 8 assert(num_nonzero <= 16); 9 10 if ((image->use_clr_fmt==1 || image->use_clr_fmt==2) && chroma_flag) { 11 static const int remap_arr[] = {4, 1, 2, 3, 5, 6, 7}; 12 int temp[14]; 13 int idx; 14 for (idx = 0 ; idx < 14 ; idx += 1) 15 temp[idx] = 0; 16 17 int remap_off = 0; 18 if (image->use_clr_fmt==1/*YUV420*/) 19 remap_off = 1; 20 21 int count_chr = 14; 22 if (image->use_clr_fmt==1/*YUV420*/) 23 count_chr = 6; 24 25 int k, i = 0; 26 for (k = 0; k < num_nonzero; k+=1) { 27 i += RLCoeffs[k*2+0]; 28 temp[i] = RLCoeffs[k*2+1]; 29 i += 1; 30 } 31 ... On line 12 an integer array named temp is declared on the stack with 14 elements. On line 26 that integer array is populated in a for loop running from 0 to a maximum value of 16 iterations. The flash binary shows there is an explicit check on line 8 to bound num_nonzero to <= 16. On it's face this loop could write 2 integers beyond the end of the temp stack buffer. The last available index into tmp is 13 and the loop can write to index 14 and 15 just following the i+=1 on line 29. However, it's worse than that due to the fact that the i variable increases not just by 1 each time through the loop but also by another user supplied value on line 27! The RLCoeffs array is populated with user data on line 4 with the r_DECODE_BLOCK function. The stack frame for this function looks like this: ... -000000BC RLCoeffs dd 32 dup(?) -0000003C temp dd 14 dup(?) -00000004 cookie dd ? +00000000 s db 4 dup(?) +00000004 r db 4 dup(?) +00000008 image dd ? ... Compiler settings are good with the arrays at the end of the stack and a canary value between them and the saved ebp and return address. However, because we are writing to the stack non-sequentially it's possible to hop over the stack cookie and corrupt other bits of the stack. PoC attached. There are three files: LoadImg.as - Action Script that will load the file img.img LoadImg.swf - Compiled LoadImg.as file img.img - proof of concept JPEG-XR to exercise the vulnerability When loading LoadImg.swf through Chrome flash will request and load the img.img file. The vulnerabile function is hit when the image is being decoded. It is called multiple times but the one that exercises the stack corruption will set num_nonzero to 8 and will then index out of bounds of the temp array to hop over the stack canary to corrupt saved ebp with a negitive value. A crash will occur two instructions after _jxr_r_MB_LP returns in Windows 7 32-bit running Chrome 41.0.2272.89: 63bd26dc e80e47ffff call pepflashplayer!PPP_ShutdownBroker+0x4d5bfc (63bc6def) ; _jxr_r_MB_LP 63bd26e1 83c410 add esp,10h 63bd26e4 ff75f4 push dword ptr [ebp-0Ch] ss:0023:ffffffef=???????? eax=0716a340 ebx=0716a000 ecx=50b3cf2a edx=00000000 esi=0716a80c edi=001ad16c eip=63bd26e4 esp=001ad0e4 ebp=fffffffb iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206 pepflashplayer!PPP_ShutdownBroker+0x4e14f1: 63bd26e4 ff75f4 push dword ptr [ebp-0Ch] ss:0023:ffffffef=???????? This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public.
Project Member
Comment 1
by
scvitti@google.com,
Mar 17 2015
,
Apr 2 2015
,
Apr 10 2015
,
Apr 14 2015
,
Apr 22 2015
|
|||||
| ► Sign in to add a comment | |||||