[SWF] CVE-2015-7645

[SWF] CVE-2015-7645

0x00. Intro

  • Vender : Adobe
  • Used : Sofacy Group
  • Target : foreign affairs ministries (외교부처)
  • Method : Spear Phishing By E-mail
  • Vulnerability Type : Method Confusion

0x10. TimeLine

0x20. Summary

CVE-2015-7645 취약점은 "잘못된 주소 참조"에 따른 취약점이라 할 수 있는 Type Confusion 취약점이다. 좀 더 정확히 표현하자면 Type Confusion 중 Method Confusion이다.

  • 취약점 Method : IExternalizable.writeExternal

즉, writeExternal을 Method가 아닌 Value로 오버로딩 후 접근할 때 Memory Corruption이 발생해 "잘못된 주소 참조"가 발생한다.

  • 발생 위치 : AVM Serializer

따라서 IExternalizable.writeExternal의 오버로딩이 어떻게 이루어졌는지를 확인하면 취약점이 존재하는 SWF 파일인지 여부를 판단할 수 있다.

0x30. Analyze - 동적 분석

0x40. Analyze - 정적 분석

  • 사용 도구 : JPEXS Free Decompiler
  • 샘플(SHA-256) : CE3C0DA64772F3BEAF7C0F25A85459D7B82E199EDDB56F737C823B2DC51F310D
  • 악성동작이 없는 PoC 샘플

Method Confusion이 발생하기 위해선 함수 오버로딩이 필요하므로 다수의 DoABC 태그가 존재한다.

그 중 마지막 DoABC Tag를 디컴파일하면 위와 같이 취약한 Method를 오버로딩하는 것을 볼 수 있다. PoC 샘플이므로 위의 그림과 같이 pushstring 명령어를 통해 실제 취약점이 발생할 때 사용할 데이터를 넣는 위치를 확인할 수 있다. 이러한 점을 바탕으로 현재까지 다음과 같은 패턴을 알 수 있다.

  • 패턴 1. DoABC Tag 내에서 IExternalizable.writeExternal을 오버로딩 한다.
  • 패턴 2. 함수 오버로딩을 위해 3개 이상의 DoABC Tag가 존재한다.

이러한 패턴을 바탕으로 분석대상 SWF 파일의 악성 여부를 판단해 볼 수 있다.

PySWF의 확장모듈로 개발한 모듈을 통해 디스어셈블리하면 다음과 같은 AVM2 Code를 볼 수 있다.

[DoABC1]

0xd0    getlocal_0
0x30    pushscope
0xf1    debugfile(C:\Users\natashenka\Adobe Flash Builder 4.7\externalizable\src;;externalizable.as)
0xef    debug (Type:0x1, Name:b, Register:0x00000000)
0xef    debug (Type:0x1, Name:obj, Register:0x00000001)
0xd0    getlocal_0
0x49    constructsuper (arg_count: 0x00000000)
0x5d    findpropstrict Package :subexternalizable
0xf0    debugline(Line:0x0000000c)
0x4a    Package :subexternalizable(arg_count: 0x00000000)
0xd6    setlocal_2
0x60    getlex Package flash.net:registerClassAlias
0x64    getglobalscope
0xf0    debugline(Line:0x0000000d)
0x2c    pushstring test
0x60    getlex Package :subexternalizable
0x41    call(arg_count: 2)
0x29    pop
0x5d    findpropstrict Package flash.utils:ByteArray
0xf0    debugline(Line:0x0000000e)
0x4a    Package flash.utils:ByteArray(arg_count: 0x00000000)
0xd5    setlocal_1
0xd1    getlocal_1
0xd2    getlocal_2
0xf0    debugline(Line:0x0000000f)
0x46    writeObject:['Private externalizable', 'Protected externalizable', 'Static externalizable', 'Static flash.display:Sprite', 'Static flash.display:DisplayObjectContainer', 'Static flash.display:InteractiveObject', 'Static flash.display:DisplayObject', 'Static flash.events:EventDispatcher', 'Static Object', 'Package ', 'Internal ', 'Private FilePrivateNS:externalizable', 'Namespace http://adobe.com/AS3/2006/builtin'](arg_count: 1)
0x29    pop
0x47    return void

