0:00:00.000,0:00:19.960
36c3 preroll music
0:00:19.960,0:00:25.420
Herald: So, Samuel is working at Google[br]Project Zero on especially vulnerabilities
0:00:25.420,0:00:30.200
in Web browsers and mobile devices. He was[br]part of the team that discovered some of
0:00:30.200,0:00:33.960
the vulnerabilities that he will be[br]presenting in this talk today in detail
0:00:33.960,0:00:41.370
about the no user interaction[br]vulnerability that will be able to
0:00:41.370,0:00:48.660
remotely exploit and compromise iPhones[br]through iMessage. Please give Samuel a
0:00:48.660,0:00:55.890
warm round of applause.[br]Applause
0:00:55.890,0:01:00.880
Samuel: OK. Thanks, everyone. Welcome to[br]my talk. One note before I start,
0:01:00.880,0:01:05.900
unfortunately, I only have one hour. So I[br]had to omit quite a lot of details. But
0:01:05.900,0:01:09.760
there will be a blog post coming out[br]hopefully very soon that has a lot more
0:01:09.760,0:01:14.729
details. But for this talk, I wanted to[br]get everything in there and leave out some
0:01:14.729,0:01:21.840
details. OK. So this is about iMessage in[br]theory some of it applies, or quite a lot
0:01:21.840,0:01:26.050
actually applies to other messengers, but[br]we'll focus on iMessage. So what is
0:01:26.050,0:01:31.290
iMessage? Yeah, it's a messaging service[br]by Apple. We've heard about it in the
0:01:31.290,0:01:37.700
previous talk a bit. As far as I know, it[br]is enabled by default. As soon as someone
0:01:37.700,0:01:42.759
signs into an iPhone with their account,[br]which I guess most people do, because
0:01:42.759,0:01:48.540
otherwise you can't download apps.[br]Interestingly, anyone can send messages to
0:01:48.540,0:01:55.211
anyone else. So it's like SMS or phone[br]calling. And then if you do this, then it
0:01:55.211,0:02:01.390
pops up some notifications, which you can[br]see that here on the right screenshot,
0:02:01.390,0:02:06.879
which means that there must be some kind[br]of processing happening. And so, yeah,
0:02:06.879,0:02:11.080
this is like default enabled, zero click[br]attack surface without the user doing
0:02:11.080,0:02:15.780
anything, there's stuff happening. And[br]then on the very right screenshot, you can
0:02:15.780,0:02:23.700
see that you can receive messages from[br]unknown senders. It just like says there.
0:02:23.700,0:02:29.829
This sender is not in your contact list,[br]but all the processing still happens. In
0:02:29.829,0:02:36.920
terms of architecture, this is roughly how[br]iMessage is structured, not very, yeah,
0:02:36.920,0:02:42.760
anything too interesting, I guess. You[br]have Apple cloud servers and then sender
0:02:42.760,0:02:48.240
and receiver are connected to these[br]servers. That's pretty much it. Content is
0:02:48.240,0:02:53.830
end to end encrypted, which is very good.[br]We heard this before, also. Interestingly,
0:02:53.830,0:02:58.320
this also means that Apple can hardly[br]detect or block these exploits though,
0:02:58.320,0:03:06.130
because, well, they are encrypted, right?[br]So that's an interesting thing to note. So
0:03:06.130,0:03:11.920
what does an iMessage exploit look like? [br]So in terms of prerequisites, really the
0:03:11.920,0:03:16.120
attacker only needs to know the phone[br]number or the email address, which is the
0:03:16.120,0:03:22.160
Apple account. The iPhone has to be in[br]default configuration so you can disable
0:03:22.160,0:03:26.910
iMessage. But that's not done by default.[br]And the iPhone has to be connected to the
0:03:26.910,0:03:31.980
Internet. And in terms of prerequisites,[br]that's pretty much all you need for this
0:03:31.980,0:03:38.169
exploit to work. So that's quite a lot of[br]iPhones. The outcome is the attacker has
0:03:38.169,0:03:43.410
full control over the iPhone. After a few[br]minutes, I think it takes like five to
0:03:43.410,0:03:48.970
six, seven minutes maybe. And it is also[br]possible without any visual indicator. So
0:03:48.970,0:03:53.880
there's no... you can make it so there are[br]no notifications during this entire
0:03:53.880,0:03:59.981
exploit. OK. But before we get to[br]exploiting, of course, we need a
0:03:59.981,0:04:04.460
vulnerability and for that we need to do[br]some reverse engineering. So I want to
0:04:04.460,0:04:09.060
highlight a bit how we started this or how[br]we approached this. And I guess the first
0:04:09.060,0:04:14.450
question, you might be interested in, is[br]what daemon or what service is handling
0:04:14.450,0:04:20.989
iMessages. And one easy way to figure[br]this out is you can just make a guess. You
0:04:20.989,0:04:26.429
look at your process list on your Mac, the[br]Mac can also receive iMessages. You, like,
0:04:26.429,0:04:30.890
stop one of these processes and then you[br]see if iMessages are still delivered. And
0:04:30.890,0:04:36.140
if not, then probably you found a[br]process that's somewhat related to
0:04:36.140,0:04:43.680
iMessages. If you do this, you'll find[br]"imagent", already sounds kind of related.
0:04:43.680,0:04:47.510
If you look at it, it also has an iMessage[br]library that it's loading. Ok, so this
0:04:47.510,0:04:55.170
seems very relevant. And then you can load[br]this library in IDA. You see a screenshot
0:04:55.170,0:05:00.010
top right. And you find a lot of handlers.[br]So for example, this
0:05:00.010,0:05:03.840
"MessageServiceSession handler:[br]incomingMessage:", and then you can set a
0:05:03.840,0:05:07.170
breakpoint there. And then at that point[br]you can see these messages as they come
0:05:07.170,0:05:13.230
in. You can dump them, display them, look[br]at them, change them. And so this is a
0:05:13.230,0:05:17.040
good way to get started. Of course, from[br]there, you want to figure out how these
0:05:17.040,0:05:22.460
messages look like. So, yeah, you can dump[br]them in there when they come in in the
0:05:22.460,0:05:30.000
handler, on the right side you see how[br]these iMessages look like more or less on
0:05:30.000,0:05:37.460
the wire. They are encoded as a PList,[br]which is an Apple proprietary format.
0:05:37.460,0:05:45.140
Yeah, think of it like JSON or XML. And I[br]guess some fields are self-explanatory.
0:05:45.140,0:05:50.160
So, "p", that's the participants in this[br]case this is me sending a message to
0:05:50.160,0:05:57.270
another account I own. You have "T" which[br]is the text content of the message. So
0:05:57.270,0:06:04.530
"Hello 36C3!". You have a version, for[br]some reason you also have an XML or HTML-
0:06:04.530,0:06:11.190
ish field, which is probably some legacy[br]stuff. It's being parsed, this XML. But
0:06:11.190,0:06:14.170
yeah, the whole thing looks kind of[br]complex already. I mean maybe you would
0:06:14.170,0:06:20.200
expect a simple string message to just be[br]a string. In reality, it's sending this
0:06:20.200,0:06:29.340
dictionary over the wire. So let's do some[br]more attack service enumeration. If you
0:06:29.340,0:06:34.980
then do more reverse engineering, read the[br]code of the handler, you find two
0:06:34.980,0:06:41.250
interesting keys that can be present,[br]which is ATI and BP, and they can contain
0:06:41.250,0:06:49.270
NSKeyedUnarchiver data, which is another[br]Apple proprietary serialization format.
0:06:49.270,0:06:55.340
It's quite complex, it has had quite a few[br]bugs in the past. On the left side you see
0:06:55.340,0:07:01.930
an example for such an archive. It's yeah,[br]it's being encoded in a plist and then
0:07:01.930,0:07:08.360
it's pretty much one big array that has,[br]like, every object has an index in this
0:07:08.360,0:07:15.360
array. And here you can see, for example,[br]number 7 is some object, is the class
0:07:15.360,0:07:24.500
NSSharedKeyDictionary. And I think key one[br]is an instance of that class and so on. So
0:07:24.500,0:07:30.590
it's quite powerful. But really what this[br]means is that this serializer is now zero
0:07:30.590,0:07:35.430
click attack surface because it's being[br]passed on this path without any user
0:07:35.430,0:07:42.850
interaction. So I said it's quite complex.[br]It even supports things like cyclic
0:07:42.850,0:07:47.889
references. So you can send an object[br]graph where A points to B and B points
0:07:47.889,0:07:55.540
back to A for whatever reason you might[br]want that. Natalie wrote a great blog post
0:07:55.540,0:08:00.040
where she describes this in more detail.[br]What I have here is just an example for
0:08:00.040,0:08:06.200
the API, how you use it. This is Objective[br]C at the bottom. If you're not familiar
0:08:06.200,0:08:12.190
with Objective C, you can think of these[br]brackets as just being method calls. So
0:08:12.190,0:08:17.360
this is doing, in the last line, it's[br]calling the unarchivedObjectOfClasses
0:08:17.360,0:08:25.170
method for this NSKeyedUnarchiver. You can[br]see you can pass a whitelist of classes.
0:08:25.170,0:08:31.880
So in this case, it will only decode[br]dictionary, strings, data, etc. So looks
0:08:31.880,0:08:38.750
quite okay. Interestingly, if you dig[br]deeper into this, this is not quite true
0:08:38.750,0:08:44.470
because it also allows all the subclasses[br]to be decoded. So if you have an NS-
0:08:44.470,0:08:49.089
something-something dictionary that[br]inherits from NSDictionary, then that can
0:08:49.089,0:08:55.280
also be decoded here, which is quite[br]unintuitive I think. And this really blows
0:08:55.280,0:09:01.760
up the attack surface because now you have[br]not only these 7 or so classes, but you
0:09:01.760,0:09:09.650
have like 50. Okay. So this is what we[br]focused on when me and Natalie were
0:09:09.650,0:09:17.230
looking for vulnerabilities. It seemed[br]like the most complex thing we found. We
0:09:17.230,0:09:22.390
reported quite a few vulnerabilities here,[br]you can see it maybe a bit on the left.
0:09:22.390,0:09:31.420
The one I decided to write an exploit for[br]is this 1917, reported on July 29th and
0:09:31.420,0:09:38.400
then exploits sent on August 9th. Yeah,[br]mostly I decided to use this one because
0:09:38.400,0:09:42.900
it seemed the most convenient. I do think[br]many of the other ones could be exploited
0:09:42.900,0:09:47.610
in a similar way, but not quite as nice,[br]so would maybe take some more heap
0:09:47.610,0:09:55.700
manipulation, etc. So then Apple first[br]pushed the mitigation quite quickly, which
0:09:55.700,0:10:01.180
basically blocks this code from being[br]reached over iMessage. In particular, what
0:10:01.180,0:10:08.430
they did is, they exactly no longer allow[br]subclasses to be decoded in iMessage. So
0:10:08.430,0:10:12.760
that's quite a good mitigation, it blocks[br]off maybe 90 percent of the attack surface
0:10:12.760,0:10:22.589
here. Yeah. So then they fully fixed it in[br]iOS 13.2. But again, after August 26th
0:10:22.589,0:10:32.840
this was only just local attack surface.[br]OK, so what is the bug? It's some
0:10:32.840,0:10:37.390
initialization problem during decoding,[br]the vulnerable class is
0:10:37.390,0:10:42.000
SharedKeyDictionary, which again, it's a[br]subclass of NSDictionary, so it's allowed
0:10:42.000,0:10:50.260
to be decoded. So let's take a look at[br]that. So, yeah. SharedKeyDictionary.
0:10:50.260,0:10:56.000
Here's some pseudocode in Python. It's a[br]dictionary. So its purpose is to, well,
0:10:56.000,0:11:01.880
look up keys to values or map keys to[br]values. The lookup method is really
0:11:01.880,0:11:08.120
simple. It just looks up an index in a key[br]set. So every key dictionary has a shared
0:11:08.120,0:11:13.760
key set and then that index is used to[br]index into some area. OK, so that's quite
0:11:13.760,0:11:21.060
simple so most of the magic happens in the[br]SharedKeySet. And so what that does is
0:11:21.060,0:11:27.690
something like compute a hash of the key.[br]Use that hash to index into something
0:11:27.690,0:11:35.350
called a rankTable, which is an array of[br]indices. And then if that index is valid,
0:11:35.350,0:11:41.530
so it's being bounced, checked against the[br]number of keys. Then it has found the the
0:11:41.530,0:11:47.260
correct index and if not, it can recurse[br]to another SharedKeySet. So every
0:11:47.260,0:11:53.260
SharedKeySet, can have a sub-SharedKeySet,[br]and then it repeats the same procedure. So
0:11:53.260,0:11:57.980
it already looks kind of complex. Why does[br]it have... why does it need this
0:11:57.980,0:12:03.160
recursion? I'm not quite sure, but it's[br]there. And so now we look at how this goes
0:12:03.160,0:12:11.060
wrong. So this is the initWithCoder, which[br]is the SharedKeySet constructor used
0:12:11.060,0:12:18.289
during decoding with the keyedUnarchiver.[br]And it looks pretty solid at first, it's
0:12:18.289,0:12:26.070
really just taking the values out of the[br]archive and then storing them as the
0:12:26.070,0:12:32.370
fields of this SharedKeySet. I have a, I'm[br]gonna go through the code here in, like,
0:12:32.370,0:12:36.650
single step to highlight where it goes[br]wrong or what goes wrong here, what's
0:12:36.650,0:12:43.339
wrong with this code. So we start with[br]SharedKeySet1 which implies there's gonna
0:12:43.339,0:12:48.800
be another one. And at the start it's all[br]zero initialized. It's basically being
0:12:48.800,0:12:54.220
allocated through ?calloc?. So everything[br]is zero. Then we execute the first line.
0:12:54.220,0:13:02.020
Okay. So numKey, you see some interesting[br]values coming. So far this is all fine.
0:13:02.020,0:13:06.600
Note, that you can set numKey, at this[br]point numkey can be anything because it's
0:13:06.600,0:13:12.550
only being validated three lines further[br]down, right? Where it's making sure that
0:13:12.550,0:13:20.670
numKey matches the the real length of this[br]array. So this is fine, but here it's now
0:13:20.670,0:13:25.260
recursing and it's decoding another[br]SharedKeySet. So we start again. We have
0:13:25.260,0:13:32.680
another SharedKeySet, all filled with[br]zeros and we start from the top. Again,
0:13:32.680,0:13:39.740
numKey is one, so this is this is a[br]legitimate SharedKeySet, decoding a
0:13:39.740,0:13:47.620
rankTable. And here we are making a[br]circle. So for SharedKeySet2 we pretend
0:13:47.620,0:13:53.979
that its sub-KeySet is SharedKeySet1. And[br]this actually works. So the
0:13:53.979,0:13:59.730
NSKeyedUnarchiver has special handling to[br]handle this correctly. So it does not
0:13:59.730,0:14:06.410
create a third object and it makes the[br]cycle. And we're good to go. Okay. Next to
0:14:06.410,0:14:13.950
decode the keys area. So this is fine.[br]SharedKeySet2 seems legitimate so far. And
0:14:13.950,0:14:19.490
now it's doing some sanity checking. Where[br]it's trying, where it's making sure that
0:14:19.490,0:14:25.941
this SharedKeySet can look up every key.[br]And so it does this for the only key it
0:14:25.941,0:14:32.910
has, key one. Now, at this point, it's[br]again, remember, it's hashing the key
0:14:32.910,0:14:39.120
going into rank table, takes out 42, which[br]is bigger than numKey. So in this case,
0:14:39.120,0:14:44.819
this look up here has failed. And now it's[br]recursing to SharedKeySet1. Right? This
0:14:44.819,0:14:53.530
was the logic. And at this point it's[br]taking out this hex41414141 as index,
0:14:53.530,0:15:00.380
compares it against hexffffffff and that's[br]fine, and now it's accessing, null
0:15:00.380,0:15:07.560
pointer, which is.. the keys area is still[br]null pointer plus, well, 41 41 41 41 times
0:15:07.560,0:15:13.910
8. So at this point it's crashing. It's[br]accessing invalid memory, precisely
0:15:13.910,0:15:21.140
because in this situation the[br]SharedKeySet1 hasn't been validated yet.
0:15:21.140,0:15:30.500
OK, so that's the bug we're going to[br]exploit. I have these checkpoints just to
0:15:30.500,0:15:35.490
think where we are, so we now have a[br]vulnerability in this NSUnarchiver API. We
0:15:35.490,0:15:41.990
can trigger it through iMessage. So what[br]Exploit Primitive do we have? Let's take a
0:15:41.990,0:15:50.240
look again at the lookup function, which[br]we saw before. So here where it's bold,
0:15:50.240,0:15:54.770
this is where we crash. keys is null[br]pointer, index is fully controlled. So we
0:15:54.770,0:16:00.959
can access null pointer plus offset. And[br]then what happens is the result of this
0:16:00.959,0:16:06.220
memory access is going to be used as some[br]Object-C Object. So this is all
0:16:06.220,0:16:09.660
Objective-C in reality, it's doing some[br]comparison, which means it does something
0:16:09.660,0:16:16.940
like it called some method called[br]isNSString, for example. And then also
0:16:16.940,0:16:24.529
eventually it calls dealloc, which is the[br]destructor. So yeah, we have... the thing
0:16:24.529,0:16:29.209
it reads from whatever, it will treat it[br]as an objectif C-Object calls a
0:16:29.209,0:16:36.410
message on it. And that's our Exploitation[br]Primitive. Okay, so here we are. How do we
0:16:36.410,0:16:44.030
exploit this? So the rough idea for[br]exploiting such vulnerabilities looks like
0:16:44.030,0:16:49.850
this. You want to have some fake[br]Objective-C object somewhere in memory
0:16:49.850,0:16:55.079
that you're referencing. So again, we have[br]an we can access an arbitrary absolute
0:16:55.079,0:17:00.150
address. We want some fake Objective-C[br]object there. Every Objective-C object has
0:17:00.150,0:17:06.509
a pointer to its class. And then the class[br]has something called a method table, which
0:17:06.509,0:17:10.940
basically has function pointers to these[br]methods. Right. And so if we fake this
0:17:10.940,0:17:17.309
entire data structure thing, the fake[br]object and the fake class, then as soon as
0:17:17.309,0:17:22.379
the process calls some method on our fake[br]thing, we get code execution. So we get
0:17:22.379,0:17:28.459
control over the instruction pointer and[br]then it's game over. So that's going to be
0:17:28.459,0:17:37.770
our goal for this exploit. So here we have[br]two different types of addresses: On the
0:17:37.770,0:17:43.159
left side we have heap addresses or data,[br]really. And on the right side, in this
0:17:43.159,0:17:49.929
NSString-thing we need library addresses[br]or code addresses, simply because on iOS
0:17:49.929,0:17:57.200
you can't have writeable code regions. So[br]we have to necessarily reuse existing
0:17:57.200,0:18:00.919
code, do so to something like ROP also.[br]So we need to know where libraries are
0:18:00.919,0:18:07.290
mapped for this. And this is exactly the[br]problem we are gonna face now because
0:18:07.290,0:18:12.310
there is something called ASLR, Address[br]Space Layout Randomization. And what it
0:18:12.310,0:18:17.269
does is it will randomize this entire[br]address space. So on the left side, you
0:18:17.269,0:18:23.419
can see how a process looks like, how the[br]virtual memory of a process looks like
0:18:23.419,0:18:28.529
before ASLR. And there everything is[br]always mapped at the same address. So if
0:18:28.529,0:18:33.069
you start the same address twice on[br]different phones, maybe even without ASLR
0:18:33.069,0:18:37.200
the same library is at the same address,[br]the heap is always at the same address
0:18:37.200,0:18:41.559
stack. Everything is the same. And so this[br]would be really simple to exploit now
0:18:41.559,0:18:47.539
because, well, everything is the same.[br]With ASLR everything is shifted and now
0:18:47.539,0:18:53.000
all the addresses are randomized and we[br]don't really know where anything is. And
0:18:53.000,0:19:00.220
so that makes it harder to exploit this.[br]So we need an ASLR bypass is what this
0:19:00.220,0:19:07.309
means. We're gonna divide it into two[br]parts. So the heap addresses we get them
0:19:07.309,0:19:11.519
from in a different way than the library[br]addresses. So let's see how we get heap
0:19:11.519,0:19:18.100
addresses. It's really simple honestly,[br]what you can do is heap spraying, which is
0:19:18.100,0:19:24.749
an old technique. I think 15 years old[br]maybe. And it does still work today. The
0:19:24.749,0:19:29.789
idea is that you simply allocate lots of[br]memory. So if you look at this code there
0:19:29.789,0:19:35.069
put on the right, which you can use to[br]test that, what it does is that it allocates
0:19:35.069,0:19:40.999
256 megabytes of memory on the heap with[br]malloc. And then afterwards there's one
0:19:40.999,0:19:47.629
address or there's many addresses. But in[br]this case, I'm using this hex110000000
0:19:47.629,0:19:54.059
where you will find your data at. Okay. So[br]just spraying 256 megabytes lets you put
0:19:54.059,0:19:59.659
controlled data at a controlled address,[br]which is enough for this first part of the
0:19:59.659,0:20:05.330
exploit. The remaining question is how can[br]you heap spray over a iMessage. That's a
0:20:05.330,0:20:10.830
bit more complicated. But it is possible[br]because NSKeyedUnarchiver is great and it
0:20:10.830,0:20:18.260
lets you do all sorts of weird stuff which[br]you can abuse for heap spraying. So, yeah.
0:20:18.260,0:20:24.299
Blog posts will have more details. Okay.[br]So we have these, the heap addresses. We
0:20:24.299,0:20:32.340
have them. We need the library addresses.[br]Let's go back to the virtual memory space.
0:20:32.340,0:20:38.149
On iOS and also on macOS the libraries -[br]so maybe in this case all three libraries,
0:20:38.149,0:20:42.919
but in reality, it's like hundreds of[br]system libraries - they are all prelinked
0:20:42.919,0:20:48.849
into one gigantic binary blob, which is[br]called a dyld_shared_cache. The idea is
0:20:48.849,0:20:53.539
that this speeds up like loading times[br]because all the interdependencies between
0:20:53.539,0:20:59.270
libraries are resolved pretty much at[br]compile time. But yeah, so we have this
0:20:59.270,0:21:04.981
gigantic binary blob and it has everything[br]we need. So it has all the code, it has
0:21:04.981,0:21:10.769
all the ROP gadgets and it has all the[br]Objective-C classes. So we have to know
0:21:10.769,0:21:18.980
where this dyld_shared_cache is mapped. If[br]you dig into that a bit or if you look at
0:21:18.980,0:21:25.499
the documentation or the the binaries, you[br]can find out that it is going to be mapped
0:21:25.499,0:21:32.380
always between these two addresses. So[br]between 0x180000000 and 0x280000000, which
0:21:32.380,0:21:37.429
leaves only a 4 gigabyte region, so it's[br]only being mapped in these 4 gigabytes.
0:21:37.429,0:21:43.409
And then the randomization granularity is[br]also 0x4000 because iOS uses large pages
0:21:43.409,0:21:49.759
so it can only randomize with page[br]granularity, and that page granularity is
0:21:49.759,0:21:57.760
0x4000. But really what's most interesting[br]is that on the same device, the
0:21:57.760,0:22:03.570
dyld_shared_cache is only randomized once[br]per boot. So if if you have two different
0:22:03.570,0:22:08.270
processes on the same device, the shared[br]cache is at the same virtual address. And
0:22:08.270,0:22:12.259
if you have one process, then it crashes[br]and you have another one. And so on, like
0:22:12.259,0:22:17.590
the shared cache is always going to be at[br]the same address. And that makes it really
0:22:17.590,0:22:24.249
interesting. And also, it's one gigabyte[br]in size. It's gigantic. So it's not too
0:22:24.249,0:22:31.650
hard to find in this four gigabyte region.[br]Right. So this is what our our task has
0:22:31.650,0:22:37.340
boiled down to at this point. We have this[br]address range, we have the shared cache.
0:22:37.340,0:22:44.649
And all we need to know now is what is[br]this offset? So let's make a thought
0:22:44.649,0:22:51.039
experiment. Let's say we had an oracle[br]which would tell us... which we could give
0:22:51.039,0:22:55.729
an address. And it would tell us if this[br]address is mapped in the remote process.
0:22:55.729,0:23:03.480
OK, if we have this, it suddenly becomes[br]really easy to solve this problem, because
0:23:03.480,0:23:08.500
then all you have to do is you go in 1[br]gigabyte steps the the size of the shared
0:23:08.500,0:23:16.250
cache between these two addresses and then[br]at some point you find a valid address. So
0:23:16.250,0:23:20.750
maybe here after 3 steps, you find a valid[br]address, and then from there you just do a
0:23:20.750,0:23:26.210
binary search. Right. Because you know[br]that somewhere between the green and the
0:23:26.210,0:23:31.100
second red arrow, the shared cache starts.[br]So you can do a binary search and you find
0:23:31.100,0:23:39.740
the the start address in logarithmic time[br]in a few seconds, minutes, whatever. So
0:23:39.740,0:23:43.650
obviously the question is what? How? Where[br]would we get this oracle from? This seems
0:23:43.650,0:23:51.399
kind of weird. So let's look at receipts,[br]message receipts. So iMessage like many
0:23:51.399,0:23:57.859
other messengers - I think pretty much all[br]of them that I know - send receipts for
0:23:57.859,0:24:04.779
different things. iMessage in particular[br]has delivery receipts and read receipts.
0:24:04.779,0:24:11.230
Delivery received means the device[br]received the message, read receipt means
0:24:11.230,0:24:15.929
the user actually looked - opened the app,[br]looked at the message. You can turn off
0:24:15.929,0:24:21.469
read receipts, but as far as I know, you[br]cannot turn off delivery receipts. And so
0:24:21.469,0:24:27.769
here on the left you see a screenshot.[br]Three different messages were sent and
0:24:27.769,0:24:31.810
they have three different states. The[br]first message was marked as read, which
0:24:31.810,0:24:37.020
means it got a delivery receipt and a read[br]receipt. The second message is marked as
0:24:37.020,0:24:41.899
delivered. So it only got a delivery[br]receipt and the third message doesn't have
0:24:41.899,0:24:51.049
anything. So it hasn't received any[br]receipt. OK. So why is it useful? Here on
0:24:51.049,0:24:58.000
the left is some pseudocode of imagent's[br]handling of how it handles messages and
0:24:58.000,0:25:04.369
when it sends these receipts. And so you[br]can see that it first parses the plist
0:25:04.369,0:25:10.319
that's coming in and it's then doing this[br]nsUnarchive at some later time. And this
0:25:10.319,0:25:14.769
is this is exactly why all but would[br]trigger during nsUnarchive. And only then
0:25:14.769,0:25:22.970
does it send a delivery receipt. Right. So[br]what that means is if during our during
0:25:22.970,0:25:27.580
our nsUnarchive, if we can trigger the bug[br]and cause a crash, then we have somewhat
0:25:27.580,0:25:33.750
of a one bit sidechannel. Right. Because[br]if we cause a crash, then we won't see a
0:25:33.750,0:25:38.690
delivery receipt. And if we don't cause a[br]crash, then we see a delivery receipt. So
0:25:38.690,0:25:47.670
it's a one bit of information. And this is[br]going to be our oracle. All right. So
0:25:47.670,0:25:53.080
ideally, you have a vulnerability that[br]gives you this perfect oracle of is an
0:25:53.080,0:25:59.249
address mapped or not? So crash, if it is[br]not mapped, don't crash if it mapped. In
0:25:59.249,0:26:04.110
reality, you probably will not get this[br]perfect oracle from your bug. On the left
0:26:04.110,0:26:10.040
side, you see the real Oracle function for[br]this vulnerability, which is, well it has
0:26:10.040,0:26:18.159
to be mapped. OK. But then it's also using[br]the value that it's reading. And so it
0:26:18.159,0:26:24.039
will only not crash if the value is either[br]0 or if it has the most significant bit
0:26:24.039,0:26:29.340
set, that is some like pointer taking[br]stuff or if it's a real legitimate pointer
0:26:29.340,0:26:34.899
to an Objective-C object. So this Oracle[br]function is a bit more complex, but the
0:26:34.899,0:26:41.059
similar idea still works. So you can still[br]do something like a binary search, and
0:26:41.059,0:26:48.439
then infer the shared cache start address[br]in logarithmic time. Right. And so it only
0:26:48.439,0:26:54.049
takes maybe five minutes or so to do this.[br]But for this for this part, again, I have
0:26:54.049,0:27:01.519
to refer to the blog post which will cover[br]how this works. OK. So this is the summary
0:27:01.519,0:27:07.710
of the remote ASLR bypass. Two phases,[br]there's linear scan where it's just
0:27:07.710,0:27:13.289
scanning, sending these payloads and[br]checking if it gets the receipt back, and
0:27:13.289,0:27:17.459
the first time it gets a receipt back, it[br]knows. OK. This address is valid. I now
0:27:17.459,0:27:22.090
found an address that is within the shared[br]cache. And at that point it starts this
0:27:22.090,0:27:28.429
searching phase, which in logarithmic time[br]figures out the exact, precise starting
0:27:28.429,0:27:36.940
address. So there's a few common questions[br]about this that I want to briefly go into.
0:27:36.940,0:27:42.169
The first maybe obvious question is, can[br]you really just crash this agent like 20
0:27:42.169,0:27:49.799
plus times? And the answer is yes. There's[br]no indicator or anything that the user
0:27:49.799,0:27:55.759
would would see that this demon crashes.[br]The only thing you can do is you can go
0:27:55.759,0:27:59.899
into like settings, privacy, something[br]something, crash log something, and then
0:27:59.899,0:28:07.129
you can see these crash logs. Second[br]question is you can I think by default,
0:28:07.129,0:28:11.820
the iPhone is configured to send crash[br]logs to the vendor, to Apple. So isn't
0:28:11.820,0:28:17.499
that a problem? So I think I looked at[br]this briefly. What I stumbled across was
0:28:17.499,0:28:25.499
that it seems that iOS collects at most 25[br]crash logs per service. This is not
0:28:25.499,0:28:30.659
designed to be like a security feature.[br]Right. So this makes sense. But what that
0:28:30.659,0:28:37.610
means is that an attacker can use some[br]kind of, well, resource exhaustion bug to
0:28:37.610,0:28:44.599
crash this daemon maybe 25 times first,[br]and then only start to exploit and then no
0:28:44.599,0:28:52.129
trace of the exploit will be sent over.[br]Third question is whether this can be
0:28:52.129,0:28:56.879
fixed by simply sending the delivery[br]receipt very early on. I think this is...
0:28:56.879,0:29:01.909
this was my first suggestion to Apple to[br]just send this delivery receipt right at
0:29:01.909,0:29:06.659
the start. Eventually I figured out it[br]doesn't really work because you can still
0:29:06.659,0:29:12.459
make some kind of timing side channel,[br]because when when a demon crashes multiple
0:29:12.459,0:29:17.789
times, it's subject to some penalty and it[br]will only restart like a few seconds or
0:29:17.789,0:29:24.369
even minutes later. So from the timing of[br]getting a delivery receipt, you can then
0:29:24.369,0:29:30.269
still basically get this oracle. Right. So[br]it doesn't really work by just sending it
0:29:30.269,0:29:38.289
earlier. I'll go into some other ideas[br]that might work later. Okay. So at this
0:29:38.289,0:29:47.929
point I'm starting the demo. The demo is[br]two parts. Let's see where it is. Right.
0:29:47.929,0:29:54.059
So I have this iPhone here and you can[br]with QuickTime... the screen is mirrored
0:29:54.059,0:30:05.799
to the projector. So this iPhone is it's a[br]10S, so it's from last year. It's on 12.4,
0:30:05.799,0:30:10.879
which is the last vulnerable version. So[br]that's like half a year old at this point.
0:30:10.879,0:30:23.199
And what else? So there is no existing[br]chats open. Okay. And let's see. So I hope
0:30:23.199,0:30:27.889
the Wi-Fi works. What you can see here is[br]the way the exploit works that it's
0:30:27.889,0:30:35.259
hooking with Frida into... Do we get[br]delivery receipt? Uh, do we? Yeah. Okay,
0:30:35.259,0:30:41.179
cool. It works. So, yeah, it's popping up[br]these messages. The way the exploit works
0:30:41.179,0:30:46.330
that it's hooking the messages app on[br]macOS with Frida and then it's sending
0:30:46.330,0:30:54.289
these specific marker messages like[br]INJECT_ATI, and then the Frida hook
0:30:54.289,0:30:58.259
replaces this message with like the[br]current payload. Right. And now it's
0:30:58.259,0:31:09.039
testing these addresses. It's not too slow[br]I guess. Yeah. And it's popping up some
0:31:09.039,0:31:13.110
nice messages. Okay. It already found.[br]Okay. So this is already the end of the
0:31:13.110,0:31:18.619
first stage. So that was quite fast. It[br]found a valid address in this like first
0:31:18.619,0:31:25.409
probing step and now it has 21,000[br]candidates for the shared cache base. I
0:31:25.409,0:31:31.139
know it's doing this kind of binary search[br]thing to half that in every step. Okay.
0:31:31.139,0:31:38.580
Now it only has 10,000 left and so it's[br]quite fast and quite efficient. Okay.
0:31:38.580,0:31:49.869
While this runs, um, let's continue. So[br]this is where we are. We can now create
0:31:49.869,0:31:55.831
fake objects. We have all the addresses we[br]need. It's like this 1170 is where we can
0:31:55.831,0:32:02.379
place our stuff and then we will gain[br]control over the program counter. And from
0:32:02.379,0:32:07.009
there it's standard stuff, right? It's[br]what you would do in all of these exploits
0:32:07.009,0:32:11.820
you pivot maybe to the stack, you do[br]return oriented programing and then you
0:32:11.820,0:32:17.070
can run your code and you've succeeded.[br]Now, at this point, there is another thing
0:32:17.070,0:32:23.649
coming in. Pointer authentication is a new[br]security feature that Apple designed and
0:32:23.649,0:32:32.279
implemented first in the 10S, so this[br]device from 2018. And the idea is that you
0:32:32.279,0:32:37.190
can now - for this you need CPU support -[br]the idea that you can now store a
0:32:37.190,0:32:43.269
cryptographic signature in the top bits of[br]a pointer. OK, so here on the very left
0:32:43.269,0:32:47.879
side, you have a raw pointer. So the top[br]bits are zero because the way the address
0:32:47.879,0:32:57.330
space works. Now there's a set of[br]instructions that sign a pointer and they
0:32:57.330,0:33:02.299
will maybe take a context on it, but they[br]use some key that's not in memory - that's
0:33:02.299,0:33:07.769
in a register, compute a signature of this[br]pointer and store the signature in the top
0:33:07.769,0:33:12.319
bits. And that's what you see on the right[br]side. The green things. That's the
0:33:12.319,0:33:20.499
signature. And now before using this[br]pointer, the code will now authenticate by
0:33:20.499,0:33:24.999
running another instruction. And this[br]instruction, if the verification fails, it
0:33:24.999,0:33:28.899
will basically clobber this pointer,[br]make it invalid. And then the following
0:33:28.899,0:33:34.360
instructions will just crash. Right. So[br]here this is the function called the BL,
0:33:34.360,0:33:38.879
branch and link instruction. This is doing[br]a function call to a function pointer. But
0:33:38.879,0:33:43.259
first it's authenticating this pointer.[br]And if this authentication step fails,
0:33:43.259,0:33:49.820
then the process will crash right there.[br]What this means for an attacker is that
0:33:49.820,0:33:55.509
more or less, ROP is dead, because ROP[br]involves faking a bunch of function
0:33:55.509,0:33:59.839
point... or like, well, code pointers[br]really, that point in the middle of
0:33:59.839,0:34:05.210
existing code. So this is no longer[br]possible because an attacker cannot
0:34:05.210,0:34:13.109
generate these signatures. So this is[br]where our exploit breaks, right, the red
0:34:13.109,0:34:20.240
thing. Well, we have a fake objective C[br]class with our own function pointer. This
0:34:20.240,0:34:25.550
does no longer work because we cannot[br]compute these signatures. So what do we
0:34:25.550,0:34:32.510
do? One thing that's still possible and[br]it's even documented in the documentation
0:34:32.510,0:34:37.870
is that this class pointer in the object -[br]what's also called the ISA pointer -
0:34:37.870,0:34:44.970
it's not protected by PAC in any way.[br]Which means we can fake instances of
0:34:44.970,0:34:51.510
legitimate existing classes. Right. So in[br]this case here we can have a fake object
0:34:51.510,0:34:58.770
that points to a real class that has real,[br]legitimately signed method pointers. So
0:34:58.770,0:35:05.640
this tool works. And with this, we can now[br]get existing methods called, out of place
0:35:05.640,0:35:10.070
and kind of manipulate the control flow.[br]And these existing methods are basically
0:35:10.070,0:35:20.120
now gadgets. So if you want to think about[br]it that way. So what can we do with this?
0:35:20.120,0:35:24.860
One very interesting method we can get[br]called is dealloc, the destructor. So I
0:35:24.860,0:35:30.110
think in quite a few, maybe most of the[br]Objective-C exploitation scenarios, you
0:35:30.110,0:35:36.220
can probably get a dealloc method called.[br]Now what you do is you just enumerate all
0:35:36.220,0:35:41.390
the destructors in the shared cache.[br]There's tons of them, I think 50,000, and
0:35:41.390,0:35:46.610
you can get any of those called. And then[br]one of them or a few of them are really
0:35:46.610,0:35:52.500
interesting because they call this invoke[br]method, which is part of the NSInvocation
0:35:52.500,0:35:59.200
object, or class. And an NCInvocation is[br]basically a bound function. So it has a
0:35:59.200,0:36:05.240
target object, the method to be called and[br]all the arguments. And as soon as you call
0:36:05.240,0:36:09.660
invoke on this NCInvocation, it does this[br]method call with fully control arguments.
0:36:09.660,0:36:15.310
Right. So what that means is with this[br]destructor, we can now make a fake object
0:36:15.310,0:36:20.840
with a fake NSInvocation that has any[br]method call we would like to perform, and
0:36:20.840,0:36:28.060
then it's going to do that because it's[br]running this invoke here. Again, you see
0:36:28.060,0:36:33.510
this shield here, which I put in place for[br]things that Apple has hardened since we
0:36:33.510,0:36:39.210
sent them the exploit. So what they did so[br]far is they hardened NSInvocation and it's
0:36:39.210,0:36:46.730
now no longer easily possible to abuse it[br]in this way. But yeah. So for us, we can
0:36:46.730,0:36:52.910
now run arbitrary Objective-C methods with[br]controlled arguments. What about
0:36:52.910,0:36:58.860
sandboxing? If you do some more reverse[br]engineering and figure out what services
0:36:58.860,0:37:03.970
play into iMessage, this is what you end[br]up with. On the right side. So you have a
0:37:03.970,0:37:08.750
number of services. Most of them are[br]sandboxed. If it has the red border, it
0:37:08.750,0:37:15.320
means there's a sandbox. Interestingly,[br]Springboard also does some NSUnarchiver
0:37:15.320,0:37:22.510
stuff. So it's decoding the BP key. So it[br]could also trigger our vulnerability and
0:37:22.510,0:37:26.520
Springboard is not sandboxed. So it's the[br]main UI process. It's basically what's
0:37:26.520,0:37:34.900
handling showing the the welcome screen.[br]And so on. And so what that means is,
0:37:34.900,0:37:38.690
well, we can just target Springboard and[br]then we get code execution outside of the
0:37:38.690,0:37:43.740
sandbox so we don't actually need to worry[br]too much about the sandbox. As of iOS 13,
0:37:43.740,0:37:51.310
this is fixed and this key is now decoded[br]in the sandbox. Cool, so we can execute
0:37:51.310,0:37:56.370
Objective-C methods outside of the[br]sandbox. We can with that access user
0:37:56.370,0:38:00.980
data, activate camera, microphone, etc.[br]This is all possible through Objective-C
0:38:00.980,0:38:06.250
quite easily. But of course we don't care[br]about that. What we want is a calculator
0:38:06.250,0:38:10.960
and this is also quite easy, with one[br]Objective-C call - UIApplication
0:38:10.960,0:38:17.180
launchApplication blah blah blah. And so[br]let's see if this works. Go back to the
0:38:17.180,0:38:26.260
demo. So where are we at? So the, uh, the[br]ASLR bypass ran through. You can nicely
0:38:26.260,0:38:30.680
see that it roughly halved the candidates[br]in every round, or with every message
0:38:30.680,0:38:35.900
it had to send. It ended up with just[br]one message. Yeah, well with just one
0:38:35.900,0:38:40.920
candidate at the end. And that is the[br]shared cache base in this case
0:38:40.920,0:38:50.900
0x18a608000. Now it's preparing the heap[br]spray. This is all kind of hacked
0:38:50.900,0:38:59.160
together. I think if you wanted to do this[br]properly, for one, you can send the whole
0:38:59.160,0:39:06.680
heap spray in one message. I'm just lazy.[br]It's also probably way too big. Another
0:39:06.680,0:39:11.760
thing is, I think you would probably not[br]target springboard in reality just because
0:39:11.760,0:39:15.450
spring board is very sensitive. So if you[br]crash, did you get this re-spring and the
0:39:15.450,0:39:20.360
UI restarts. So I think in reality you[br]would probably target IM agent and then
0:39:20.360,0:39:26.250
chain the sandbox escape. Because while[br]this bug would also get you out of the
0:39:26.250,0:39:32.390
sandbox. So looks should be doable. Okay.[br]So I think the last message arrived. It's
0:39:32.390,0:39:35.850
freezing here for a couple of seconds. I[br]don't actually know why I never bothered,
0:39:35.850,0:39:44.760
but it does work.[br]Applause
0:39:44.760,0:39:52.460
Thank you. Yeah. So that was a demo. It's[br]it's kind of naturally reliable, this
0:39:52.460,0:39:59.270
exploit, because there is not much of heap[br]manipulation involved except this one
0:39:59.270,0:40:09.490
heaps spray, which is controllable. Okay.[br]Um, so what's left? I think one more thing
0:40:09.490,0:40:14.740
you can do is you can attack the kernel if[br]you want that. You have to deal with two
0:40:14.740,0:40:19.970
problems here. One is code signing. You[br]cannot execute unsigned code on iOS. And
0:40:19.970,0:40:24.960
then the standard workaround for that is[br]you abuse JIT pages in safari. But we are
0:40:24.960,0:40:29.770
not in safari or we are not in web[br]content, so we don't have JIT pages. What
0:40:29.770,0:40:36.130
I did here is I basically pivoted into[br]JavaScript core, which is the the JS
0:40:36.130,0:40:42.300
library. You can use it from from any app[br]also. And then I'm just bridging syscalls
0:40:42.300,0:40:48.120
into JavaScript and then implementing the[br]kernel exploit in JavaScript. This does
0:40:48.120,0:40:53.170
not require any more vulnerabilities. So[br]you do not need a JavaScript core bug to
0:40:53.170,0:40:58.870
do this. And the idea is very similar to[br]pwn.js. Maybe some of you know about that.
0:40:58.870,0:41:03.300
It's a library. I think initially[br]developed for Edge because they did
0:41:03.300,0:41:10.580
something similar was like JIT page[br]hardnings. So what I decided to do is take
0:41:10.580,0:41:18.750
SockPuppet from Ned or CVE-2019-8605,[br]which works on this version, it works on
0:41:18.750,0:41:26.870
12.4. This is the trigger for it. And I[br]only ported the trigger. I didn't bother
0:41:26.870,0:41:31.100
re -implementing the entire exploit. So[br]yeah, this is the trigger. It will cause a
0:41:31.100,0:41:36.560
kernel panic. It's quite short. Which is[br]nice. So if you want to run this from
0:41:36.560,0:41:41.750
JavaScript, really, there's only three[br]things you care about, right? So the first
0:41:41.750,0:41:48.020
one is you need the syscalls. So[br]highlighted here, there is like four or so
0:41:48.020,0:41:52.360
different syscalls here. Not a lot. And[br]you just have to be able to call them from
0:41:52.360,0:41:58.360
JavaScript. The other thing is you need[br]constants, right? So I have AF_INET6,
0:41:58.360,0:42:01.730
SOCK_STREAM. These are all integer[br]constants. So this is really easy, right?
0:42:01.730,0:42:07.020
You just need to look up what these values[br]end up being. And then the last thing is
0:42:07.020,0:42:13.520
you need some data structures. So in this[br]case, I need this so_np_extension thing.
0:42:13.520,0:42:21.500
It needs some integer value to pass[br]pointers to and so on. Yeah. And then this
0:42:21.500,0:42:28.370
is kind of the the magic that happens. You[br]take sock_puppet.c extract the syscalls
0:42:28.370,0:42:34.161
etc. There is one Objective C message you[br]can call which is very convenient, which
0:42:34.161,0:42:42.030
gives you a dlsym. What this lets you do[br]is, it lets you get native C function
0:42:42.030,0:42:46.680
pointers that are signed, right. Because[br]so far we can only call Objective C
0:42:46.680,0:42:51.270
methods, but we need to be able to call[br]syscalls or at least the C wrapper
0:42:51.270,0:42:59.720
functions. So with this dlsym method thing[br]we can get signed pointers to C functions.
0:42:59.720,0:43:03.190
Then we need to be able to pivot into[br]JavaScript code, which is also really easy
0:43:03.190,0:43:08.830
with one method call, the JSContext[br]evaluateScript. We need to mess around
0:43:08.830,0:43:12.840
with memory a bit like corrupt some[br]objects from outside, corrupt some area
0:43:12.840,0:43:18.810
buffers in javascript, get read, write.[br]Kind of standard browser exploitation
0:43:18.810,0:43:23.220
tricks I guess. But yeah. So if you do[br]this what you end up with is
0:43:23.220,0:43:30.920
sock_puppet.js. It looks very similar. You[br]can see a bit of my javascript API that
0:43:30.920,0:43:36.920
lets you allocate memory buffers. I read[br]and write memory, have some integer
0:43:36.920,0:43:42.050
constants and yeah, apart from that, it[br]doesn't really look much different from
0:43:42.050,0:43:49.370
the initial trigger. And so this can now[br]be served over, well, staged onto the
0:43:49.370,0:43:55.350
iMessage exploit building on top of this[br]object a C method called primitive. And I
0:43:55.350,0:43:59.740
guess at least in theory I didn't fully[br]implement it. This should be able to just
0:43:59.740,0:44:08.390
run a kernel exploit and fully compromise[br]the device without any interaction in
0:44:08.390,0:44:13.990
probably less than 10 minutes. Okay, so[br]this was the first part. How does how does
0:44:13.990,0:44:19.260
this exploit work. What I have now is a[br]number of suggestions how to make this
0:44:19.260,0:44:25.910
harder and how to improve things. So one[br]of the first things that is really
0:44:25.910,0:44:30.420
critical for this exploit is the ASLR[br]bypass, which relies on a couple of
0:44:30.420,0:44:36.620
things. And I think a lot of this ALSR[br]bypass also works on other platforms. So
0:44:36.620,0:44:41.960
Android has a very similar problem with[br]like mappings being at the same address
0:44:41.960,0:44:47.350
across processes. And other messengers[br]have these like receipts and so on. So I
0:44:47.350,0:44:51.640
think a lot of this applies not just to[br]Apple but to Android and to other
0:44:51.640,0:44:57.490
messengers. But okay. What is the first[br]point? So weak ALSR, this is basically the
0:44:57.490,0:45:03.530
heap spraying, which is just too easy.[br]This shouldn't be so easy. In terms of
0:45:03.530,0:45:07.890
theoretical ASLR, you can see it maybe[br]sketched here on the right. In theory,
0:45:07.890,0:45:12.660
ASLR could be much stronger, much more[br]randomized. In reality, it's just like the
0:45:12.660,0:45:18.800
small red bar. So it really it should just[br]have much more entropy to make heap
0:45:18.800,0:45:30.180
springing not viable anymore. The next[br]problem with ASLR is per-boot stuff. At
0:45:30.180,0:45:33.240
the bottom you can see it, right? So you[br]have three different processes, the shared
0:45:33.240,0:45:37.330
cache is always at the same address,[br]similar problems on other platforms, I
0:45:37.330,0:45:44.270
mentioned that. This is probably hard to[br]fix because by this point a lot of, quite
0:45:44.270,0:45:50.040
a lot relies on this. And it would be a[br]big performance hit to change this. But
0:45:50.040,0:45:55.960
maybe some clever engineers can figure out[br]how to do it better. The third part here
0:45:55.960,0:46:01.280
is the delivery receipts, which,[br]interestingly, they can give this side
0:46:01.280,0:46:06.370
channel, this one bit information side[br]channel and this can be enough to break
0:46:06.370,0:46:11.250
ASLR. And as I've mentioned before, I[br]think a lot of other messengers have this
0:46:11.250,0:46:21.270
same problem. What might work is to[br]either, well, remove these receipts. Sure.
0:46:21.270,0:46:25.270
Or maybe send them from a different[br]process so you can't do this timing thing
0:46:25.270,0:46:29.520
or even from the server. I think if you[br]send them, if the server already sends the
0:46:29.520,0:46:37.760
delivery receipt, it's a bit of cheating.[br]But at least this attack doesn't work.
0:46:37.760,0:46:43.020
Sandboxing, another thing, it's probably[br]obvious, right? So the everything that's
0:46:43.020,0:46:50.100
on zero click attack surface should be[br]sandboxed as much as possible. Of course,
0:46:50.100,0:46:55.770
to, you know, to require the attacker to[br]do another full exploit after getting code
0:46:55.770,0:47:02.270
execution. But Sandboxing can also[br]complicate information leaks. So not only
0:47:02.270,0:47:07.660
had this other iMessage bug[br]CVE-2019-8646, there's a blog post about
0:47:07.660,0:47:15.160
this one. It basically lets you. She was[br]able to send to cause a Springboard to
0:47:15.160,0:47:20.480
send HTTP requests to some server and[br]those would contain pictures, data,
0:47:20.480,0:47:27.320
whatever. If Springboard would've been[br]sandbox to not allow network activities,
0:47:27.320,0:47:31.190
this would have been much harder. So[br]sandboxing is not necessarily just about
0:47:31.190,0:47:36.550
this second breakout. What I do want to[br]say about sandboxing, ithat it shouldn't
0:47:36.550,0:47:41.510
be relied on. So I think that this remote[br]attack surface is pretty hard. And it's
0:47:41.510,0:47:46.480
not unlikely that it's actually harder[br]than the sandboxing attack surface. And
0:47:46.480,0:47:50.770
also on top of that, this bug, the[br]NSKeyedUnarchiver bug, it would also get
0:47:50.770,0:47:56.460
you out of the sandbox because the same[br]API is used locally for IPC. So there's
0:47:56.460,0:48:03.160
that. Yeah. This would be nice if the zero[br]click attack surface code would be open
0:48:03.160,0:48:08.530
source. Would have been nice for us. It[br]would have been easier to audit. Maybe
0:48:08.530,0:48:17.160
someday. Another feature that I would like[br]to see or another theme is reduced zero
0:48:17.160,0:48:21.780
attack surface. Make it one click at least[br]one click attack surface. Right. So before
0:48:21.780,0:48:28.070
and here you could see that an unknown[br]sender can send any messages. It would be
0:48:28.070,0:48:32.300
nice if there would be some pop up that's[br]like, well, do you actually want to accept
0:48:32.300,0:48:37.390
messages? Threema lets you block unknown[br]senders. I think that's a cool feature. So
0:48:37.390,0:48:44.791
yeah, there's more work to be done here.[br]Also, this restarting service problem, I
0:48:44.791,0:48:51.740
think it could get bigger even. So, here[br]we have pretty much unlimited tries for
0:48:51.740,0:48:56.840
the ASLR bypass. It's probably going to[br]become even more relevant with memory
0:48:56.840,0:49:03.680
tagging, which we can also be defeated if[br]you have many tries. So yeah, I guess if
0:49:03.680,0:49:08.330
there's some process or some critical[br]demon crashes ten times, maybe not restart
0:49:08.330,0:49:15.280
it. I don't know. It's gonna need some[br]more thinking, right? You don't want to
0:49:15.280,0:49:20.660
denial-of-service the user by just not[br]restarting this demon that crashed for
0:49:20.660,0:49:26.080
some unrelated reason. But yeah, this[br]would be a very good idea to have some
0:49:26.080,0:49:33.210
kind of limit here. Okay. Conclusion. So[br]yeah, zero click exploit, they are thing.
0:49:33.210,0:49:39.310
They do exist. It is possible to exploit[br]single memory corruption bugs on this
0:49:39.310,0:49:45.490
surface with, you know, without separate[br]info leaks. Despite all the mitigations we
0:49:45.490,0:49:51.240
have. However, I do think by turning the[br]right knobs, this could be made much
0:49:51.240,0:49:57.180
harder. So I gave some suggestions here.[br]And yeah, we need more atack surface
0:49:57.180,0:50:01.650
reduction, especially on the zero click[br]surface. But I think there is progress
0:50:01.650,0:50:06.500
being made. And with that thanks for your[br]attention. And I think we have time for
0:50:06.500,0:50:08.910
questions. Thank you.
0:50:08.910,0:50:16.270
applause
0:50:16.270,0:50:21.080
Herald: We do have time for questions. And[br]if you're in the room, you should line up
0:50:21.080,0:50:25.790
at the microphones and then we might also[br]have questions from the Internet. One
0:50:25.790,0:50:32.960
quick reminder is that all fun things that[br]what they work with explicit consent that
0:50:32.960,0:50:38.890
includes photos. So the photo policy of[br]the CCC is that if you take a photo, you
0:50:38.890,0:50:43.490
need to have explicit consent by the[br]people in the frame. So remember, don't do
0:50:43.490,0:50:47.880
any long shots into the crowd because you[br]want to have the consent of everybody
0:50:47.880,0:50:53.300
there. Good. We have the first question[br]from the Internet.
0:50:53.300,0:50:57.110
Question: The Internet wants to know. Did[br]Apple give you some kind of a reward? And
0:50:57.110,0:51:01.750
was it in your iPhone?[br]Answer: No, we did not get any kind of
0:51:01.750,0:51:11.520
reward. But we also didn't ask for it. No,[br]I didn't get a new iPhone, but I'm still
0:51:11.520,0:51:20.590
using mine. Which is it? Yeah. I mean,[br]this is a Xs, right? Current hardware
0:51:20.590,0:51:28.920
models can be defeated with this, if that[br]is the question.
0:51:28.920,0:51:31.870
Herald: Good. We have a question for[br]microphone number 3.
0:51:31.870,0:51:41.480
Q: Hello. Uh, just a question. I did not[br]truly understand how the fix with the
0:51:41.480,0:51:47.620
server or having another process, uh,[br]sending that there every message will fix
0:51:47.620,0:51:53.800
the problem because if it does work, if[br]you are in the right addresses, the thing
0:51:53.800,0:52:02.100
just will work. Make the server or the[br]process, send the delivery message and if
0:52:02.100,0:52:10.820
it crashes, it doesn't do anything so...[br]A: So the idea would be in this case, I'm
0:52:10.820,0:52:15.020
like sending this one method that would[br]crash and then either I get a delivery
0:52:15.020,0:52:20.030
received or I don't. If the server already[br]sends the delivery receipt before it
0:52:20.030,0:52:26.260
actually gives the message to the client[br]or to the receiver, then I would always
0:52:26.260,0:52:30.310
see a delivery receipt and I wouldn't be[br]able to figure out if my message caused
0:52:30.310,0:52:36.150
the crash or not. So that's the idea[br]behind maybe sending it on the server
0:52:36.150,0:52:38.890
side, if that makes sense.[br]Follow-up question: Yeah. But in this
0:52:38.890,0:52:47.180
case, if legit people send a message and[br]it doesn't reach the people because...
0:52:47.180,0:52:52.660
A: Yeah. Yeah. It's a hack. Right. So it's[br]not perfect. I mean the server could only
0:52:52.660,0:52:58.960
send to find this delivery receipt once it[br]like send it out over TCP and maybe got a
0:52:58.960,0:53:05.900
TCP ACK or whatever happens in the kernel.[br]But it's a hack in any case. Yeah. Like
0:53:05.900,0:53:08.130
it's a tradeoff.[br]Herald: We have a question for microphone
0:53:08.130,0:53:14.210
number two.[br]Q: Hello. Okay. Thanks for the talk. Two
0:53:14.210,0:53:20.530
questions. First: Is OS X also a[br]potential candidate for this bug. And
0:53:20.530,0:53:26.270
second: Can you distinguish multiple[br]devices with your address based
0:53:26.270,0:53:31.440
randomization detection?[br]A: Mm hmm. So yes: OS X or MacOS is
0:53:31.440,0:53:36.940
affected just the same. I think this[br]specific exploit wouldn't directly work
0:53:36.940,0:53:40.290
because address space looks a bit[br]different, but I think you could make it
0:53:40.290,0:53:45.280
work and it's affected. In terms of[br]multiple devices, so I haven't played
0:53:45.280,0:53:51.270
around with that. I could imagine that it[br]is possible to somehow figure out that
0:53:51.270,0:53:56.920
there are multiple devices or that you[br]know which device just crashed. But I
0:53:56.920,0:54:01.010
haven't investigated. That's the answer.[br]Follow-up: Thanks.
0:54:01.010,0:54:03.770
Herald: We still have time for more[br]questions. There was a question from
0:54:03.770,0:54:08.490
microphone number 1.[br]Q: Hi. Thanks for the talk. Quick
0:54:08.490,0:54:15.520
question. You said that exploitation could[br]be made without having any notification.
0:54:15.520,0:54:21.040
How would that be made?[br]A: Yeah, I briefly looked into how it
0:54:21.040,0:54:29.120
could work. Well. So for one, you can take[br]out parts of the message so that it fails
0:54:29.120,0:54:34.480
parsing later on in the processing and[br]then it will just be like thrown away
0:54:34.480,0:54:39.490
because it says, well, this is garbage.[br]The other thing is, of course, once you
0:54:39.490,0:54:45.160
get with the like very last message where[br]you get code execution, you cannot prevent
0:54:45.160,0:54:48.620
it from showing a message like a[br]notification, because that happens
0:54:48.620,0:54:52.720
afterwards.[br]Follow-up Q: But until you get the code
0:54:52.720,0:54:56.690
execution, you can't remove it. So you[br]see the first message?
0:54:56.690,0:55:01.140
A: So but you can do the other. The other[br]thing, like make it make the message look
0:55:01.140,0:55:05.690
bad - bad enough that like later parsing[br]stages will throw them away.
0:55:05.690,0:55:08.510
Follow-up: Thanks.[br]Herald: Good. We have a couple of more
0:55:08.510,0:55:11.130
questions. Remember, if you don't feel[br]comfortable lining up behind the
0:55:11.130,0:55:15.180
microphones, you can ask through the[br]signal angel through the Internet.
0:55:15.180,0:55:19.720
Microphone number 4, please.[br]Q: Yes. Hi. Hi Samuel. Um, I was curious
0:55:19.720,0:55:24.340
you have some suggestions about reducing[br]the attack surface. Are there any
0:55:24.340,0:55:28.400
suggestions that you'd make to save, like[br]Apple or Google? You know, in terms of
0:55:28.400,0:55:31.830
what they can see. You mentioned logging a[br]little bit earlier.
0:55:31.830,0:55:39.590
A: Yeah. So I sent pretty much this list[br]with the exploit I sent to Apple. And I
0:55:39.590,0:55:47.280
think the blog post will have a bit more.[br]But yeah, I told them the same thing.
0:55:47.280,0:55:50.190
Yeah, if that's your question, did I get[br]it right?
0:55:50.190,0:55:53.770
Follow-up Q: Yes. I mean, maybe I[br]misunderstood a little bit, but I suppose
0:55:53.770,0:55:57.400
that some of these reductions in the attack[br]surface seem to be in terms of like what's
0:55:57.400,0:56:01.710
happening on the device. Yeah. Whereas I'm[br]wondering in terms of monitoring. So being
0:56:01.710,0:56:03.560
able to catch something like this in[br]progress.
0:56:03.560,0:56:07.600
A: Right. Right. So this is gonna be[br]really hard because of end-to-end
0:56:07.600,0:56:13.210
encryption. So the server just sees like[br]encrypted garbage and has no way of
0:56:13.210,0:56:18.570
knowing is this an image? Is that the[br]text? This is an exploit? So on the
0:56:18.570,0:56:25.619
server, I don't think you can do much[br]there. I think it's gonna have to be on
0:56:25.619,0:56:29.050
the device.[br]Herald: We have a question from the
0:56:29.050,0:56:33.500
Internet.[br]Q: How do you approach a attack surface
0:56:33.500,0:56:41.430
mapping?[br]A: Um, well, reverse engineering, playing
0:56:41.430,0:56:47.760
around, looking at this message format. In[br]this case, what was somewhat obvious what
0:56:47.760,0:56:51.590
an attack surface was. Right. So figure[br]out which key is off this message are
0:56:51.590,0:56:57.770
being processed in some way. Make a note.[br]Decide which one looks most complex. Go
0:56:57.770,0:57:03.090
for that first. That's what we did.[br]Herald: We have a question from microphone
0:57:03.090,0:57:07.020
number 2, please.[br]Q: Hi. How long did you and your colleague
0:57:07.020,0:57:14.590
research to get the export running?[br]A: So the the vulnerability finding thing
0:57:14.590,0:57:21.510
was not only I think we spend maybe three[br]months finding the exploit. So I had a
0:57:21.510,0:57:26.710
rough idea how I wanted to how how I would[br]approach this exploit. So I think at the
0:57:26.710,0:57:33.990
end it took me maybe a week to finish it.[br]But I had thought about doing that for
0:57:33.990,0:57:38.790
like, while a looking while looking for[br]vulnerabilities and those two to three
0:57:38.790,0:57:42.190
months.[br]Herad: We have another question from
0:57:42.190,0:57:48.550
microphone number three.[br]Q: Um, is there the, uh, threat that the
0:57:48.550,0:57:54.500
attacked iPhone would itself turn into a[br]tack up by the exploit?
0:57:54.500,0:57:59.270
A: Sure. Yeah, you can do that. I mean,[br]you have full control, right? So you have
0:57:59.270,0:58:05.000
access to the contacts list and you can[br]send out iMessages. The question is if
0:58:05.000,0:58:09.260
it's necessary. Right. I mean, you can[br]also send messages from you don't really
0:58:09.260,0:58:15.860
need them, the iPhone to send the[br]messages. But I think in theory: Yes,
0:58:15.860,0:58:19.000
that's possible.[br]Herald: Do we have more questions from the
0:58:19.000,0:58:25.440
Internet?[br]Q: Does the phone stay compromised after
0:58:25.440,0:58:28.740
restart?[br]A: So there is no persistence exploit
0:58:28.740,0:58:34.410
here. No. You will need another exploit a[br]littlelailo did a talk. I think just an
0:58:34.410,0:58:40.130
hour ago about persistence. So you would[br]need to change this with what, for
0:58:40.130,0:58:45.040
example, to exploit that he showed.[br]Herald: And if you have questions in the
0:58:45.040,0:58:47.800
room, please line up behind the[br]microphones. Do we have more questions
0:58:47.800,0:58:55.150
from the Internet.[br]Q: Yes. So you've achieved the most novel
0:58:55.150,0:59:02.330
buck ever found to be fine in iOS. What's[br]the next big thing you'll be looking at?
0:59:02.330,0:59:06.480
A: Good question. I don't really know[br]myself, but I'm going to stay probably
0:59:06.480,0:59:12.520
around for zero click attack surface reduction[br]for a bit more.
0:59:12.520,0:59:16.100
Herald: Looks like we don't have any brave[br]people asking questions in the room. Does
0:59:16.100,0:59:21.080
the Internet have more courage?[br]Q: How long does discovery and
0:59:21.080,0:59:26.750
exploitation and development take and how[br]much does the team work to improve the
0:59:26.750,0:59:33.710
process and development time?[br]A: Okay, so how much how long does this
0:59:33.710,0:59:39.530
exploitation process work? That's the[br]first question. Yes. Yeah. I mean, this is
0:59:39.530,0:59:45.020
generally a hard thing to answer. Right.[br]There's like years of hacking around and
0:59:45.020,0:59:50.670
learning how to do this stuff, etc. that[br]you have to take into account. But as I
0:59:50.670,0:59:54.500
said, I had a rough idea how this exploit[br]would look like. So then really
0:59:54.500,1:00:00.600
implementing it was like one or two weeks.[br]The initial part of reverse engineering
1:00:00.600,1:00:04.811
iMessage reverse engineering this[br]NSUnarchiver thing. I kind of I think this
1:00:04.811,1:00:10.650
took forever. This took many months and it[br]was also very necessary for exploit
1:00:10.650,1:00:17.030
writing. Right. So a lot of the expert[br]primitives I use, they also abuse the
1:00:17.030,1:00:21.760
NSKeyUnarchiver thing.[br]Herald: We have time for perhaps two quick
1:00:21.760,1:00:27.480
questions. Mike number 4, please.[br]Q: Super. Uh, I'm not super familiar with
1:00:27.480,1:00:32.980
iOS virtual memory address space but you[br]should two heap regions when you showed the
1:00:32.980,1:00:37.360
picture of it. And I'm wondering why are[br]there two heap regions?
1:00:37.360,1:00:42.510
A: OK, because there is only a minor[br]detail, but I think there is one region
1:00:42.510,1:00:48.700
initially like below the shared cache and[br]one state is full. It just makes another
1:00:48.700,1:00:56.150
one above it. So it's really just like if[br]the one gets used or gets gets used up, it
1:00:56.150,1:00:59.340
makes another one. And that's going to be[br]like above the shared cache. I think
1:00:59.340,1:01:03.300
that's the picture you're referring to.[br]Follow-up: Yeah, thank you.
1:01:03.300,1:01:06.910
Heralds: And unfortunately, we are out of[br]time. So the person that might have some
1:01:06.910,1:01:10.690
number one, please come up to the stage[br]afterwards and perhaps you can grab a talk.
1:01:10.690,1:01:17.287
So please give a warm. I can't say this[br]exactly. applause Thanks.
1:01:17.287,1:01:22.797
applause
1:01:22.797,1:01:26.942
Postroll music
1:01:26.942,1:01:50.000
Subtitles created by c3subtitles.de[br]in the year 2020. Join, and help us!