The Year In FlashThe year in Flash bugs, exploits and mitigations

Natalie Silvanovich@natashenka

About me●●●●●Natalie Silvanovich
AKA natashenka AKA Flashtasha
Project Zero member
Previously did mobile security on
Android and BlackBerry
Flash enthusiast
Reporter of ⅓ of Flashvulnerabilities

My goalMy goal● Bug finding is my top priority○○○○

Mostly code review
Some fuzzing (with Mateusz Jurczyk AKA j00ru)
1 bug per day -> 1 bug per week
Flash bugs stay gone

● Analyze external bugs and exploitsMy goal● Occasionally exploit bugs to answer questions○ Is exploitation possible?
○ Is exploitation reliable?
○ How does X impact exploitability● Work on mitigations (with James Forshaw andMark Brand)

This talk

● Attack surface● The year in Flash○ New bugs and bug classes○ 0-days, 1-days and other exploits○ Mitigations● The future?

Flash is ...

● AS2 -- ActionScript 2○○○○

Interpreted legacy Flash Scripts with own VM
Reduced API set
Generally more bugs with lower exploitability
Blurry boundaries between VM and APIs

Flash is ...

● AS3 -- ActionScript 3○ Modern VM with JIT and interpreter■ Extendible■ GC Heap / Fixed Heap
■ Optimized for Flash○ Open source VM○ Open and closed source APIs
○ Bugs are less dense but more exploitableFlash is ...

● Anticorpus○ Functionality outside of script○ MP4 parser, zlib, regex, image decoders, etc

Warning

Timeline
APSA15-03

Aug

July 2015

CVE-2015-5119

CVE-2015-5122
CVE-2015-5123

Hacking Team

SepOctNov

Dec

JanFeb

July 2015
● Large update (36 bugs)● Hacking Team dump
● Mitigations

July 2015
● Hacking Team dump contained two 0-days and two fixedbugs○○○○

ByteArray/OpaqueBackground -- 0-day UaFs due to valueOf redefinition(CVE-2015-0349 and CVE-2015-05122)
ConvolutionFilter issue shown earlier (CVE-2015-3039/CVE-2015-0349)
Integer overflow in Function.apply -- reported via Chromium VRP before use(CVE-2015-0387)
NULL pointer in BitmapData, not exploitable (CVE-2015-05123)

CVE-2015-3039● Redefinition issue in ConvolutionFilter (alsoreported by bilou)● AS2 allows any method to be redefined in script(monkey-patching)● Generally native methods accept any type andconvert objects with valueOf, toString, object
constructor, etc.

CVE-2015-3039[{{ valueOf : ts }]}var filter = new ConvolutionFilter(...);
var n = { valueOf : ts };var a = [];a[0] = n;ConvolutionFilter
filter.matrix = a;function ts(){
float* matrix
filter.matrix = [1];...
}float* []1.0

float* []1.0

July 2015

● valueOf/toString bugs receive increased
attention○ Many similar bugs reported in next few months○ Adobe starts efforts to pre-emptively fix similar bugs

● 33 bugs in regular update● Vector mitigations implemented

Vector Mitigation"I don't afraid Adobe analysts at all" -- Vitaly Toropov● Adds checksums to Vectors that are checked before doing
sensitive functions● Some Vectors are also on their own heap page
● Reduced the reusability of exploit code
● Generally increases the quality of bug needed for an exploit● Substitution of ByteArray or BitmapData is possible, but not
as goodCVE-2015-3130● Redefinition issue involving valueOf[{name:[{name: "john","john", city:city: "omaha"},"omaha"},[]{name:"bob",city:"omaha"},{name: "bob", city: "omaha"}]{valueOf : gl}]CVE-2015-3130
var s = 1;
var rec_array:Array = new Array();
rec_array.push({name: "john", city: "omaha"});rec_array.push({name: "bob", city: "omaha"});rec_array.length = {valueOf : gl};rec_array.sortOn(["name", "city"]);function gl(){if(s< 3){s++;return 100000;}else{
return 2;}}

if (array->getLength() == 0){ return; }int length = array->getLength();char** s = new char*[array->getLength()]memcpy(s, array->items, length);Timeline
APSA15-03

AugJuly 2015

CVE-2015-5119

CVE-2015-5122
CVE-2015-5123

Hacking TeamSepOct

NovDecJanFebAugust 2016

