[00:03.020 --> 00:09.520] So our next speaker is Jonathan Bar-Orr on how getting a free phone got me to report [00:09.520 --> 00:14.120] critical vulnerabilities affecting millions of Android devices. I am so glad you did that. [00:14.120 --> 00:20.880] Thank you. Jonathan Bar-Orr, or J-B-O, is the Microsoft Defender Research Architect for [00:20.880 --> 00:26.920] cross-platform... blah, blah, blah. I rented these lips this morning. They're not working. [00:27.460 --> 00:34.380] Research Architect for cross-platform, focusing on macOS, Linux, Android, and iOS research. [00:34.420 --> 00:39.240] Jonathan has rich offensive security research on various platforms and architectures, [00:39.240 --> 00:42.960] as well as a combination of defensive skills and threat research. [00:42.960 --> 00:45.720] So without any further ado, Jonathan, take it over. [00:57.060 --> 00:59.640] You need to pick up a microphone in order to... [00:59.640 --> 01:01.100] Yeah, I know. Hold on. [01:01.100 --> 01:02.080] Turn it on. [01:03.080 --> 01:05.700] Hold on. Do I pick that with R or L? [01:11.680 --> 01:12.960] Leave it to R. [01:14.320 --> 01:15.960] Just the left click. [01:18.720 --> 01:22.680] Jesus. All right. Can anyone hear me at all? [01:23.960 --> 01:24.560] I can. [01:24.560 --> 01:26.000] Yes, we hear you just fine. [01:26.740 --> 01:29.000] So I do have the mic right now? [01:30.380 --> 01:31.680] I think so. [01:31.840 --> 01:32.920] All right. Awesome. [01:32.920 --> 01:33.740] Let me check real quick. [01:36.620 --> 01:38.640] Doesn't look like I have the mic, but let me... [01:39.100 --> 01:43.220] Okay. I turned megaphone on for you, so it should work. [01:43.220 --> 01:45.340] All right. Awesome. Thank you so much. [01:45.340 --> 01:47.520] So let's go on the next slide, please. [01:49.340 --> 01:54.360] Who am I? My name is Jonathan Boror, or JBO for short. [01:54.480 --> 01:57.260] That's my Twitter handle if you ever want to contact. [01:57.720 --> 02:02.400] As I was introduced, I'm the Microsoft Defender for Cross-Platform Research Architect. [02:02.400 --> 02:08.420] That's basically a very long name, but it basically means that I look at everything [02:08.420 --> 02:12.500] that does not run Windows, and that's my responsibility. [02:12.500 --> 02:17.680] I do Windows once in a while, though, especially when it comes to, you know, [02:17.680 --> 02:23.960] the things that intertwine between Windows and other operating systems like WSL and WSA. [02:24.020 --> 02:28.680] And I released some cool blog posts this year on all of these platforms. [02:28.740 --> 02:31.000] The Chrome OS one will be released soon. [02:31.380 --> 02:32.440] Next slide, please. [02:35.460 --> 02:38.180] Well, how did this get started? [02:38.180 --> 02:43.060] I relocated to the US back in 2017, and I'm an Android user, [02:43.060 --> 02:46.520] so I relocated with the same old Android phone that I had back home. [02:47.080 --> 02:53.620] And my carrier, who shall not be named, decommissioned 3G and transitioned into 5G, [02:53.620 --> 02:56.000] right, with all the cool stuff that it brings. [02:56.160 --> 03:02.420] And because my phone didn't support 5G, it basically became useless. [03:02.420 --> 03:06.000] So they decided to send me a free phone as compensation. [03:06.000 --> 03:12.400] And, you know, my brain started pounding, and I'm like, should I really trust them? [03:12.500 --> 03:17.220] And I decided not to trust their phone blindly and actually see what's inside [03:17.220 --> 03:20.860] and buy myself a new phone and play with the old one. [03:20.920 --> 03:22.860] Next slide, please. [03:25.940 --> 03:29.400] So when exploring a brand new phone, you can do a bunch of stuff. [03:29.400 --> 03:34.420] But first thing first, you know, the easiest things, I decided to look at apps. [03:34.420 --> 03:38.860] And I discovered that there are tons of system apps there. [03:38.920 --> 03:43.480] And one of them seemed to be bundled with something called DTE Ignite, [03:43.480 --> 03:48.440] which is an advertisement framework that might install new apps on your phone silently [03:48.440 --> 03:50.480] based on your browsing habits. [03:50.480 --> 03:54.760] It sounds terrible, but I'm actually not here to talk about that. [03:54.760 --> 03:57.220] I'm here to talk about something else that I discovered. [03:57.220 --> 04:01.360] So I discovered tons of stuff, but one thing in particular caught my eye. [04:02.000 --> 04:06.380] And that was something called a device health app. [04:06.380 --> 04:09.340] And it's a system app and had tons of permissions. [04:09.340 --> 04:11.100] And that's our focus for today. [04:11.100 --> 04:11.920] Next slide, please. [04:14.080 --> 04:17.720] Just some background, if you're really unfamiliar with Android. [04:17.720 --> 04:20.380] Android apps are conceptually archives. [04:20.380 --> 04:23.420] They're not really archives, but you can think of them as archives. [04:23.420 --> 04:25.220] And they contain various files. [04:25.220 --> 04:29.520] And those files are resources, code, metadata, digital signatures. [04:29.520 --> 04:33.160] They're all separated by design and are basically different files. [04:33.760 --> 04:37.300] And one of the most important sections there is called a manifest, [04:37.300 --> 04:42.200] which contains metadata about the app, the app name, version, activities in it, [04:42.200 --> 04:43.700] as well as permissions. [04:43.980 --> 04:48.700] And the first thing in any Android app analysis is to examine the permissions that it has. [04:48.700 --> 04:52.280] It's saved under androidmanifest.xml as a binary data, [04:52.280 --> 04:57.000] but any basic Android analysis tool translates that XML to a human-readable text. [04:57.140 --> 04:58.700] So just some background. [04:58.700 --> 04:59.500] Next slide, please. [05:02.280 --> 05:04.280] And this is a list. [05:04.280 --> 05:07.780] I don't know how much you can see with the OutSpace VR thingy, [05:07.780 --> 05:12.080] but this is a pretty big list of what the app is capable of doing. [05:12.080 --> 05:16.520] And basically, it can access the internet, access Wi-Fi state, read phone state, [05:16.520 --> 05:22.320] read external storage, get package size, use the camera, use the fingerprints, [05:22.320 --> 05:24.440] record audio, read phone numbers. [05:24.440 --> 05:30.980] And it can do a bunch of stuff that is really overwhelming what it can do. [05:31.540 --> 05:33.100] And the list goes on and on. [05:33.100 --> 05:35.280] This is just a partial screenshot. [05:44.080 --> 05:50.720] So when you look at the activities, they're also in the manifest.xml file, [05:50.720 --> 05:54.080] the thing that shows the metadata of the package. [05:54.440 --> 05:59.940] You can see that there is the main activity called com.mceMainActivity. [05:59.940 --> 06:04.040] And then there are a bunch of other stuff there, like the actions and so on. [06:04.040 --> 06:08.300] And the thing that caught my eye is the last two readable lines, [06:08.300 --> 06:13.620] the one that says browsable, and then it has the Android scheme mceDigital. [06:13.620 --> 06:17.640] So this is basically like the main activity, and it's browsable. [06:17.640 --> 06:18.900] Next slide, please. [06:20.580 --> 06:26.180] So browsable activities, the app registers a new schema called mceDigital, right? [06:26.180 --> 06:30.700] And basically, when the schema is browsed to, this is an Android feature, right? [06:30.700 --> 06:32.600] The main activity starts. [06:32.600 --> 06:36.300] And this is, for example, how when you open like a Zoom link, [06:36.300 --> 06:40.460] you know, Android knows to start Zoom with the right parameters. [06:40.500 --> 06:44.680] It's basically a way for an app to say, hey, I want to register that schema. [06:44.680 --> 06:48.880] And whenever that schema is accessed, please, please wake me up. [06:49.440 --> 06:54.140] And this is the first obvious foothold for a logical remote code execution. [06:54.140 --> 06:57.300] Mentally, that's how I imagine it in my mind. [06:57.300 --> 06:59.860] And sometimes an attacker can pass malicious data [06:59.860 --> 07:02.580] with a schema that will be parsed by the activity, [07:02.580 --> 07:06.120] like a buggy schema, URL, get parameters, info. [07:06.680 --> 07:09.780] And the next analysis goal for me is, well, [07:09.780 --> 07:12.740] what does the app do once it launches through the schema? [07:12.740 --> 07:18.640] And can I give it any meaningful input, right, from the URL that's being accessed? [07:18.640 --> 07:20.300] Next slide, please. [07:22.200 --> 07:23.720] Something about web views, [07:23.720 --> 07:27.700] if you've completely been living under a rock in the Android world. [07:27.700 --> 07:31.720] In Android, web views are basically components that can parse and present web content, [07:31.720 --> 07:34.000] including JavaScript capabilities. [07:34.000 --> 07:36.880] So they're like almost mini browsers, if you will. [07:37.460 --> 07:39.400] They're useful for app developers, [07:39.400 --> 07:43.080] especially for engines that use them extensively cross-platform, right? [07:43.080 --> 07:48.180] So if you want to write an app and make it available in Android and iOS, [07:48.180 --> 07:49.440] you can use that. [07:49.440 --> 07:51.500] And web view is a component. [07:51.500 --> 07:53.120] Well, React will do that. [07:53.120 --> 07:57.620] But web view is a component that will be used extensively, actually, to run that app. [07:57.620 --> 07:59.380] And a lot of apps rely on web views. [07:59.380 --> 08:02.400] That's not very, very new. [08:02.520 --> 08:04.540] And, you know, a security question is that [08:04.540 --> 08:07.380] granting web view capabilities to do certain things, [08:07.380 --> 08:10.540] because a lot of apps are, you know, relying on web views, [08:10.920 --> 08:15.120] granting the web view capabilities to do certain things is quite problematic. [08:15.120 --> 08:19.940] Think of unlimited file access from something that behaves like a browser, right? [08:20.100 --> 08:22.860] And plausible scenarios that attacker could actually [08:22.860 --> 08:25.380] inject malicious coding to the web view. [08:25.380 --> 08:28.420] And the question is, how does Android solve this problem? [08:28.420 --> 08:29.560] Next slide, please. [08:30.980 --> 08:35.120] And this is achieved by something called an Android base bridge. [08:35.140 --> 08:38.900] An app, it's a web view, and it can declare a JavaScript interface [08:38.900 --> 08:40.480] and attach it to the web view. [08:40.540 --> 08:44.680] And from that point on, the web view can actually invoke methods in the app [08:44.680 --> 08:49.020] by that interface and get responses back. [08:49.200 --> 08:55.980] The data that can be sent is limited to primitive data types in the Java virtual machine. [08:56.120 --> 08:58.900] And this is what's called an Android.js bridge. [08:58.900 --> 09:00.280] Next slide, please. [09:00.740 --> 09:04.500] This is a toy example of Android.js bridge. [09:04.500 --> 09:13.240] In the first part, you can see Java code that will run in the Java app on the Android device. [09:13.920 --> 09:16.800] You can see that I declare a class called JS interface. [09:16.800 --> 09:19.940] I have to declare something called JavaScript interface. [09:19.940 --> 09:21.920] That's an annotation to a method. [09:22.200 --> 09:24.440] And then the method actually just adds two numbers. [09:24.440 --> 09:26.040] So nothing scary here. [09:26.380 --> 09:30.100] And you can see that I had to do two other things. [09:30.260 --> 09:34.360] Given a web view, I had to basically enable JavaScript. [09:34.440 --> 09:40.700] Then I basically add JavaScript interface with that sense of that class that I just said. [09:40.700 --> 09:42.320] And expose it under name. [09:42.320 --> 09:45.460] In this case, I expose it under some name. [09:45.560 --> 09:48.240] And then the web view can run JavaScript. [09:48.240 --> 09:51.080] That's the lower part of the page here. [09:51.360 --> 09:55.360] And it will basically invoke window.someName.addNumbers. [09:55.360 --> 09:56.860] Just invoke it like that. [09:56.860 --> 10:02.580] And the parameters and everything will be sent from the web view to the Android app. [10:02.580 --> 10:04.440] And then basically invoked. [10:04.440 --> 10:06.100] And I can also get the result. [10:06.100 --> 10:10.280] So this is how you add two numbers with an Android.js bridge. [10:10.280 --> 10:11.460] Next slide, please. [10:12.320 --> 10:15.780] So, only methods. [10:15.780 --> 10:20.280] This is something, just a little more background on Android.js bridges. [10:20.280 --> 10:23.980] Only methods that are annotated with a JavaScript interface annotation. [10:23.980 --> 10:26.660] You've seen that one slide, two slides ago. [10:26.660 --> 10:31.360] Can be invoked starting API level four, which is ages ago. [10:31.360 --> 10:34.480] Otherwise, you get this funny vulnerability where you say, [10:34.480 --> 10:40.120] where the web view can do windows.withName.getClassForName, whatever. [10:40.120 --> 10:44.480] You can basically get the runtime.exec method. [10:44.580 --> 10:47.740] This happened in 2004 or something. [10:47.740 --> 10:49.300] So very, very old. [10:50.620 --> 10:57.500] And you can't do that anymore after Android API level four. [10:58.260 --> 11:01.660] And therefore, what I'm trying to say is that an analysis of a JS interface [11:01.660 --> 11:05.840] should examine the methods that are annotated with a JavaScript interface. [11:05.880 --> 11:10.100] So this is kind of like a background on why I'm doing what I'm doing. [11:10.120 --> 11:11.800] Next slide, please. [11:12.900 --> 11:17.600] If we're going back to my app analysis, we have the health app, right? [11:17.700 --> 11:20.160] And the health app basically is browsable. [11:20.160 --> 11:25.520] And one thing that I discovered is that it also has a web view called JarvisWebView. [11:25.520 --> 11:27.280] That's how they expose it to the... [11:29.220 --> 11:30.420] Actually, not expose it. [11:30.420 --> 11:32.800] This is how they declare it in the classes there. [11:32.820 --> 11:37.740] And the web view has an attached JavaScript interface called JarvisJSInterface. [11:37.740 --> 11:39.620] That's just the name that they expose. [11:40.120 --> 11:48.080] And the interfaces can be accessed from within the web page via the JavaScript bridges [11:48.080 --> 11:50.900] and invoke accessible methods. [11:52.100 --> 11:56.860] And one remark is that they're notorious for trust issues, right? [11:56.860 --> 12:01.300] In many cases, the app can blindly trust the web view's input, right? [12:01.300 --> 12:03.140] And next slide, please. [12:03.520 --> 12:08.980] This is kind of like a code blurb of the annotated methods that I found. [12:09.560 --> 12:12.240] Three out of four of the annotated methods. [12:12.240 --> 12:15.420] And I'll explain why I added the third one as well. [12:15.460 --> 12:16.880] The first one is called init. [12:16.880 --> 12:18.220] It gets a string. [12:18.220 --> 12:25.260] And it basically saves something that I, you know, while reverting, just called a callback name. [12:25.260 --> 12:26.760] The second one is called request. [12:26.760 --> 12:27.860] It gets a string. [12:27.860 --> 12:31.180] And it calls super.request with that string. [12:31.460 --> 12:34.580] The third one is called sendResponse. [12:34.580 --> 12:38.960] And it's not annotated, so you can't really access it from the web view. [12:38.980 --> 12:43.240] And the fourth one is called window.close, which is not very interesting. [12:43.240 --> 12:46.040] And I'm just not going to talk about that at all. [12:46.040 --> 12:47.120] Slide, please. [12:48.520 --> 12:54.060] From a software design perspective, the JarvisJS interface that we saw in the app, [12:54.060 --> 12:58.780] it works as an asynchronous server to the JavaScript client. [12:58.780 --> 13:04.020] It gets requests in the three methods that I've just shown you. [13:04.240 --> 13:08.120] And returns callbacks by injecting JavaScript back to the web view. [13:08.660 --> 13:11.800] This kind of explains the stuff that we saw earlier. [13:13.200 --> 13:15.700] Init basically gets a string and saves it. [13:15.700 --> 13:18.340] That string is going to be used later as a callback function, [13:18.340 --> 13:20.720] JavaScript function, to the client. [13:21.020 --> 13:22.500] CloseWindow is not very interesting. [13:22.500 --> 13:26.320] And request serves requests from the JavaScript client. [13:26.540 --> 13:30.760] And this also explains the response methods that we saw earlier. [13:30.760 --> 13:31.800] The response methods... [13:31.800 --> 13:33.900] Would you actually mind going back one slide? [13:33.900 --> 13:35.000] Is that possible? [13:35.580 --> 13:36.720] Awesome, thank you. [13:36.720 --> 13:42.360] The sendResponse method that we saw is going to be invoked later by the app [13:42.360 --> 13:45.280] when it's ready to send a response. [13:45.580 --> 13:48.580] And if you can see the code there, I know it's a bit difficult. [13:48.580 --> 13:53.980] But basically, it's going to build a URL that starts with JavaScript colon [13:53.980 --> 13:56.380] and add some JavaScript code there. [13:56.380 --> 13:59.280] That also includes the callback name, by the way. [13:59.340 --> 14:02.700] And basically, inject it with loadUrl. [14:02.700 --> 14:05.680] That's the last line in the third method here. [14:06.400 --> 14:09.020] Next slide, and then next slide again. [14:11.820 --> 14:13.840] The request method is... [14:14.740 --> 14:20.000] Well, the request method actually invokes the superclass.request. [14:20.080 --> 14:25.320] And the superclass for that JavaJS interface is just called serviceTransport. [14:25.460 --> 14:29.600] And after some unimportant tasks, I examined what it does. [14:29.600 --> 14:32.680] And it will treat the input string as a JSON object. [14:32.680 --> 14:34.620] And it extracts some members from it. [14:35.120 --> 14:36.720] Those are the four members. [14:36.720 --> 14:40.720] First of all, there is context, which I think of as a request ID. [14:40.720 --> 14:44.980] Basically, in an asynchronous model, when you have a client in a server, [14:44.980 --> 14:48.220] the client needs to supply, or in some way, [14:48.220 --> 14:50.540] there needs to be tracing of some request ID. [14:50.540 --> 14:52.320] So that's the context, basically. [14:52.640 --> 14:54.280] Service is a service name. [14:54.280 --> 14:55.680] More on that later. [14:55.680 --> 14:57.080] Command is an integer. [14:57.080 --> 14:58.860] Effectively, it's a command number. [14:58.860 --> 15:03.340] And data is effectively the arguments that are sent with that command. [15:03.340 --> 15:04.300] Next slide, please. [15:06.420 --> 15:10.980] And, you know, when you start to take a look at the services that are implemented, [15:10.980 --> 15:13.660] again, let me remind everyone, [15:13.660 --> 15:17.080] if I have malicious code that runs in the web view, [15:17.080 --> 15:23.480] I can basically invoke the JavaJS interface methods. [15:23.480 --> 15:25.180] One of them is called request. [15:25.300 --> 15:28.940] And with request, I can actually invoke services. [15:28.940 --> 15:30.280] And what does that mean? [15:30.500 --> 15:32.580] So I started reverse engineering that thing. [15:32.580 --> 15:36.820] And there are many services that get registered in a global table. [15:36.820 --> 15:40.140] I won't bore you with the gory details too much. [15:40.140 --> 15:43.300] But basically, there is a global table that is saved. [15:43.300 --> 15:46.240] And each service declares its exposed methods, [15:46.240 --> 15:48.020] maps them to command members, [15:48.020 --> 15:51.020] along with the argument names and types it expects. [15:51.160 --> 15:57.240] And the entire request is being translated on the flight with JavaScript reflection. [15:57.360 --> 16:00.780] And each request can also invoke the send response methods [16:00.780 --> 16:05.540] that we saw earlier to actually return a response to the client. [16:05.820 --> 16:07.140] Next slide, please. [16:07.880 --> 16:11.580] Some of the invocable services that I saw, [16:11.580 --> 16:16.660] this is a very partial list of interesting services that are accessible from the web view. [16:16.660 --> 16:18.020] One of them is audio. [16:18.020 --> 16:19.720] You can control audio on the phone, [16:19.720 --> 16:22.780] including peripheral volumes and stuff like that. [16:22.780 --> 16:25.980] Camera, you can take silent camera pictures. [16:26.260 --> 16:30.440] Connectivity, you can basically control Wi-Fi, Bluetooth, NFC, and whatnot. [16:30.440 --> 16:33.040] Device controls many aspects of the device. [16:33.040 --> 16:35.940] I also found the command injection there, more on that later. [16:36.160 --> 16:39.740] Location, you can access GPS and whatnot. [16:39.740 --> 16:43.860] Package manager, you can control packages, you can install new apps, [16:43.860 --> 16:48.020] which, by the way, because you're a system app, you can do that silently. [16:48.020 --> 16:50.100] So, not great. [16:50.760 --> 16:54.640] So, basically, my understanding is that [16:54.640 --> 16:57.880] Hiku controls the JavaScript, controls the device. [16:57.880 --> 17:00.400] If you're able to get malicious JavaScript code, [17:00.400 --> 17:02.680] the web view, you basically win. [17:02.680 --> 17:06.560] Because it can do a lot of those stuff and many, many more. [17:06.560 --> 17:07.820] Next slide, please. [17:08.660 --> 17:11.640] This is an example of the camera service. [17:11.900 --> 17:14.440] This is actually how the code looks like. [17:14.500 --> 17:16.780] After some predefining by me. [17:16.880 --> 17:18.000] You have basically... [17:18.720 --> 17:22.800] all services must implement something called set service methods map. [17:22.800 --> 17:28.800] That's what I referred to earlier as kind of registering their own methods. [17:28.800 --> 17:31.340] And you can see that there are two methods exposed here. [17:31.340 --> 17:32.740] One of them is get camera list. [17:32.740 --> 17:35.360] And the other one is capture still image no preview. [17:35.360 --> 17:40.500] And get camera list basically gets no arguments. [17:40.500 --> 17:46.160] And capture still image no preview gets one argument, which is called camera ID. [17:46.160 --> 17:47.260] And it's a string. [17:47.860 --> 17:55.220] And there is another class called IPC, which maps the method names to the actual numbers. [17:55.220 --> 17:57.900] So, method number zero is get camera list. [17:57.900 --> 18:00.840] Method number one is capture still image no preview. [18:00.840 --> 18:03.040] That's just an example of how a service looks like. [18:03.040 --> 18:06.900] And then the service can implement those methods however it sees fit. [18:06.900 --> 18:08.440] Next slide, please. [18:10.020 --> 18:14.440] Well, one of the services in device specifically gets... [18:14.440 --> 18:16.300] this is just a command injection that I found. [18:16.300 --> 18:17.900] I mentioned that two slides ago. [18:17.900 --> 18:23.720] One of the services that gets an activity name and tries to stop it by running the following command. [18:23.720 --> 18:29.060] am force-stop, open quotes, activity name, close quotes. [18:29.060 --> 18:33.440] And guess what happens when the activity name has quotation marks. [18:33.440 --> 18:37.580] So, surprise, surprise, if the activity name has quotation marks, [18:37.580 --> 18:39.860] you can basically run arbitrary commands, right? [18:39.860 --> 18:41.780] So, this is kind of a command injection. [18:41.780 --> 18:45.320] Just in case I wanted to take control of the device even further, [18:45.700 --> 18:47.640] this would basically allow me to... [18:47.640 --> 18:51.220] if I'm able to run malicious code in the web view, [18:51.220 --> 18:57.600] to inject arbitrary code to run as the device health app, which is a system app again. [18:58.140 --> 19:01.480] So, this is just one thing, one minor thing that I found. [19:01.500 --> 19:02.760] Slide, please. [19:04.060 --> 19:08.060] At this point, I was pretty convinced that, you know, this is big. [19:08.120 --> 19:14.520] And I assume that a JavaScript injection is possible somehow to the web view. [19:14.520 --> 19:18.900] And if we assume that, we can control the phone with all the services. [19:18.900 --> 19:23.460] And we can abuse the command injection or simply do other fun stuff, [19:23.460 --> 19:27.680] like taking camera snapshots, turning on the microphone, [19:27.680 --> 19:30.600] you know, all the fun stuff that you see in the movies. [19:31.040 --> 19:34.380] So, you know, you have to do this kind of mental exercise. [19:34.380 --> 19:38.220] And, you know, I was like, this is too good not to inject into. [19:38.220 --> 19:39.280] There must be a way. [19:39.280 --> 19:43.620] So, even before I was convinced I'm going to inject into the web view, [19:43.620 --> 19:46.700] I basically implemented my own exploit, [19:46.700 --> 19:49.020] which is kind of like a post-exploit, if you think about it, [19:49.020 --> 19:51.200] because you still have to inject into the web view. [19:51.520 --> 19:52.640] And this is what I did. [19:52.640 --> 19:53.760] Next slide, please. [19:55.140 --> 19:57.920] This is kind of like a post-exploit code. [19:57.920 --> 20:05.200] You basically implement just the thing that the web view is supposed to implement, right? [20:05.200 --> 20:09.040] So, basically, create some map. [20:09.060 --> 20:11.720] I created a C2 just for us to have fun. [20:11.720 --> 20:13.880] And you can invoke that with Ajax. [20:13.960 --> 20:15.500] And you can set the callback. [20:15.500 --> 20:23.000] If you can see in the last part, it says window.response callback equals whatever. [20:23.000 --> 20:28.230] And then you can actually call the bridge and initiate that with whatnot. [20:28.880 --> 20:29.950] Next slide, please. [20:31.120 --> 20:36.160] And this is kind of like a generic code for the send request part. [20:36.160 --> 20:43.090] This actually sends a request to the web view, to the JS bridge, sorry. [20:43.090 --> 20:45.510] And this makes everything very simple. [20:45.510 --> 20:48.670] Because now, if you look at the right part, you will see that it says, [20:48.670 --> 20:53.630] basically, this is how you run stuff from the web view, if you could inject into it. [20:53.630 --> 20:56.010] You basically do exploit equals new exploit. [20:56.010 --> 21:01.130] And then exploit.getCameraList, exploit.storage, do whatever, and so on. [21:01.130 --> 21:04.210] So, you can just invoke those methods freely. [21:04.210 --> 21:06.630] As I said, you can basically control the phone. [21:06.710 --> 21:07.850] So, I prepared that. [21:07.850 --> 21:13.050] And, you know, I basically patched the app just to see that it works and it works well. [21:13.730 --> 21:15.550] Next slide, please. [21:16.710 --> 21:20.190] Kind of like a mid-talk summary, because we've been through a lot. [21:20.230 --> 21:21.590] Have a system app. [21:21.590 --> 21:24.630] That system app is pre-installed on the phone. [21:24.750 --> 21:30.590] And it has a remotely invocable main activity through a browsable activity, right? [21:30.590 --> 21:32.910] If you... the MC digital thing. [21:32.910 --> 21:35.470] The activity loads a web view, right? [21:35.470 --> 21:39.390] That if... and I put a strong emphasis on if. [21:39.390 --> 21:42.830] If injected into can essentially take over the phone. [21:43.090 --> 21:47.690] And we can build an exploit code that does just that. [21:47.690 --> 21:50.510] But can we really inject into web view? [21:50.510 --> 21:52.750] That's the question that I had in mind. [21:52.750 --> 21:58.810] And that's the 1 million vulnerable Android apps... devices question. [21:58.810 --> 21:59.810] Next slide, please. [22:01.630 --> 22:05.570] Well, the first attempt to inject was that... [22:07.510 --> 22:11.930] I discovered that the page that is being loaded to the web view is loaded... [22:12.510 --> 22:15.750] is actually embedded in the app itself as an asset. [22:16.010 --> 22:20.890] So a web view can, you know, just like a normal browser, can just load stuff from HTTP. [22:20.890 --> 22:24.950] Or it can load stuff from like file, comma, slash, slash, right? [22:24.950 --> 22:26.210] Like an asset. [22:26.230 --> 22:28.570] And this is what happens in this case. [22:28.590 --> 22:34.630] And the JavaScript code that runs on the web is quite obfuscated and was extremely long. [22:34.730 --> 22:37.770] Like 100k lines long. [22:37.910 --> 22:41.070] And, you know, at this point, by the way, I did forget to mention, [22:41.070 --> 22:43.950] like, it became too big for me. [22:43.950 --> 22:47.670] And I'm like, okay, let's involve our Android team, because why not? [22:47.690 --> 22:52.130] And I basically involved our Android V team in Defender. [22:52.130 --> 22:55.190] And we reversed engineered parts of it. [22:55.190 --> 22:59.630] But we couldn't find meaningful ways to affect the behavior from the browsable intent. [22:59.850 --> 23:01.990] So that was kind of a bummer. [23:02.210 --> 23:05.450] And the second hope that I had was to basically have, [23:05.450 --> 23:08.490] like, kind of like a person in the middle story. [23:08.490 --> 23:12.810] If the app is opened and the web view opens a plain text page, [23:12.810 --> 23:16.810] I can basically inject as just because I'm like a person in the middle [23:16.810 --> 23:18.630] between the phone and the internet. [23:18.690 --> 23:21.870] And we did find several scenarios when that happens. [23:21.870 --> 23:24.350] And this is kind of like a success, right? [23:24.350 --> 23:30.110] Because basically what you have to do right now is, in my opinion, [23:30.110 --> 23:32.630] you know, it's not trivial, but it's not impossible. [23:32.630 --> 23:34.130] Next slide, please. [23:35.950 --> 23:39.830] So the scenario for remote code execution in this case. [23:39.950 --> 23:41.690] Be a person in the middle, right? [23:41.690 --> 23:43.630] You can achieve that in numerous ways. [23:43.630 --> 23:47.690] Like I can open, you know, a Starbucks Wi-Fi on my phone or something. [23:47.690 --> 23:52.650] I can, you know, control your router or do other stuff. [23:53.090 --> 23:57.050] Send a link to the target or inject it into a normal plain text web view [23:57.050 --> 23:59.290] that the target just browses into. [23:59.290 --> 24:03.210] And trigger the browsable activity, the MC digital thing. [24:03.210 --> 24:07.190] Because the MC digital browser activity actually kicks in [24:07.190 --> 24:09.910] and it's registered by that device health app, [24:09.910 --> 24:13.250] which is a system app that was, by the way, hidden from the UI. [24:13.410 --> 24:14.990] The app kicks in. [24:14.990 --> 24:18.570] The app loads the web view, which runs complicated logic [24:18.570 --> 24:23.190] and ends up viewing more contents in plain text, right? [24:23.190 --> 24:26.510] Load stuff from external HTTP over plain text. [24:26.510 --> 24:30.870] And then I inject malicious JavaScript code into the plain text code. [24:30.870 --> 24:34.850] And, you know, I run my exploit and I basically take over the phone. [24:34.850 --> 24:36.690] So that's pretty good. [24:37.530 --> 24:39.290] Next slide, please. [24:40.030 --> 24:45.190] It sounds like our kind of fun RCE on Android is over. [24:45.190 --> 24:51.850] But, you know, one thing that got me a bit worried or a bit, you know, intrigued [24:51.850 --> 24:54.530] was the fact that during the reverse engineering, [24:54.530 --> 25:00.290] we saw that, like, you know, I got my phone from my carrier. [25:00.290 --> 25:03.810] In all of the class names and whatnot, when reverse engineering that app, [25:03.810 --> 25:06.770] we didn't see that, like, carrier name at all. [25:07.490 --> 25:10.270] And we suspected that there is an entire framework, [25:10.270 --> 25:12.190] which was not carrier specific, right? [25:12.190 --> 25:15.770] You did see that MCA digital thing and so on. [25:17.090 --> 25:20.870] And basically tried to assess, you know, we already had an RCE [25:20.870 --> 25:27.370] and I was going to basically disclose it responsibly. [25:27.530 --> 25:30.270] But when assessing the number of affected devices, [25:30.270 --> 25:33.910] we decided to hunt for similar apps that might be using the same framework. [25:33.910 --> 25:39.330] And, you know, there is no shame to say we actually just used VirusTotal. [25:39.470 --> 25:42.870] And surprisingly, we discovered numerous telcos [25:42.870 --> 25:45.410] that use the same framework, right? [25:45.410 --> 25:47.010] So imagine all the big telcos. [25:47.010 --> 25:49.730] I will not mention anyone because I don't want to be sued. [25:49.770 --> 25:54.430] But imagine, you know, all the big telcos in America and whatnot. [25:54.710 --> 25:59.330] I mean, this was embedded in five of them and big ones. [26:00.670 --> 26:05.390] There seemed to be some customization per telco. [26:05.390 --> 26:07.350] So one telco might have certain features [26:07.350 --> 26:10.250] and a different telco might have other features. [26:10.270 --> 26:14.770] Obviously, besides the app name and logos that are used and stuff like that. [26:14.770 --> 26:19.150] And not all apps were susceptible to like the person in the middle attack, right? [26:19.150 --> 26:25.470] Some of them actually did not load external code from plain text. [26:25.470 --> 26:28.610] So the remote code execution part didn't work. [26:28.610 --> 26:35.550] And one thing that I also discovered is that besides those five telcos, [26:36.150 --> 26:38.570] there are certain apps that use that framework [26:38.570 --> 26:43.750] that might be installed by phone repair shops or for trading purposes. [26:43.750 --> 26:47.010] So if it wasn't clear, the device health app is supposed to basically [26:47.010 --> 26:51.250] make sure that the camera is working, that the microphone is working. [26:51.250 --> 26:54.050] This is why it needed all of those permissions. [26:54.050 --> 26:59.590] And basically, some of those telcos pre-installed it in the firmware, right? [26:59.590 --> 27:01.930] That's what I've got initially. [27:01.930 --> 27:07.610] But we also discovered that there is a specific app that can be installed by repair shops. [27:07.610 --> 27:10.810] And sometimes they forget to uninstall the app [27:10.810 --> 27:14.990] after you get your phone back from fixed and whatnot. [27:14.990 --> 27:18.350] So this is another issue that we saw. [27:18.990 --> 27:24.110] Users are always, in this case, either because the app is baked into the firmware [27:24.110 --> 27:29.430] or because you got your phone fixed and someone installed an app unbeknownst to you. [27:29.510 --> 27:33.770] And users were always, to the best of my knowledge, [27:33.770 --> 27:36.630] unsuspecting that this thing even existed. [27:37.070 --> 27:38.510] Next slide, please. [27:39.990 --> 27:44.710] So we decided to dig deeper and see if we could exploit the apps [27:44.710 --> 27:48.190] that were not susceptible to the person-in-the-middle JavaScript injection. [27:48.890 --> 27:52.430] And eventually, we found a local JavaScript injection. [27:53.090 --> 27:57.090] And this is like... I won't actually wait for responses. [27:57.090 --> 28:01.390] But the question is, can you spot the injection opportunity with the next slide? [28:03.410 --> 28:05.210] So this is kind of like... [28:05.930 --> 28:09.470] Well, this code is taken from multiple methods. [28:09.470 --> 28:17.470] But basically, the injection part actually resides in the last part, [28:17.470 --> 28:18.890] in the third part. [28:19.210 --> 28:24.330] But basically, what's going to happen here is that you get some parameter called flow input [28:24.330 --> 28:28.310] that I will mention what it does briefly in a sec. [28:28.310 --> 28:33.970] But basically, this flow input is going to be sent to the WebView's init function. [28:34.070 --> 28:37.890] The init function is going to basically see if it's empty. [28:37.890 --> 28:42.710] And if it's not empty, it's going to save it in other member name. [28:42.710 --> 28:45.910] And later, that member name, if it's not empty, [28:45.910 --> 28:51.750] is going to be basically loaded into the WebView with load URL again, [28:51.750 --> 28:54.690] just like the JavaScript injection that we saw earlier. [28:54.950 --> 28:56.150] Next slide, please. [28:58.270 --> 29:00.590] This is kind of like what I mentioned. [29:00.590 --> 29:03.470] There is a member called mflow SDK input. [29:03.470 --> 29:05.850] By the way, I have no idea what it's supposed to do. [29:05.850 --> 29:07.850] I never saw it actually being used. [29:07.850 --> 29:09.650] But the member exists. [29:09.870 --> 29:15.610] And the member is a JSON object stringified and perfectly injected into the WebView, as we saw. [29:15.610 --> 29:19.650] The interesting part, and this is where the injection kicks in, [29:19.650 --> 29:24.230] there is no string sanitization on the string itself, [29:24.230 --> 29:28.750] which means that we could inject it to control that member, right? [29:28.750 --> 29:34.260] If I can control that member, I can actually inject JavaScript into the WebView locally. [29:35.290 --> 29:37.910] And the member is initialized very indirectly, [29:37.910 --> 29:40.530] like there are four or five different classes there, [29:41.020 --> 29:43.390] by the intent that creates the app. [29:43.390 --> 29:46.810] Interestingly, from a Google Firebase parcel, [29:46.810 --> 29:51.990] it doesn't really matter that much, but just because it's funny to me. [29:52.330 --> 29:54.090] Next slide, please. [29:54.390 --> 29:56.790] I did have one pesky limitation. [29:56.790 --> 30:01.530] That the entire payload, because we're talking about the JSON object, [30:01.530 --> 30:08.010] and it's going to be, you know, eventually turned into a string, [30:08.010 --> 30:13.010] and then injected into the WebView with a JavaScript injection, [30:13.390 --> 30:18.250] the entire payload can contain new lines, because JSON stuff, [30:18.250 --> 30:23.150] but you can easily overcome that with eval, a2b, and then base64 encoded payload. [30:23.150 --> 30:26.230] So, if you have a payload, you can just turn it into base64, [30:26.230 --> 30:31.090] and then add some code to, you know, unwrap and undo what you wanted, [30:31.090 --> 30:36.230] like the entire base64 thingy. [30:36.410 --> 30:41.170] And basically, this is kind of like how you run JavaScript code in one line, right? [30:41.170 --> 30:43.370] Which is not a big thing, but still. [30:43.930 --> 30:45.490] Next slide, please. [30:46.670 --> 30:52.490] Oh, this has a nice PowerPoint animation. Kudos to me. [30:52.890 --> 30:55.470] In the left side, you can see the app itself. [30:55.470 --> 30:57.710] In the middle part, you can see the WebView. [30:57.710 --> 31:00.950] And in the right part, there is an attacker, right? [31:00.950 --> 31:06.270] And basically, what's going to happen, and can you click one time, please? [31:07.310 --> 31:10.690] You basically, I prepared like the second stage JS loader. [31:10.690 --> 31:13.910] That's the first, like, part where, you know, [31:13.910 --> 31:17.330] the entire payload where I assumed that I could inject. [31:17.330 --> 31:18.770] So, I have that code. [31:18.770 --> 31:20.370] And then, next, click, please. [31:21.310 --> 31:27.490] I wrap it with eval a2b and base64, but just to make it a one-liner. [31:27.510 --> 31:28.930] Next, please. [31:29.630 --> 31:33.150] I wrap it into some member that is called dynamic. [31:33.150 --> 31:35.930] This is how Google Firebase works in this case. [31:35.930 --> 31:37.350] Next one, please. [31:37.690 --> 31:40.090] I wrap it into something called a parcel. [31:40.090 --> 31:46.410] How objects are basically being serialized in Android. [31:46.690 --> 31:47.870] Next, please. [31:48.890 --> 31:52.850] This thing is turned into bytes, because this is how you, like, [31:52.850 --> 31:54.930] intents can just contain bytes. [31:54.930 --> 31:55.930] Next one, please. [31:56.830 --> 32:00.670] Then, I wrap it into an intent. [32:00.670 --> 32:04.310] An intent, basically, I didn't mention it, but that's the way that you, [32:04.310 --> 32:07.710] that's a very popular IPC in Android. [32:08.170 --> 32:12.790] And basically, it's the thing that fires apps and activities and whatnot. [32:13.250 --> 32:14.770] Next, click, please. [32:15.030 --> 32:16.970] So, the intent gets into the app. [32:16.970 --> 32:17.870] Next, click. [32:18.890 --> 32:27.890] And then, the app unwraps it, takes the bytes, unwraps it, [32:27.890 --> 32:29.910] takes the parcel, unwraps it, and so on. [32:29.910 --> 32:31.430] It does all of those things. [32:31.430 --> 32:35.250] And eventually, it will basically run the second stage JS loader. [32:35.250 --> 32:37.790] It will load the JavaScript into the web view. [32:37.790 --> 32:39.270] Next one, please. [32:39.810 --> 32:41.970] The web view loads the JavaScript. [32:41.970 --> 32:46.290] The web view actually loads additional JavaScript from my C2. [32:46.490 --> 32:48.030] Next one, please. [32:49.290 --> 32:52.170] It invokes client requests, right? [32:52.170 --> 32:53.550] And next one, please. [32:54.170 --> 32:56.070] It provides responses. [32:56.090 --> 33:00.890] Also, by the way, if you want to take pictures of, you know, [33:00.890 --> 33:06.050] cameras or turn on the microphone and whatnot, this all works well. [33:06.350 --> 33:10.190] And I mentioned here local injection, because if it wasn't clear, [33:10.190 --> 33:13.810] to fire that intent with the very specific bytes inside, [33:13.810 --> 33:19.570] you have to run and get the app inside to the system app that, [33:19.570 --> 33:21.830] you know, the device health app. [33:21.870 --> 33:26.470] But this is still considered an elevation of privilege for obvious reasons. [33:26.470 --> 33:30.430] Like, your initial app doesn't have to have any permissions. [33:30.430 --> 33:32.610] If you can inject and do all of those things, [33:32.610 --> 33:34.730] you can basically take over the phone. [33:34.970 --> 33:36.410] Next slide, please. [33:38.090 --> 33:40.190] This is my exploit code. [33:41.510 --> 33:44.970] I won't dive too much into it, but you can see in the first part [33:44.970 --> 33:48.270] that I basically take the JavaScript payload. [33:48.530 --> 33:53.830] I basically add some code to embed that payload into the web view itself [33:53.830 --> 33:57.190] by just inserting a new script element [33:58.230 --> 34:03.270] and loading the source from my C2. [34:03.690 --> 34:14.430] And basically, I had to append an extra quote, [34:14.430 --> 34:17.070] and then I just put A's there for fun. [34:17.070 --> 34:19.370] And the idea behind that is that, you know, [34:19.370 --> 34:21.850] this is how the JavaScript injection works, right? [34:21.850 --> 34:26.970] Like, it takes my input and treats it as a string with quotation marks. [34:26.970 --> 34:28.530] So, if I finish a quotation, [34:28.530 --> 34:31.350] I can actually inject more JavaScript stuff there. [34:31.590 --> 34:37.170] And then basically, the second part was to encode everything into a single statement [34:37.170 --> 34:40.890] that's just, you know, basic C4 encoding. [34:40.890 --> 34:42.210] Next slide, please. [34:45.960 --> 34:50.140] And this basically is kind of... [34:50.140 --> 34:52.460] Oh, and in the previous slide... [34:52.460 --> 34:53.960] Sorry, can you go one slide back? [34:53.960 --> 34:55.020] I apologize. [34:55.020 --> 34:57.780] The thing that has the red rectangle [34:57.780 --> 35:00.580] is basically where the other injection kicks in. [35:00.580 --> 35:04.840] You basically have to put, like, a single quote, right? [35:04.940 --> 35:10.640] This is where the JavaScript injection actually kicks in. [35:12.360 --> 35:15.280] Flow input member that we discussed. [35:15.280 --> 35:16.960] Sorry, now next slide. [35:18.400 --> 35:21.300] This basically continues building the entire thing. [35:21.300 --> 35:23.780] I build something called a dynamic link data. [35:25.080 --> 35:27.820] And basically, in that dynamic link data, [35:27.820 --> 35:31.060] the only thing that actually was meaningful [35:31.060 --> 35:35.400] is building it eventually as a parcel. [35:35.400 --> 35:37.980] And then the parcel, I have to embed into... [35:37.980 --> 35:39.320] Like, I have to marshal it. [35:39.320 --> 35:40.460] It turns into bytes. [35:40.460 --> 35:44.380] And then those bytes are basically embedded in the app itself. [35:44.380 --> 35:46.020] In the intent itself. [35:46.020 --> 35:47.060] I apologize. [35:47.380 --> 35:51.140] As the com.google.firebase.dynamic.links.dynamic.link.data. [35:51.140 --> 35:54.980] That's the last part of this right here. [35:55.700 --> 35:57.380] Next slide, please. [35:58.060 --> 36:01.480] This is a recording of the local injection. [36:01.480 --> 36:03.140] I hope it plays well. [36:03.140 --> 36:04.820] Can you please try to play it? [36:06.140 --> 36:07.940] See how that works. [36:10.180 --> 36:11.100] Hey, okay. [36:11.100 --> 36:13.930] So, on the left side, you can see the two... [36:14.820 --> 36:18.400] We actually had two servers for C2 for other reasons. [36:18.440 --> 36:22.480] And then on the right side, you can see the checkup app. [36:22.480 --> 36:28.220] And this is our PC app that injects into the system app. [36:28.220 --> 36:30.760] The system app, by the way, doesn't have to be turned on. [36:30.760 --> 36:32.060] I just turned it off. [36:32.060 --> 36:32.540] That's fine. [36:32.540 --> 36:33.660] It doesn't really matter. [36:33.660 --> 36:36.120] Because we can always start an intent. [36:36.280 --> 36:38.280] This will basically start an intent. [36:38.360 --> 36:42.240] And on the left side, you can see that it actually starts getting data, right? [36:42.260 --> 36:45.520] So, this is basically how our exploit works. [36:46.580 --> 36:48.680] This is our recording. [36:48.980 --> 36:50.120] Next slide, please. [36:52.760 --> 36:53.500] Okay. [36:53.500 --> 36:55.000] Responsible disclosure. [36:56.120 --> 37:01.340] We disclosed everything to the company that maintains the framework itself, [37:01.340 --> 37:05.280] like the entire SDK, as well as all the telcos that were involved. [37:05.280 --> 37:06.760] There are five in total. [37:06.920 --> 37:09.220] I can't give an exact number. [37:09.220 --> 37:13.080] But we're talking about millions of Android devices with vulnerable system apps [37:13.080 --> 37:16.920] affected by bugs ranging from full RCE to local EOP. [37:18.180 --> 37:20.820] And it took a lot of months, actually. [37:20.820 --> 37:22.340] This is quite problematic. [37:22.340 --> 37:27.820] You can't really even remove system apps from your Android phone. [37:27.820 --> 37:32.500] At least my grandma kind of users can't do that. [37:32.520 --> 37:36.380] And we basically released details in coordination with everyone involved [37:36.380 --> 37:40.240] to make sure that no end user is put in danger. [37:40.660 --> 37:45.800] Because releasing new firmware and basically making sure that everyone updates and so on [37:45.800 --> 37:48.320] is very painful to those telcos. [37:48.320 --> 37:51.940] And we also constantly work together with Google [37:51.940 --> 37:57.500] to actually improve Google Play Protect and spot similar bugs automatically. [37:58.540 --> 38:00.320] This is kind of interesting. [38:00.960 --> 38:07.320] Those apps, those device health apps or that SDK, actually, was in Google Play. [38:07.320 --> 38:11.040] And it still is, by the way, in the Google Play Store. [38:11.740 --> 38:15.320] And Google Play has basically something called Google Play Protect, [38:15.320 --> 38:19.660] which scans your apps against evil and also vulnerabilities. [38:20.040 --> 38:24.540] But they simply didn't have good handling of that vulnerability class, [38:24.540 --> 38:27.540] like vulnerabilities that involve JS interfaces. [38:28.200 --> 38:31.820] So we are working with Google on that. [38:32.240 --> 38:34.040] Next slide, please. [38:35.360 --> 38:36.400] Resolution. [38:36.400 --> 38:39.840] So disclosure happened around September 2021, [38:39.840 --> 38:45.300] but it took more than six months until user risk became sufficiently low for public disclosure. [38:46.220 --> 38:49.500] And this is just my take on the thing. [38:49.500 --> 38:53.080] One of the main problems is that those were system apps, right? [38:53.260 --> 38:57.300] I don't want to use the term bloatware, but I already used it. [38:57.300 --> 38:59.080] So let's call it bloatware. [39:00.080 --> 39:03.480] System apps are baked into the device firmware image. [39:03.480 --> 39:05.040] You can't turn them off. [39:05.040 --> 39:07.320] And there are many unsuspecting users. [39:07.320 --> 39:10.400] Like, I bet if some of you are Android users, [39:11.480 --> 39:17.100] I'm willing to bet that you don't know at least 30% of the system apps [39:17.100 --> 39:19.940] that are installed on your phone at any given time. [39:21.360 --> 39:26.820] And basically, me working as Microsoft for Defender, [39:26.820 --> 39:29.400] we also have Microsoft Defender on Android, [39:29.400 --> 39:32.540] and we support something called vulnerability management, [39:32.540 --> 39:35.640] which does indicate the existence of vulnerable apps. [39:35.640 --> 39:39.300] So if you have a vulnerable app on your phone, [39:40.140 --> 39:42.960] and specifically that set of vulnerabilities, [39:42.960 --> 39:45.220] we'd be able to at least tell you. [39:45.240 --> 39:48.460] So, you know, you can't uninstall the system app, [39:48.460 --> 39:50.820] but that's a good start, I think. [39:51.660 --> 39:53.320] Next slide, please. [39:54.440 --> 39:57.420] A quick note for Android developers. [39:58.240 --> 40:00.640] Overpowered web views with JS interfaces [40:00.640 --> 40:03.760] are the source of many interesting security bugs. [40:03.960 --> 40:05.840] And apps, as I mentioned before, [40:05.840 --> 40:08.960] sometimes just blindly trust input from the web views, right? [40:08.960 --> 40:11.560] You have a web view and you have your app, [40:11.560 --> 40:15.080] and the app simply trusts it without thinking [40:15.080 --> 40:17.500] whether it could be injected into or not. [40:17.680 --> 40:19.320] And that's one thing. [40:19.320 --> 40:21.700] So whenever you develop an app, you know, [40:21.700 --> 40:23.360] be mindful of those things. [40:23.360 --> 40:26.300] If you implement an asynchronous client-server module [40:26.300 --> 40:29.320] by JavaScript injection, then please don't do that. [40:29.320 --> 40:30.700] It's really bad practice, [40:30.700 --> 40:34.320] and there are good APIs that are included [40:34.320 --> 40:37.680] in AndroidX Web Message Listener specifically. [40:37.680 --> 40:42.780] Google pointed that out, and we actually look at that code. [40:42.960 --> 40:47.120] And the entire serialization is, in my opinion, [40:47.120 --> 40:48.560] pretty flawless there, [40:48.560 --> 40:53.020] unlike injecting JavaScript and not sanitizing your strings. [40:53.720 --> 40:58.060] So use your own API and don't develop something from scratch. [40:58.500 --> 41:03.400] And again, and this is like a recurring theme in cybersecurity, [41:03.400 --> 41:05.220] if you're forced to inject JavaScript, [41:05.220 --> 41:06.800] sanitize your inputs. [41:06.800 --> 41:08.560] That should be obvious. [41:08.760 --> 41:10.720] Next slide, please. [41:10.940 --> 41:12.580] These are kind of conclusions. [41:12.640 --> 41:15.900] System apps, in my opinion, do not get enough attention [41:15.900 --> 41:17.460] from the security industry. [41:17.980 --> 41:21.720] They're especially bad because they can't be easily removed. [41:21.740 --> 41:26.020] End users never suspect they have all these apps to begin with. [41:26.260 --> 41:30.080] Bloatware, that's what some of us call them. [41:30.080 --> 41:34.300] I did mention other suspicious-looking bloatware [41:34.300 --> 41:36.320] that were also installed on that phone. [41:38.280 --> 41:41.460] But no, I didn't pay too much attention to them. [41:41.460 --> 41:44.460] I just really need to find the time, to be honest. [41:44.460 --> 41:48.300] But I bet there are other things in that phone as well. [41:48.360 --> 41:51.500] And there are special thanks here to the Android V team [41:51.500 --> 41:55.400] that worked with me, which is Shengxin Zhang, Michael Peck, [41:55.400 --> 41:57.300] Joe Mancer, and Apoorva Kumar, [41:57.300 --> 42:00.660] and the entire Microsoft 365 Defender research team. [42:00.660 --> 42:02.560] And with that, I'm done. [42:02.560 --> 42:06.060] If you have any questions, please do ask them now, [42:06.060 --> 42:08.960] or you can just reach out over Twitter or something. [42:08.960 --> 42:10.380] My DMs are open. [42:10.420 --> 42:11.920] Thank you so much for attending. [42:14.100 --> 42:15.860] I have a question. [42:16.340 --> 42:17.380] Yes. [42:18.780 --> 42:26.520] So, like, this is like, the device, the device, I think, [42:26.520 --> 42:33.020] is it like one of those system apps that come with Android, [42:33.020 --> 42:37.600] or is it one of those carrier system apps, [42:37.600 --> 42:46.500] like the synonym for running apps [42:46.500 --> 42:49.820] that you get when you get from that specific carrier? [42:50.540 --> 42:57.520] So, it's actually, well, it's not done by Google or by... [42:58.280 --> 43:01.220] Yeah, it's more of the latter than the former. [43:01.220 --> 43:03.220] Although you could actually, as I said, [43:03.220 --> 43:05.140] you can actually install that from Google Play, [43:05.140 --> 43:09.160] or if you ever get your phone fixed or traded in or something, [43:09.160 --> 43:11.140] it might be installed there already. [43:11.140 --> 43:16.360] So, it can be either someone installing that, [43:16.360 --> 43:21.420] or it could be baked into your firmware just by the carrier itself. [43:21.740 --> 43:23.400] I hope that answers the question. [43:23.560 --> 43:24.560] Okay, yes. [43:25.320 --> 43:27.100] What's the carrier thing? [43:27.280 --> 43:29.780] Yeah, that's why I mentioned those telcos. [43:29.780 --> 43:32.760] It's done, well, not by the telcos. [43:32.760 --> 43:34.820] They're actually just using that other company [43:34.820 --> 43:37.840] that developed the SDK with customization. [43:37.840 --> 43:42.660] But basically, the telcos are kind of responsible for that in this case. [43:43.740 --> 43:44.520] Okay. [43:47.100 --> 43:47.820] Some... [43:50.600 --> 43:51.920] Go ahead. [43:57.060 --> 44:06.040] I'm just trying to think about those kinds of exploits between those that... [44:06.940 --> 44:12.880] You know how you need root to have to remove the system apps and stuff? [44:12.880 --> 44:21.360] I was thinking, how actually... [44:25.120 --> 44:29.860] I mean, if you run as root, yes, you can uninstall those system apps. [44:29.860 --> 44:35.670] I mean, is it just... [44:36.510 --> 44:43.130] Does the exploit doesn't really have any practical use for other things? [44:43.170 --> 44:47.970] Other things, you know, or just, you know, thread actor stuff? [44:48.490 --> 44:56.770] I mean, generally, those kind of exploits could mostly be used, in my opinion, for bad stuff. [44:56.770 --> 45:05.130] Could be like an NSO kind of level exploit where someone remotely can just hack your phone. [45:05.670 --> 45:11.090] Also, because it's a system app, in most cases, it can actually install apps silently, [45:11.090 --> 45:15.870] which a normal app, if you try to install an app, it would actually pop up and at least [45:15.870 --> 45:17.970] ask the user for permission. [45:18.150 --> 45:20.770] But as far as I remember, not for system apps. [45:22.550 --> 45:26.490] And I mean, it's hard for me to say. [45:26.490 --> 45:33.630] Exploits are usually used for, you know, either bad guys or for educational purposes. [45:33.630 --> 45:34.670] In this case, we actually... [45:35.350 --> 45:36.430] Yeah, go ahead. [45:37.350 --> 45:46.790] Yeah, because I know like, yeah, you know, because not those exploits are used for an [45:46.790 --> 45:48.010] exploit chain. [45:49.090 --> 45:53.850] Oh, oh, you mean, yeah, you mean like for jailbreaking and stuff like that? [45:53.850 --> 45:54.670] Yeah, that's what I'm saying. [45:54.670 --> 46:02.530] The difference between, you know, the exploits, is it more of an exploit can also be used [46:02.530 --> 46:03.470] for that? [46:03.470 --> 46:08.530] Or is it mostly just for the really, really bad stuff? [46:09.070 --> 46:12.790] Well, to be honest, I think mostly not for that. [46:12.790 --> 46:19.570] I mean, for jailbreak, you'll have to run as root normally, or flash a new bootloader [46:19.570 --> 46:20.390] or whatnot. [46:20.450 --> 46:23.130] This is not this kind of exploit. [46:23.130 --> 46:30.210] This exploit, I mean, it is beneficial in some cases to run as a system app, but it's [46:30.210 --> 46:31.510] not running as root. [46:32.530 --> 46:34.510] Oh, okay. [46:34.510 --> 46:38.270] Yeah, so it's not really useful for that kind of stuff. [46:38.270 --> 46:38.830] More so just... [46:39.890 --> 46:42.130] Oh, it's mostly for bad guys. [46:42.190 --> 46:43.810] Yeah, that's what I was asking. [46:44.910 --> 46:46.130] Thank you. [46:47.210 --> 46:48.910] Any more questions? [46:50.230 --> 46:54.210] I wanted to ask, like, oftentimes I've heard horror stories of people revealing vulnerabilities [46:54.210 --> 46:57.930] with big companies and getting some negative responses. [46:58.640 --> 47:03.290] Did you get any kind of negative response from big telco companies when you kind of [47:03.290 --> 47:07.350] revealed to them that there's this kind of vulnerability on their product? [47:07.570 --> 47:08.660] Good question. [47:08.950 --> 47:13.270] This is kind of like a political question, so it's hard for me to answer, but I would [47:13.270 --> 47:16.750] say that the responses were mixed. [47:16.750 --> 47:21.450] I think that the telco industry is not as mature as other companies, and they might [47:21.450 --> 47:25.050] not see you exploiting their stuff with a... [47:27.370 --> 47:33.490] They don't see it as a nice gesture, even though we really worked hard to do responsible [47:33.490 --> 47:34.270] disclosure. [47:34.270 --> 47:34.770] We also... [47:34.770 --> 47:40.710] I didn't mention that, but after that company, the company that develops everything, patched [47:40.710 --> 47:44.370] everything, we actually tested to make sure that they did everything properly. [47:44.370 --> 47:45.750] We did code reviews and whatnot. [47:45.750 --> 47:47.950] So it's not just about the exploitation. [47:47.950 --> 47:54.210] It's also about how to get that fixed, and they were pretty collaborative, to be honest. [47:54.310 --> 47:56.410] The telcos, it's mixed. [47:56.410 --> 48:05.490] Some of them were really open and really receptive to basically that kind of disclosure. [48:05.550 --> 48:09.510] Others were not as much and had to be convinced. [48:10.170 --> 48:14.490] In this case, I would say I'm lucky that I'm running... [48:15.210 --> 48:19.250] I'm basically part of a big company that can... [48:20.190 --> 48:24.390] Someone important from my company can talk to someone important from that telco. [48:24.390 --> 48:28.870] But if you're an individual researcher, I don't know. [48:28.870 --> 48:31.210] I think it would have been much more difficult. [48:32.310 --> 48:34.910] I would probably say that. [48:37.710 --> 48:42.130] Large men in fancy suits would come for your house. [48:42.910 --> 48:43.770] Yeah, yeah. [48:43.770 --> 48:45.370] Hopefully not. [48:46.230 --> 48:47.950] Hopefully not. [48:48.570 --> 48:49.770] Yeah. [48:50.910 --> 48:54.090] I have a guard cat in my home, so... [48:55.690 --> 48:56.630] Awesome. [48:56.630 --> 48:58.550] Yes, perfect. [48:59.410 --> 49:00.410] Yes, perfect. [49:00.410 --> 49:06.310] Make sure you protect both the front and back door. [49:06.510 --> 49:07.150] Yeah, yeah. [49:07.150 --> 49:08.930] Well, I need another cat. [49:09.110 --> 49:10.610] More questions. [49:13.770 --> 49:14.430] Awesome. [49:14.430 --> 49:18.270] Well, if there are any follow-up questions or you want to get more technical data or whatnot, [49:18.270 --> 49:19.410] just reach out to me. [49:19.410 --> 49:24.430] I do also macOS, Linux, Chrome OS, iOS, those sort of things. [49:24.430 --> 49:26.790] And I'm interested in everything that runs code. [49:26.790 --> 49:28.070] So thank you so much. [49:28.070 --> 49:29.490] And I'll see you guys around. [49:41.850 --> 49:43.310] Thank you, Jonathan. [49:43.630 --> 49:47.350] Give our speaker a warm round of applause. [49:47.850 --> 49:50.970] We've got roughly 10 minutes to our next speaker. [49:50.970 --> 49:53.190] So good time to take a bio break. [49:53.190 --> 49:56.930] And choose with the people that are here and network. [49:57.490 --> 49:59.090] And then look around for Easter eggs. [49:59.090 --> 50:00.710] And we'll see you back in about 10 minutes.