1 00:00:01,500 --> 00:00:03,320 Hi, everyone. 2 00:00:03,320 --> 00:00:05,240 My name is Feng Xiao from Georgia Tech. 3 00:00:05,240 --> 00:00:14,800 It seems like I'm the first DEF CON safe mode main talk, and I really hope everyone can enjoy attending my work. 4 00:00:14,920 --> 00:00:22,880 So this is, of course, not only my work, but also the work of my wonderful co-authors from Georgia Tech and Texas A&M. 5 00:00:22,880 --> 00:00:28,480 Today, I'm going to talk about some interesting new vulnerabilities in the Node.js ecosystems. 6 00:00:29,360 --> 00:00:34,840 Before the talk normally begins, please let me introduce myself a little more. 7 00:00:34,920 --> 00:00:38,280 I am a CS PhD student at Georgia Tech. 8 00:00:38,280 --> 00:00:44,200 My research goal is about building automatic systems to detect and exploit vulnerabilities. 9 00:00:44,300 --> 00:00:53,940 We want the tools to exploit vulnerabilities because we want the people to know the existence and the consequence of their security bugs. 10 00:00:54,120 --> 00:00:58,040 And I do research in the web and application security. 11 00:00:58,040 --> 00:01:06,340 But I'm also researching security problems in other areas, such as the software defining networks and x86 virtualizations. 12 00:01:07,100 --> 00:01:10,540 Okay, so this is the topic I'm going to cover today. 13 00:01:10,540 --> 00:01:13,820 The talk will be divided into three parts. 14 00:01:14,280 --> 00:01:20,480 First, I will introduce the technical details of the new vulnerabilities and discuss their exploitation. 15 00:01:20,840 --> 00:01:34,660 Then, I will talk more about the bug-finding parts, which is about the lessons and the insights from building one kind of a tool to detect and exploit HPA. 16 00:01:34,960 --> 00:01:43,800 And in the last part, I will give an impact analysis of the new risk and some evaluation data about the tools. 17 00:01:45,300 --> 00:01:51,140 So first of all, let's take a quick look at the vulnerabilities we found during our research. 18 00:01:51,920 --> 00:02:02,640 So in total, we discovered 13 zero-day vulnerabilities from widely used programs, such as MongoDB official drivers, class validators. 19 00:02:02,900 --> 00:02:12,640 And these bugs can be exploited to launch serious attacks, such as leaking credential data, bypassing security checks, and denial of services. 20 00:02:13,120 --> 00:02:23,280 So before we touch the technical details of these vulnerabilities, let's have a brief background introduction about Node.js. 21 00:02:24,260 --> 00:02:28,480 Node.js is for executing JavaScript code outside of browsers. 22 00:02:28,900 --> 00:02:33,140 The picture on the right is the overall system diagram of Node.js. 23 00:02:33,260 --> 00:02:45,300 To interrupt and execute JavaScript, the Node.js implements a runtime engine based on Chrome V8 to satisfy the needs of the server-side languages. 24 00:02:46,160 --> 00:02:52,940 The runtime engine also provides a set of API to let JavaScript interact with the host environments. 25 00:02:53,280 --> 00:03:01,980 By providing such APIs, the JavaScript code can access the host environments like any other server-side languages. 26 00:03:01,980 --> 00:03:07,980 For example, it can read and write file systems or execute system commands. 27 00:03:08,280 --> 00:03:10,560 So Node.js is pretty powerful. 28 00:03:12,100 --> 00:03:15,520 Nowadays, many websites are deploying Node.js. 29 00:03:15,520 --> 00:03:21,300 For example, Node.js are intensively used in companies like PayPal and LinkedIn. 30 00:03:21,300 --> 00:03:28,740 Also, we are all using a lot of electronic apps such as Skype or Skogs, Discord. 31 00:03:28,740 --> 00:03:33,280 And such electronic apps are also based on Node.js runtime. 32 00:03:34,540 --> 00:03:37,640 We've seen so many Node.js applications. 33 00:03:37,640 --> 00:03:42,580 The web-based apps are one of the most common types of Node.js programs. 34 00:03:42,940 --> 00:03:53,560 For those web-based applications, taking the communication data into object representations like JSON is pretty common. 35 00:03:53,780 --> 00:03:56,100 And this feature is convenient. 36 00:03:56,660 --> 00:04:03,660 For example, Node.js can use this feature to send and receive very complex data structure. 37 00:04:03,760 --> 00:04:14,060 From the monthly download statistic picture on the right, we can have an idea of how the object sharing is being supported and used by the Node.js ecosystems. 38 00:04:15,740 --> 00:04:22,820 The diagram demonstrates how the object sharing is being used in the Node.js ecosystem. 39 00:04:22,860 --> 00:04:28,880 There are two major methods of serialization of object data. 40 00:04:28,880 --> 00:04:34,920 The first is the query-stream-based serialization, and the second is the JSON-based serialization. 41 00:04:34,940 --> 00:04:49,080 As shown in the picture, if the user wants to update the age information in the Node.js web, he can send his data either via a standard query stream in the URL or a JSON stream in the request body. 42 00:04:49,140 --> 00:05:02,720 Upon receiving the request, the web application will convert the JSON data or the query stream data into an object so that the object can further propagate in the program logics. 43 00:05:03,380 --> 00:05:09,280 Okay, so basically this is how the object sharing is carried out in Node.js ecosystems. 44 00:05:09,280 --> 00:05:25,680 Usually, if we want to evaluate the security of such a program, we may want to inject different payloads into the age field so that we can try to trigger certain vulnerabilities such as SQL injections or cross-site scripts. 45 00:05:26,660 --> 00:05:32,360 However, what if we choose not to test the existing data field? 46 00:05:32,800 --> 00:05:42,860 Since we can pass an object into the program, what will happen if we inject additional properties that are not expected to be received by the server program? 47 00:05:42,860 --> 00:05:58,220 In particular, if an attacker can send the properties that forge or override the certain internal program states, the attacker may easily obtain dangerous abilities to manipulate the key program logics. 48 00:05:59,500 --> 00:06:04,820 So we are going to introduce the hidden property abusing, HPA. 49 00:06:04,820 --> 00:06:12,680 So the hidden property abusing leverages the object sharing in Node.js to tamper or forge critical program states. 50 00:06:12,680 --> 00:06:24,200 We call the additional properties we inject as the hidden properties because these properties are kind of like some hidden parameters which is valid to the endpoint user API. 51 00:06:24,620 --> 00:06:29,480 These parameters are associated with certain internal program states. 52 00:06:29,480 --> 00:06:36,360 However, nobody knows their existence until an attacker leverages HPA to tamper the states. 53 00:06:37,000 --> 00:06:47,240 In this talk, we mainly focus on the server-side scenarios where a remote attacker wants to attack the Node.js web applications or some microservices. 54 00:06:47,420 --> 00:06:56,980 To explore the vulnerabilities, the attacker will access the legitimate interfaces such as the web API endpoint to send his payloads. 55 00:06:56,980 --> 00:07:07,040 In most cases, the attacker payloads should be in the form of planned object, which is the simplest object representation in Node.js. 56 00:07:08,860 --> 00:07:15,280 During our research, we discovered two types of typical attack vectors of HPA. 57 00:07:15,660 --> 00:07:20,400 We call the first one as the app-specific attribute manipulation. 58 00:07:20,520 --> 00:07:27,000 This one is for manipulating certain internal properties defined by the application themselves. 59 00:07:27,000 --> 00:07:33,180 Search internal properties are supposed to be initialized and managed by their internal functions. 60 00:07:33,180 --> 00:07:39,140 However, they usually represent certain internal states of the programs. 61 00:07:39,240 --> 00:07:49,060 So as shown in the picture, the INIT row is an internal function that is responsible for maintaining the access right on the user object. 62 00:07:49,300 --> 00:07:56,360 However, with HPA, the attacker can propagate a conflicting name property to the user object. 63 00:07:56,360 --> 00:08:01,720 And thus control the internal states of the program. 64 00:08:01,900 --> 00:08:08,260 As shown in the picture, the program also provides an API called update. 65 00:08:08,260 --> 00:08:10,740 This is for external usage. 66 00:08:11,060 --> 00:08:29,660 However, if a malicious user injects additional key-value pair, which is access and admin in the picture to the API, then the additional properties will override the existing access right. 67 00:08:30,000 --> 00:08:42,760 So this payload is pretty useful when we want to abuse certain concrete logics in large applications, such as some older information or user-privileged any management logics. 68 00:08:43,340 --> 00:08:50,240 Also, HPA can target some unique JavaScript schemes, such as prototyping. 69 00:08:50,240 --> 00:08:55,420 We call the second attack scenarios as prototype inheritance hijacking. 70 00:08:56,220 --> 00:09:00,700 In JavaScript, every object has a link to a prototype object. 71 00:09:00,860 --> 00:09:17,260 When the JavaScript code wants to access a property of an object, the property will not only be searched on the object, but also the prototype of the object, and even the prototype of the prototype, until a property with a matching name is found. 72 00:09:17,740 --> 00:09:29,160 As shown in the picture, when the JavaScript code wants to get the constructor property from the input object, it will first search locally within the input object. 73 00:09:29,160 --> 00:09:40,060 Since there is no property named constructor here, the code will continually search to his prototype, where the constructor is really located. 74 00:09:40,760 --> 00:09:49,700 So with HPA, we can hijack the inheritance chain and forge our own payloads as the internal properties on the chain. 75 00:09:49,900 --> 00:09:57,120 As shown in the picture, if we inject a property named constructor, the search process will be very different. 76 00:09:57,120 --> 00:10:09,180 Since there is already a property named constructor within the input object, the search will immediately stop and end up with retaining a user-controlled value. 77 00:10:09,300 --> 00:10:18,600 As demonstrated in the red circle, the value of the constructor will become a string, rig and multi, rather than a normal JavaScript function. 78 00:10:19,280 --> 00:10:34,700 So the second attack vector is really useful because we found many JavaScript developers tend to trust the properties inherited from prototypes and make many security-sensitive decisions based on them. 79 00:10:34,940 --> 00:10:42,220 Also, we should be aware of the differences between these attack vectors with the prototype pollution. 80 00:10:42,240 --> 00:10:45,900 The two attacks are totally different. 81 00:10:45,900 --> 00:10:52,540 The prototype pollution, as the name suggests, is about tampering the prototype object. 82 00:10:52,540 --> 00:10:58,760 However, our attack vector does not modify the prototype object. 83 00:11:00,650 --> 00:11:12,610 The root cause of the HPA is that the Node.js fails to isolate the unsafe object, such as the user input, from the critical internal states. 84 00:11:13,030 --> 00:11:29,770 So, to make a clear classification, the HPA can be seen as a new security risk under the Common Weakness Category 915, whose child variants are all about improper modification of the dynamic object attributes. 85 00:11:30,290 --> 00:11:40,730 As shown in the hierarchy tree on the right, there are some similar issues on other language platforms, such as Ruby Math Assignment, the PHP Object Injections. 86 00:11:40,870 --> 00:11:51,930 Although these variants share the same behavior feature dominated by 915, they all have their own data patterns due to the language differences. 87 00:11:52,170 --> 00:12:02,810 For example, the Ruby Math Assignment is a set of vulnerabilities discovered in widely used Ruby web application framework called Ruby on Rails. 88 00:12:03,170 --> 00:12:08,190 Unlike HPA, the attacker does not pass objects into the program. 89 00:12:08,190 --> 00:12:20,110 Instead, the attacker abuses a framework-specific assignment feature in Ruby on Rails to modify certain existing objects on the right side of the assignment. 90 00:12:20,170 --> 00:12:24,150 And the payloads between the two attacks are also different. 91 00:12:24,190 --> 00:12:27,430 The Math Assignment payloads are literal value. 92 00:12:27,430 --> 00:12:34,810 However, HPA can introduce hidden properties with either literal value or nested object form. 93 00:12:34,810 --> 00:12:43,210 More importantly, the Ruby is strongly typed, so the Math Assignment vulnerabilities cannot introduce new properties to the objects. 94 00:12:43,210 --> 00:12:52,210 However, the HPA can inject arbitrary properties, which make HPA really flexible and powerful. 95 00:12:53,710 --> 00:13:00,940 OK, so with several pages of concept introduction, I think it's time we can hack some real targets. 96 00:13:01,440 --> 00:13:08,340 In this example, we target at a popular web framework named Routing Controller. 97 00:13:08,360 --> 00:13:19,500 We will attack its official example code to demonstrate an end-to-end prototype inheritance hijack exploit, from security check bypassing to cycle injection. 98 00:13:20,340 --> 00:13:24,820 The figure on the right can give you a brief idea on how our example works. 99 00:13:24,820 --> 00:13:30,060 In the example, a server program is deployed using Routing Controllers. 100 00:13:30,680 --> 00:13:37,300 If a remote user wants to authenticate with the server, his data will flow into the following components. 101 00:13:37,420 --> 00:13:43,140 First, he will send his serialized data into the authentication module. 102 00:13:43,220 --> 00:13:52,280 Then, the authentication module will instantiate the objects according to the JSON he provides and send it to the param handler. 103 00:13:52,280 --> 00:13:57,080 Here, we use the green box to demonstrate the user data objects. 104 00:13:57,080 --> 00:14:03,320 The param handler is responsible for ensuring user input object is not malicious. 105 00:14:03,620 --> 00:14:18,320 The handler will first collect internal format specification object, which is the blue box in the picture, and he will merge the specification with the input object and invoke the input validation API. 106 00:14:18,320 --> 00:14:25,220 The input validation API will sanitize the user input data according to the format specification. 107 00:14:25,300 --> 00:14:30,020 In this case, it will check if the email field is legitimate or not. 108 00:14:30,020 --> 00:14:35,320 If the check passes, the user object will flow into the database. 109 00:14:35,600 --> 00:14:38,100 Okay, so this is the overall data flow. 110 00:14:38,100 --> 00:14:42,140 Let's analyze how we can attack the logic step by step. 111 00:14:43,000 --> 00:14:57,320 So, the first step is the hidden property injection, in which the malicious attacker injects hidden properties in his request, which is the constructor in this case. 112 00:14:57,320 --> 00:15:13,580 As shown in the picture, when the server program instantiates the user object, there will be an additional property named the constructor, which is a payload for bypassing the input validation module. 113 00:15:13,580 --> 00:15:20,820 So, in the second step, the program will prepare the parameters needed by the input validation API. 114 00:15:20,820 --> 00:15:29,280 The server program will merge the user input, which is the param, with an object named the schema. 115 00:15:29,280 --> 00:15:36,900 The merging operation is carried out by putting every property from the param objects into the schema object. 116 00:15:36,900 --> 00:15:41,280 So, this process is very much like object assignment. 117 00:15:41,280 --> 00:15:47,280 To simplify the demonstration, let's just use object assignment in this example. 118 00:15:47,360 --> 00:15:55,060 By performing such merging operations, the hidden property constructor will also transform to the schema. 119 00:15:55,540 --> 00:16:02,440 And after the transformation, we now can hijack the inheritance of the constructor on the schema. 120 00:16:02,440 --> 00:16:09,460 Actually, the constructor of the schema plays a very important role in the input validation module. 121 00:16:09,460 --> 00:16:19,120 As shown in the picture, the constructor actually stores the important format restriction information. 122 00:16:19,120 --> 00:16:27,900 As a result, the merging operation enables us to hijack the inheritance of these important format restrictions. 123 00:16:27,900 --> 00:16:38,860 As shown in the picture, when the constructor is read by the getSchema function, our hidden property will be immediately matched and returned to the code. 124 00:16:38,860 --> 00:16:49,700 To bypass the input validation, we just need to set the format specification as an invalid value, so that our SQL injection payload can escape the check. 125 00:16:50,020 --> 00:16:53,740 Now, the last step is much more straightforward. 126 00:16:53,740 --> 00:16:59,600 The validate payload then flows into the sensitive API to finish the entire attack. 127 00:16:59,720 --> 00:17:03,960 So, this is how an entire HPA chain looks like. 128 00:17:03,960 --> 00:17:09,040 Actually, the code logics behind vulnerability is much more complex. 129 00:17:09,040 --> 00:17:17,320 For example, the input validation module contains 30,000 lines of code. 130 00:17:17,320 --> 00:17:27,980 So, it would be helpful if we can find a tool that automatically track these data structures and discover time for hidden properties exist in the program logics. 131 00:17:28,700 --> 00:17:31,920 So, what are the challenges of building such a tool? 132 00:17:31,920 --> 00:17:34,060 First of all, it is JavaScript. 133 00:17:34,060 --> 00:17:38,180 Analyzing JavaScript is known to be hard due to the dynamic nature. 134 00:17:39,160 --> 00:17:46,320 And second, HPA is a tech that creates unexpected and new data dependencies. 135 00:17:46,360 --> 00:17:56,080 However, program analysis, such as data flow tracking, is mainly for analyzing the existing flows. 136 00:17:56,080 --> 00:18:02,340 Third, from our run examples, we can observe that HPA tampers internal program states. 137 00:18:02,760 --> 00:18:08,260 So, the attack effects highly depend on the roles of the compromised states. 138 00:18:08,260 --> 00:18:11,020 This makes the detection more challenging. 139 00:18:11,440 --> 00:18:22,420 To overcome these challenges, we design and implement Lynx, a hybrid JavaScript program analysis tool, to detect and exploit HPA vulnerabilities. 140 00:18:22,700 --> 00:18:25,300 Lynx mainly consists of two components. 141 00:18:26,160 --> 00:18:31,980 The first component on the left is for identifying potential hidden properties. 142 00:18:31,980 --> 00:18:43,440 It combines dynamic data flow tracking and static synthetics analysis to track all the user input and infer potential candidates. 143 00:18:43,440 --> 00:18:50,400 And the component on the right is for detecting the harmful hidden properties and generating exploits for them. 144 00:18:50,400 --> 00:19:01,360 To help future Node.js security research, we decided to open-source our Lynx project at the GitHub links in the bottom. 145 00:19:02,100 --> 00:19:08,920 So, if you are interested in the technical details, you can check it in the GitHub report. 146 00:19:09,760 --> 00:19:14,660 So, the very first thing Lynx will do is dynamic data flow tracking. 147 00:19:14,660 --> 00:19:22,520 First of all, Lynx will generate a label object, which is a unique key and value piv. 148 00:19:22,980 --> 00:19:27,880 Lynx will inject the label into the input data of the program. 149 00:19:28,300 --> 00:19:38,040 Since different properties from the input object may flow into different program logics, we want to track all these propagations. 150 00:19:38,040 --> 00:19:43,820 So, we perform the label injection in a recursive manner. 151 00:19:43,900 --> 00:19:53,640 That is, as shown in the picture on the left, Lynx will generate three different inputs by label injecting the original test case. 152 00:19:53,640 --> 00:19:57,980 In each time, Lynx will inject the label into our different properties. 153 00:19:58,740 --> 00:20:03,280 After the injection, Lynx will observe the program execution. 154 00:20:03,280 --> 00:20:10,380 We leverage a JavaScript analysis framework called Jalanki to instrument our test programs. 155 00:20:10,380 --> 00:20:18,500 Since we are studying the data flow, we instrument the variable reads and writes, object property indexing and function calls. 156 00:20:18,500 --> 00:20:21,060 Then, we execute the test program. 157 00:20:21,060 --> 00:20:26,040 During the execution, Lynx will examine every object within the data flow. 158 00:20:26,040 --> 00:20:32,520 If an object can't carry our property labels, we will record it for further analysis. 159 00:20:33,440 --> 00:20:37,380 So now we have a list of property carriers. 160 00:20:37,580 --> 00:20:46,080 Record that an object is flagged as a property carrier because we detect our injected label under his body. 161 00:20:46,080 --> 00:20:56,420 So if we can propagate our label here, maybe we can also propagate another malicious property here also. 162 00:20:56,420 --> 00:21:09,360 More specifically, if we can inject a property that has a conflicting name with certain internal properties the program has, maybe we can control that property by overwriting them. 163 00:21:10,840 --> 00:21:22,340 So now we want to extract all the child properties from the original programs of the property carriers and flag them as hidden property candidates. 164 00:21:22,340 --> 00:21:32,040 To achieve this goal, we need static syntax analysis to extract the necessary syntactic information from the code. 165 00:21:32,040 --> 00:21:37,460 The picture on the right demonstrates how we parse our statement from our running example. 166 00:21:37,460 --> 00:21:45,500 Lynx will traverse the syntax tree until reaching a property carrier, which is circled by the red line in the graph. 167 00:21:45,500 --> 00:21:49,520 Then it records all the properties under the carrier. 168 00:21:49,520 --> 00:21:53,800 In our case, the hidden property candidate is the constructor. 169 00:21:55,780 --> 00:22:01,140 So here is an output screenshot of the first component. 170 00:22:01,140 --> 00:22:10,800 As you can observe, the Lynx will first instrument the code base, and then we tracked 43 property carriers. 171 00:22:10,800 --> 00:22:17,940 As indicated by the red circle, Lynx successfully detects a hidden property named constructor. 172 00:22:19,520 --> 00:22:25,240 So in the previous component, we discovered the key name of the potential hidden properties. 173 00:22:25,240 --> 00:22:30,440 By injecting the property with the same key, we might overwrite certain internal states. 174 00:22:30,440 --> 00:22:36,240 However, we still don't know whether the candidates can be controlled or not. 175 00:22:36,240 --> 00:22:41,200 And we also don't know how to introduce attack effects with these candidates. 176 00:22:41,220 --> 00:22:44,340 So apparently, Lynx could do more. 177 00:22:46,060 --> 00:22:54,260 Let's revisit our running example to see if there is any insights to help us to design such an exploitation component. 178 00:22:54,340 --> 00:22:58,980 The figure on the left is the vulnerable code from our running example. 179 00:22:58,980 --> 00:23:09,960 As we have discussed many times, hidden property tampers internal program states, which means HPA exploitation highly relates it to the code context. 180 00:23:10,060 --> 00:23:15,400 So it is important to conclude a set of vulnerable sensitive behaviors. 181 00:23:15,400 --> 00:23:24,880 These behaviors should clearly indicate certain security consequences, so that we can decouple the harmfulness detection from the code context. 182 00:23:24,880 --> 00:23:31,760 Also, from the running example, the exploitation is mainly about manipulating the return result. 183 00:23:32,540 --> 00:23:36,660 More specifically, there are two possible paths here. 184 00:23:36,660 --> 00:23:43,400 If the execution enters the branch on line 19, we will get a validation failed. 185 00:23:43,400 --> 00:23:49,100 But if we can go into the line 21, we can successfully pass the check. 186 00:23:49,100 --> 00:24:00,100 So the exploitation point and the override point may not be the same place, which means we shouldn't stop our analysis at line 11. 187 00:24:00,100 --> 00:24:07,440 Instead, we should continue exploring all the possible paths that can be triggered by manipulating the hidden properties. 188 00:24:08,420 --> 00:24:13,580 So we studied and concluded six general types of sensitive things. 189 00:24:14,560 --> 00:24:19,960 Due to the time constraint, I will not introduce the details of each type. 190 00:24:19,960 --> 00:24:23,600 If you want to know more, you can check our Git report. 191 00:24:24,960 --> 00:24:36,420 So after defining our sensitive things, we want the hidden property to trigger as many as possible branches, and monitor whether we can hit a sink. 192 00:24:36,420 --> 00:24:42,480 To achieve this goal, we use symbolic execution to explore all the hidden property value space. 193 00:24:42,480 --> 00:24:49,920 Lynx first generates an exploit template that can reach the potential hidden vulnerable property. 194 00:24:50,080 --> 00:25:01,180 We denote such data structure as an exploit template, because Lynx does not specify a concrete value in the input. 195 00:25:01,180 --> 00:25:08,840 Instead, we insert a special placeholder, which will be used by the symbolic execution later on. 196 00:25:08,840 --> 00:25:18,020 Then, we run the test program with our constructed templates, and symbolically execute the hidden property. 197 00:25:18,020 --> 00:25:43,860 As shown in the picture, the Lynx will explore all the path constraints along the input path, and if Lynx finds that it has hit a sink, for example, in this example, it hit the sink i2, then he will fetch the corresponding payload that can trigger the sink as the final exploit. 198 00:25:44,240 --> 00:25:55,540 So a little background about the sink i2 is the sink we define to detect that whether our input can manipulate the return value of a module or not. 199 00:25:57,990 --> 00:26:01,610 So this is the output of the exploit module. 200 00:26:01,610 --> 00:26:09,790 From the circled area, we can observe that the key value pair constructN1 triggered the sink i2. 201 00:26:09,870 --> 00:26:19,270 In the last line, we can find that the Lynx successfully bypassed the generator exploit that can lead to the successful validation. 202 00:26:19,710 --> 00:26:23,010 So this is pretty much about how our system works. 203 00:26:23,010 --> 00:26:26,850 Let's see some interesting new results of our research. 204 00:26:26,850 --> 00:26:33,150 During our research, we choose 60 widely used programs from Node NPM. 205 00:26:33,150 --> 00:26:36,690 There are 55 modules and 5 web applications. 206 00:26:36,990 --> 00:26:49,330 And with the help of Lynx, we tracked more than 1,300 carriers, and detected more than 300 hidden property candidates associated with those carriers. 207 00:26:49,330 --> 00:26:53,130 In the end, we confirmed 13 zero-day vulnerabilities. 208 00:26:53,130 --> 00:26:59,510 With the help of symbolic execution, Lynx even synthesized 10 exploits automatically. 209 00:27:00,310 --> 00:27:03,630 So how is the impact of these vulnerabilities? 210 00:27:03,670 --> 00:27:15,030 We found that HPA can introduce various attack effects, such as leaking credential data, denial of services, or bypassing security checks. 211 00:27:15,030 --> 00:27:26,670 Based on the impact analysis, we can observe that the HPA can compromise previously unreachable program states, which effectively enlarge the attack surface. 212 00:27:26,850 --> 00:27:36,730 Even more, we could notice that HPA is not a simple input validation issue, and many input validators themselves are also vulnerable to HPA. 213 00:27:37,170 --> 00:27:45,230 So in the following slides, I will pick up two interesting vulnerabilities from our results and case study them. 214 00:27:45,910 --> 00:27:49,970 So the first case comes from MongoDB official driver. 215 00:27:49,970 --> 00:27:54,930 We found that we can tamper an internal state named the BSON type. 216 00:27:55,090 --> 00:28:05,270 Our background here is that the MongoDB leveraged the internal state BSON type to indicate the data type of the query object. 217 00:28:05,270 --> 00:28:13,190 However, when serializing the query object, MongoDB will ignore the object with unknown BSON type. 218 00:28:13,330 --> 00:28:18,270 So what if we abuse the logic for a query condition object? 219 00:28:18,270 --> 00:28:22,530 The code on the right is from an open source online game. 220 00:28:22,530 --> 00:28:27,610 The online game used a vulnerable API to implement the user management logics. 221 00:28:27,650 --> 00:28:42,730 As shown in the picture, by injecting the unknown BSON type to the input, the attacker can force the MongoDB not serializing the query object condition, so that the MongoDB will always return the first user on top of the database. 222 00:28:42,730 --> 00:28:51,190 With this ability, the attacker can log in or delete arbitrary accounts. 223 00:28:52,590 --> 00:28:57,250 The second case is from another widely used in-memory database. 224 00:28:57,250 --> 00:29:02,990 The hidden property is more like a backdoor which helps the user accessing the sensitive data. 225 00:29:02,990 --> 00:29:14,010 In TafiDB, we discover a hidden property named id, which is an internal index for each database data item. 226 00:29:14,010 --> 00:29:24,370 Once we specify our own id in the query, TafiDB will ignore other query conditions and directly return the result associated with the index. 227 00:29:24,370 --> 00:29:37,670 As shown in the picture, even though we got wrong password and username, we can still leak the valid user data from the database with our crafted hidden properties. 228 00:29:38,450 --> 00:29:40,690 Thanks for attending our talk. 229 00:29:40,690 --> 00:29:43,430 I hope you guys keep safe in this special year.