● Many more bugs similar to HT bugs
● MC UaFs pour inCVE-2015-5550 (MovieClip UaFs)● Very common AS2 bug, 100+ reported this year
○ Small variety of freed object● Also works with TextFields● Root cause is that display fields are freed
outside of garbage collection○ Always, for real, even if there are references (in AS2)

CVE-2015-5550 (MovieClip UaFs)● Happens when function parameters areconverted after local variables are initialized, but
before they are used
● Fixed by enforcing convert -> intialize -> useorderCVE-2015-5550 (MovieClip UaFs)

AS2 ScriptObject
void* native_data

var clip1 = this.createEmptyMovieClip("clip1", 1);
var clip2 = this.createEmptyMovieClip("clip2", 2);
var n = {toString: func};
clip1.swapDepths(n);void* destoy_func
table* properties...

MovieClipfunction func(){clip1.removeMovieClip();
return "clip2";}
SO *s = GetObject()
MC *m = native_data[10];...

Timeline
APSA15-03

AugJuly 2015

CVE-2015-5119

CVE-2015-5122
CVE-2015-5123

Hacking TeamSepOctNov

DecJanFebSeptember/October 2015

● 23 bugs in September updates and 20 inOctober○ Mostly UaFs and other redefinition bugs

● 0-day immediately after October update(reported by TrendMicro, NATO targets)

CVE-2015-7645● Reported two weeks before it was found in thewild● Type confusion in serializations, due to weird
AVM behaviour● Two other variants also reported and fixed inemergency patch● None of these bugs compileCVE-2015-7645
From the AVM:// In theory we should reject duplicate slots here;// in practice we don't, as it causes problems with some existing content//if (basetb->findBinding(name, ns) != BIND_NONE)// toplevel->throwVerifyError(kIllegalOverrideError, toplevel->core()>toErrorString(qn), toplevel->core()->toErrorString(this));tl;dr a method can be overridden by a var
Most natives don’t make assumptions, but some do. Especially interfaces.

CVE-2015-7645
class superclass{…
public function writeExternal(){return 1;}}class subclass extends superclass{public var writeExternal:uint = 7;...
}

CVE-2015-7645
From the AVM:
Multiname mn(core->getPublicNamespace(t->pool),core->internConstantStringLatin1(kWriteExternal));m_functionBinding = toplevel->getBinding(t, &mn);

and later:
MethodEnv* method =obj->vtable->methods[AvmCore::bindingToMethodId(info->get_functionBinding())];
method->coerceEnter(argc, argv);

How was this bug exploited?

● Traits property array is variable-sized● Corrupted ByteArray to get R/W access to entire
memory spaceTimeline
APSA15-03

AugJuly 2015

CVE-2015-5119

CVE-2015-5122
CVE-2015-5123

Hacking TeamSepOctNov

DecJanFeb

November and December 2015

● Huge Dec update, 79 bugs, mostly MC UaF○ Structural changes to AS2 to make broad fixes● New mitigations○ Checksumming on ByteArray○ Isolated Heap
○ NOP slide mitigations● Exploit kit 1-day and 0-day

CVE-2015-8446● 1-day in Angler● Similar to CVE-2015-5560● Integer overflow in ID3 allocation○ Controllable size
○ Controllable overwrite● Exploited using BitmapDataCVE-2015-8651● Integer overflow leading to heap overflow in JIT(reported by Huawei)

CVE-2015-8651● SWF contained two exploits○ Typical vector exploit○ Post Isolated Heap exploit including such elements as■■■■Long if statements nested almost 100 times
Using both a media file and an image to fill heap slots at different
points in the exploit
Triggering the bug ~600 times
Final results was memory space access via ByteArray

Timeline
APSA15-03

AugJuly 2015

CVE-2015-5119

CVE-2015-5122
CVE-2015-5123

Hacking TeamSepOctNovDecJan

CVE-2015-8651

FebFebruary 2016● 22 bugs fixed○ UaF straglers○ Fuzz bugs, mostly media○ Exception-related bugs

CVE-2016-0985●●Unusual type confusion in AS3
Occurs due to catching an exception○Should have been fatal error

CVE-2016-0985
try{
var t = new TextField();} catch(e:Error){var t2 = new TextField();}

MovieObjecttext* textAsset...

Assets0001 : myFont (type font)0002 : myVideo (type video)
FFF7 : myFont1 (type font)
text)
...
FFF7 : emptyTxt (type text)

CVE-2016-0984● Read-only UaF in Sound class● Exception-related

CVE-2016-0984

