1 00:00:00,000 --> 00:00:02,780 Hello, IoT Village, first and foremost. 2 00:00:02,900 --> 00:00:04,820 What it be, what it do. 3 00:00:05,280 --> 00:00:08,540 I'm Mark, and boy, have I got some zero days for you. 4 00:00:08,640 --> 00:00:17,240 Now, the reason why I call this talk Assembly Voluntron isn't just because I'm hacking a robot and it's a cool name, and incredibly clever, too. 5 00:00:17,240 --> 00:00:25,460 But also because there's four unique CVEs in this target, and when they work together, they kind of create something that's greater than the sum of its parts. 6 00:00:25,500 --> 00:00:27,940 Just like a mech you might have heard of. 7 00:00:29,300 --> 00:00:34,360 So, the next thing you might be wondering is, who are you, and why should we care what we have to say? 8 00:00:34,540 --> 00:00:40,060 Well, to start off, like I said, I'm Mark, to which there's really only one natural response. 9 00:00:41,680 --> 00:00:44,200 And you can find me on Twitter, at Ropsicle. 10 00:00:45,260 --> 00:00:53,400 And I'm currently a security researcher for McAfee's Advanced Threat Research Team, which I'll be referring to as ATR from now on, because it's kind of a mouthful. 11 00:00:54,120 --> 00:00:58,420 Now, my focus has been on finding zero-day vulnerabilities, particularly in embedded systems. 12 00:00:58,420 --> 00:01:01,540 So, this talk is really on-brand for me, so to speak. 13 00:01:02,140 --> 00:01:09,600 Now, as for previous experience, I spoke at last year's DEF CON and ICS Village, so I'm basically a celebrity. 14 00:01:10,280 --> 00:01:13,120 Now, for hobbies, I really only do two things. 15 00:01:13,120 --> 00:01:15,960 I hack and I squat. 16 00:01:18,000 --> 00:01:23,460 Now, depending on how nice you guys are to me in the Discord channel after, I might add streaming to that list. 17 00:01:23,460 --> 00:01:25,120 But for now, it's just those two. 18 00:01:25,920 --> 00:01:28,260 Okay, so let's move on to the target. 19 00:01:28,740 --> 00:01:31,640 Temmie or Teemee, or however you want to pronounce it. 20 00:01:32,040 --> 00:01:35,460 The fact is, it's actually a pretty cutting-edge piece of tech. 21 00:01:35,860 --> 00:01:43,260 So, the marketing describes it as the world's first truly intelligent, mobile, personal robot for your home. 22 00:01:43,400 --> 00:01:44,940 That's a lot of qualifiers. 23 00:01:45,380 --> 00:01:49,500 And as you can see here, it's actually a pretty small device. 24 00:01:49,500 --> 00:01:53,280 It's about four feet tall, and it's got kind of like an Android brain. 25 00:01:54,340 --> 00:01:59,660 That's like an Android tablet at the top with like a camera and a microphone and a fully functioning touchscreen. 26 00:02:00,600 --> 00:02:05,880 Now, this device was created by RoboTemmie Global LTD, and they're sort of like a startup company. 27 00:02:05,880 --> 00:02:09,360 This is their first venture into the consumer space. 28 00:02:09,360 --> 00:02:15,980 But they actually spun off of a parent company called RoboTeam, which did military robotics based out of Israel. 29 00:02:16,520 --> 00:02:17,500 Now, this thing isn't cheap. 30 00:02:17,500 --> 00:02:22,600 It's going to set you back about two grand, but you do get a lot of hardware for that price point. 31 00:02:22,700 --> 00:02:27,100 So, it has the ability to do remote teleconferencing, thanks to its camera and microphone. 32 00:02:27,520 --> 00:02:34,960 But more importantly, it also has autonomous movement and obstacle detection, thanks to the various sensors it features, and also the 360 LiDAR. 33 00:02:35,780 --> 00:02:41,220 And finally, as you'd expect, it has Alexa and smart device integration, being a smart IoT device. 34 00:02:41,420 --> 00:02:44,280 And you get all the standard things you'd expect from an Android tablet. 35 00:02:44,280 --> 00:02:50,280 Wi-Fi, Bluetooth, it even has a wireless charging pad on the back that doubles as a coaster, at least for us. 36 00:02:51,020 --> 00:03:02,640 So, although RoboTaming likes to advertise their robot as being, you know, sort of a consumer device, the reality is that it's actually seen a lot of use outside of that space. 37 00:03:02,980 --> 00:03:08,580 So, I think one of the biggest things we've seen recently is that it's used sort of as a mobile kiosk. 38 00:03:08,580 --> 00:03:23,700 So, in places like the Mall of America and the Nautilus Hotel, and even in certain corporate environments, like TransFighter corporate offices, you'll see that it serves as an informational kiosk that has the advantage of being able to show people around. 39 00:03:23,700 --> 00:03:29,460 So, instead of just telling people where to find, you know, like Jimmy John's in the mall, for example, it can actually navigate them there. 40 00:03:30,640 --> 00:03:37,840 But perhaps the most important and impactful application of this robot is in healthcare, especially given the recent pandemic. 41 00:03:37,880 --> 00:03:49,300 So, with doctors' visits becoming more and more, you know, the standards becoming more remote visits and remote, you know, teleconferencing for doctors' appointments, this has actually seen a lot of pickup in the healthcare space. 42 00:03:49,360 --> 00:03:53,180 So, already we're seeing it being used by places like Trillium Health Resources. 43 00:03:53,800 --> 00:04:04,760 In fact, it's also been picked up by Israel's Ministry of Defense as, like, the de facto teleconferencing solution for the medical wards throughout Israel. 44 00:04:04,900 --> 00:04:15,260 And we also see a lot of applications in Southeast Asia, of all places, with places like China and South Korea, you know, ordering hundreds of these units for their nursing homes and medical institutions. 45 00:04:15,680 --> 00:04:26,400 And to accommodate this increased demand, RoboTemy has actually increased production of these units to about a thousand a month, I believe, just to meet this growing demand in the medical space. 46 00:04:27,400 --> 00:04:40,080 So, now that we know what Temy is, what it's capable of, and where it's being used, it's important for us to sort of draw a box about what the normal operations of it look like, so then we can have a lot of fun breaking that box. 47 00:04:40,660 --> 00:04:48,680 So, to start off, normal operation of the Temy is done through a use of its smartphone app, and this is both on Android and iOS. 48 00:04:48,840 --> 00:04:53,220 So, you can call the Temy from it, you remotely control it that way, that sort of thing. 49 00:04:54,000 --> 00:05:00,640 And the registration process for using this app is, basically, you just put in your phone number and it verifies it, and that's how it identifies you. 50 00:05:00,640 --> 00:05:07,040 So, if you reinstall the app and use the same phone number, it'll still find up your account details. 51 00:05:07,520 --> 00:05:15,060 Now, upon first booting up the robot, which already was a super fun experience unboxing this thing, but we are prompted to scan a QR code. 52 00:05:15,120 --> 00:05:22,440 And this, basically, just turns whatever user scans that QR code into the de facto admin of that Temy robot. 53 00:05:22,500 --> 00:05:28,200 And the admin is only one per Temy, and they have sort of the highest privileges for that robot. 54 00:05:29,160 --> 00:05:32,860 Now, it doesn't mean that other people can't call your robot or even use it. 55 00:05:32,860 --> 00:05:41,560 Phone contacts that use the Temy app, so phone contacts in, like, your smartphone, if they have the Temy app installed, they're synced automatically. 56 00:05:41,560 --> 00:05:43,280 And this can be done one of two ways. 57 00:05:43,280 --> 00:05:49,880 If the admin has phone contacts that have the Temy app, they'll be synced automatically to the robot, and the robot will be aware of them. 58 00:05:50,400 --> 00:06:01,260 Alternatively, if you're just a regular user of the phone app, you don't own a Temy, but you have a friend that does, for example, and they're in your phone contacts list, you'll be able to call your friend's Temy robot from the app. 59 00:06:01,640 --> 00:06:03,800 And we can sort of show you how that works. 60 00:06:04,000 --> 00:06:12,440 So once you boot up the app, if it finds a contact that owns a Temy, they'll show up down here on the left under your contacts list. 61 00:06:12,720 --> 00:06:17,040 So here, we have a lab phone as one of the contacts that owns a Temy. 62 00:06:17,080 --> 00:06:23,460 And by selecting this contact, you can see the Temy robot associated with it, and even has a button that lets you just call it straight from the screen. 63 00:06:25,380 --> 00:06:29,520 And then once a call is actually initiated, this is sort of the interface you're presented with. 64 00:06:29,520 --> 00:06:34,860 You can drive the robot around, control your audio options, pretty standard stuff. 65 00:06:36,260 --> 00:06:42,360 Now, calling is very much so the primo functionality of this robot. 66 00:06:42,360 --> 00:06:45,980 And really, callers get a lot of control over the device during the call. 67 00:06:45,980 --> 00:06:56,380 They get audio and video feeds from the Temy, but they also have control of its movement, which they can control manually using the little D-pad you saw, but also has access to all of its saved locations. 68 00:06:57,300 --> 00:07:01,600 So this immediately became a very interesting potential attack vector to us. 69 00:07:01,600 --> 00:07:05,840 Now, the Temy does ring when someone besides its admin calls it. 70 00:07:05,840 --> 00:07:14,620 So in that sense, if you just added someone's phone number that they don't know you, it turns into basically just trying to cold call a cell phone. 71 00:07:15,000 --> 00:07:24,160 There is one exception to this, and the admins can actually grant certain users in their contacts list special privileges to bypass this limitation. 72 00:07:24,380 --> 00:07:34,500 So if you have like a family that all uses the same robot, and you can't be bothered with having to pick up on the other end each time, an admin can grant several other users the ability to call in without having it ring. 73 00:07:35,500 --> 00:07:37,160 And this is also done through the phone app. 74 00:07:37,160 --> 00:07:43,740 You can just invite new members and then select whatever contacts you want to be able to control the robot, whatever they want. 75 00:07:45,020 --> 00:07:53,200 So now that we have a good grasp of what the normal operation of this device looks like, we can sort of get into the spirit of trying to hack this thing now. 76 00:07:53,340 --> 00:08:01,380 Now, although this tech is pretty novel and cutting edge in a lot of ways, the approach we took to ReconnaSense was fairly standard and typical. 77 00:08:01,800 --> 00:08:04,840 So we started with trying to get a local shell on the device. 78 00:08:04,840 --> 00:08:18,940 This was actually super easy and short-circuited by the fact that the device comes with developer options, which include ADB, or Android Debug Bridge, which allows you to remotely connect to it like you would an SSH session. 79 00:08:18,940 --> 00:08:24,160 So that already made our lives a lot easier for moving files around and accessing the device at startup. 80 00:08:24,860 --> 00:08:31,040 The next thing we tried to do was actually capture traffic on the device using Wireshark. 81 00:08:31,040 --> 00:08:37,220 And during stuff like boot up and during phone calls, we saw three IPs being hit pretty frequently. 82 00:08:37,420 --> 00:08:39,540 One of these mapped to a Yahoo URL. 83 00:08:39,540 --> 00:08:41,780 So this is probably being used for its news app. 84 00:08:41,800 --> 00:08:48,720 And then two more mapped to Amazon AWS instances, which while not surprising, don't really reveal much either. 85 00:08:50,260 --> 00:08:57,320 The next thing we did was used our ADB shell to actually run... sorry, not ADB, that's a little later. 86 00:08:57,320 --> 00:09:01,700 We ran an Nmap port scan on the device to see what the ports it was listening on. 87 00:09:01,700 --> 00:09:04,180 Another standard thing you'd do for attack vectors. 88 00:09:04,260 --> 00:09:14,620 And the only port it identified as being open was the port 4443, which Nmap classified as being used for the service Feros, which is actually related to printing. 89 00:09:14,620 --> 00:09:16,840 So this is probably a false classification. 90 00:09:17,140 --> 00:09:23,320 It's more likely that this port is being used as an alternative to the standard 443 you'd see used for HTTPS. 91 00:09:24,740 --> 00:09:42,360 Now, to verify that, we actually used the ADB shell we had to the device to run Netstat, and actually found that the service associated with this port is something called com-roboteam-teamy-usa, which looks a lot more like an Android application than it does, 92 00:09:42,360 --> 00:09:44,060 you know, a standard Linux binary. 93 00:09:44,700 --> 00:09:46,080 And sure enough, that was the case. 94 00:09:46,080 --> 00:09:53,660 By parsing the list of installed packages on the device, we actually found the APK associated with this Android application. 95 00:09:53,660 --> 00:10:00,700 And using our ADB shell, it was trivial to pull this APK off and start examining the software. 96 00:10:01,640 --> 00:10:10,180 So now that we had access to the software, and we also had access to the phone app software at this stage as well, because we could just download the APK from the Play Store. 97 00:10:10,180 --> 00:10:13,600 It's completely free, and you don't even need to own a Temi to run it. 98 00:10:13,600 --> 00:10:18,000 So we could, you know, start looking at both of those at the same time. 99 00:10:18,180 --> 00:10:22,840 Now, the rest of this is really going to be, like, 80% reversing and static analysis. 100 00:10:22,980 --> 00:10:25,100 That's just sort of the nature of this project. 101 00:10:25,100 --> 00:10:27,800 Now, why, you might ask, why? 102 00:10:28,000 --> 00:10:36,440 Well, a great man once said, the road to exploitation is paved with months of staring a decompiled Java code. 103 00:10:36,840 --> 00:10:38,140 That man's name? 104 00:10:38,440 --> 00:10:39,580 Albert Einstein. 105 00:10:40,620 --> 00:10:43,060 So who am I to argue with that? 106 00:10:45,510 --> 00:10:54,290 Now, once we actually got to decompiling the code, we decided to use a program called JADX. 107 00:10:54,310 --> 00:11:05,350 And JADX was sort of a favorite of ours because it has a functionality of being able to right click on any symbol and click on it to find usage, which became really important later on. 108 00:11:06,630 --> 00:11:09,070 From there, we had to pick a vector. 109 00:11:09,330 --> 00:11:17,030 Now, I don't know how many of you have actually looked at reversing in a full Android app, but they have massive code bases frequently, and Temi was no exception. 110 00:11:17,270 --> 00:11:23,930 Instead of groping in the dark, we decided that we needed to sort of hone in on a specific subset of the code to refine our search. 111 00:11:24,710 --> 00:11:31,690 In our case, we were already interested in the calling functionality of the robot, since that would grant us the greatest level of control entirely remotely. 112 00:11:32,210 --> 00:11:37,630 So we began digging through the different libraries that are part of the APK. 113 00:11:37,970 --> 00:11:43,410 After Googling around a bit, the one that jumped out at us particularly was something called Lib Agora. 114 00:11:43,410 --> 00:11:51,750 And this is actually a binary related to the Agora video SDK, which is a third party library used specifically for video calling functionality. 115 00:11:51,750 --> 00:11:53,110 Okay, that's perfect. 116 00:11:53,110 --> 00:11:54,970 That's exactly what we're interested in. 117 00:11:55,290 --> 00:11:59,710 So from there, we needed to find an entry point related to the attack vector. 118 00:11:59,710 --> 00:12:07,890 And you can sort of imagine this as being like a strand on like a wool sweater, the thing you start pulling on to really unravel the whole thing. 119 00:12:08,790 --> 00:12:17,170 So we began by actually pulling up this library in IDA and looking at its exports, and immediately the function native join channel jumped out at us. 120 00:12:17,170 --> 00:12:20,610 It looked like something related to joining a chat room, for example. 121 00:12:21,470 --> 00:12:28,910 Opening up the APK now, we saw the same function with the same signature appear in the decompiled app. 122 00:12:29,290 --> 00:12:30,930 So that was a good sign. 123 00:12:31,090 --> 00:12:40,990 So from there, we could use JADX's find usage feature like about 600 times to sort of begin tracing the code path taken for starting video calls. 124 00:12:41,690 --> 00:12:46,730 Now, at this stage, there really is no more advice or cool shortcuts. 125 00:12:46,730 --> 00:12:49,690 It really is, you just have to draw the rest of the L. 126 00:12:49,690 --> 00:12:58,530 You really have to just put in the legwork to trace the different function calls that are being made in order to get a better understanding of how the code works. 127 00:12:58,650 --> 00:13:02,210 But the fruits of our labor in this case was actually pretty impressive. 128 00:13:02,610 --> 00:13:05,590 It's sort of like staring at the sun, so I'll only show it briefly. 129 00:13:08,560 --> 00:13:09,960 Did you catch that? 130 00:13:11,720 --> 00:13:12,620 All right. 131 00:13:12,680 --> 00:13:14,740 Let's take a closer look at it. 132 00:13:14,840 --> 00:13:21,860 So highlighted in the different colors near the top are the different entry points for the calling code. 133 00:13:22,000 --> 00:13:26,060 So there's four ways to initiate a call from the phone app, and that correlates to these four. 134 00:13:26,060 --> 00:13:37,600 You can call a phone contact, you can call a robot contact, you can call either contact from the recent calls list, and if you happen to be a Temi admin, you can also call your specific robot. 135 00:13:38,240 --> 00:13:48,280 Moreover, we decided to segregate these based on the code flow that's either for outgoing calls indicated in red or incoming calls indicated in blue. 136 00:13:48,560 --> 00:13:56,580 And I'm not going to go through this too deeply because it's sort of massive, but this did serve as a good reference point for a lot of the reversing we had to do later. 137 00:13:58,160 --> 00:13:58,720 Okay. 138 00:13:58,720 --> 00:14:02,080 So we have four vulnerabilities to get through, so let's just jump right into it. 139 00:14:02,080 --> 00:14:08,440 The very first one, both chronologically and in terms of complexity, is the CVE ending in 70. 140 00:14:09,180 --> 00:14:14,160 And we can see here that it's categorized as being a use of hard-coded credentials. 141 00:14:14,720 --> 00:14:17,360 And it's present in the Temi Android app. 142 00:14:18,440 --> 00:14:26,200 Now, to have a better understanding of what this vulnerability entails, let's go through the process we used to actually discover it. 143 00:14:26,780 --> 00:14:29,960 So this really consisted of four easy steps. 144 00:14:30,320 --> 00:14:32,060 R, T, F, and M. 145 00:14:32,380 --> 00:14:34,040 And I do mean that pretty literally. 146 00:14:34,080 --> 00:14:42,720 Just by looking through the Agora documentation for their video calling API, we were able to get 80% of the way to finding this vulnerability. 147 00:14:44,040 --> 00:14:50,100 So specifically, we decided to take a second look at that join channel function we saw earlier. 148 00:14:50,240 --> 00:14:55,260 According to the Agora documentation, it has two required parameters and two optional ones. 149 00:14:55,480 --> 00:14:59,560 And this is really all that's needed to join an existing video call. 150 00:14:59,980 --> 00:15:02,860 Now, the first one is something called a token. 151 00:15:02,860 --> 00:15:09,580 And it seems that a token, if the user uses a static app ID, the token is also optional and can be set as null. 152 00:15:09,740 --> 00:15:11,260 This was interesting to us. 153 00:15:11,320 --> 00:15:16,720 And the second required parameter for joining a channel is a channel name. 154 00:15:16,720 --> 00:15:18,520 This is something we'll touch on a bit later. 155 00:15:18,520 --> 00:15:24,280 For now, we were interested in the static app ID and whether the Temi was using a token at all. 156 00:15:25,020 --> 00:15:35,180 Taking a look at the same function in the code, we found that it is indeed setting that token parameter to null, which means that it's likely using a static app ID as indicated in the documentation. 157 00:15:36,360 --> 00:15:40,260 Okay, so then we decided to start looking for this static app ID. 158 00:15:40,260 --> 00:15:41,320 Where could it be found? 159 00:15:41,540 --> 00:15:48,660 Referring back to the Agora documentation, we found the one function or the one API call that actually uses it as a parameter. 160 00:15:48,660 --> 00:15:51,740 And that's the rtcengine.create function. 161 00:15:52,320 --> 00:15:59,280 And it uses it as a parameter and it describes it as being an app ID issued by Agora to the developers, which is sort of vague. 162 00:15:59,280 --> 00:16:11,020 But after some more digging, we sort of discovered that this is used as a sort of namespace that segregates different users or different implementations on the Agora remote servers. 163 00:16:11,020 --> 00:16:19,100 So what it means is that you have a set static app ID that's shared amongst all Temi robots and Temi phone app users. 164 00:16:19,100 --> 00:16:25,460 And the app ID ensures that users of that service can only call other Temi users. 165 00:16:25,460 --> 00:16:29,380 They can't call an arbitrary Agora client. 166 00:16:29,940 --> 00:16:33,520 So this is actually a pretty important credential to have access to. 167 00:16:33,660 --> 00:16:39,880 Well, since we knew the function that takes it argument, we decided to look for this function in the Temi's decompiled code. 168 00:16:40,320 --> 00:16:49,660 And sure enough, there was the app ID hard-coded directly into the app that's freely accessible at the Play Store and fairly trivial to decompile. 169 00:16:50,320 --> 00:16:52,300 So this was already a good start. 170 00:16:52,300 --> 00:16:59,820 But really, to exploit this as a vulnerability, we needed not only the app ID, but also the channel name. 171 00:16:59,820 --> 00:17:02,280 So we could actually join an potentially. 172 00:17:03,800 --> 00:17:07,160 So if we still needed the channel name, how could we get it? 173 00:17:07,160 --> 00:17:15,120 Well, by going through that nice little graph I showed earlier, we were able to trace down what function actually generates the channel name. 174 00:17:15,120 --> 00:17:16,840 And here it's being called a session ID. 175 00:17:16,840 --> 00:17:18,220 But they're really the same thing. 176 00:17:18,800 --> 00:17:22,320 And as you can see, this is doing something not too complicated. 177 00:17:22,320 --> 00:17:26,160 It's actually just generating a random six-digit value. 178 00:17:26,340 --> 00:17:34,980 Now, this is important because, you know, 900,000 possibilities may seem like a lot, but it's well within the range of brute-forceable attack vectors. 179 00:17:36,580 --> 00:17:44,280 So in theory, an attacker could use the hard-coded app ID they extracted from downloading the app, which is shared amongst all Temmie installs. 180 00:17:44,320 --> 00:17:51,460 And then they could just use a brute-force method to try and guess every single possible channel name. 181 00:17:51,460 --> 00:17:58,880 And by doing so, they could potentially intercept every ongoing Temmie call used by any Temmie install. 182 00:17:59,540 --> 00:18:04,380 Now, obviously, we couldn't test such a brute-force attack vector against a live production server. 183 00:18:04,380 --> 00:18:11,980 But what we could do is we could create a custom Agora app to join a Temmie call just launched locally. 184 00:18:11,980 --> 00:18:16,980 And we did this by logging the channel name using ADB. 185 00:18:17,220 --> 00:18:28,700 And sure enough, using this custom app, we were able to join the existing call and essentially spy on the other two call members. 186 00:18:28,700 --> 00:18:32,320 So thereby proving this is a legitimate attack vector. 187 00:18:33,320 --> 00:18:37,940 So the next vulnerability I'm going to discuss is sort of a helper vulnerability. 188 00:18:38,020 --> 00:18:45,500 It is classified as an origin validation error, and it is also present in the Temmie Android app. 189 00:18:47,860 --> 00:19:05,500 Now, the reason why we call this a helper vulnerability is that it actually is related to the fact that you can modify the Temmie app and it still has full access to all the remote services it uses. 190 00:19:05,500 --> 00:19:13,540 It doesn't perform any kind of tamper checking to make sure that it's not running on a rooted device, that the code for the app hasn't been modified in any way. 191 00:19:13,540 --> 00:19:15,300 It just isn't aware of that. 192 00:19:15,600 --> 00:19:31,500 And the reason we were motivated to even pursue this as an attack vector is that it's much easier to modify an existing code than to start from scratch, but more importantly, the Temmie Android app already has access to all those remote services, which requires some degree of authentication. 193 00:19:31,500 --> 00:19:42,680 Instead of trying to extract the keys it's using and whatever other authentication mechanisms from the app and trying to make it our own, we just leverage the existing app and inject our code into it. 194 00:19:43,680 --> 00:19:50,700 So the way we'd accomplish this is by first unpacking the APK, which we can do using APK tool. 195 00:19:52,220 --> 00:19:56,520 Next, we would search for the particular piece of code that we want to modify. 196 00:19:56,600 --> 00:20:01,940 This could be either through the decompiled code or through the various resource files included with the APK. 197 00:20:02,100 --> 00:20:09,140 As a proof of concept, we decided to try and change the text for the call button, which we found through some grepping. 198 00:20:09,940 --> 00:20:15,740 Okay, so now that we knew which part of the APK we wanted to change, the next thing was to simply make that modification. 199 00:20:16,080 --> 00:20:21,380 And that was as simple as pulling it up in a text editor and replacing the string with what we wanted. 200 00:20:21,380 --> 00:20:24,240 In this case, we decided to rename it Pwn, give it a little more spice. 201 00:20:25,560 --> 00:20:30,120 And the last but not least, we had to repack but also re-sign the app. 202 00:20:30,120 --> 00:20:38,120 And the reason why we need to re-sign it is Android does not allow apps that are not signed to be installed on the device. 203 00:20:38,240 --> 00:20:42,920 And by modifying the existing app's contents, we invalidated the existing signature. 204 00:20:42,920 --> 00:20:50,440 But no worries, since the signature is not being checked by the device, there's no reason why we can't just create our own signature and use that. 205 00:20:51,240 --> 00:20:55,640 So the repacking process is once again done using APK tool. 206 00:20:55,740 --> 00:21:01,780 And then we create a signature using a combination of key tool and jar signer, as shown here. 207 00:21:03,140 --> 00:21:09,140 And the end result was that we were able to successfully change the string on this call button. 208 00:21:09,140 --> 00:21:20,980 And perhaps more importantly, modifying the app in this way proved not to impact this functionality in the least, meaning that we could potentially make non-trivial changes and still be able to perform things like calling. 209 00:21:22,540 --> 00:21:32,840 Now, exploitation of this vulnerability is a little tricky without spoiling the rest of the presentation, because really its main application is used to help exploit the next two vulnerabilities. 210 00:21:32,900 --> 00:21:34,720 So we'll save the discussion for that. 211 00:21:35,240 --> 00:21:36,500 No spoilers. 212 00:21:37,440 --> 00:21:38,160 Okay. 213 00:21:39,420 --> 00:21:41,380 Vulnerability numero trace. 214 00:21:41,520 --> 00:21:45,960 So this one is actually missing authentication for a critical function. 215 00:21:45,960 --> 00:21:47,860 A little more serious than the last two. 216 00:21:47,860 --> 00:21:57,180 And this is actually present in Temi's MQTT broker, which if you don't know what MQTT is, I'm going to give you guys a real quick crash course on it, just so we're all on the same page. 217 00:21:58,580 --> 00:22:05,540 So MQTT is a publish-subscribe messaging protocol that's specifically designed for IoT and other lightweight devices. 218 00:22:05,640 --> 00:22:08,800 So it's not too surprising to see Temi using it. 219 00:22:09,380 --> 00:22:17,820 Now, the way it works is that clients will publish messages to certain topics, and then subscribers to those topics then receive the messages. 220 00:22:17,860 --> 00:22:26,100 You can think of it as sort of being like subscribing to a YouTube channel, and then receiving notifications whenever your favorite YouTubers upload, for example. 221 00:22:27,780 --> 00:22:35,620 And then the topics themselves are strings that are organized into a hierarchy, and the hierarchy itself is delineated much in the same way that a Unix file system is. 222 00:22:35,620 --> 00:22:37,020 So just forward slashes. 223 00:22:38,320 --> 00:22:46,540 Now, in terms of the Temi, it uses MQTT for basically all communication between itself, the phone app, and the various cloud services. 224 00:22:46,980 --> 00:22:57,620 So you see it being used for things like video call invitations, syncing contacts from the admin, and even, most importantly, privilege management, which is something we'll delve into in the next vulnerability. 225 00:23:01,000 --> 00:23:04,640 So let's get into the discovery and exploitation of this vulnerability. 226 00:23:05,100 --> 00:23:09,660 How are we using MQTT, and what authentication is not being implemented? 227 00:23:10,420 --> 00:23:15,940 Well, we started by looking at the code that was used by the app to subscribe to its call invite topic. 228 00:23:15,940 --> 00:23:19,660 After all, we are interested first and foremost in the calling functionality. 229 00:23:20,180 --> 00:23:31,740 This is just the topic that either a phone app or a robot will listen on when it receives phone calls, and then the person creating a call for that user will publish a message to that same topic. 230 00:23:32,920 --> 00:23:38,900 So in our case, it takes the form... you can see it being invoked here on line 408. 231 00:23:38,900 --> 00:23:43,200 That's the actual function that is used to subscribe to that topic. 232 00:23:43,200 --> 00:23:47,920 And the topic string itself takes the form client something followed by invite. 233 00:23:47,920 --> 00:23:53,540 And that something in the middle is a client ID, or an MQTT client ID, rather. 234 00:23:53,740 --> 00:24:00,280 And an MQTT client ID is just a unique identifier for a specific client that's connected to the same MQTT broker. 235 00:24:00,280 --> 00:24:03,020 It's a way to identify different users. 236 00:24:03,900 --> 00:24:06,100 So this actually gave us an idea. 237 00:24:06,760 --> 00:24:11,500 Could we subscribe to someone else's call invite topic if we're able to modify the app? 238 00:24:14,020 --> 00:24:17,660 Well, in order to do that, we would need to know their client ID. 239 00:24:18,260 --> 00:24:22,240 So we would need to somehow get this information. 240 00:24:22,380 --> 00:24:24,920 But how are these client IDs even assigned? 241 00:24:25,920 --> 00:24:30,360 Well, looking back at how recent calls are initiated actually gave us a clue. 242 00:24:32,040 --> 00:24:39,100 So if you try to initiate a call from the recent calls list, this is the call code that gets executed. 243 00:24:39,420 --> 00:24:43,080 It invokes a function called telepresence service dot initiate call. 244 00:24:43,080 --> 00:24:48,700 And the first parameter is actually an identifier for the contact you're trying to initiate a call with. 245 00:24:48,820 --> 00:24:54,020 In this case, it gets that ID by invoking a function called get MD5 phone number. 246 00:24:54,660 --> 00:25:02,040 At this point, we were thinking, is it possible that the client ID is just an MD5 hash of the phone number the user used to register? 247 00:25:02,280 --> 00:25:04,560 We decided to verify this theory. 248 00:25:05,440 --> 00:25:17,000 So we did this simply by taking the Google voice number we used for our Temi admin, computing the MD5 hash, and then searching for that exact hash in all the various Temi files we had. 249 00:25:17,000 --> 00:25:20,520 And sure enough, we got a hit in one of the logs we recorded during a call. 250 00:25:20,520 --> 00:25:23,040 And it classifies it right there as client ID. 251 00:25:23,380 --> 00:25:25,200 Seems pretty straightforward to me. 252 00:25:27,080 --> 00:25:33,700 Now, at this stage, we decided to modify the app, taking advantage of the previous vulnerability we outlined. 253 00:25:34,220 --> 00:25:45,440 And using this technique, we were able to successfully subscribe to another user's call invite topic instead of our own, which basically meant that every single time they received a call, we would get that same call. 254 00:25:45,900 --> 00:25:53,200 And the only thing we needed to make this happen is the victim's phone number, which telemarketers will constantly remind us is not a high bar. 255 00:25:54,800 --> 00:25:55,720 Okay. 256 00:25:56,220 --> 00:25:59,920 So getting to the last and easily the most impactful vulnerability. 257 00:26:00,780 --> 00:26:05,420 This one is an authentication bypass using an alternate path or channel. 258 00:26:05,420 --> 00:26:09,840 And this is present in the Temi's REST API, which is something we'll cover as well. 259 00:26:11,380 --> 00:26:16,540 Now, in order to understand the authentication bypass, we first need to understand the authentication. 260 00:26:16,700 --> 00:26:24,140 And this is related to Temi's privilege management system, which is something I've already sort of touched on with the admin versus regular contacts thing. 261 00:26:26,380 --> 00:26:28,460 So we already know about admins. 262 00:26:28,460 --> 00:26:31,400 That's just the person that first registers with the QR code. 263 00:26:31,480 --> 00:26:34,900 But there's also two other types of privilege levels. 264 00:26:35,900 --> 00:26:41,900 Another one is contacts, which are just the default permissions given to a user. 265 00:26:41,900 --> 00:26:43,580 It's also the lowest level. 266 00:26:45,020 --> 00:26:48,760 Now , there are two ways to become a contact. 267 00:26:48,760 --> 00:26:51,180 The first is simply by cold calling the Temi. 268 00:26:51,180 --> 00:26:56,380 And the other is through the Temi admin syncing contacts to the robot. 269 00:26:56,620 --> 00:26:59,340 We'll be focusing on this latter use case. 270 00:27:00,100 --> 00:27:07,580 So the Temi robot actually listens on the topic sync contacts and then followed by its MQTT client ID or its robot ID. 271 00:27:07,580 --> 00:27:08,920 They're the same thing. 272 00:27:08,940 --> 00:27:13,820 For requests from the admin to sync contacts, as we can see here. 273 00:27:14,780 --> 00:27:18,800 Now, the requests themselves have the following structure. 274 00:27:18,800 --> 00:27:23,060 They're called... it uses an object of type sync contacts message. 275 00:27:23,060 --> 00:27:29,480 And all this contains is a list of contacts and the client ID of the person sending the request. 276 00:27:29,680 --> 00:27:37,080 And then the contact list is just a tuples of MQTT client IDs and the display names. 277 00:27:37,220 --> 00:27:38,400 Pretty straightforward. 278 00:27:39,120 --> 00:27:48,780 And the reason why the sender client ID is included is because the Temi locally ensures that the sender is equivalent to the ID of its admin. 279 00:27:48,800 --> 00:27:50,540 Just as a sanity check. 280 00:27:51,440 --> 00:27:52,040 Okay. 281 00:27:52,040 --> 00:27:53,360 So that's contacts. 282 00:27:53,360 --> 00:27:57,640 The third privilege level that's possible is something called an owner. 283 00:27:58,700 --> 00:28:11,500 And owners are actually related to that functionality I showed earlier where you can add certain users as an admin and let them call into the Temi remotely without having it ring. 284 00:28:12,740 --> 00:28:20,000 So, a Temi admin can send... now, sorry, let me back up a bit here. 285 00:28:20,140 --> 00:28:39,100 This is actually a little bit different from adding contacts because while adding a contact is pretty straightforward, adding owners is a little more complex because the request sent by the admin from the phone app is actually quite a bit different than what the Temi expects on the receiving end. 286 00:28:39,480 --> 00:28:46,400 So, the admin sends its request to a REST API at the following URL as we can see here. 287 00:28:47,800 --> 00:28:50,700 And the requests themselves have the following structure. 288 00:28:51,540 --> 00:28:59,080 They contain an inner request and also a signature that's basically generated using the client's private key. 289 00:28:59,080 --> 00:29:02,120 It's a way to identify who the origin is. 290 00:29:02,680 --> 00:29:06,640 And then the inner request consists of the list of the users... 291 00:29:09,900 --> 00:29:28,000 the list of users that we want to promote to owners, the ID of the robot that we're sending the request for, the source of the request, a timestamp, and then finally a type which is simply adding an owner or removing. 292 00:29:32,580 --> 00:29:36,540 Now, how is this different from what the Temi expects to receive on the other end? 293 00:29:36,540 --> 00:29:37,860 Well, it's quite a bit different. 294 00:29:38,160 --> 00:29:41,480 First of all, the Temi is listening on an entirely different channel. 295 00:29:41,880 --> 00:29:48,040 While the admin is sending its request to a REST API, the Temi robot is listening on an MQTT topic. 296 00:29:49,460 --> 00:29:50,840 This one specifically. 297 00:29:51,800 --> 00:29:56,000 And also the structure of the request has also changed. 298 00:29:56,280 --> 00:30:07,320 It seems to be a subset of the request that the admin is sending where it still has the list of owner IDs and the type, but has been stripped of its signature, its timestamp, and its source. 299 00:30:08,100 --> 00:30:18,840 Now, at this point, we speculated that the reason for this is because the REST API itself is being used as an authentication mechanism for adding owners. 300 00:30:18,840 --> 00:30:22,380 This is sort of a sensitive privilege escalation type of deal. 301 00:30:23,000 --> 00:30:37,580 And so what the REST API would do is it verifies the request by checking the signature, and then it strips out all that verified information before sending it off to the Temi's MQTT topic, essentially serving as like a middleman. 302 00:30:39,240 --> 00:30:42,580 So that means that our flowchart sort of looks like this. 303 00:30:42,580 --> 00:30:49,020 And presumably, if the verification server deems the signature invalid, nothing happens. 304 00:30:49,900 --> 00:30:55,560 Okay, so these privilege levels mostly have utility in how calling works. 305 00:30:55,840 --> 00:31:05,600 So when a Temi receives a call from a user, if that caller is either an admin or an owner, the Temi will pick up the call automatically. 306 00:31:06,200 --> 00:31:10,780 On the other hand, if the caller is a contact, it'll ring. 307 00:31:11,240 --> 00:31:17,400 So unfortunately, as an attacker, if we just tried to cold call a Temi, we would become a contact, and the Temi would ring. 308 00:31:19,020 --> 00:31:20,280 What do we want? 309 00:31:20,520 --> 00:31:24,100 Well, we want to be able to call the Temi and have it pick up automatically. 310 00:31:24,600 --> 00:31:27,340 This is because calling is sort of the endgame. 311 00:31:27,340 --> 00:31:32,580 You know, you get full control of the Temi's movement and also audio and video feeds to it. 312 00:31:34,560 --> 00:31:39,040 So what do we already know and what do we already have that can help us get there? 313 00:31:39,500 --> 00:31:43,800 Well, we do know that the Temi uses MQTT for calling and privilege management. 314 00:31:44,380 --> 00:31:51,220 And we know that we can subscribe to arbitrary topics, like we showed when we subscribed to someone else's call-invite topic. 315 00:31:51,780 --> 00:31:56,640 So our next question was, can we also publish to arbitrary topics? 316 00:31:56,800 --> 00:32:14,220 Because if we could, we may be able to escalate our privilege by publishing the owner's message that the Temi expects to get from the authentication server directly, and just publish it right to that MQTT topic it's listening on, thereby bypassing that authentication middleman entirely. 317 00:32:15,360 --> 00:32:20,060 Well, this all sounds well and good, but there was a slight caveat here. 318 00:32:21,020 --> 00:32:26,920 And that was, the Temi will only process privilege escalation requests for existing contacts. 319 00:32:27,060 --> 00:32:28,360 Now, why is this a problem? 320 00:32:28,560 --> 00:32:39,140 Well, there's only two ways to become a contact, one of which is the cold call to Temi, which is far from ideal because that might arouse suspicion for various reasons, if you have some stranger calling your robot. 321 00:32:39,660 --> 00:32:44,480 And then the other way is to have an admin send the sync's contacts message with you on it. 322 00:32:44,500 --> 00:32:46,220 Those are really the only two ways. 323 00:32:47,140 --> 00:32:50,060 Well, the solution is actually trying... is that's the latter. 324 00:32:50,060 --> 00:33:01,500 What we can do is we can actually spoof the admin's sync contacts message by simply setting the sender client ID to the admin's client ID, since the Temi just implicitly trusts that this value is accurate. 325 00:33:02,180 --> 00:33:09,980 In this way, we can send a sync contacts message first, followed by an add owner's message, and then finally initiate the call of the robot. 326 00:33:11,200 --> 00:33:17,880 So, this is sort of what the same functionality looks like after we've modified the app in the following ways. 327 00:33:18,000 --> 00:33:20,680 We can see already that it's a lot simpler. 328 00:33:22,540 --> 00:33:26,240 And in order to become a contact, we just send a malformed request. 329 00:33:26,460 --> 00:33:31,780 In order to escalate to becoming an owner, we just send another malformed MQTT request. 330 00:33:32,140 --> 00:33:39,580 And then finally, unlike before, now that we have owner privileges, the Temi will pick up the call automatically. 331 00:33:45,040 --> 00:33:53,080 Now, just as a quick recap of what these vulnerabilities can do together, it's sort of a recipe for disaster. 332 00:33:53,080 --> 00:33:56,180 And the recipe includes these following steps. 333 00:33:56,240 --> 00:33:58,600 First, you find a vulnerability in the Temi. 334 00:33:58,660 --> 00:34:01,020 And then you just find three more. 335 00:34:01,600 --> 00:34:05,800 And here's a completely unrelated graphic of a bucket with holes. 336 00:34:05,800 --> 00:34:07,040 I just like buckets. 337 00:34:08,340 --> 00:34:13,620 The ingredients for this recipe involved just the user's phone number and honestly not much else. 338 00:34:14,280 --> 00:34:28,060 And what this produces is the ability to spy on calls, the ability to intercept calls intended for other users, and most importantly, the ability to remotely control the robot and see through its eyes and hear through its ears. 339 00:34:31,340 --> 00:34:33,500 Now, I've been teasing you guys enough. 340 00:34:33,500 --> 00:34:38,120 So, at this point, I think it's a good time to show you guys a demo of how this all works. 341 00:34:53,530 --> 00:34:59,650 So, Shane or Sam, if you guys could queue up the video. 342 00:35:00,790 --> 00:35:01,670 Hopefully. 343 00:35:03,690 --> 00:35:05,130 Demo is playing. 344 00:35:05,170 --> 00:35:05,890 Okay. 345 00:35:05,890 --> 00:35:08,230 So, on the left, we have the Temi admin. 346 00:35:08,390 --> 00:35:11,750 And on the right, we have the attacker's phone. 347 00:35:12,050 --> 00:35:18,350 And we can see that I've already added the admin as a phone contact, thereby syncing it to the Temi's contact list. 348 00:35:18,610 --> 00:35:21,690 And the first thing I'm going to do is I'm going install the Temi app. 349 00:35:25,370 --> 00:35:30,490 Normally, unmodified, just straight from the Play Store, just to show that there's no smoke and mirrors involved. 350 00:35:31,230 --> 00:35:40,130 We'll later be using the modified app with the exact same credentials and going through the same registration process to show you that it really is the vulnerabilities that gives us the greater privileges. 351 00:35:44,010 --> 00:35:47,570 So, once we're done registering it, we're just going to attempt to cold call the Temi. 352 00:35:49,330 --> 00:35:52,610 And you can see the Temi screen in the bottom center there. 353 00:35:54,930 --> 00:35:57,030 Now, as expected, the Temi rings. 354 00:35:57,030 --> 00:35:58,590 It does not pick up automatically. 355 00:35:58,590 --> 00:36:01,590 This is because we only have contact privileges at this stage. 356 00:36:01,590 --> 00:36:03,910 The admin hasn't granted us any special rights. 357 00:36:11,200 --> 00:36:11,880 Okay. 358 00:36:11,900 --> 00:36:18,700 Now that we know what the normal operation looks like, let's go ahead and install our custom modified app that leverages these vulnerabilities. 359 00:36:25,000 --> 00:36:29,000 And right off the bat, you'll see this actually looks very similar to the original app. 360 00:36:29,080 --> 00:36:31,280 We only modified what we needed to do. 361 00:36:31,400 --> 00:36:34,560 It's not until we initiate a call that we'll see how different it is. 362 00:36:35,160 --> 00:36:38,980 So, as I stated previously, we'll be using the exact same credentials to register. 363 00:36:39,560 --> 00:36:42,100 And, in theory, we should have the same privileges. 364 00:36:49,220 --> 00:36:49,740 All right. 365 00:36:49,740 --> 00:36:52,440 Now the registration is done, we'll try initiating the call again. 366 00:36:52,640 --> 00:36:56,480 Except this time, it says Pwn instead of Call, so you know it's going to work. 367 00:37:03,560 --> 00:37:12,300 This time, the Temi picks up the call automatically, and the attacker now has full access to the Temi's movement, its camera, and its microphone. 368 00:37:12,580 --> 00:37:21,560 Now, the first thing an attacker might do is actually mute the microphone, their microphone, I mean, and turn off their camera, thereby essentially remaining anonymous as they do this. 369 00:37:22,000 --> 00:37:28,620 And you can start driving around whatever location it's in, looking around at whiteboards and other sensitive information. 370 00:37:29,020 --> 00:37:32,420 And you can also, you know, modify its volume to annoy people. 371 00:37:32,420 --> 00:37:36,180 But more importantly, you can actually navigate to its various save locations. 372 00:37:36,820 --> 00:37:40,820 So here we're going to navigate back to its home base, just so it doesn't run out of battery. 373 00:37:52,980 --> 00:37:58,300 So that attack vector leveraged that last vulnerability it described, which gives us owner privileges. 374 00:37:58,700 --> 00:38:05,620 Let's look at how we can exploit the previous vulnerability, which had to do with intercepting calls. 375 00:38:06,120 --> 00:38:11,240 So first, we'll begin by starting a call from the Temi for its admin. 376 00:38:11,900 --> 00:38:18,180 And as normal, you know, all's well with the world, the admin gets the call, but the attacker doesn't. 377 00:38:18,180 --> 00:38:19,720 This is expected behavior. 378 00:38:23,880 --> 00:38:28,160 But from the HackDAF, with a simple button press, we can change this entirely. 379 00:38:31,660 --> 00:38:41,300 By subscribing to the admin's call invite topic, now when the Temi calls it again, both the attacker and the admin will receive the call. 380 00:38:41,860 --> 00:38:48,180 And the attacker is free to pick up this and gain the same control over the robot it did with the other attack vector. 381 00:38:56,860 --> 00:38:59,680 All right, that concludes the demo. 382 00:39:02,280 --> 00:39:04,920 Got a couple slides to finish off. 383 00:39:06,980 --> 00:39:10,720 So let's talk about the vendor's response to our research. 384 00:39:12,180 --> 00:39:18,200 So we disclosed all four vulnerabilities to RoboTemi Global LTD on March 5th. 385 00:39:19,200 --> 00:39:27,500 They responded very quickly, and they were very receptive to all the suggested mitigations for these vulnerabilities that we outlined in our report. 386 00:39:27,640 --> 00:39:36,960 But perhaps most importantly, they maintained constant communication throughout the process, working with us to mitigate the vulnerabilities. 387 00:39:38,340 --> 00:39:43,380 Speaking of which, all four CVEs are actually patched as of July 15th. 388 00:39:44,020 --> 00:39:51,900 And McAfee ATR, my team, has reviewed the patches and has confirmed that they successfully mitigate all four CVEs. 389 00:39:53,220 --> 00:39:59,460 Now, all code shown as a result is from the older vulnerable versions of the APKs. 390 00:39:59,460 --> 00:40:03,180 In fact, the code is now heavily obfuscated and much harder to parse. 391 00:40:03,300 --> 00:40:20,720 And this is sort of the gold standard we seek out in security researcher and vendor relationships, where it's a mutually beneficial thing where the vendor responds quickly and we're able to get these things patched as soon as possible, ultimately resulting in a safer product for everyone. 392 00:40:23,580 --> 00:40:34,060 Now, before I let you guys go, I do want to discuss really briefly the various impact scenarios you might see used for these vulnerabilities. 393 00:40:34,920 --> 00:40:37,160 I think the biggest one is healthcare. 394 00:40:38,000 --> 00:40:46,180 There's obvious privacy concerns whenever you, you know, spy on a potential medical appointment or anything to do with health information. 395 00:40:46,180 --> 00:40:48,100 That's why HIPAA is such a big deal. 396 00:40:48,640 --> 00:40:57,360 But another potential attack vector might be, you know, using it as a sort of espionage for getting the status or location of persons of interest within a hospital. 397 00:40:58,220 --> 00:41:01,660 That might be something a nation-state actor might be interested in. 398 00:41:02,620 --> 00:41:07,600 Another attack scenario I want to have you guys think about is the enterprise one. 399 00:41:07,600 --> 00:41:10,880 We've already seen that these robots are being used in corporate offices. 400 00:41:12,760 --> 00:41:20,780 Now, you know, this actually would grant an attacker access to certain information that simply isn't accessible from a network-based attack scenario. 401 00:41:20,780 --> 00:41:25,960 Things like, you know, information posted on bulletin boards, on post-its, on computers. 402 00:41:25,960 --> 00:41:28,600 I hope it wouldn't be a password , but who knows? 403 00:41:28,780 --> 00:41:32,140 Network diagrams on whiteboards and other sensitive information. 404 00:41:32,140 --> 00:41:36,620 And perhaps more obviously, the ability to spy on boardroom meetings. 405 00:41:36,620 --> 00:41:41,540 What kind of sensitive information or trade secrets could be listened through? 406 00:41:41,540 --> 00:41:47,600 And it's not too surprising to see a teleconference robot being used in a room for teleconferencing. 407 00:41:48,820 --> 00:41:52,200 And with that said, that concludes my talk. 408 00:41:52,200 --> 00:41:56,280 I will be present in the Discord server to answer any questions you guys have. 409 00:41:56,680 --> 00:41:59,500 And thanks for tuning in.