Dear viewer, these subtitles were generated by a machine via the service Trint and therefore are (very) buggy. If you are capable, please help us to create good quality subtitles: https://c3subtitles.de/talk/1072 Thanks!
[Music]
jonathan wonderful good morning
you're gonna tell us about the last 12
months on what you have done
so your talk is called from zero to zero
day
this is jonathan jay from the msrc in
israel a division of microsoft and the
stage is yours and that is your applause
thank you
so hi everyone
my name is jonathan and i'm a security
researcher in an msrc in israel
on my free time i play ctfs with team
perfect blue and i also do research on
my own
i'm just an 18 year old and i started
doing security related stuff last year
so the first part of this talk is going
to be about what i learned in a past
year and how i learned it so if you're
just starting off in security and you
want to
learn what
to pick up what i did and learn from
what what i did
this is uh this could be helpful for you
and for the more experienced security
researchers in the audience the second
part of this talk is going to be about a
zero day i found in chakra a jit type
confusion
so we're going to die
we're going to dive deep into that and
even if you're just starting in security
a basic understanding in programming is
probably going to be enough to follow up
there's going to be a lot of code but
it's fine it's not too complex
and last but not least we're going to
finish up with a demo hopefully working
one
so yeah let's let's start off so why
vulnerability research
vulnerabilities are for me some sort of
riddles there's some sort of
very challenging riddles that we have to
find some flaws that the developers did
not consider
this is very challenging and very
interesting for me at least and i found
it awesome to to do so what is a
vulnerability there are a lot of
definitions to it and when when you want
to understand something you start a job
on wikipedia um there are a lot of
definitions as you can see it's somewhat
weird like the probability that an asset
will be unable to resist the actions of
a threat agent
i don't know what that means um yeah for
me a vulnerability is some sort of flaw
in a program that allows you to
change the intended flow of the of the
program
that's what i consider as a
vulnerability and the definitions we've
just seen do not really tell me how i
find them so how do we find
vulnerabilities
so when when i started i had some
knowledge in programming i wasn't i
wasn't the best developer out there i
was just a decent one an underground
level and c and assembling and os
internals to understand how things
actually work in python to actually
write some code
so i wasn't the best developer but i had
some knowledge
for example i read the c programming
language which is a great book and will
give you all the c knowledge you need to
know in order to actually
get into vulnerability research
the next thing i did was to expose
myself to vulnerability research basics
so i read online about some basic
vulnerabilities like classic stack
buffer overflows like enterage overflows
and so on
and then i try to practice my knowledge
and that was through war games war games
are some challenges that are offline and
you can try to solve them there are
security related challenges like you
have to find some vulnerability and
exploit it
so that's what i did next and at first i
failed like badly but it's okay because
i read the solutions i read the write
apps and i learned how to actually
approach the solutions and actually how
to solve them so it comes with time and
it's okay to fail because we all do
the next thing i did was to expose
myself to ctfs now ctfs are
capture the flag contests and they're
basically competitions
where you have to solve some challenges
and compete against other teams this is
a team effort and you play with other
players your friends and this is how i
met my teammates so we met through uh
ctfs through irc and we play together
and sometimes we fail like miserably but
sometimes we actually do well and we got
to qualify to some finals and we
actually got to travel the world because
when you qualify the finals they
sometimes pay for the trip so we
actually got to see some cool places and
yeah that was awesome
and
i actually think ctf's are a great way
to get into security
so
next thing i did
was i dove into the deep water so once
you know the basics it's important to
not stay there for too long you have to
expose yourself to harder things i try i
was afraid to see and try to solve the
harder challenges at first but with time
i managed to understand that
nothing too bad would happen even if i
fail
so i try to solve challenges and i
failed but with time i managed to pick
up the tricks and the ways to solve to
solve the harder challenges
and i think this is very important to
not be afraid to solve things because
even if you fail you learn from others
other people's solutions and it's fine
it's totally okay
a great tweet by live overflow which
also should be in the audience or in the
top in the conference and basically says
what i really believe in which is move
away from the basics as soon as possible
and expose yourself to harder things
which you don't understand this will
make you understand things that you
thought you understood but you actually
didn't
and also it's important to learn from
different resources this way you learn
different tricks and different ways to
approach uh problem solving and it's
very important in my opinion
so yeah live overflows also has a great
youtube channel which i also watch and
he talks about vulnerability and
security uh research and i really
recommend watching his videos as well
so
after i had some knowledge and
like ctfs and war games i practiced and
i practiced a lot so it's really
important to practice and solve
challenges on your own because this way
you actually get to
pick up those
tricks that you have to understand in
order to solve some challenges so some
vulnerabilities have patterns in them
and the way you catch on those patterns
is by seeing them quite a few times and
a great way to do that and to pick that
up is by solving a lot of challenges
um this is where i also expose myself to
actual real world vulnerabilities i did
that through uh like a lot of websites
there's the project zero bug tracker
which you have you can read the
vulnerabilities and
about exploits and and all and so on
so
this is where i also expose myself to
real-world vulnerabilities and i also
realized that uh there is a great
connection between vulnerabilities in
ctfs and in real world so
vulnerabilities are essentially bugs and
they exist both in ctfs and in real life
and the the main problem that you think
you have when you actually try to
do real world research is that you think
that the code base is huge and stuff
like that but even if the code base is
your bugs are still out there so don't
be afraid to look at it because the odds
of vulnerabilities running out just when
you're starting to look at something are
very low so you can start to try and
solve things and by solving things i
mean looking at actual code bases
after doing some practice i realized
that how do we find our vulnerabilities
and once we actually start and repeat
the process of solving challenges and
practicing we notice that
vulnerability research is about
identifying bugs and we do that by
looking at code so looking at code is
essentially understanding the code and
we have to find vulnerabilities in it
right because we want to find them
and that's through actually auditing the
code and that comes with practice so
practice is really important in
vulnerability research and once we must
we master that even though i'm not a
master and i'm not near anywhere that i
still think that practice is important
so how do we actually find
vulnerabilities so after as i said
before vulnerabilities have patterns in
them and patterns are something that you
catch up with time and we might i wasn't
doing that for so long i'm doing it just
for a year so how did i catch it up that
was basically through a practice as i
said before practice can be it can cover
the time that you're not doing that for
so long
so i managed to notice that
vulnerabilities have patterns in them
for example programming uh errors like
integer overflows and and sadness issue
um these are bugs that actually exist
because people make mistakes and we're
all humans and humans make mistakes
we're not perfect a great example for
such a mistake is the following code so
on the third line we have an integer
overflow which uh a lot of developers
know and know about the existence of
this vulnerability yet they still make
this mistake it's
it's as i said before it's about it's
because we are all humans and humans
make mistakes so uh don't be afraid to
look at actual code bases because these
this kind of bugs actually exist in
actual code bases uh not only in ctfs so
don't be afraid to look at actual
vulnerabilities you can find simple ones
as well
so there's a great difference between
ctfs and real-world vulnerabilities
in ctfs usually when you find the
vulnerability you know what you need to
do with it you know what you have to
progress with it you know what you need
to have what you need to exploit how you
need to exploit it so sometimes you have
a stock buffer overflow so you need to
override some variable the return
address or you can override a function
pointer there are
you mostly when you see vulnerability in
ctf you know what you need to do with it
in real world you usually have a set of
weird states a set of primitives that
you have primitives are essentially
capabilities we have
as attackers so you usually have some
primitives that we can chain together to
do something greater and that can later
lead to vulnerability and
such example of that will be the
vulnerability i found in chakra which is
basically a bunch of primitives together
chained together to
make an actual vulnerability
so this is basically everything i knew
about vulnerability research and
security research before i started
looking in chakra
um
so
yeah let's dive into some javascript so
javascript engines uh i didn't say i
learned javascript because i didn't and
javascript is a very readable language
it's uh once you have learned a few uh
programming languages reading javascript
would probably be more smooth a more
smooth process so doing that would not
be too hard
now js engines are basically what's
capable of running the code that you
write as a javascript developer
they have a lot of parts to them and uh
the one the most important one for us is
the jit compiler now jit stands for just
in time compiler what it essentially
does is when some function gets hot and
it's being called a lot of times it
compiles this function to a machine code
to improve performance
now
this compilation is this just this jig
compiler is also incapable of is also
responsible of
doing optimizations for the code
it has a lot of assumptions about the
code and doesn't want assumptions to be
broken
so
we'll see just how that works later and
about jit compiler vulnerabilities
so about javascript basics so javascript
is a dynamically typed language and it's
fairly readable
you can make arrays in different ways
you can have arrays with different type
of elements and you can have console.log
to actually print stuff
so javascript has prototypes prototypes
are essentially
something that you can in some way you
can inherit features from other objects
so for example in our case we have a
parent object and a child object so the
child object if if it the prototype of
it is the parent object then it will
inherit some features in this case the
properties
x and y so this actually is very fairly
important to us in the exploit and the
vulnerability i found
and you can modify the prototype by
accessing the proto up the proto uh
property
javascript also has something called
proxy now proxy is an object that can
wrap another object and redefine basic
uh basic operations like getters and
setters so in our case we redefined the
getter so
we really find together in which we
we're supposed to get x to be one three
three seven but due to the fact that the
proxy redefines the behavior what
happens is the getter handler is
actually being called so we redefine the
basic the basic operation of the getter
and in this way we actually tracked a
function the function call to the getter
of this object
so javascript has arrays as we've seen
but chakra has arrays with types so the
first type we're going to talk about is
called the javascript native entry and
it is the way ja chakra calls integer
array basically it's an array that
stores integer which are which are four
bytes per element and
they're basically integers uh javascript
also has a native float array which is
essentially floats and unlike the c
definition for float this this float is
actually eight bytes
and uh they store floats and they're
eight byte parameters
and we have javascript arrays which are
uh object they store objects essentially
pointers
and they are also aided by spur element
uh so let's see about about how we can
convert between the types so if we start
off with an array of integers and we add
a flow to it what happens is we convert
the array to a float array and if we add
a object to it the conversion that takes
place is a conversion to a javascript
array
if we have both floats and integers uh
the outcome is a float array
uh so if we have both uh floats and
integers and some and objects and mixer
a what happens is this array is
considered to be a javascript array and
the most weird conversion that takes
place is this one and you usually don't
see this when you see about conversions
in javascript engines but this is very
crucial for our talk so when you have
two arrays and you assign one of them to
be the prototype of another one uh the
prototype one is directly converted to a
javascript array
now this is going to be very important
to us later so keep that in mind
and this basically the conversion takes
place
right when this right when the
assignment takes place
so
let's see about how array layout
actually looks like in memory so when we
have an array for example in this case a
javascript array it has some flags which
indicate some some things about the
array and it's called the red flags we
have the length of the array and we have
the head now a head is a pointer
essentially to a segment and a segment
is a contiguous memory region which has
elements in this so it has some of the
elements in the array and it stores
another pointer to the next segment so
what what comes out is essentially a
linked list of segments that start off
with the head pointer in the javascript
array
so let's see how that actually looks in
memory we have this simple example where
we have uh 2.2 uh two values in this
case integers and we have an array with
two values so
uh and let's see how it actually looks
like in memory so in red we have the
javascript array properties so we can
see
the initial array value which is the
array flags value and we have in
in green we have the actual segment so
we can see the segment has the length
and the size and in blue we can actually
see the memory layout of the segment and
if you notice uh on the right bottom we
have the two elements we defined
so we actually can see this in memory
and this is how it looks like
so what is uh the array flags i was just
talking about so array flags basically
some flags that indicate uh some things
about the array in our case it's and
it's defined as an enum and the
interesting uh field for us is there has
no missing values
flag
and so if we
for uh for those of you who notice the
the initial array value that was defined
as our array flags is actually composed
of two different flags it's composed of
the array object array flags tag and it
has no missing values tag
um so the the first one is not really
important for our tags so we'll focus on
the second one which basically means
that the array doesn't have any holes in
it
now what does a hole mean so we can
create an array and have some values
between the like we have for in this
case we have three elements but the
middle one is missing
uh so it's important to say that uh the
values i put there are the way the way
they're represented in memory is uh by
those constants and i try i chose them
because it will be easier for us to to
see them to actually notice them when we
see the memory layout as we've seen
before
so
as you can see this one has a hole and
the array flags doesn't have that has no
missing values
on which means we have
a hole in the array
and things actually make sense but when
we look at the memory layout we see some
weird thing so as you can see we have
the dead beef and the four one but
between them where the missing value
where the hole was we have some magic
constant
now
makes sense that this constant would
represent a missing value or a hole in
the array but as we've seen before the
there's already something that rep that
tells we tells us when we have holes in
array it's there has no missing values
flag so we know that there is one way to
indicate holes in the array and it's the
flag we've seen before but it seems like
there is another way to tell if there's
a hole in the there's holes in arrays
so that's kind of weird that raises a
lot of questions um we have uh basically
have here we potentially can have here
two things that indicate should indicate
the same state we have the flag of the
array which is there has no missing
values flag and we have the content of
the array which we've seen before and is
the
fff constant
so
if we can what happens with if they're
if they're like mismatched what if what
happens when if we can if we can do that
uh get the has no missing values to be
set to true and therefore says that we
don't have any holes but we actually
have a missing value in the array
also we mix we some sort of mix data and
metadata together because if the
constant is being used in a control flow
that could be that could be interesting
for us if we can fake it
and it actually is very interesting and
we can it turns out that we can actually
fake a missing value and this was a
vulnerability find by loki heart and
story my bad and got cve for it so
basically what they did is they faked a
missing value by putting the constant
we've just seen before into a float
array so we could uh beforehand the
value was not the same one that we've
seen and it was something that you could
actually represent as a
valid float number so you could actually
put it in and this could be turned to a
vulnerability now this would mitigate it
in a few ways and it the constant change
so you couldn't represent it as is and
what also happened is they added a few
more checks to harden uh to harden
things
so we'll talk about how this can be
turned into
out this weird state can be turned into
vulnerability and weak act and how we
can actually exploit it
uh but
before that we actually want to talk
about something interesting so as i just
said the the exploit the vulnerability
sorry my bad and lockheed found was in
native float array
um so
apparently javascript arrays don't store
floats as nade as actual floats they
first do something called boxing so they
first xor these values with this
constant you can see here so before you
put the float into the array this value
is being xored with the flows you're
trying to put in
so the question that comes up next is
whether we can actually have missing
values in javascript array and if so
does the constant change because as we
see here we change the way we represent
values and therefore we can represent
new values
so theoretically we should be able
theoretically the engine should change
the constant
otherwise we could potentially
get there and actually represent it
and it turns out that the constant does
not change
therefore we can actually represent it
by first boxing it
so what we did is we first uh boxed it
and it soared the constant with the fff
we've just seen here
uh so that
that that in turn gives us the ability
to have the constant uh as the original
constant value um why you're wondering
because this property of xor so when you
have uh xor of three elements and two of
them are the same then they cancel out
and they give you the the other one uh
so if we have two of them to be uh the
the
if you have two of them to be the this
value
so and the one of them to be the the
magic value what happens is we actually
get in turn the magic value and
therefore we actually can represent it
and this is exactly the vulnerability i
found which is truly truly heavily
relies on the fact that we have basic
understanding of javascript engines this
uh boxing is one of the first things we
learn when we learn about javascript
engines so we used this uh idea of
boxing things and turned in supposedly
unexploitable state to be a
vulnerability
uh so basically what we did is as you
can see here uh we first box it and then
we put it into an array that has uh that
is a javascript array and not a float
array
so
how do we turn this one this weird state
into a vulnerability
so when what what happens first thing we
need to understand is how
vulnerabilities look like so jit stands
for just in time as i already explained
uh
bugs are usually what we see today are
usually type confusions so type
infusions are essentially confusion
between two types that uh the the mach
the program thinks something is of one
type but actually of the other type
so uh two types of phrases the most
common ones are uh due to side effects
now side effects are some things that
take place in the jitted code now did
that code i refer to the machine code
that is emitted when the
the jit compiler uh compiles the hot
function
so in our case uh in the usual case i
mean what happens is you have some
function let's call it foo which changes
a type of some some object let's let's
think of it as an array and then the
function that got jitted doesn't know
about this conversion so it thinks that
everything's still the same and nothing
has changed
so it's going to work with it as if as
if as it did before
and this leads to a target fusion so
let's look at an example
so first thing we do when we have such
vulnerability is we make the function
hot as i explained before to make the
function be compiled into machine code
we first have to make it hot
we do that by calling the function a lot
of times and this is this can be done by
a simple loop
and the next thing okay so also it's
important to to say that
jet the jit compiler has a lot of
assumptions
these assumptions are on some types on
some things that take place during the
execution of the function so for
instance when we call foo
and it thinks that foo doesn't do
anything it knows that it doesn't need
to check things again because if food
doesn't change any state of the program
why would we check something again
because that would make the function way
more slower and jet compilers are all
about
making things faster
so it has a lot of assumptions that are
there to improve performance
so once we do uh that and we have
something that break the assumption we
can we can eventually get to a weird
states where dates and from there we can
turn this into a vulnerability so in
this case once we call the function and
we make it uh be compiled into machine
code
and we actually call the function again
but this time we want to trigger the
type confusion so what happens here is
foo will change the type of the array
and therefore the assumption that food
doesn't change anything breaks
that this gives us the ability to to
have the
jit compiler think that nothing happened
but we actually changed something this
is very important because jit compiler
bugs are very complex sometimes and this
one is not too complex what happens here
we essentially made the
major compiler forget don to not know
about the
the conversion that happened so if foo
converts array to a javascript array uh
something happened but the jit compiler
doesn't know about it so it's very
crucial to understand that and the
assumptions essentially break because we
change something in the function that we
called
so this is basically about jit type
confusions we have we essentially have
some function to make it hot and then we
have another function which gets
gets emitted to machine code and in that
function we
call some other function which will have
side effects side effects are things
that the jit compiler is not aware of um
so let's actually move on to my
vulnerability so to turn uh the
the mismatch between the flags if you
remember we had a flag that indicates it
has no missing values and we also have
the array content so once we have the
mismatch and we actually managed to fake
a missing value uh to turn that into a
vulnerability uh it's quite interesting
so the way loki heart and saw my bed did
that was uh basically through calling
this function concat which uh had an s
which relied on has no missing values
and also relied on the content of the
array uh this uh allowed that mismatch
to be to to get us to into a weird
states which shouldn't happen because in
normal case why would we have the the
missing values and the content of the
array to have not
a mismatch between them so in our case
uh in in lockheed hart's case they got
the array
flags tag they got their red flags to be
mismatched with the continent of the
array and they call concat now the way
concat was called was once we make a
fake array let's call it buggy and the
buggy has a
fake missing value in it but
the flag that indicates if there are any
missing values is not set to true
so we set this fake array and we call
concat with it now the first thing that
happens when we call concat is we get to
this code now this is the part with that
where we have a lot of code now bear
with me it's not too hard it's just a
lot of code so first thing we get is we
get to this function this function
essentially is called concat args and a
item in this case is the fake array the
buggy we have um it's called we invoke
is fill from prototypes and we would
essentially want
fill form prototypes to return false in
order to get into that if statement
now is fill from prototypes essentially
checks the following things first thing
it checks is that there's only one
segment in the array and that check is
through the fact that it checks that the
next the next segment of the header head
segment is null and uh the another thing
that it checks is that the length of the
array is equal to the length of this
segment therefore this segment is the
only segment in the array
so these are the first this is the first
thing that it checks and the second
thing that it checks is that the flag
has no missing values is set to true now
this can be easily bypassed because
we've already seen that we can fake a
missing value and set the flag to true
uh by doing that we can actually get its
film from prototypes to return false
and we can actually successfully get and
get into the if statement next thing we
reach is this else statement which calls
copyright elements
with our uh
array as an argument as you can see it's
the p autumn array
once for this copy of elements is
essentially copying an internal function
and which does the following now this
part is very it's very interesting for
us so first thing that happens is
they make an enumerator out of the array
a numerator will enumerate every single
element in the array and will uh
increase the counter every time it
engages in a new element
now let's see how this enumerator is
actually implemented so this is a code
for the move next function and as we can
see on the red uh box
when we encounter a value that is
actually a missing value we actually
skip it so what happened here is that
every time we we got into the sorry
every time we got into the while loop
and there was a missing value it skipped
it therefore the count that we had there
is not equal to the amount of elements
in the array
uh this is because every time we we get
we find a missing value it doesn't
increase the counter and therefore we
can actually get into this if statement
and call internal fill from prototypes
now
this also is a very interesting function
for us because it
basically first thing it does is loop
through the prototype chain now if you
remember the prototype chain is
basically if the prototype is basically
some object that we inherit features
from so we can have our prototype to
have another prototype and therefore we
forge a prototype chain
so this thing this function first loops
through the prototype chain and uh
then what it does it called it calls
this long function name with our
prototype as an argument
so
if you remember prototype is actually
directly converted into a javascript
array when assigning a prototype
remember from the conversion slide so
essentially what happens here it knows
that the prototypes or should know that
the prototype is a javascript array and
we loop through it
so
every time we get in here what happens
is the prototype is being passed through
the object argument and is then
converted to a javascript array through
the in ensure non-native array so as you
can guess insurance very basically
ensures the array is not of a native
type uh therefore it's a javascript
array
and this is the interesting part for us
so what we've seen so far is so to quick
recap okay so what happened so far is we
managed to get concat to convert some
array into a javascript array and there
is nothing that indicates this
conversion
it's important to know that
once we fake a missing value and we call
the prototype we call the concat the all
of the prototype chain is being
converted to javascript array now as
we've seen before prototypes in the
prototype chain are not native types so
we
shouldn't be able to put there any type
because
it should be javascript array so
it turns out that we actually can do
that so remember proxy proxy can wrap a
an existing functionality and redefine
its functionality in our case we can and
it's pretty fun that we can do that is
we can
redefine the functionality of get
prototype
so what this allows us is whenever we
call get prototype we redefine a a
behavior so remember that prototype
chain so what we do here is basically we
redefine this prototype chain uh loop uh
and by doing so we allow us to return to
call an arbitrary function now if we
call an arbitrary function of our choice
for example in any function uh what
happens is uh the the jit compiler
checks if this function is marked as
having side effects or not
if the function is marked as having side
effects the whole function that got
jitted is about as having side effects
and it's not good for us because we
don't want the jit compiler to know that
some side effect took place because we
wanted to get a tagline fusion so what
we do is we use an existing function
which is called value off and is marked
as not having side effects
this basically allows us to return any
object in the prototype chain by calling
get prototype so let's see an example
for that this is the proof of concept
code and we'll go through every single
part of it and i'll explain everything
so first thing we do as i explained
before we loop through the we loop
through uh this first loop to make the
function hot and therefore you get it
gets compiled to machine code next thing
we do is we define two arrays buggy
array which is going to be the array we
fake a missing value inside of it and an
array which is called er and is going to
be our target for type confusion now
it's important to notice that the target
which will be converted to a javascript
array is not buggy it's array so notice
that
next thing we do is we redefine the get
prototype off so get prototype off is
basically the get prototype function and
by doing uh by calling by redefining it
to be value off whenever the function
get prototype is called uh on a or we
redefine the implementation and get it
to return the error itself this allows
us to return a r whenever get prototype
is called this is huge because uh if we
define a proxy what happens is we
essentially made uh the get prototype
loop to return us a javascript native
float array so if you notice uh on the
line before whenever get prototype is
called we call value off
and if we loop through the prototype
chain and value off is the get prototype
the return the return value is going to
be error which is a javascript native
float array as you can see here
this allows us to uh essentially have a
native float array even though there
shouldn't be any of those in the
prototype chain next thing we do is we
redefine uh we define the missing value
constant and by doing so we still have
there has no missing values flag for
buggy set to true this is the
interesting part because this is where
the mismatch takes place so we have a
missing value but we don't have the flag
set to true
so next thing we do is we call the
jitted function
so this is the
the key part here so when we call this
function what happens is this function
is uh this code is uh being grand so
first thing we do is we define the
temporary and we define the first
element of the uh array object the array
array to be a a float this makes the jet
know that whenever it uses array and no
conversions happened it still thinks
it's a javascript float array
and then we call the temp we call the
concat function and we give it the buggy
as an argument this will essentially
loop through all of the prototype chain
and one of the prototype in the
prototype chain is the proxy as we can
see here and when we call the net the
get prototype for the proxy we get the
arr and when we call the get prototype
for the amr we get we sorry when we get
we call the prototype for uh the buggy
we get proxy when we go we can't get
prototype 40 proxy we invoke the get
prototype for arr which will return us
the a or r
and therefore what happens is ar is
converted to a javascript array whenever
the prototype chain loop takes place
afterwards in the last line of the jit
function we basically write some value
into the array and therefore make uh
write a float into some array that was
converted to javascript a float
javascript array so array is the same
array that is in the prototype chain and
therefore we still overwrite we
overwrite some pointers with
a
float which in our case is one two three
four
so
last thing we do is call console.log and
we crash because we have a object which
is defined for this address and it's not
mapped
so this is essentially the
proof of concept code and what we do
here is fairly simple we first thing we
do is we make a function hot and by
doing so we make it be compiled into
machine code next thing we do is we
redefine uh the
the behavior of uh the get prototype
function and we allow it to return an
arbitrary object whenever we call get
prototype
then we invoke the
jet then we fake a missing value and we
call the jet digited function which in
turn allows us to uh convert in all of
the prototype chain to be uh some
javascript arrays uh now even though one
of most of them are javascript arrays
one of them the array one is not because
we redefined the the implementation for
get prototype this in turns allow this
in turn allows us to have a javascript
float array converted to a javascript
array and we can still act with it still
operate with it as if it were a
javascript float array and therefore the
last line here allows us to write a
point and number as a pointer and
therefore we have what we call in the
beginning a type confusion
so we essentially had a type confusion
between a float and a pointer because
the jit did not understand that some
conversion took place
now this is essentially the bug and to
exploit it we actually had to do a few
things so uh first thing we did was uh
we targeted uh a a fake object primitive
now what is the fake of definitive the
thing we've just seen was that we faked
an object at an arbitrary address in our
case it was faked in datus 1234 as seen
here
but the thing is we actually can fake an
object at an arbitrary address the
object we decided to fake was a dataview
object which has some fields of it which
are a pointer you can read from and
write to
this in turns gives us a read write
primitive and from there what we did was
to use a known trick which is to find a
stack address and overwrite it to run to
execute our code in rob so uh to do all
that we used a great library which is
called pawn.js and we used that we had
to fix a few things but it it did most
of the work what it did was basically do
what we explained it
it requires us to have a read write
primitive and then what it does
is to scan uh the program to find a
stack pointer from there it overrides
the stack with uh
whatever we want because we got an
arbitrary red right primitive uh and
then what happens is we can execute code
and drop now we first exploited it on
edge but to actually execute uh our own
code
what to sorry well when we actually
execute our own code uh we had we
executed it in the sandbox context so it
wasn't any nice for a demo because it
would uh not allow us to pop a
calculator or something but uh so what
we did was we actually compiled chakra
core for linux and we exploited it for
linux the exploit for linux was similar
because we still overwrite this overall
stack with some things we controlled as
we had a read write primitive
and from there we basically executed
code and rob
so
that's basically what we did to get a
poc a crashing proof of concept to
actually execute our own code
so let's see a demo for that
let's hope it actually works
one second
you can see my screen
sorry
a second
oh wait
no
so let's let's hope everything works
so
uh basically this
we have a chakra core compiled for linux
and this is how it looks like so to
execute it we actually have to give it a
source file so in our case we give it an
exploit and our exploit so notice this
is going to be a very fast exploit
because chakra is super fast and it has
super optimizations because why not
so it's going to be super fast so beware
and
therefore we have okay we have a shell
so to prove them uh we actually got code
execution let's draw let's let's run a
calculator oops
oops
and we have a calculator as well so we
actually can actually execute code and
everything works as expected
so
a few things about let's get back to the
talk
oops
wait
sorry
so
what we've seen here sorry what we've
seen here was basically we had some uh
we okay so the demo shows us a very
simple thing we first
did what we did in the proof of concept
we got the jet compiler to to not been
to not be to not know that some side
effect took place this side effect in
our case was some conversion that
allowed us to convert summary into
javascript array and then in turn allows
us to write
floats as
pointers and this basically gives us a
top confusion primitive which we
exploited by having by faking an object
which gives us a read write primitive
and therefore we continue to write our
code and rob
uh so i really hope that my talk was
helpful for so so for those of you who
want to get into security research and i
hope it was entertaining for those of
you who just wanted to hear about the
technical stuff
and i want to thank everyone who helped
me out with the talk and with the slides
and
for you to come for you for coming here
and seeing my talk i know there's a
great competition and there's way cool
talks probably but you still came to
mind so thank you for that
and
yeah thanks for coming
jonathan do we have some time for
questions yeah sure okay was it the
first talk you held for such a big
audience yeah i never spoke more than
for more than that
for christ's sake that was good
[Music]
we have a couple of microphones over
here so if you have questions for
jonathan please line up over there and
shoot the questions
we could start with one from the
internet do we have one
no we don't oh
okay
don't we have any questions over here
people are good where's here
number five here we go
so thank you for the excellent talk
i was surprised to see that the
javascript engine for
edge was open source
so
is this something that they're
moving towards more open source
components
um i think that the open sourcing is
cool but i don't know how actually our
future will will be and if we'll open
source small things
i actually don't know
then we continue with microphone number
two
hey
thanks for your very interesting talk
so
obviously
jet compilers are
a pretty in-depth subject so my question
is
when you got started with all this how
much
uh prior domain knowledge of dead
compilers and dynamic language runtimes
did you have and
when you then got to chakra core
how much did you have to just read
through the whole thing
before you could actually start looking
for vulnerability in there so what i did
was when i started to
get into chakra i read a lot of by
reports and i i've seen that there's
plenty of vulnerabilities there so i
read most not every one of them but i
read a lot of them and i try to
understand what they do and why they
exist and this is basically what
got me into
looking for my own bug as well
so basically i had understanding of
javascript engines in general and then i
read about how chakra works and read
about specific vulnerabilities in chakra
thank you
and over to microphone one please
um you mentioned
the process in windows runs in a sandbox
so you weren't able to
calculator um would this uh stop the
exploit in the wild or is there a way uh
this could be dangerous even in the
sandbox so uh to actually execute your
arbitrary code you have to
escape the sandbox um there's things you
can do with the sandbox but they're
pretty limited uh i didn't exploit i
didn't find a sandbox escape yet i hope
i will find one day but uh to actually
execute uh interesting stuff you need to
do a sandbox escape because there's
plenty of mitigations
nowadays and specifically for edge does
a lot
and i don't know specifically if you
could do anything you could do any
anything interesting without a sandbox
escape but you could actually run code
so you could do it you could do stuff
i'm not sure if it's uh interesting
enough to to to actually do something in
the wild
and over to microphone number two
hey a great research and a work
um
how much time did you work on it
um so
i worked on chakra for about i think
uh from
july i think i when i started i started
reading about chakra in july but i had
understand i had some knowledge about
javascript engines before for about like
two two months i think uh so not enough
for i mean the more important part for
me was to actually uh read about
examples and see examples more than
spending a lot of time on it like i
think it comes with practice as i
explained before what i do believe in is
practice and my practice was through
reading a lot of research and a lot of
internal stuff about chakra
so it's about i think from july and
about maybe two months before
all right
nobody's queuing up on the microphones
or have i overseen someone
jonathan
excellent thanks that's it
that's your applause
that was jonathan j from zero to zero
day thank you very much
[Music]
you