1 00:00:00,000 --> 00:00:09,520 Hello hackers. This is a talk about a bug in the Microchip. And I'm Nini Chen, a security 2 00:00:09,520 --> 00:00:17,160 researcher at DevCore. We are from Taiwan. And I'm also a member of Belson CTF team and a member 3 00:00:17,160 --> 00:00:26,480 of Undefined. Okay. Why? Why the router OS? Because we want to participate in the Ponzu on 4 00:00:26,480 --> 00:00:34,740 Torrento in 2022. As one of the targets, the router board of Microchip hasn't been exploited in 5 00:00:34,740 --> 00:00:41,480 the previous event. More correctly, no one tried to demo exploit against this target in the 6 00:00:41,480 --> 00:00:51,560 context. You may already know the rules of the event. Participants must find a pre-auth RCE with 7 00:00:51,560 --> 00:00:56,460 no user interaction to acquire the points of the target. Okay. So, let's talk about the 8 00:00:56,480 --> 00:01:01,120 router board of Microchip. And the SOHO's mesh app, a special category was introduced in 2022. 9 00:01:01,960 --> 00:01:08,960 Participants have to chain a router when site exploits and another device exploits to earn the 10 00:01:08,960 --> 00:01:15,700 points and bounty. The bounty and point in this category are relatively high. So, it's a good 11 00:01:15,700 --> 00:01:24,140 target for us to earn more to win the contest. Let's recap some backseting quickly. The router 12 00:01:24,140 --> 00:01:30,480 OS, the router board of Microchip is quite popular. And the router OS is the operating system of 13 00:01:30,480 --> 00:01:35,180 router board hardware. By scanning the Microchip, we can observe about 3 million device online. 14 00:01:35,960 --> 00:01:42,360 Router OS is a standalone operating system based on the Linux kernel. And Microchip also offers 15 00:01:42,360 --> 00:01:50,940 ISO images so we can run it as a VM. It's closed source and also a closed ecosystem. According to 16 00:01:50,940 --> 00:01:54,120 the download terms on Microchip's website, you pay the price for the operating system. So, you can 17 00:01:54,140 --> 00:02:03,240 pay 45 bucks to get a GPL source code. What a bargain. And currently, there are two version of 18 00:02:03,240 --> 00:02:09,300 router OS, the V7 and the V6. That should be considered two branches because their 19 00:02:09,300 --> 00:02:15,380 implementation are slightly different. And the cloud hosting router is the router OS image for 20 00:02:15,380 --> 00:02:24,120 for for VM. But only the AMD 64 version is available. Most of the services that are available 21 00:02:24,140 --> 00:02:30,820 on router OS are implemented by Microchip themselves. And they share a similar architecture. So, we 22 00:02:30,820 --> 00:02:37,420 name them Nova binary afterwards. And they use Nova message to talk to each other. Though the router 23 00:02:37,420 --> 00:02:44,220 OS is based on Linux kernel. Users are trapped inside a customized COI. And there's no official 24 00:02:44,620 --> 00:02:51,120 method to access the underlying Linux system. Only developers can install a backdoor package to 25 00:02:51,120 --> 00:02:53,540 access the Linux system for debugging purpose. 26 00:02:54,400 --> 00:03:02,140 An administrator can manage their routers via the web web panel or Winbox, which is a Windows 27 00:03:02,140 --> 00:03:08,540 UI application. It's also a popular attack service. Because the Winbox interface on the router can 28 00:03:08,540 --> 00:03:16,960 be used to talk to other Nova binary. Some of them can be accessed without authentication. To 29 00:03:16,960 --> 00:03:23,480 understand how people research the router OS, let's have a look at test CVEs of the router OS. 30 00:03:24,140 --> 00:03:34,740 There are a total of 80 CVEs. And 28 of them are pre-auth exploitable. And the victim is the router 31 00:03:34,740 --> 00:03:45,940 itself. 16 out of the 28 are those in various components. 8 out of 28 are DNS poisoning, allowing 32 00:03:45,940 --> 00:03:54,120 attacker to MITM or firewall evasion. Only 4 pre-auth vulnerabilities in history can run a 33 00:03:54,120 --> 00:04:01,660 lead to a share or login as admin directly without user interaction. These are what we care 34 00:04:01,660 --> 00:04:13,440 about. 3 out of 4 were found between 2017 and 2019. And 3 out of 4 are in the wild. Let's 35 00:04:13,440 --> 00:04:20,920 have a close look. CVE 2017-20149 aka Chimerae. It's one of the exploits leaked from the 36 00:04:20,920 --> 00:04:28,880 CIA in the 2017. By sending an HDTV request with crafty content lens we can corrupt stack to 37 00:04:28,880 --> 00:04:38,500 execute arbitrary code by slack- by stack clash. CVE 2018-7445 is a buffer overflow in SMB 38 00:04:38,500 --> 00:04:47,880 found by black box- black box forcing. CVE 2018-14847 is also one of the exploits leaked 39 00:04:47,880 --> 00:04:50,900 from the CIA in 2017. CVE 2018-14847 is also one of the exploits leaked from the CIA in 2017. 40 00:04:50,920 --> 00:04:58,140 This bug allows unauthenticated attackers to read arbitrary file on router os. It sounds not a 41 00:04:58,140 --> 00:05:04,860 big deal in the first place, but since the password stored on router os was from simply 42 00:05:04,860 --> 00:05:12,960 repeating x or password in plain text with the hash of the username and fixed string at that time. 43 00:05:13,480 --> 00:05:20,800 So the password can be recovered easily and a bug with arbitrary file reading is sufficient to lock in as admin. 44 00:05:22,280 --> 00:05:31,280 CVE-2021-41987 is a HIPAA overflow in the decode of the SEP service. This was 45 00:05:31,280 --> 00:05:39,340 discovered on an APTC2 server in 2021. As we can see, these vulnerabilities are 46 00:05:39,340 --> 00:05:47,400 mostly in the wild. We can't learn too much from them directly. So, let's take a look at some 47 00:05:47,400 --> 00:05:53,780 talks and articles about the RouterOS. In 2017, there are three talks and they are about the 48 00:05:53,780 --> 00:05:59,920 package format adopted by the RouterOS, the developer's backdoor, how the RouterOS stores 49 00:05:59,920 --> 00:06:06,360 the password, et cetera. Uh, talks are interesting and helpful to have a big picture of the 50 00:06:06,360 --> 00:06:13,860 RouterOS. In 2018, the talk, Bug Hunting in RouterOS, Analyze the Normal Message in Binary 51 00:06:13,860 --> 00:06:17,180 and JSON Formats, introduced the How WinBugs Client. 52 00:06:17,400 --> 00:06:27,300 Talk to the WinBugs Interface by Normal Message and found a post-old stack overflow. In 2019, 53 00:06:27,620 --> 00:06:33,660 the first one is the same as the previous one. So, the next one is Mikrotik Firewall and Net 54 00:06:33,660 --> 00:06:39,280 Bypass. It's a talk about the vulnerability in the WinBugs that can be used to scan the 55 00:06:39,280 --> 00:06:47,380 intranet if the WinBugs is exposed to the intranet. The next, Finding and Exploiting 56 00:06:47,400 --> 00:06:56,420 CVE, found a stack buffer overflow in SMB by black box passing and explained how they got the 57 00:06:56,420 --> 00:07:05,220 shell, whose layer is deployed on the RouterOS VM. And the Deep Dive Mikrotik Exploits is a 58 00:07:05,220 --> 00:07:12,600 security, uh, analytes about the CIA exploits and the massive exploit event based on the 59 00:07:12,600 --> 00:07:17,380 liquid payload. The next one Help Me Vulnerability. You Are My Only Home! Ad from Microsoft. 60 00:07:17,400 --> 00:07:24,800 release a tool to help users to jailbreak their device to check if leaky exploit was already 61 00:07:24,800 --> 00:07:32,440 compromising them. And the last one. RouterOS chain to root is uh it's about chaining DNS 62 00:07:32,440 --> 00:07:40,580 poisoning vulnerability and uh downgrade attack to get a share. Finally in 2022 Pauline 63 00:07:40,580 --> 00:07:47,240 Microchip in Zoola Limeline talk more about Nova message and disclose uh post auth vulnerability 64 00:07:47,400 --> 00:07:53,140 in triple W that can be used to jailbreak. They also released a tool to help researchers 65 00:07:53,140 --> 00:08:01,180 quickly get a share on the AMD 64 version of RouterOS with the vulnerability. It seems like the 66 00:08:01,180 --> 00:08:07,160 whole world is talking about the Nova message in the IPC of the RouterOS. So we also try to 67 00:08:07,160 --> 00:08:14,200 understand what it is. Let's talk about the IPC of RouterOS with an example. While a user 68 00:08:14,200 --> 00:08:17,380 logging through a telnet to access the console of RouterOS. The IPC of RouterOS is a 69 00:08:17,400 --> 00:08:24,500 TLS. The telnet will immediately call an EXECL to execute the logging process to ask the user for a 70 00:08:24,500 --> 00:08:31,140 username and password. Then the logging process will send a Nova message with your username and 71 00:08:31,140 --> 00:08:38,760 password. So the user process to check if they are correct. The user process also responds in 72 00:08:38,760 --> 00:08:46,780 Nova message. The Nova message consists of key value pairs and the key can only be numbers. The key 73 00:08:46,780 --> 00:08:53,320 the sys2 and the sysform are arrays containing the ID of Nova binary and the ID of the handler. 74 00:08:55,080 --> 00:09:00,320 The communication between two processes is something like this. Every message is sent to the 75 00:09:00,320 --> 00:09:08,720 loader via socket and the loader dispatches the message to the corresponding binary. Logging 76 00:09:08,720 --> 00:09:16,380 process send a request with a username and password to the user process. The ver- the value of sys2 means the 77 00:09:16,380 --> 00:09:25,260 target is the handler 4 and the binary ID is 13. And the process itself does- doesn't have to 78 00:09:25,260 --> 00:09:32,060 fill the sysform with its process ID because the loader will do this- will do that based on which 79 00:09:32,060 --> 00:09:39,880 the socket is received the message from. Next, uh the loader removes the target binary ID in sys2 80 00:09:39,880 --> 00:09:46,360 as the source ID to sysform and then forward the message to the target process. The loader will 81 00:09:46,380 --> 00:09:49,660 then send the message to the sys2. When the user process receive the message from the socket, it 82 00:09:49,660 --> 00:09:55,620 also remove the handler from the sys2 and pass it to the corresponding handler. Then the handler 83 00:09:55,620 --> 00:10:02,240 does the rest of thing. We mentioned that a Winbox interface on the router OS is a popular 84 00:10:02,680 --> 00:10:09,280 attack service since it can be used to assess all the process. That's because the protocol Winbox 85 00:10:09,280 --> 00:10:16,160 client used to talk to the interface on the router is basically a Nova message in the TCP packet. 86 00:10:16,380 --> 00:10:22,480 So, if the target handler fail to check the sender's pri- privilege, that can cause problems. 87 00:10:23,960 --> 00:10:31,320 No- Nova message is type value mapping and can contain various types and also Nova message itself. 88 00:10:32,980 --> 00:10:39,880 Because the JSON format of the Nova message is duplicated, s- we only talk about the binary form 89 00:10:39,880 --> 00:10:46,360 today. Okay, the M2 at- at the beginning is the magic bytes for the Nova message. So, the 90 00:10:46,380 --> 00:10:53,980 Nova message. Then it use 4 bytes to describe a key. The first 3 bytes of key are id and the last 91 00:10:53,980 --> 00:11:03,020 byte is- is type. And the bytes following are the value for that key. So, this message's id types and 92 00:11:03,020 --> 00:11:10,820 values look like this. Types like bool can be expressed with one bit. Directly using the lower 93 00:11:10,820 --> 00:11:16,360 bit of the type bytes. To understand which binary corresponding to the id, you need to use the 94 00:11:16,360 --> 00:11:22,880 id in the sysform and sys2. We need to parse x3 file under the loader directory. It's kind of 95 00:11:23,260 --> 00:11:31,300 xml, but in binary form. If a binary was introduced by installing a package this id is on the 96 00:11:31,300 --> 00:11:41,680 loader DS of the package. So, in this can- can be found in the x3 file. Because the process is not 97 00:11:41,680 --> 00:11:46,340 persistent. The id is just a serial number like the S- sin define. To brok- is videos in theокой 98 00:11:46,340 --> 00:11:53,220 locking process we just mentioned. Other binaries also have their x3 files for different 99 00:11:53,220 --> 00:12:01,300 purpose. For example the x3 of triple w of triple w describe which URI should be handled by 100 00:12:01,300 --> 00:12:08,720 which servlet. It seems like it's a good target for fuzzing right? But we can't just fuzz it 101 00:12:08,720 --> 00:12:16,320 and expect that we get something after two months. Now, it's a spoiler. While we're 102 00:12:16,340 --> 00:12:23,160 writing our exploit with the vulnerability that I will introduce later, uh talk at POC 2022 103 00:12:24,180 --> 00:12:31,440 MicroTik router OS security the forgotten IPC message. Though I think it's far from forgotten 104 00:12:31,440 --> 00:12:39,180 but anyway. The talk is about fuzzing and the nova message. And it founds lots of post-auth 105 00:12:39,180 --> 00:12:46,040 CVEs. By the number of CVEs it looks like the fuzzer has been running for a long time. 106 00:12:46,660 --> 00:12:52,320 A bit of an afterthought. I don't think we can get a better result if we do the same 107 00:12:52,320 --> 00:13:00,580 thing at that time. Not to mention that we only have two months. So, is it still possible to 108 00:13:00,580 --> 00:13:07,700 pull the router OS? Review this CVEs again. Most of the most of the vulnerability we think 109 00:13:07,700 --> 00:13:16,240 interesting were discovered many years ago. Researchers also found lots of vulnerability but as we can see the MicroTik 110 00:13:16,340 --> 00:13:23,700 becomes safer and safer. But in 2021, a vulnerability in the SCEP server we just mentioned was 111 00:13:23,700 --> 00:13:32,540 discovered by analyzing and in a wild exploit on the APT C2 server. Was it uh was it 112 00:13:32,540 --> 00:13:39,800 undiscovered until until then because it was not a default feature or is it just because people 113 00:13:39,800 --> 00:13:46,320 have overlooked something? Most talks and articles focus on jailbreakers and the fact that the jailbreakers 114 00:13:46,340 --> 00:13:52,780 are breaking. Analyzing the in the wild exploits and normal message in IPC. I have a summary after 115 00:13:52,780 --> 00:14:00,360 reading them and starting to reverse by ourself. That is, no one with sanity would like to dive into 116 00:14:00,360 --> 00:14:09,340 the details of normal binaries. I mean is expect for the exploits from the CIA and APT. Most of the 117 00:14:09,340 --> 00:14:16,100 research about bug hunting is fussing the protocol playing with normal message or fussing normal message. 118 00:14:16,340 --> 00:14:24,360 By the outcome, it seems like attackers are familiar with the router OS than us. We need more 119 00:14:24,360 --> 00:14:31,400 details about the normal message. And don't get me wrong, I'm not against fussing but we have to ensure 120 00:14:31,400 --> 00:14:39,560 we check everything to take to take advantage of the contest. I don't think the system is perfect 121 00:14:39,560 --> 00:14:46,060 now. There is a gap between researchers and attackers. So what was missed if we want to find some pre-auth 122 00:14:46,340 --> 00:14:56,380 C box in router OS. The first question is, where are the entry point to the customized IPC? Most of them can only access by 123 00:14:56,380 --> 00:15:05,020 authenticated user. We can foresee that playing with normal message in IPC will result in lots of post auth bugs. 124 00:15:06,340 --> 00:15:15,780 IPC just a part of implementation of the most functionality. We want to review the crucial part directly and carefully. For 125 00:15:16,340 --> 00:15:26,640 example, how does the DHCP process pass a DHCP packet to extract the info in it? Then, we have to mention the 126 00:15:26,640 --> 00:15:34,140 architecture of the normal message, normal binary. Every normal binary has a looper. The looper use port to check the 127 00:15:34,140 --> 00:15:43,080 status of socket and process event in each loop. Just like a regular event loop you've seen everywhere. Looper is 128 00:15:43,080 --> 00:15:48,300 responsible for the communication between the current process and the loader. The looper register a 129 00:15:48,300 --> 00:15:55,560 special callback for a unit socket which is used to communicate with loader. The special callback on MSG 130 00:15:55,560 --> 00:16:01,400 sock will dispatch the message to the corresponding handler once it received normal message from the 131 00:16:01,400 --> 00:16:09,260 socket. So, how does the handler work? While the looper receive a normal message, you dispatch it to the 132 00:16:09,260 --> 00:16:17,520 corresponding handler. Look at the right hand side. And let's assume that handler one is responsible 133 00:16:17,520 --> 00:16:25,280 for the normal message. And then you call a function in Vtable with the CMD prefix like corresponding to 134 00:16:25,280 --> 00:16:33,860 the command specified by the C-CMD. There are many functions here, but because the handler is the 135 00:16:33,860 --> 00:16:39,240 base class, commands relative to objects are uninfluenced. So, the handler will not be able to receive the message. So, 136 00:16:39,260 --> 00:16:47,020 you need to implement it. The CMD unknown is often overridden and used to extend the customized 137 00:16:47,020 --> 00:16:56,480 command. Sometimes the developers override the handle CMD instead of the CMD unknown. You may have 138 00:16:56,480 --> 00:17:04,200 already read some of this in a past research. But most of the time, the normal binary use the derived 139 00:17:04,200 --> 00:17:09,240 classes rather than the best handler class. The derived classes can store a number of messages. So, 140 00:17:09,240 --> 00:17:15,300 you can store a collection of objects of a specific type. For example, while the user is setting up a DHCP 141 00:17:15,300 --> 00:17:21,540 server, they will send a message to the handler zero of the DHCP process to create a DHCP server. 142 00:17:22,260 --> 00:17:30,260 The handler zero, which is an instance of a-map, calls the function on its Vtable with offset, hex 7c, 143 00:17:30,420 --> 00:17:39,220 to create a DHCP server object and insert it into a tree. The 7c is the offset to the constructor object. 144 00:17:39,240 --> 00:17:45,260 of the inner object. And you can find the offset of such function in other derived classes by 145 00:17:45,260 --> 00:17:54,400 reversing the cmd add object. In the previous example, the web panel sends a NOVA message to 146 00:17:54,400 --> 00:18:01,540 DHCP to create a DHCP server. But what if I told you that some functionality don't even use the 147 00:18:01,540 --> 00:18:09,160 NOVA message? Take the CDP and the LLDP for example. They are implemented in this cover. The 148 00:18:09,240 --> 00:18:15,140 looper register two callback functions. The looper keeps looping and check the status of 149 00:18:15,140 --> 00:18:22,880 sockets. If there are incoming packets, the looper call the callback function. The callback of CDP 150 00:18:22,880 --> 00:18:28,680 will check if the interface that receive the packet is not filtered by firewall rule. Then 151 00:18:28,680 --> 00:18:35,180 extract the information from the packet and store them directly into another ASEC map without 152 00:18:35,180 --> 00:18:38,800 sending NOVA message. So there's no NOVA message here. 153 00:18:40,720 --> 00:18:47,140 So, we started to review the router OS by enumerating functions and reversing them. Then we 154 00:18:47,140 --> 00:18:54,040 found something strange. One day, while plugging and unplugging some cable connect to the router, 155 00:18:54,880 --> 00:19:01,840 suddenly the log file show that RADVD crashed several times. So we tried to reproduce the crash 156 00:19:01,840 --> 00:19:08,680 by manually plugging and unplugging cables about a thousand times. But couldn't figure out the crash 157 00:19:08,680 --> 00:19:15,980 condition. The condition is unknown and the crash appears randomly. Instead of mindlessly 158 00:19:16,700 --> 00:19:23,140 unplugging and plugging the cables, we reverse the RADVD to see if we can find something 159 00:19:23,140 --> 00:19:30,760 interesting. We didn't find the root cause of the crash, but we got something better. So, 160 00:19:30,760 --> 00:19:41,280 what is RADVD? RADVD is a service about SLAAC of IPv6. Let's say a computer or a node wants to 161 00:19:41,280 --> 00:19:48,200 get an IPv6 address. It will first mutlcate the router-router solicitation to all router, 162 00:19:48,340 --> 00:19:56,700 asking for a network prefix. Then, if a router receives the RS, we will-it will mutlcate the 163 00:19:56,700 --> 00:20:00,340 router advertisement with network prefix to all nodes. 164 00:20:00,760 --> 00:20:09,280 After that, a node can calculate its IPv6 address by combining the network prefix and EUI64, 165 00:20:09,680 --> 00:20:16,340 which is calculated from the MAC address. Another scenario is that if an upstream router, 166 00:20:16,540 --> 00:20:25,540 router A, maybe it's an ISP, they give you a prefix with slash 48, which assign in advance by 167 00:20:25,540 --> 00:20:30,740 email or something. Then, you can use them with whatever-whatever-whatever you want. 168 00:20:30,740 --> 00:20:39,640 in your LAN. Then, here comes the link prefix and router prefix. First, the router B, 169 00:20:39,800 --> 00:20:46,720 act-act as a node on the interface that link to the router A. The router B asks router A for a 170 00:20:46,720 --> 00:20:53,840 prefix. The router A send a slash 64 prefix for router B to calculate its IPv6 address. 171 00:20:54,520 --> 00:21:00,720 Router B calculate an IPv6 address. Let's say it's 2001-2007-2007-2007. Router B will be using the 172 00:21:00,740 --> 00:21:07,060 colon DBA, colon colon one. And use it on the interface that links to- with router A. So 173 00:21:07,060 --> 00:21:18,380 now, the router A can route all traffic to the address on the slash 48 to router B. Now, 174 00:21:18,440 --> 00:21:25,140 when nodes want to get IPv6 and send RS to the router B, the router B just multicast the 175 00:21:25,140 --> 00:21:32,980 slash 48 prefix to nodes. Then the nodes act as usual. So the functionality of RADVD in router 176 00:21:32,980 --> 00:21:41,840 OS should have two functional- two functionality. It- first, it can act as a node to receive RA. 177 00:21:42,460 --> 00:21:50,660 And it can also multicast RA to the LAN. Let's follow the execution flow of RADVD to find 178 00:21:50,660 --> 00:21:55,120 a bug. The RADVD have a similar design pattern to the discard. The RADVD have a similar design 179 00:21:55,120 --> 00:21:55,140 pattern to the discard. They all have the sameregister method. The RADVD can register a 180 00:21:55,140 --> 00:22:00,200 We have a process that we mentioned earlier. You register a callback. The looper pull a 181 00:22:00,200 --> 00:22:08,540 socket in every loop. And if there is an incoming ICMPV6 sub packet the looper call the register 182 00:22:08,540 --> 00:22:24,460 callback. What callback do is roughly like this. It check if the packet is a valid RA or a valid RS. If it is an RA, then extract information and store them 183 00:22:24,460 --> 00:22:31,900 in the handler one, which is AMAP. And if it is an RA, it will multicase the RA immediately. 184 00:22:32,640 --> 00:22:41,460 Sorry, if it is RS, it will multicase RA immediately. There are three cases the router OS 185 00:22:41,460 --> 00:22:47,840 will multicase the prefix to nodes. The first one is when you receive the RAs from nodes. The 186 00:22:47,840 --> 00:22:54,000 second is when you receive an RA from upstream router. The last one is when you, uh let, 187 00:22:54,000 --> 00:23:01,220 sorry, the last one is the router will multicase prefix in a default period, which is in 188 00:23:01,220 --> 00:23:09,100 two hundred to six hundred seconds. And yes, the router will multicase the RA to nodes once 189 00:23:09,100 --> 00:23:16,960 it receives a RA. But it's hard to trace this behavior directly because this is about a 190 00:23:16,960 --> 00:23:23,980 subscription. I'll talk about it later. We didn't know that then. But the other thing is 191 00:23:24,000 --> 00:23:29,940 the router to case can be traced directly, directly. The RADVD calls send RA right after it 192 00:23:29,940 --> 00:23:39,420 receives an RS. The handler one register a timer to send RA periodically. So, we can find the 193 00:23:39,420 --> 00:23:46,620 send RA function by tracing these two methods. Following the send RA function, we found 194 00:23:46,620 --> 00:23:53,980 something interesting while the RADVD deal with DNS advisory. It will advise DNS to know that the 195 00:23:54,000 --> 00:24:01,420 RADVD nodes based on the DNS list it received from upstream. The ADD DNS function is used to 196 00:24:01,420 --> 00:24:09,800 flatten the DNS tree and then add it to the ICMPV6. The RA row is the ICMPV6 payload, which is 197 00:24:09,800 --> 00:24:18,780 the local variable with the size of four hundred ninety-six bytes. Step into the ADD DNS and we 198 00:24:18,780 --> 00:24:23,320 can immediately find out there is a probably, uh, stack bubble overflow. So, this is the 199 00:24:24,860 --> 00:24:25,580 program that's causing the stack bubble to overflow if it'stop location is big enough. The 200 00:24:25,580 --> 00:24:33,020 function at DNS to packet by memory copy without any, without any bundling check. The causes 201 00:24:33,020 --> 00:24:39,580 the stack bubble to overflow in if the DNS is speaking nice. The DNS addresses are from the 202 00:24:39,580 --> 00:24:47,900 RDNSS of the RA. But theEMX length of the RDNSS of an RA is 8 bytes. 8 bytes. Which 203 00:24:47,900 --> 00:24:53,300 is insufficient to override the return address. But if this is not a function, we have only nine 204 00:24:53,300 --> 00:25:01,860 first time, the router OS receive an RA. The RA DVD have to expire all RDNSS. That makes the 205 00:25:01,860 --> 00:25:11,960 RD- RA DVD flatten another tree to override more bytes fo- for us. So, what we have to do is 206 00:25:13,170 --> 00:25:19,980 we have to act as a bay neighbor. Let's send a router advertisement with a big RDNSS list to 207 00:25:19,980 --> 00:25:27,640 the target router. Then, send another router advi- advertisement with the big RDNSS list. 208 00:25:28,540 --> 00:25:37,720 Now, the return address is overri- overwritten with an IPv6 address in the RDNSS of the first RA. 209 00:25:38,920 --> 00:25:44,380 It's time to construct the exploits. And it looks easy because there is no protection 210 00:25:44,380 --> 00:25:49,960 enable. So, let's find a way to jump on the stack and run our RA. So, let's find a way to run our 211 00:25:49,980 --> 00:25:59,940 shellcode. That should be easy. Thank you. The overflow IPv6 addresses are sorted since they 212 00:25:59,940 --> 00:26:06,300 were stored in the tree. To make the order of the IP addresses stable to ensure the shellcode is 213 00:26:06,300 --> 00:26:13,420 good, we can use part of the IPv6 prefix as a serial number and put a jump and at the end of 214 00:26:13,420 --> 00:26:19,960 each address to jump over the prefix because they are not valid instructions. But, because of the 215 00:26:19,980 --> 00:26:27,400 delay slots of MIPS, which means, uh, the instruction after the branch instruction will always 216 00:26:27,400 --> 00:26:34,160 be executed before the branch instruction itself. We have to move the jump instruction forward. 217 00:26:34,720 --> 00:26:43,660 But, the other problem is that you cannot do a syscall in the delay slot. So, basically, this is a 218 00:26:43,660 --> 00:26:49,960 bad idea. It's actually a CTF 101 problem. Just make a prefix, uh, very interesting. So, let's 219 00:26:49,980 --> 00:26:54,540 have a look at the instruction. They won't affect our gadget or shellcode. Then, everything is fine. 220 00:26:55,860 --> 00:27:02,980 And because we didn't leak any stack address, plus, we didn't find any gadget that can be used to 221 00:27:02,980 --> 00:27:11,360 move stack pointer to register T9 for jumping instruction in the first place. So, what we did 222 00:27:11,360 --> 00:27:19,700 here is, first, write our gadget on memory then jump to that gadget. Finally, our shellcode would be 223 00:27:19,700 --> 00:27:19,960 executed. And then, we can use the capture to run the app. And then after that, we can run our 224 00:27:19,960 --> 00:27:28,420 executed. Sounds good. But there is iCache. The MIPS CPU has two cache. The instruction cache 225 00:27:28,420 --> 00:27:34,360 and the data cache. While writing our gadget on memory, we are actually writing on 226 00:27:34,360 --> 00:27:41,620 de-cache. Now, when we try to control the execution flow of executes, uh, sorry, to execute 227 00:27:41,620 --> 00:27:47,940 the gadget for running our shellcode, the process- the processor first check if the 228 00:27:47,940 --> 00:27:55,740 instruction are already in the iCache. Because we wrote our gadget on the data section, the 229 00:27:55,740 --> 00:28:04,540 cache always miss it. So, the memory content will be loaded into iCache. The cost of the 230 00:28:04,540 --> 00:28:12,520 process- the cost of the processor to execute a bunch of nob- nob until the program crash. To 231 00:28:12,520 --> 00:28:17,680 flush the de-cache, we need to make the processor content switch or exhaust the de-cache. 232 00:28:17,940 --> 00:28:24,400 The de-cache is a function whose size is 32 kilobytes. There is no sleep in RADVD. Other 233 00:28:24,400 --> 00:28:29,160 functions will also trap into the kernel, but they don't guarantee the context switch will 234 00:28:29,160 --> 00:28:36,920 always happen. To make our exploit consistently successful in maximizing the chance to win the 235 00:28:36,920 --> 00:28:45,760 game, we have to flush the 32 kilobyte de-cache. Luckily, the value in randomize VA space of 236 00:28:45,760 --> 00:28:53,560 router OS is 1, which means the heap is not randomized. The only things we need to do is do 237 00:28:53,560 --> 00:29:00,360 some memory allocation to extend the heap a-and write some gadget on it. We may run out of 238 00:29:00,360 --> 00:29:09,880 bytes for shellcode because of that. But, the DNS addresses were stored in a tree. They cost lots 239 00:29:09,880 --> 00:29:15,740 of memory space. The heap is already larger than 32 kilobytes during the process. So, we need to 240 00:29:15,740 --> 00:29:23,900 during the processing of a request. So we can call the memory copy by GOT hijacked to write 241 00:29:23,900 --> 00:29:31,500 32 kilobytes garbage on the heap to flush the de-cache for our shulker directly. And the 242 00:29:31,500 --> 00:29:39,140 profit. The vulnerability was assigned CVE two thousand twenty-two thousand twenty-three. 243 00:29:39,140 --> 00:29:46,400 Three two one five four. And it's already been fixed. After that we found a vulnerable code had 244 00:29:46,400 --> 00:29:54,600 exist at least since the router OS v six. This means the vulnerability has exist since two 245 00:29:54,600 --> 00:30:02,720 thousand thirteen. Nine years until we found it and ten years until they fixed it. So no one with 246 00:30:02,720 --> 00:30:07,600 sanity would like to dive into the details of normal binary. QED you're welcome. So let's 247 00:30:09,200 --> 00:30:14,680 combine the exploit with our exploit from the Canon printer for the point to own. The 248 00:30:14,680 --> 00:30:20,000 attacking scenario is that an attacker is a bad neighbor of the micro ticker router sending 249 00:30:20,000 --> 00:30:28,420 crafty ICMP v six to attacking the router. And if we if we compromise the router successfully we 250 00:30:28,420 --> 00:30:34,640 can forward our payload to attack the printer behind the router. The whole set up can be 251 00:30:34,640 --> 00:30:39,120 simplified as such in the context. Just let our laptop and our computer do the job. So we can 252 00:30:39,140 --> 00:30:46,560 act act act as the upstream router of the target router. We can almost see our hundred k 253 00:30:46,560 --> 00:30:55,080 balting. But. Another but. Our exploit only working on Mac OS and fail on Ubuntu. Whether it's 254 00:30:55,080 --> 00:31:02,420 a VM or not. We try to debug the exploit by running the exploit on VM and recording the 255 00:31:02,420 --> 00:31:09,120 traffic. Down below traffic and replay it. It just fail as we expected. But we can see that the 256 00:31:09,140 --> 00:31:13,780 output is in the network. We also downed the traffic from Ubuntu and replay it on Mac. 257 00:31:14,460 --> 00:31:25,040 However, it somehow succeed. So we guess there is an OS that will reorder the packet. We put a 258 00:31:25,040 --> 00:31:31,640 thing for our router to monitor the traffic from Mac and Ubuntu. And because the AF packet is not 259 00:31:31,640 --> 00:31:39,120 affected by any firewall chance. The result should be reliable. But it looks like the 260 00:31:39,140 --> 00:31:46,020 the same. The last resort could be that I have to go to Torrento in person but we can't 261 00:31:46,020 --> 00:31:51,660 leave it like that because who knows if the bug will suddenly happen again during the 262 00:31:51,660 --> 00:31:59,700 contest even on the Mac OS. Eventually we find a problem. It's all about speed. The gaps look 263 00:31:59,700 --> 00:32:06,960 tiny and you may never notice in Wireshark but the difference between them is actually 390 264 00:32:06,960 --> 00:32:13,660 times. The problem is not on Ubuntu, it's just because the Mac sends two packet too quickly 265 00:32:14,420 --> 00:32:20,020 causing rest condition. Plus, we were lazy and did not actually calculate how many bytes we 266 00:32:20,020 --> 00:32:25,740 need to override the return address. We just send a bunch of garbage and do the pattern 267 00:32:25,740 --> 00:32:33,200 matching. So the solution is put a sleep before sending a second RA and fixing the offset of our 268 00:32:33,200 --> 00:32:36,940 payload. Then it's very stable. The probability of sleep is very low. So the problem is that 269 00:32:36,960 --> 00:32:44,260 success is almost hundred percent. But how? The RADVD is only one thread. How could there be a 270 00:32:44,260 --> 00:32:50,380 rest condition? I didn't mention that while the RADVD parsing the incoming packet, the DNS 271 00:32:50,380 --> 00:32:57,300 address are stored in a vector. But somehow the handler pass a DNS tree to the add DNS function. 272 00:32:58,060 --> 00:33:05,180 What's the relationship between these two members? It's actually about why we can't find where the 273 00:33:05,180 --> 00:33:06,940 code bay function multicates the RADVD. So, let's look at the RADVD. So, let's look at the RADVD. So, 274 00:33:06,960 --> 00:33:07,200 let's look at the RADVD. So, let's look at the RADVD. So, let's look at the RADVD. So, there is a 275 00:33:07,200 --> 00:33:12,160 GOT report for storage associated with RA when you receive an RA packet. Let's look closely 276 00:33:12,160 --> 00:33:17,420 at the code bay function. There is an array responsible for storing something called the remote 277 00:33:17,420 --> 00:33:24,540 remote object. Then it looks straightforward. Just enter the new DNS vector then do RODNS on 278 00:33:24,540 --> 00:33:30,140 each of them and append the result to the DNS remote object vector. So, what is the remote 279 00:33:30,140 --> 00:33:35,820 object? The remote object is a mechanism to store common resources in the process and other 280 00:33:35,820 --> 00:33:41,400 process can access them via ID. For example, a DNS remote object is actually stored in the 281 00:33:41,400 --> 00:33:48,440 handle 2 of the resolver and the RADVD only preserve the ID of the object in handle 1. Now, 282 00:33:48,520 --> 00:33:55,360 let's talk about the subscription in Nova binary. The binary IP pool 6 is responsible for 283 00:33:55,360 --> 00:34:03,080 managing the IPv6 address pool. The DHCP subscribe to it so the DHCP can react to the change. It's 284 00:34:03,080 --> 00:34:09,740 done by sending a subscribe Nova message and the sys notify cmd can specify which command you 285 00:34:09,740 --> 00:34:10,400 want to subscribe. 286 00:34:11,980 --> 00:34:20,820 The F-E-O-O-O-B means notification. So, if there is another binary try to add an object to 287 00:34:20,820 --> 00:34:26,860 the handler 1 of IP pool 6 by sending a Nova message the add object of handler 1 will be 288 00:34:26,860 --> 00:34:35,100 executed. In most cases the add object will call send not-notifies to notify subscribers who 289 00:34:35,100 --> 00:34:41,380 subscribed to F-E-O-O-O-B to inform them that the IP pool 6 has changed. So, the F-E-O-O-O-B 290 00:34:41,400 --> 00:34:46,500 will have the same function as a RADVD. So, when the RADVD receive RA from an upstream router it 291 00:34:46,500 --> 00:34:55,120 call RO DNS to create DNS remote object for each IPv6 address in RDNS of RA. The cammed add object 292 00:34:55,120 --> 00:35:03,820 of handler 4 in the resolver is responsible for such a request and we'll add the IPV6 object in 293 00:35:03,820 --> 00:35:11,380 the handler 2. Also, because the handler 1 of RADVD subscribes to the resolver's handle 2, the 294 00:35:11,380 --> 00:35:18,020 The handler two will notify it with every DNS addresses it has now. So the handler one 295 00:35:18,020 --> 00:35:25,600 constructs the RA for LAN with these DNS addresses. The problem is in the implementation of 296 00:35:25,600 --> 00:35:32,920 RO-DNS. Let's send Nova message by post message which is non-blocking. It means the remote 297 00:35:32,920 --> 00:35:41,080 object won't get the object ID immediately. So if we send request too fast, the second RA 298 00:35:41,380 --> 00:35:48,720 arrives before the RA-DVD gets the object ID of the old remote object, the RA-DVD can only 299 00:35:48,720 --> 00:35:58,800 soft delete those old objects rather than really delete them. That cause the rest condition. This 300 00:35:58,800 --> 00:36:03,940 is what happen if we follow them step by step. Because both process are single thread, let's 301 00:36:03,940 --> 00:36:10,560 assume they are in the first loop of the looper while the RA-DVD receive the first RA from 302 00:36:10,560 --> 00:36:18,920 when. With one DNS address, the RA-DVD creates a remote object in a resolver by sending a Nova 303 00:36:18,920 --> 00:36:26,880 message. And the resolver will set up a timer after receiving the first request. Because it 304 00:36:26,880 --> 00:36:35,840 cannot tell how many 18 operations should be grouped. Issues- it just set a timer and send 305 00:36:35,840 --> 00:36:40,540 only one notification when the time's up. Apart from the RA-DVD, we can't use the RA-DVD in the 306 00:36:40,540 --> 00:36:48,320 from notification, the resolver should send a response back to tell RADVD the object ID of the 307 00:36:48,320 --> 00:36:56,180 remote object it just asked for. But if we send the second RA quickly before the resolver sends 308 00:36:56,180 --> 00:37:05,140 the object ID back, the RADVD can only mark the old DNS remote object as destroyed. Then keep 309 00:37:05,140 --> 00:37:13,300 going to create the DNS remote object for the old DNS in the second RA. Then we'll send a 310 00:37:13,300 --> 00:37:20,120 request to the resolver but as I say, we send the second RA too quickly. The resolver is still in 311 00:37:20,120 --> 00:37:28,700 the first loop which try to send the object ID it created in the first loop. So our request will 312 00:37:28,700 --> 00:37:35,120 stay in the socket. Now, the resolver sends the object ID back. The response is still in the 313 00:37:35,140 --> 00:37:40,840 socket, but the response handler, uh, is a callback re- registered by the first request, will 314 00:37:40,840 --> 00:37:48,540 handle the response. The handler finds out the object has already been marked as soft delete. So 315 00:37:48,540 --> 00:37:56,280 that it won't update the object ID. Instead, it will post another request to the resolver to 316 00:37:56,280 --> 00:38:04,520 delete that object. The request will will be processed in the third loop of the resolver after 317 00:38:05,140 --> 00:38:12,520 request of creating the DNS remote object for the second RA. In the second loop of the 318 00:38:12,520 --> 00:38:19,480 resolver, it processes the creation request with the DNS address from the second RA and the 319 00:38:19,480 --> 00:38:29,040 response with object ID. Now, time's up. The timer of the resolver think a group of 18 320 00:38:29,040 --> 00:38:34,880 operations should have been done and it's time to notify everyone what DNS addresses it 321 00:38:34,880 --> 00:38:41,340 has. And because the handle one of RA DVD subscribes to the handle two of the 322 00:38:41,340 --> 00:38:49,820 resolvers, it receive the DNS addresses in the normal message. Then store them as a tree and use 323 00:38:49,820 --> 00:38:57,940 them to construct the RA for LAN in the RA routine. At the moment, the result of two requests 324 00:38:57,940 --> 00:39:04,640 is missing. That's why our first version of the exploit can only work on MacOS because 325 00:39:04,640 --> 00:39:11,860 we trigger the rest condition. It seems hard to achieve a rest condition because there is a timer, 326 00:39:12,380 --> 00:39:19,780 but the mechanism is actually more complex than I just explained. So, the rest will always 327 00:39:19,780 --> 00:39:28,400 happen as long as the two RAs arrive at the router in the short period. So, the pattern of the 328 00:39:28,400 --> 00:39:34,500 rest condition in a remote object is as follows. Use non-blocking method to create the 329 00:39:34,640 --> 00:39:42,100 lead remote object. And the target process subscribes to the remote object. Then we can mix 330 00:39:42,100 --> 00:39:52,020 the result of two requests into one. They might make us bypass some checks in the binary. We 331 00:39:52,020 --> 00:39:59,560 try to find other vulnerability with this pattern. So, that we can so that we could register the 332 00:39:59,560 --> 00:40:07,380 the LAN category of the router in . But we ran out of time and did not manage to find 333 00:40:07,380 --> 00:40:14,240 other vulnerability to exploit the LAN side of router OS. But at least we are the first 334 00:40:14,240 --> 00:40:19,560 team to exploit the SOHO smash up category successfully and also won the title of master 335 00:40:19,560 --> 00:40:28,660 of Pong. Okay. In summary, MikroTik re-implement everything with its own design IPC. The business 336 00:40:28,660 --> 00:40:36,800 logic is skated all over. We have to have an abstract concept of NOVA binary to find the 337 00:40:36,800 --> 00:40:44,500 most critical code to reversing. And there is a pre-auth RCE on WAN that has existed for 338 00:40:44,500 --> 00:40:51,640 nine years. Also, we introduced a pattern of REST condition in remote object due to non-blocking 339 00:40:51,640 --> 00:40:58,440 method to you. And the last thing, we will drop tools that we use in the Pong2Own events 340 00:40:58,440 --> 00:41:05,440 then to ease the reversing of router OS at GitHub. And that's it. Any question?