Knock, Knock, Let me In: Evaluating Attack Susceptibility

Report
An Examination of String
Allocations: IE-9 Edition
Chris Valasek, Director of Security Intelligence
IOActive
@nudehaberdasher
An Examination of String
Allocations: IE-9 Edition
An Examination of String
Allocations: IE-9 & 10 Edition
An Examination of String
Allocations: IE-9 to11 Edition
Chris Valasek, Director of Security Intelligence
IOActive
@nudehaberdasher
Introduction
Chris Valasek
•
•
•
•
•
•
Director of Security Intel @ IOA
<3 Windows memory stuff
Car Hacking!
Pittsburgh PA USA
Chairman of Summercon
Fun Fact: I like cheese
Overview
•
•
•
•
•
•
•
Brief history of Javascript string allocations in IE6-7
JavaScript string changes in IE-9
IE-9 Core JavaScript Methods
IE-9 DOM Strings
Premier: heapLib2
Note: Non-comprehensive list
Note: Algorithms seem to be the same for IE-10 and IE-11
Why?
•
•
•
•
Nico’s APT talk at Blackhat USA 2010 mentioned the following:
“IE 8 introduced a weak heap spray protection”
There didn’t appear to be any public information explaining the
statement
Sotirov published “Heap Feng Shui” but no such information was
available for IE-9 (Skipping IE-8 at this point…)
Memory management makes me smile…then scream…then
cry…then smile again.
Impact
•
Browser exploitation requires knowledge of sizes / objects for
subsequent allocation/de-allocation of those objects
•
•
•
For example: Use-after-free bugs, to be exploited without ‘pray-after-free’,
will require intricate knowledge of object sizes and subsequent
allocations/frees
Heap spraying still tends to be common during browser
exploitation but has had limited updates since IE-8
•
See Corelan Team & Nico’s references in later slides
Exploitation can take less time with added knowledge of JS and
DOM objects
Requisite Reading
•
•
•
Nico Waisman – “Aleatory Persistent Threat”
http://www.immunitysec.com/downloads/APT_kiwicon.pdf
Alex Sotirov – “Heap Feng Shui in JavaScript”
http://www.phreedom.org/research/heap-feng-shui/
Dowd, Smith, Dewey – “Attacking Interoperability”
http://www.hustlelabs.com/stuff/bh2009_dowd_smith_dewey.pdf
History
History: I
•
•
•
Heap spraying made wildly popular by Skylined in MS04-040
•
Wow, its been a long time
Sotirov documented the allocation / de-allocation process
•
•
•
Concatenating strings could cause allocations (jscript!JsStrConcat)
Creating substrings could cause allocations (jscript!JsStrSubstrCore)
Freeing of chunks could be achieved by setting a string to NULL and
performing garbage collection
It was quite easy to make allocations in IE6-7
History: II
Each iteration of the loop would create a new copy of the string, storing it in the array
History: III
•
•
•
The aforementioned method no longer worked in IE-8
Corelan Team suggested some variations
•
https://www.corelan.be/index.php/2011/12/31/exploit-writing-tutorialpart-11-heap-spraying-demystified/
Nico also suggested a work around (that inspired this research)
History: IV
Substring? Array Assignment? Not really sure since I didn’t look at IE-8
IE-9 Strings
JavaScript Strings: IE-9
•
•
•
•
Not just a simple bstr object anymore
Concatenation and substring calls don’t mindlessly allocate
memory
Jscript9.dll has replaced jscript.dll
•
Jscript.dll is NOT loaded in IE-9
Versions
•
•
Jscript9.dll 9.0.8112.16450 (might be a few versions off)
Mshtml.dll 9.0.8112.16464
Core Methods
Core: ArenaLiteralString
•
•
•
•
Js::ArenaLiteralString::New
Base for static strings created in JS
•
•
•
Var a = “CHRIS”;
Var b = new String(“Chris”);
Var c = unescape(“%u9090”);
Transformed as needed
•
Example: unescape() == Js::StringBuilderString::New()
The strings are allocated from an arena, so you won’t see
allocations for individual strings in default heap
•
Var a = “AAAABBBB” != malloc((a.length * 2) + 6) [Like it did in IE-6]
Core: ConcatString
•
•
•
•
•
Js::ConcatString::New
Stores pointers to the concat-er and concat-ee
No longer will allocate per concatenation
•
We’ll see later how and were allocations occur
The strings passed can be any JavascriptString
•
StringBuilderString, ArenaLiteralString, even another ConcatString
Smells like:
Core: ConcatString cont.
The ConcatString objects come from pre-allocated, page aligned HeapBuckets.
Core: ConcatString cont. II
Pointers are stored instead of allocating/copying data.
Core: SubString
•
•
•
•
Js::SubString::New
Will expand the JavaScript string if need be
•
Allocations will come from PageAllocator, so completely controlled
allocations will not occur 
Holds references and will expand/flatten only 1x
Smells like:
Core: SubString cont.
Core: Example
Core: Example Part I
•
Events
•
•
•
•
•
Js::ArenaLiteralString::New with “%u9090%u9090%u9090%u9090”
•
•
The string has yet to be unescaped at this point
Also, the memory holding the string isn’t allocated from the default heap, instead it uses a
page-based allocator for string objects
Js::GlobalObject::EntryUnEscape
•
•
Convert the values to 0x9090 0x9090 0x9090
Call the functions below….
Js::JavascriptConversion::ToString
Js::StringBuilderString::New
As you see, this does NOT have a precise allocation from the
default heap
Core: Example Part II
•
Iterations
1.
2.
3.
4.
5.
•
•
ConcatString [LHS=>str_builder, RHS=>str_builder, length=>0x10]
•
LHS => StringBuilderString | RHS = StringBuilderString
ConcatString [LHS=>str_builder, RHS=>str_builder, length=>0x20]
•
LHS => ConcatString | RHS = ConcatString
ConcatString [LHS=>str_builder, RHS=>str_builder, length=>0x40]
•
LHS => ConcatString | RHS = ConcatString
ConcatString [LHS=>str_builder, RHS=>str_builder, length=>0x80]
•
LHS => ConcatString | RHS = ConcatString
ConcatString [LHS=>str_builder, RHS=>str_builder, length=>0x100]
•
LHS => ConcatString | RHS = ConcatString
After the 1st iteration ‘str_builder’ is now a ConcatString
No allocation occur during this process
•
Also ConcatString->str == NULL
Core: Example Part III
•
Events
•
•
•
•
•
•
•
•
Js::Substring::New passing the ConcatString created in our loop
If str_builder->str == NULL { str_builder->GetSz }
•
This is the case, so Js::ConcatString::GetSz() will be called
Js::ConcatString::GetSz() will call Js::ConcatString::Flatten
Js::ConcatString::Flatten call Recycler::AllocLeaf
Recycler::AllocLeaf check size
If str_builder.length < 0x400
HeapBucket::SnailAlloc(Recycler, this, Round16(str_builder.length), 0);
*This will allocate from the Recyler PagePool
If str_builder.length >= 0x400
Recycler::TryLargeAlloc(str_builder.length, this, Recycler, 0);
*This can possibly trigger a call to VirtualAlloc, but won’t be exact
*VirtualMemory Allocation granularity
Again, not precise direct allocations from default heap…
Core: Example Part IV
•
Events
•
•
•
•
Js::Substring::New passing the ConcatString created in our loop
If str_builder->str == NULL { str_builder->GetSz }
•
This is the case, so Js::ConcatString::GetSz() will be NOT called
Since our ConcatString has been flattened / copied in the previous call to
“substring” it doesn’t need to happen again
String allocation from the pool only happens once to avoid the need of
multiple copies of the same string
Core: Conclusion
•
•
•
•
•
Static strings are allocated from a page-aligned memory
•
i.e. var a = “CHRIS” does NOT directly hit the default heap
JavaScript objects are allocated from HeapBuckets
•
•
i.e. ConcatString, SubString, etc
HeapBucket is pooled memory which will only alloc from default heap in
pages
Much more efficient an allocations for substrings/concatenations
While not officially ‘heap spray protection’, it does prevent
previous methods from achieving their goal
Are there still ways to get allocations from the default process
heap with JS strings?
•
Hint: Yup
DOM Memory Management
DOM: Elements
•
•
•
•
•
Most familiar piece of the Document Object Model
Each tag is allocated from the default process heap
Each tag also consists of a certain amount of bytes
For example:
•
•
Anchor Tag “<A>” == 0x64 byte allocation
Bold Tag “<B>” == 0x30 byte allocation
Simple way to create elements statically or dynamically for
precise allocations from the default heap
DOM: Elements cont.
•
•
•
I’ve created a script that will attempt to pull the allocation call
for each HTML tag in MSHTML.DLL
Nico’s chart in his APT talk. Instead of re-creating I wrote a script
It’s called “get_elements.py”
DOM: Attributes
•
•
•
•
•
•
Element attributes are allocated directly (well, sort of) from the
default heap
They last the lifetime of the page (or until you remove them)
•
i.e. fully controlled
Creates null terminated string
•
<string><2-byte NULL>
They have a certain Variant type
•
See Dowd, Smith, Dewey paper
Certain global attributes exist for all elements, such as ‘title’
See mshtml_1.html
DOM: Custom Attributes
•
•
•
•
•
•
•
HTML5 supports custom attributes
For example: <h1 wonk-attr=“specialvalue”>Hello</h1>
•
Yes I know this breaks W3 standards. Should start with “data-”
Above custom attribute with the name “wonk-attr”
The value “specialvalue” will be allocated based on its string
length from the default process heap!
They last the lifetime of the page (or until you remove them)
•
i.e. fully controlled
Creates your typical bstr object
•
<DWORD size><string><2-byte NULL>
See mshtml_2.html
DOM: Attribute Shellcode
•
•
•
•
Since we know that attributes can be used to directly allocate
user-controlled amounts of data from the default process heap…
Let’s have UTF-8 and UTF-16 be our friends
‘html_spray.py’
•
•
•
Python code to generate massive payload statically in HTML
Gzip from the server, drastically shrinking the size, and send to client
*Note: I haven’t not thoroughly tested this, only saw allocations working
See ‘html_spray.html’
DOM: Static Attributes
•
•
•
•
All the attributes we talked about in the last few slides would
static. i.e. known before the DOM has been laid out
Follow the call chain:
•
•
•
•
MSHTML!BASICPROPPARAMS::SetString
=>MSHTML!CAttrArray::SetString
=> CAttrValue::InitVariant
=> MSHTML!_HeapAllocString
_HeapAllocString will allocate the amount of bytes in the string
from the default process heap and copy the data
But I don’t wanna create all the elements before hand….
DOM: Credit
•
•
•
•
•
Corelan Team had the right idea
Certain attributes exist for all elements, such as ‘title’
https://www.corelan.be/index.php/2013/02/19/deps-preciseheap-spray-on-firefox-and-ie10/
There’s a reason this works really well
•
‘title’ is a slightly different variant type as opposed to custom attribute
Attributes are just another Variant type in IE
•
See Dowd, Smith, Dewey paper
Custom Attributes
Custom Attibutes: Creation
•
I’m a learn by example type of guy….
Custom Attributes: Creation cont.
•
Call to ‘setAttribute()’ will marshal the JavascriptString to a bstr
used by the DOM
•
•
•
•
DispatchHelper::MarshalJsVarsToVariants
This lazy allocation ensures that the PageAllocator is used for JS strings
while the default process heap is only required when necessary, such as
augmenting the DOM
Dynamically Created Custom Attribute: Call chain
•
•
•
•
•
•
MSHTML!CAttrArray::SetAt
=> MSHTML!CAttrValue::InitVariant (Type 0x08)
=> MSHTML!EdUtil::FormsAllocStringW
=> OLEAUT32!SysAllocString
=> OLEAUT32!SysAllocStringLen
=> OLEAUT32!APP_DATA::AllocCachedMem
That last one looks familiar!
Dynamic Attribute Assign: Sidebar
•
•
•
Not all attributes are created equal
•
•
•
•
•
Global Attribute (title, class, lang, etc)
MSHTML!CAttrArray::SetString
=> MSHTML!CAttrArray::Set
=> MSHTML!CAttrValue::InitVariant (Type 0x31)
=> MSHTML!_HeapAllocString
You can see, for instance, that the ‘title’ attribute would bypass
the cache allocator, directly accessing the default process heap
Good work Corelan Team, just wanted to point out intricacies ;)
•
Hint: There are probably more. Look for XREFS to _HeapAllocString
Custom Attributes: Destruction
•
•
•
•
•
Can we free memory at will too?
Sure we can!
In the previous example we saw that ‘setAttribute(name, value)’
was used to allocate memory
All we have to do is ‘setAttribute(name, null)’ and the value will
be freed!
•
•
•
•
MSHTML!CAttrArray::SetAt
=> MSHTML!CAttrValue::Free
=> kernel32!HeapFree
=> ntdll!RtlFreeHeap
Now we have a plan for heap massaging!
heapLib2
heapLib2: Overview
•
•
•
•
•
•
•
I saw that dynamic custom attributes were allocated from
OLEAUT32!APP_DATA::AllocCachedMem
After investigation, I realized the allocator hasn’t changed since
IE-6
So long as I can refactor the plunger technique written by Sotirov
years ago, we can have precision allocations
See: http://www.phreedom.org/research/heap-feng-shui/
Steps
•
•
Populate cache before freeing
Clear cache before allocating
Also, since we can create large strings in JS and marshal them to
the default process heap, we can heap spray like it’s 2004 
Note: There is overhead with creating attributes
malloc(0x60) being one of many….
heapLib2: Example
heapLib2: Demo
Conclusions
Conclusions
•
•
•
•
•
•
Precise allocations are nearly impossible to achieve directly from
Javascript in IE-9
This seems like ‘heap spray protection’ but I think was more of
an architecture change
•
Someone from MSFT let me know if I’m wrong
To make allocations directly from the default process heap one
can leverage the DOM
I found that custom attributes were a nifty way of doing this
heapLib2 permits allocations of arbitrary sizes and provides
functionality to do easy heap sprays
There is a bunch more research to be had
•
The Recyler is really neat / confusing
Continuation!
•
•
•
•
•
•
I’ll be releasing a white paper at some point
Much more information about DOM / JS objects
Detailed notes: Recycler, HeapBuckets, PoolAllocator, etc
Follow me on Twitter (@nudehaberdasher) and check the
IOActive blog as I’ll be putting slides, examples, and heapLib2 for
public download
Alex Sotirov should get most of the credit as he figured all this
stuff out years ago, I just augmented it to work w/ IE-9 – IE-11
Thanks!
Questions?
Chris Valasek
[email protected]
[email protected]
@nudehaberdasher

similar documents