0x47    return void

0xd0    getlocal_0
0x30    pushscope
0x65    getscopeobject (local_scope_stack: 0x00000000)
0x60    getlex Package :Object
0x30    pushscope
0x60    getlex Package flash.events:EventDispatcher
0x30    pushscope
0x60    getlex Package flash.display:DisplayObject
0x30    pushscope
0x60    getlex Package flash.display:InteractiveObject
0x30    pushscope
0x60    getlex Package flash.display:DisplayObjectContainer
0x30    pushscope
0x60    getlex Package flash.display:Sprite
0x2a    dup
0x30    pushscope
0x58    newclass({'traits': [], 'method': {'return_type': None, 'param_type': ['*'], 'name': None}})
0x1d    popscope
0x1d    popscope
0x1d    popscope
0x1d    popscope
0x1d    popscope
0x1d    popscope
0x68    initproperty Package :externalizable
0x47    return void

[DoABC2]

0xd0    getlocal_0
0x30    pushscope
0xf1    debugfile(C:\Users\natashenka\Adobe Flash Builder 4.7\externalizable\src;;superexternalizable.as)
0xef    debug (Type:0x1, Name:input, Register:0x00000000)
0x60    getlex Package :trace
0x64    getglobalscope
0xf0    debugline(Line:0x00000014)
0x2c    pushstring in read external
0x41    call(arg_count: 1)
0x29    pop
0x47    return void

0xd0    getlocal_0
0x30    pushscope
0xf1    debugfile(C:\Users\natashenka\Adobe Flash Builder 4.7\externalizable\src;;superexternalizable.as)
0xef    debug (Type:0x1, Name:output, Register:0x00000000)
0x60    getlex Package :trace
0x64    getglobalscope
0xf0    debugline(Line:0x0000001a)
0x2c    pushstring in write external!!!
0x41    call(arg_count: 1)
0x29    pop
0x47    return void
None
0xd0    getlocal_0
0x30    pushscope
0xf1    debugfile(C:\Users\natashenka\Adobe Flash Builder 4.7\externalizable\src;;superexternalizable.as)
0xd0    getlocal_0
0x49    constructsuper (arg_count: 0x00000000)
0x47    return void

0x47    return void

0xd0    getlocal_0
0x30    pushscope
0x65    getscopeobject (local_scope_stack: 0x00000000)
0x60    getlex Package :Object
0x2a    dup
0x30    pushscope
0x58    newclass({'traits': [], 'method': {'return_type': None, 'param_type': ['*'], 'name': None}})
0x1d    popscope
0x68    initproperty Package :superexternalizable
0x47    return void

[DoABC3]

0xd0    getlocal_0
0x30    pushscope
0xf1    debugfile(C:\Users\natashenka\Adobe Flash Builder 4.7\externalizable\src;;subexternalizable.as)
0xef    debug (Type:0x1, Name:a, Register:0x00000000)
0x60    getlex Package :trace
0x64    getglobalscope
0xf0    debugline(Line:0x0000000e)
0x2c    pushstring in test
0x41    call(arg_count: 1)
0x29    pop
0xf0    debugline(Line:0x0000000f)
0x24    push 0x7
0x48    return value

0xd0    getlocal_0
0x30    pushscope
0xf1    debugfile(C:\Users\natashenka\Adobe Flash Builder 4.7\externalizable\src;;subexternalizable.as)
0xf0    debugline(Line:0x0000000a)
0xd0    getlocal_0
0x49    constructsuper (arg_count: 0x00000000)
0x47    return void

0x47    return void

0xd0    getlocal_0
0x30    pushscope
0x65    getscopeobject (local_scope_stack: 0x00000000)
0x60    getlex Package :Object
0x30    pushscope
0x60    getlex Package :superexternalizable
0x2a    dup
0x30    pushscope
0x58    newclass({'traits': [], 'method': {'return_type': None, 'param_type': ['*'], 'name': None}})
0x1d    popscope
0x1d    popscope
0x68    initproperty Package :subexternalizable
0x47    return void

0x90. Bug

댓글

가장 많이 본 글