Sound
char* m_pcm...

var s = new Sound();abvar b = new ByteArray(); // 1000 bytes
s.loadPCMFromByteArray(b, 100, "float", false, 2.0);
var c = new ByteArray(); // size 2
try{s.loadPCMFromByteArray(c, 1, "float", false, 2.0);}catch(e:Error){}s.extract(b, 1, 0);c...

Timeline
APSA15-03

Aug

July 2015

CVE-2015-5119

SepOctNovDec

JanFebMar

CVE-2015-8651
CVE-2016-1010

CVE-2015-5122
CVE-2015-5123

Hacking Team

CVE-2016-1019

March 2016● 22 bugs fixed○ More fuzz bugs
■ Exploited one○ UaFs● pwn2own○ 4 MC UaFs, one parsing bug in JPG● 0-day○ Overflow in Bitmap in platform-specific codeCVE-2016-0998● Exploitable fuzz bug● Caused by UaF check● Required ASLR bypass● Got around IsoHeap with JIT pages

CVE-2016-0998
var o = {};o.unwatch();void* args = alloca(numArgs);…
convertToString(args[0])Timeline
APSA15-03

Aug

July 2015

CVE-2015-5119

SepOctNovDec

JanFebMar

Apr

CVE-2015-8651
CVE-2016-1010

CVE-2015-5122
CVE-2015-5123

Hacking Team

CVE-2016-1019

April 2016● 24 bugs fixed○ Fuzzed images○ The UaFs continue● 0-day○ Reported by TrendMicro in Magnitude EK○ Type confusion in FileReference○ Did not work on current mitigation set (0 on free)CVE-2016-1019●●●0-day vulnerability
Reported some variants
Type confusion in AS2

CVE-2016-1019
var o = { toString : f };var t = new TextField(o);function f(){var fr = FileReference
fr.call(this);}FileReference
TextField
AS2 ScriptObjectchar*
int other_prop
some_prop
void* native_data
...
Type
Type
type
type
= FR
TF
table* properties...

Timeline
APSA15-03

Aug

July 2015

CVE-2015-5119

Sep

Oct

Nov

Dec

JanFeb

Mar

Apr

May

CVE-2015-8651
CVE-2016-1019

CVE-2015-5122
CVE-2015-5123

Hacking Team

CVE-2016-4117

Timeline
APSA15-03

AugJuly 2015

CVE-2015-5119

Sep

Oct

Nov

Dec

JanFebMarAprMay

Jun

CVE-2016-4171CVE-2015-8651
CVE-2016-1019

CVE-2015-5122
CVE-2015-5123

Hacking Team

CVE-2016-4117

June 2016

● 36 bugs fixed○ MC UaFs (echo from pwn2own)● 0-day○ Reported by Kaspersky○ OOB memory access in open source parser

CVE-2016-4171
void AbcParser::parseExecPolicyAttributes(const uint8_t*
metadata, MethodInfo* m){...
for (int q = 0; q < values_count; ++q){
Stringp key = pool->getString(readU30(p));
Stringp val = pool->getString(readU30(p));

CVE-2016-4171
Stringp PoolObject::getString(int32_t index) const{
ConstantStringData* dataP = _abcStrings->data + index;
if (dataP->abcPtr >= _abcStringStart && dataP->abcPtr <_abcStringEnd){uint32_t len = AvmCore::readU32(dataP->abcPtr);
Stringp s = core->internStringUTF8((const char*) dataP>abcPtr, len, true, false);
s->Stick();
dataP->abcPtr = NULLWBRC(core->gc, _abcStrings, &dataP->str, s);}return dataP->str;}

Conclusions● Finding bugs in Flash is generally getting harder○ 1 bug per day versus 1 per week
● Certain bug classes are drying up, but others aretaking their places● Flash mitigations are making it more difficult toexploit bugs, especially with low-quality bugs

The Future (What’s left?)● MC UaFs (and AS2) probably still exist, butgetting hard to exploit○ Eventually similar bugs will have marginal utility○ Display UaFs in AS3?

● Redefinition bugs are no longer ‘deep’● More AS3 bugs?

The Future (What’s left?)● More anticorpus bugs / use of anti-corpus?
○ Media (MP4, FLV)

● Open source AVM?
● Platform-specific code
● Flash deprecation○ Browsers?

Thank You● AdobeQuestions?

http://googleprojectzero.blogspot.com/@natashenka
natalie@natashenka.ca