1 00:00:00,120 --> 00:00:02,580 - Welcome to the five o'clock track three. 2 00:00:02,580 --> 00:00:06,150 Unfortunately, Orange Tsai cannot be here today. 3 00:00:06,150 --> 00:00:09,180 However, we are going to try to stream, 4 00:00:09,180 --> 00:00:11,730 I'm sorry, play his presentation for you guys. 5 00:00:11,730 --> 00:00:12,663 Alright, enjoy. 6 00:00:13,590 --> 00:00:16,620 - Hi, sorry, I couldn't be on the stage 7 00:00:16,620 --> 00:00:19,143 because of the issue of the visa. 8 00:00:20,010 --> 00:00:23,913 I hope one day we can meet face to face in Vegas. 9 00:00:25,680 --> 00:00:27,690 About 10 years ago, 10 00:00:27,690 --> 00:00:32,130 I failed my algorithm course at university, 11 00:00:32,130 --> 00:00:35,850 but I'm now here to talk about a Hash Table. 12 00:00:35,850 --> 00:00:38,673 This is a big achievement for me. 13 00:00:40,050 --> 00:00:45,050 I'm Orange and today my topic is, Let's Dance in the Cache, 14 00:00:45,750 --> 00:00:49,387 Destabilizing Hash Table on Microsoft IIS. 15 00:00:52,523 --> 00:00:56,523 Before the talk, I would like to give you a short case, 16 00:00:57,360 --> 00:01:00,450 if there is the super secret area, 17 00:01:00,450 --> 00:01:03,513 creator is protected by a super secure password. 18 00:01:05,490 --> 00:01:09,813 You cannot login, only if you know this long password. 19 00:01:11,640 --> 00:01:14,763 However, under the design of IIS, 20 00:01:17,010 --> 00:01:21,350 all of this passwords are valid 21 00:01:21,350 --> 00:01:23,613 and can log into the system. 22 00:01:24,780 --> 00:01:26,340 Amazing, right? 23 00:01:26,340 --> 00:01:30,273 I guess you might have several questions in your mind. 24 00:01:31,380 --> 00:01:35,760 This is one of the attacks I will present today, 25 00:01:35,760 --> 00:01:38,703 and you will learn the details later. 26 00:01:41,700 --> 00:01:43,290 Hi, I'm Orange 27 00:01:43,290 --> 00:01:48,270 and now the principal security researcher at DEVCORE. 28 00:01:48,270 --> 00:01:50,280 I am a zero day researcher 29 00:01:50,280 --> 00:01:53,793 and focusing on web and vacation security. 30 00:01:55,200 --> 00:01:59,310 My job is to discover the most severe bugs, 31 00:01:59,310 --> 00:02:00,720 in the tech service, 32 00:02:00,720 --> 00:02:05,013 that can impact the world ahead of the bad guys. 33 00:02:05,880 --> 00:02:10,140 My research has also received several awards, 34 00:02:10,140 --> 00:02:15,140 such as the best server-side bug of the Pwine awards, 35 00:02:15,150 --> 00:02:17,433 and the champion of Pwn2Own. 36 00:02:18,690 --> 00:02:22,380 If you are interested, you are welcome to follow my Twitter 37 00:02:22,380 --> 00:02:24,213 or chat with me later. 38 00:02:27,390 --> 00:02:29,790 This is the outline today. 39 00:02:29,790 --> 00:02:34,790 First we will introduce several essential concepts. 40 00:02:35,010 --> 00:02:36,990 Those concepts are important 41 00:02:36,990 --> 00:02:41,990 to let you into Microsoft IIS internals and our topic today, 42 00:02:44,100 --> 00:02:48,240 after having a good understanding of IIS internal 43 00:02:48,240 --> 00:02:50,550 and a cache mechanism, 44 00:02:50,550 --> 00:02:53,580 we will elaborate on our research, 45 00:02:53,580 --> 00:02:57,903 followed by three different types of vulnerabilities. 46 00:02:59,400 --> 00:03:03,870 Also, we will demonstrate how we apply a text 47 00:03:03,870 --> 00:03:07,713 to Microsoft exchange server, as a showcase. 48 00:03:09,330 --> 00:03:13,770 Of course, we will provide mitigations, recommendations 49 00:03:13,770 --> 00:03:17,043 and future works to those components. 50 00:03:19,800 --> 00:03:23,373 So first one is the hash table. 51 00:03:24,900 --> 00:03:28,470 Hash table is the most fundamental data structure 52 00:03:28,470 --> 00:03:30,870 in computer science. 53 00:03:30,870 --> 00:03:34,713 And it's purposes is to store data. 54 00:03:35,940 --> 00:03:38,370 No matter what the data is, 55 00:03:38,370 --> 00:03:42,063 hash table can hold a data in memory very well. 56 00:03:43,410 --> 00:03:48,410 Hash table is especially good at handling the key value pair 57 00:03:49,530 --> 00:03:53,433 and can operate data with the high performance. 58 00:03:55,210 --> 00:03:59,090 Due to those benefits hash table is used extensively 59 00:04:00,090 --> 00:04:05,090 in computer infrastructures, such as the operating system, 60 00:04:05,790 --> 00:04:09,843 programming language, database or web server. 61 00:04:12,660 --> 00:04:15,930 Here is an example of the hash table usage 62 00:04:15,930 --> 00:04:17,583 in programming language. 63 00:04:18,510 --> 00:04:22,290 Programming language uses the hash table widely, 64 00:04:22,290 --> 00:04:26,940 however you don't know because they write the hash table 65 00:04:26,940 --> 00:04:29,250 into a more high level structure 66 00:04:29,250 --> 00:04:34,200 such as the array, dictionary or object. 67 00:04:34,200 --> 00:04:39,200 So if you are a developer, you must have used hash table. 68 00:04:41,760 --> 00:04:42,870 As the internal, 69 00:04:42,870 --> 00:04:47,870 I assume that everyone here is a good student at university, 70 00:04:48,420 --> 00:04:52,053 so I skipped the hash table internal this time. 71 00:04:55,290 --> 00:04:58,473 As for what is the hash-flooding attack. 72 00:04:59,340 --> 00:05:03,990 Also, we are not going to talk about this attack only. 73 00:05:03,990 --> 00:05:06,150 We still give it a slot 74 00:05:06,150 --> 00:05:09,980 because I believe that the hash-flooding attack 75 00:05:09,980 --> 00:05:12,930 is the best case to learn the mindset 76 00:05:12,930 --> 00:05:16,743 of how an attacker abuses the hash table. 77 00:05:19,290 --> 00:05:21,660 The idea of hash-flooding attack 78 00:05:21,660 --> 00:05:25,443 is to drop all the records into the same bucket, 79 00:05:26,940 --> 00:05:29,970 since the hash algorithm is public 80 00:05:29,970 --> 00:05:33,390 and attacker can predict its hash 81 00:05:33,390 --> 00:05:37,173 and make all records for it into the same bucket. 82 00:05:38,360 --> 00:05:42,720 At the time, the attacker degenerate the hash table, 83 00:05:42,720 --> 00:05:47,583 which can store numbers, records, into a single link list. 84 00:05:50,520 --> 00:05:53,580 For example, the attacker has crafted 85 00:05:53,580 --> 00:05:56,823 several malicious records on the left side. 86 00:05:58,140 --> 00:06:01,290 The hash function in the middle will process 87 00:06:01,290 --> 00:06:04,353 and convert the record into an index. 88 00:06:06,810 --> 00:06:10,650 The first record is convert to the index four 89 00:06:10,650 --> 00:06:13,293 and put into the corresponding bucket. 90 00:06:15,780 --> 00:06:18,603 The second is also put into the same bucket. 91 00:06:21,510 --> 00:06:22,623 The third, 92 00:06:23,850 --> 00:06:24,683 the fourth, 93 00:06:26,490 --> 00:06:28,110 the fifth, 94 00:06:28,110 --> 00:06:33,110 and the attacker can drop all records into the same bucket 95 00:06:35,160 --> 00:06:38,643 and the table now becomes a single link list. 96 00:06:41,250 --> 00:06:43,650 So the hash-flooding attack 97 00:06:43,650 --> 00:06:48,630 can make the table always sit on the worst case. 98 00:06:48,630 --> 00:06:53,280 That means for inserting and records, 99 00:06:53,280 --> 00:06:57,510 the time complexity comes to n squared. 100 00:06:57,510 --> 00:07:00,180 We should all agree that n squared 101 00:07:00,180 --> 00:07:03,333 is in a terrible performance. 102 00:07:05,940 --> 00:07:09,570 Okay, we have a good understanding of the hash table, 103 00:07:09,570 --> 00:07:11,970 let's discuss the relationship 104 00:07:11,970 --> 00:07:14,313 between the hash table and IIS. 105 00:07:17,190 --> 00:07:20,523 First, IIS loves hash table. 106 00:07:22,606 --> 00:07:26,610 As the well known and only web server in windows, 107 00:07:26,610 --> 00:07:31,610 IIS uses the hash table extensively in it's architecture 108 00:07:32,310 --> 00:07:36,120 to store information such as HTTP headers, 109 00:07:36,120 --> 00:07:40,623 server variables, configuration, and cache. 110 00:07:43,290 --> 00:07:46,890 Due to the massive use of this data structure, 111 00:07:46,890 --> 00:07:51,450 Microsoft has designed its own hash table implementation 112 00:07:51,450 --> 00:07:54,420 from a very early stage. 113 00:07:54,420 --> 00:07:57,690 The following two are older implementation 114 00:07:57,690 --> 00:08:00,810 that will be used in IIS. 115 00:08:00,810 --> 00:08:03,600 One is called Tree Hash Table, 116 00:08:03,600 --> 00:08:06,993 and the other is called LKR Hash Table. 117 00:08:09,780 --> 00:08:13,320 The tree hash table should be the most common, 118 00:08:13,320 --> 00:08:17,460 like the simple code in your textbooks 119 00:08:17,460 --> 00:08:20,940 and use the linked list to resolve the collision 120 00:08:20,940 --> 00:08:25,743 and rehash the table, when it's in an unhealthy state. 121 00:08:27,060 --> 00:08:31,140 The rehash is a series of reviewing process. 122 00:08:31,140 --> 00:08:34,170 It first enlarges the table, 123 00:08:34,170 --> 00:08:39,170 recovers all records and reposition them to their new index. 124 00:08:41,820 --> 00:08:44,700 As for what hash function is used, 125 00:08:44,700 --> 00:08:47,763 we will have a future discussion later. 126 00:08:51,150 --> 00:08:54,270 The other table is the LKR hash. 127 00:08:54,270 --> 00:08:58,440 An implementation that aims to build a scalable 128 00:08:58,440 --> 00:09:03,440 and high concurrent hash table in a multicore environment. 129 00:09:05,370 --> 00:09:10,323 The name LKR is an acronym for the name of the creators. 130 00:09:11,250 --> 00:09:15,900 This implementation was also patented by Microsoft in 1999. 131 00:09:18,013 --> 00:09:23,013 The LKRHash is the successor of linear hashing, 132 00:09:23,040 --> 00:09:27,210 which is used another better algorithm to resolve the 133 00:09:27,210 --> 00:09:31,383 expansive rehash, to enhance the performance. 134 00:09:32,370 --> 00:09:35,430 The creators put a lot of effort 135 00:09:35,430 --> 00:09:40,430 to make this implementation portable, flexible, and usable. 136 00:09:41,880 --> 00:09:46,880 The application can define its own table related functions 137 00:09:47,280 --> 00:09:51,363 to adapt to multiple products across Microsoft. 138 00:09:52,920 --> 00:09:56,440 It's interesting to note that part of the creators 139 00:09:57,480 --> 00:09:59,640 are also the IIS developer, 140 00:10:00,660 --> 00:10:04,500 which should be the reason why we find less of this 141 00:10:04,500 --> 00:10:06,397 implementation in IIS. 142 00:10:10,302 --> 00:10:14,340 Now we have a complex understanding of the hash table, 143 00:10:14,340 --> 00:10:17,283 it's time to go deep into our research. 144 00:10:18,390 --> 00:10:22,410 In this section, we will show the IIS internals 145 00:10:22,410 --> 00:10:25,803 and define the scope we really care about. 146 00:10:26,850 --> 00:10:31,850 We will first explain our mindset and idea to uncover bugs. 147 00:10:33,030 --> 00:10:37,200 We are mainly focusing on the hash table implementation 148 00:10:37,200 --> 00:10:39,570 and its usage. 149 00:10:39,570 --> 00:10:43,380 Since most of the hash tables that are used in IIS 150 00:10:43,380 --> 00:10:45,210 are cache related, 151 00:10:45,210 --> 00:10:49,083 we also study and look into it's mechanism. 152 00:10:52,260 --> 00:10:56,160 Because Microsoft has design its own hash table 153 00:10:56,160 --> 00:10:58,110 without open source. 154 00:10:58,110 --> 00:11:01,590 The implementation should be an explored area 155 00:11:01,590 --> 00:11:03,333 to discover bugs. 156 00:11:04,260 --> 00:11:09,260 So in this context we find, not only for memory corruption, 157 00:11:10,260 --> 00:11:12,483 but also logic bugs. 158 00:11:13,890 --> 00:11:18,870 Here I would like to highlight the bug CVE-2006-3017, 159 00:11:20,670 --> 00:11:24,243 it's a logic bug in the unset function of the PHP. 160 00:11:26,670 --> 00:11:28,800 The hash table implementation 161 00:11:28,800 --> 00:11:32,520 didn't distinguish the key type of an array 162 00:11:32,520 --> 00:11:36,900 so that an attacker can delete arbitrary elements 163 00:11:36,900 --> 00:11:38,733 with an index number. 164 00:11:40,140 --> 00:11:43,200 When I saw this bug it amazed me 165 00:11:43,200 --> 00:11:46,953 and I believe this is just the bug I'm looking for. 166 00:11:48,930 --> 00:11:50,640 Of course, we also look for 167 00:11:50,640 --> 00:11:53,160 the algorithm complexity problems, 168 00:11:53,160 --> 00:11:55,683 such as the hash-flooding attack. 169 00:11:57,150 --> 00:12:02,150 However, since it's already a 20 years old attack, 170 00:12:02,220 --> 00:12:05,793 most of the lower hanging fruit should be disappeared. 171 00:12:06,720 --> 00:12:08,790 So in this context, 172 00:12:08,790 --> 00:12:12,243 we put more effort into the implementation. 173 00:12:15,240 --> 00:12:17,760 As for the usage, we mentioned that 174 00:12:17,760 --> 00:12:21,090 the LKRHash is decided to be a portable, 175 00:12:21,090 --> 00:12:25,590 flexible, and easy to use algorithm 176 00:12:25,590 --> 00:12:28,683 that can be applied to any situation. 177 00:12:30,060 --> 00:12:32,940 The convention requires the application 178 00:12:32,940 --> 00:12:37,050 to configure its own table related function 179 00:12:37,050 --> 00:12:38,823 during initialization. 180 00:12:39,720 --> 00:12:44,720 This kind of extensibility gives us more opportunities 181 00:12:44,850 --> 00:12:46,563 to uncover bugs. 182 00:12:47,400 --> 00:12:51,270 When I saw this, I was curious that 183 00:12:51,270 --> 00:12:53,913 is the particular function good? 184 00:12:54,810 --> 00:12:57,540 Is the key calculation good? 185 00:12:57,540 --> 00:13:02,100 Or how does the function select the correct record 186 00:13:02,100 --> 00:13:04,113 when a collision happens? 187 00:13:05,430 --> 00:13:10,200 These types of questions all interested me. 188 00:13:10,200 --> 00:13:15,200 So in this context, we care more about the relationship 189 00:13:16,200 --> 00:13:20,073 between the record, the key and the function. 190 00:13:23,430 --> 00:13:26,670 When an HTTP request is coming, 191 00:13:26,670 --> 00:13:29,310 the kernel HTTP assist 192 00:13:29,310 --> 00:13:34,233 will first handle the connection and dispatch the request. 193 00:13:36,750 --> 00:13:41,610 The kernel checks, if there is an active IIS worker, 194 00:13:41,610 --> 00:13:46,610 if not it knocks the IIS service to spawn a new process. 195 00:13:49,805 --> 00:13:53,580 The WAS, Windows Activation Service, 196 00:13:53,580 --> 00:13:56,130 first raise the configuration 197 00:13:56,130 --> 00:13:59,220 to note several specific caches 198 00:13:59,220 --> 00:14:01,470 for the process initialization 199 00:14:03,990 --> 00:14:06,333 and spawn the worker process. 200 00:14:08,070 --> 00:14:11,103 Several IIS components are loaded here. 201 00:14:13,920 --> 00:14:16,890 The worker then loads their modules, 202 00:14:16,890 --> 00:14:19,413 which are defined in the configuration. 203 00:14:22,743 --> 00:14:26,580 IIS, by default, loads several modules 204 00:14:26,580 --> 00:14:31,290 for different purposes, such as the compression, 205 00:14:31,290 --> 00:14:35,313 redirection, authentication and the cache. 206 00:14:38,310 --> 00:14:41,580 Among all modules, the following four 207 00:14:41,580 --> 00:14:44,220 are the global cache provider 208 00:14:44,220 --> 00:14:47,073 to manage the cache between modules. 209 00:14:48,602 --> 00:14:53,130 Each module is responsible for handling a different cache, 210 00:14:53,130 --> 00:14:56,610 such as the cache for static file, 211 00:14:56,610 --> 00:14:59,100 the cache for configuration 212 00:14:59,100 --> 00:15:01,323 and the cache for windows token. 213 00:15:04,410 --> 00:15:06,450 Once the modules are loaded, 214 00:15:06,450 --> 00:15:09,813 the worker enters the request life cycle. 215 00:15:10,980 --> 00:15:13,230 The life cycle is an event loop, 216 00:15:13,230 --> 00:15:17,583 that process all the notifications from the request. 217 00:15:20,160 --> 00:15:23,610 There are several events in a life cycle, 218 00:15:23,610 --> 00:15:27,960 the module can subscribe to its interesting events 219 00:15:27,960 --> 00:15:30,033 to compare it's logic. 220 00:15:33,000 --> 00:15:35,250 There are also global events 221 00:15:35,250 --> 00:15:38,700 that the module can subscribe to. 222 00:15:38,700 --> 00:15:42,570 For example, the cache provider subscribes to 223 00:15:42,570 --> 00:15:46,890 the event cache clean up and the cache operation 224 00:15:46,890 --> 00:15:49,893 to manage the cache between modules. 225 00:15:52,530 --> 00:15:55,440 So our research is not only focusing 226 00:15:55,440 --> 00:15:58,953 on the cache between the request life cycle, 227 00:16:00,180 --> 00:16:03,150 but also the global cache providers, 228 00:16:03,150 --> 00:16:06,993 especially those four, our golden targets. 229 00:16:10,890 --> 00:16:15,600 The following section is about our research and the bugs. 230 00:16:15,600 --> 00:16:20,100 In this section, we will first elaborate on our idea 231 00:16:20,100 --> 00:16:24,210 and the direction we are trying to fight bugs. 232 00:16:24,210 --> 00:16:28,560 We will attach three different types of vulnerabilities 233 00:16:28,560 --> 00:16:30,333 to prove our idea works. 234 00:16:31,872 --> 00:16:35,907 Our bugs include a hash flooding DoS, a cache poisoning, 235 00:16:37,650 --> 00:16:40,680 and authentication bypass. 236 00:16:40,680 --> 00:16:43,710 We will also talk about the exploitation 237 00:16:43,710 --> 00:16:48,710 of how we maximize the severity to make this bugs impactful. 238 00:16:51,513 --> 00:16:54,780 Of course, a real world authentication bypass 239 00:16:54,780 --> 00:16:57,120 on Microsoft exchange server 240 00:16:57,120 --> 00:16:59,853 will be detailed and damage checked. 241 00:17:03,060 --> 00:17:05,550 Okay, the first case we would like to share 242 00:17:05,550 --> 00:17:07,503 is a hash flooding DoS. 243 00:17:10,320 --> 00:17:13,110 First, we would like to give you a spoiler 244 00:17:13,110 --> 00:17:16,920 that all hash tables implemented by Microsoft 245 00:17:16,920 --> 00:17:20,403 are affected by hash flooding attack. 246 00:17:21,600 --> 00:17:25,170 The tree hash table is vulnerable by default 247 00:17:25,170 --> 00:17:28,473 and the LKR hash is vulnerable only, 248 00:17:30,377 --> 00:17:32,973 if a poor hash function is configured, 249 00:17:35,670 --> 00:17:39,993 However, vulnerable is not equal to exploitable. 250 00:17:41,070 --> 00:17:43,410 Besides finding the entry point, 251 00:17:43,410 --> 00:17:47,283 we still have several obstacles to overcome. 252 00:17:50,520 --> 00:17:55,323 We find that URI cache module seems to be a good target. 253 00:17:56,250 --> 00:17:58,170 The purpose of this module 254 00:17:58,170 --> 00:18:01,327 is to cache configuration for URLs 255 00:18:03,270 --> 00:18:06,750 because rate configuration is costly, 256 00:18:06,750 --> 00:18:10,173 so cache is the best strategy. 257 00:18:12,150 --> 00:18:13,140 In this module, 258 00:18:13,140 --> 00:18:18,000 every HTTP access triggers the cache operation 259 00:18:18,000 --> 00:18:20,550 and the most important thing is that 260 00:18:20,550 --> 00:18:25,503 the module uses tree hash table as its cache storage. 261 00:18:28,410 --> 00:18:32,550 Well an accessible by default tree hash table 262 00:18:32,550 --> 00:18:34,503 sounds good to us. 263 00:18:37,760 --> 00:18:41,880 This is the time chart of every thousand new records 264 00:18:41,880 --> 00:18:44,340 in tree hash table. 265 00:18:44,340 --> 00:18:48,930 Because it's not open sourced, we must reverse the structure 266 00:18:48,930 --> 00:18:53,727 and code the table dynamically to get the data set. 267 00:18:53,727 --> 00:18:58,650 The line in blue is the time of inserting random records 268 00:18:58,650 --> 00:19:02,763 and the line in orange is the records with collisions. 269 00:19:04,080 --> 00:19:06,060 You should be able to figure out 270 00:19:06,060 --> 00:19:09,843 there's the huge difference between the two lines. 271 00:19:12,660 --> 00:19:17,457 However, the jitters along 35,000 and 75,000 are weird. 272 00:19:21,210 --> 00:19:22,353 What's the jitter? 273 00:19:23,490 --> 00:19:26,820 Theoretically, the lines growth in orange 274 00:19:26,820 --> 00:19:28,893 should be in linear time. 275 00:19:29,880 --> 00:19:34,880 So what actually makes the time increase unsmoothly? 276 00:19:37,603 --> 00:19:39,753 The answer is rehash. 277 00:19:40,770 --> 00:19:44,223 This is the part of the insert operation. 278 00:19:45,180 --> 00:19:49,260 The implementation first traverse the linked list 279 00:19:49,260 --> 00:19:54,260 to ensure no duplicates and do it's internal job. 280 00:19:57,480 --> 00:20:02,130 However, after the internal add operation, 281 00:20:02,130 --> 00:20:06,453 there is a code to the function, rehash table is needed. 282 00:20:09,960 --> 00:20:13,410 The function checks the number of records 283 00:20:13,410 --> 00:20:15,180 and rehash the table 284 00:20:15,180 --> 00:20:19,533 if the number is greater than two times of the threshold, 285 00:20:20,463 --> 00:20:25,463 The threshold is selected from a list of prime numbers 286 00:20:26,220 --> 00:20:31,220 and once rehash it, the function enlarges the table 287 00:20:31,440 --> 00:20:35,670 by the next prime number and remaps all records 288 00:20:35,670 --> 00:20:37,533 to their corresponding bucket. 289 00:20:39,150 --> 00:20:43,704 This is a huge and expansive operation 290 00:20:43,704 --> 00:20:48,704 and that's the reason why the chart increased unsmoothly. 291 00:20:54,450 --> 00:20:55,650 To exploit that, 292 00:20:55,650 --> 00:20:59,430 there are still several questions to be solved. 293 00:20:59,430 --> 00:21:04,083 For example, how much of the hash key we can control? 294 00:21:04,950 --> 00:21:08,523 Or how to construct the collision padlock? 295 00:21:11,850 --> 00:21:15,120 There are several elements in the cache key, 296 00:21:15,120 --> 00:21:20,120 and the only element we can control is the URL pass, 297 00:21:20,310 --> 00:21:24,183 which reflected at the end of the cache key. 298 00:21:25,650 --> 00:21:29,940 The implementation will first convert all the text 299 00:21:29,940 --> 00:21:34,023 to uppercase and send a key to the hash function. 300 00:21:36,869 --> 00:21:40,290 The hash function simply multiplies each byte 301 00:21:40,290 --> 00:21:45,243 of the cache key by 101 and just adds them up. 302 00:21:47,220 --> 00:21:52,220 The function also uses an error to scramble the result. 303 00:21:53,310 --> 00:21:54,453 However, 304 00:21:56,010 --> 00:21:58,113 is this hash function good? 305 00:22:01,500 --> 00:22:04,710 This is the answer from Alech and Zeri 306 00:22:04,710 --> 00:22:08,583 in their awesome talk at 28c3. 307 00:22:11,490 --> 00:22:16,490 This multiply then add method is a variant of DJB hash. 308 00:22:20,490 --> 00:22:23,580 And this reason algorithm has been proven 309 00:22:23,580 --> 00:22:27,783 that collidable by equivalent sub strings. 310 00:22:29,250 --> 00:22:34,250 When two keys have the same hash such as the PS and Q2, 311 00:22:36,270 --> 00:22:40,500 they must be equal no matter what you add 312 00:22:40,500 --> 00:22:42,633 before or after that. 313 00:22:44,700 --> 00:22:49,700 For example, after you add the letter A, 314 00:22:49,770 --> 00:22:53,397 the hash of PSA and the Q2A are still equal. 315 00:22:58,440 --> 00:23:03,240 By knowing this feature it's not difficult to understand 316 00:23:03,240 --> 00:23:08,070 that two equivalent sub strings can be combined 317 00:23:08,070 --> 00:23:10,290 to form different case, 318 00:23:10,290 --> 00:23:13,410 such as the PSPS, 319 00:23:13,410 --> 00:23:15,180 PSQ2, 320 00:23:15,180 --> 00:23:16,800 Q2PS 321 00:23:16,800 --> 00:23:18,003 and Q2Q2, 322 00:23:19,950 --> 00:23:22,233 they all share the same hash. 323 00:23:25,440 --> 00:23:29,370 Since you can repeat the string many times, 324 00:23:29,370 --> 00:23:32,940 constructing the payload is easy. 325 00:23:32,940 --> 00:23:37,740 You'll just need to find a few strings with the same hash 326 00:23:37,740 --> 00:23:40,743 and arrange them in combinations. 327 00:23:44,700 --> 00:23:48,873 So all of these share the same hash value, 328 00:23:49,860 --> 00:23:52,743 this is handy for our exploitation. 329 00:23:55,500 --> 00:23:59,973 However, there is a fatal floor in this attack, 330 00:24:01,140 --> 00:24:04,083 that it's too weak. 331 00:24:04,950 --> 00:24:08,130 To get a notice about slowdown, 332 00:24:08,130 --> 00:24:13,130 you must have sent about 35,000 requests at least. 333 00:24:14,130 --> 00:24:18,600 For our one request at one record exploit, 334 00:24:18,600 --> 00:24:19,683 it's too slow. 335 00:24:20,880 --> 00:24:23,940 And the (indistinct) 336 00:24:23,940 --> 00:24:27,420 is that there is a cache scavenger 337 00:24:27,420 --> 00:24:29,763 to recycle records regularly. 338 00:24:30,900 --> 00:24:35,100 The scavenger is a thread to delete unused records 339 00:24:35,100 --> 00:24:36,993 every 30 seconds. 340 00:24:38,070 --> 00:24:42,813 Those two obstacles makes our attack not so practical. 341 00:24:46,110 --> 00:24:47,520 To overcome this, 342 00:24:47,520 --> 00:24:51,333 we have to dive into the implementation more. 343 00:24:52,380 --> 00:24:54,483 During our investigation, 344 00:24:56,340 --> 00:25:01,340 we find an interesting behavior that can rescue our attack. 345 00:25:02,820 --> 00:25:06,423 The implementation will scan the key recursively. 346 00:25:07,260 --> 00:25:11,880 It trace all sub directories as new records 347 00:25:11,880 --> 00:25:14,793 and adds all of them to the table. 348 00:25:17,790 --> 00:25:21,540 For example, in our imagination, the URL 349 00:25:21,540 --> 00:25:26,283 will only trigger one search and one insert operation. 350 00:25:27,690 --> 00:25:30,810 However, each sub directory 351 00:25:30,810 --> 00:25:33,960 will also be checked as a new record 352 00:25:33,960 --> 00:25:38,960 so that the URL will trigger multiple insert operations. 353 00:25:40,470 --> 00:25:42,610 What's more interesting is that 354 00:25:44,310 --> 00:25:47,973 all new keys will be packed with the newer record. 355 00:25:48,840 --> 00:25:52,800 The scavenger is nice to the null records 356 00:25:52,800 --> 00:25:55,260 and only they list them one by one, 357 00:25:55,260 --> 00:25:59,343 instead of killing all of them in a batch. 358 00:26:02,700 --> 00:26:06,030 So the only question left is, 359 00:26:06,030 --> 00:26:10,533 How to construct the collision in this new context? 360 00:26:12,450 --> 00:26:15,480 Because all sub directories are traded 361 00:26:15,480 --> 00:26:20,480 as in independent keys, we have to construct the payload 362 00:26:20,790 --> 00:26:24,873 that satisfied all following equations. 363 00:26:26,430 --> 00:26:31,430 It may be a little hard to imagine how to make this happen, 364 00:26:32,100 --> 00:26:35,193 so it's our previous equivalent feature. 365 00:26:39,570 --> 00:26:43,650 But if we make all the results to be zero, 366 00:26:43,650 --> 00:26:46,902 then this comes much easier. 367 00:26:46,902 --> 00:26:50,250 Zero multiply anything is zero 368 00:26:50,250 --> 00:26:53,613 and zero plus zero is also zero. 369 00:26:54,720 --> 00:26:58,710 So we can satisfy all the equations, 370 00:26:58,710 --> 00:27:03,273 if we match the hash of each sub directory to zero. 371 00:27:06,090 --> 00:27:10,320 So we can prepare a set of zero hashes 372 00:27:10,320 --> 00:27:14,310 and amplify the attack 10 times, at least, 373 00:27:14,310 --> 00:27:16,353 by a slight modification. 374 00:27:19,560 --> 00:27:23,910 The result is that we can make a server unresponsive 375 00:27:23,910 --> 00:27:27,093 with about 30 connections per second. 376 00:27:28,500 --> 00:27:31,770 This is not an unreasonable number 377 00:27:31,770 --> 00:27:36,600 because IIS can handle sources of connections 378 00:27:36,600 --> 00:27:38,673 easily and concurrent. 379 00:27:40,380 --> 00:27:44,010 Because this bot affect the windows by default, 380 00:27:44,010 --> 00:27:47,343 we also award a good amount of bounty. 381 00:27:51,900 --> 00:27:53,403 Let's check out the demo. 382 00:28:00,480 --> 00:28:05,480 We first double check and ensure the server has eight cores 383 00:28:06,390 --> 00:28:08,643 and 32 gigabytes RAM. 384 00:28:13,080 --> 00:28:16,860 The window in the lower left is the script 385 00:28:16,860 --> 00:28:20,047 that monitors the status of the IIS, 386 00:28:21,180 --> 00:28:25,787 it's a while loop and checks the server every second. 387 00:28:37,680 --> 00:28:41,460 Okay, we first run the random test. 388 00:28:41,460 --> 00:28:44,407 We send random test to the IIS. 389 00:28:46,100 --> 00:28:49,893 You can see the loading is less than 10%. 390 00:29:00,730 --> 00:29:03,423 Okay, we now want the collision mode. 391 00:29:11,481 --> 00:29:15,564 As you can see the CPU is now under high loading. 392 00:29:32,075 --> 00:29:35,103 Okay, 100% CPU load. 393 00:29:42,960 --> 00:29:47,190 Okay, as you can see the monitor enters the time out, 394 00:29:47,190 --> 00:29:48,120 time out loop. 395 00:30:07,420 --> 00:30:10,333 Here, we speed a little bit up. 396 00:30:25,950 --> 00:30:29,820 Okay, as you can see the server is unavailable 397 00:30:29,820 --> 00:30:33,543 and can't handle any request anymore. 398 00:30:38,940 --> 00:30:42,693 Okay, the second case is a cache poisoning attack. 399 00:30:44,529 --> 00:30:47,557 There are two types of response cache in IIS, 400 00:30:48,450 --> 00:30:52,380 one is the static cache support by the Kernel, 401 00:30:52,380 --> 00:30:57,380 such as the picture, the CSS and the JavaScript resources. 402 00:30:58,800 --> 00:31:01,050 The other is dynamic cache, 403 00:31:01,050 --> 00:31:05,973 which is usually used to cache responses that rarely change. 404 00:31:06,930 --> 00:31:11,930 For example, the product information of an online shop 405 00:31:12,120 --> 00:31:14,883 or the news announcement of SDN. 406 00:31:16,350 --> 00:31:19,560 The benefit of the dynamic cache is that 407 00:31:19,560 --> 00:31:22,307 you can reduce the number of the database assets. 408 00:31:26,310 --> 00:31:30,870 Dynamic cache is handled by the HTTP cache module, 409 00:31:30,870 --> 00:31:33,180 and you can configure the cache 410 00:31:33,180 --> 00:31:35,643 by the output caching component. 411 00:31:39,300 --> 00:31:44,067 To use the cache, you must first set out your own rule. 412 00:31:44,067 --> 00:31:47,490 The rule can be based on several conductions 413 00:31:47,490 --> 00:31:50,100 such as the file extension, 414 00:31:50,100 --> 00:31:53,313 the correlation or the HTTP behavior. 415 00:31:54,420 --> 00:31:58,300 Here, we set out a rule for the extension of ASPX 416 00:31:59,400 --> 00:32:02,883 and cache the result based on the ID. 417 00:32:06,210 --> 00:32:10,230 So the root cause of the cache poisoning is that, 418 00:32:10,230 --> 00:32:15,033 the module used a bad parser to handle the query string. 419 00:32:16,830 --> 00:32:20,130 But then that you have already set out a rule 420 00:32:20,130 --> 00:32:23,103 to cache a specific parameter, 421 00:32:24,060 --> 00:32:28,170 an inconsistency between the module and the backend 422 00:32:28,170 --> 00:32:31,743 may lead IIS to cache the wrong result. 423 00:32:35,220 --> 00:32:40,204 In the real world, the most common backend is ASP.net. 424 00:32:40,204 --> 00:32:45,204 And a simple HTTP parameter pollution can rule them all. 425 00:32:47,400 --> 00:32:50,880 So the key duplicates in the query string, 426 00:32:50,880 --> 00:32:55,563 the module only uses the first occurrence of the cache key. 427 00:32:56,760 --> 00:33:01,413 However, the APS.net concatenate all together. 428 00:33:02,880 --> 00:33:07,590 These inconsistent positive behaviors cause the IIS 429 00:33:07,590 --> 00:33:09,753 to cache the wrong response. 430 00:33:12,540 --> 00:33:13,770 For example, 431 00:33:13,770 --> 00:33:18,343 if a patch just prints out your name based on the ID, 432 00:33:19,680 --> 00:33:22,650 the attacker can poison the result 433 00:33:22,650 --> 00:33:26,073 by repeating the ID on the URL. 434 00:33:27,270 --> 00:33:32,270 The IIS only recognize the orange of the cache key. 435 00:33:33,120 --> 00:33:38,120 However, the ASP.net will concatenate both values 436 00:33:38,700 --> 00:33:40,023 and show them up. 437 00:33:43,470 --> 00:33:45,120 So the result is that 438 00:33:45,120 --> 00:33:50,013 the next time the user answers the patch he got hacked. 439 00:33:56,460 --> 00:34:00,663 Okay, our last task is the authentication bypass. 440 00:34:03,300 --> 00:34:07,330 Back to our opening, a super secret area, 441 00:34:07,330 --> 00:34:11,103 which is protected by a super strong password, 442 00:34:12,180 --> 00:34:14,137 under the design of the IIS. 443 00:34:16,800 --> 00:34:19,353 All of this passwords are valid. 444 00:34:21,120 --> 00:34:24,180 I guess you might have several questions 445 00:34:24,180 --> 00:34:27,663 and be thinking what's the root cause? 446 00:34:28,710 --> 00:34:31,893 Or how do I get those passwords? 447 00:34:33,270 --> 00:34:36,930 Or suspect this must be a hash case, 448 00:34:36,930 --> 00:34:40,020 what kind of the scenario is vulnerable? 449 00:34:43,080 --> 00:34:48,080 First logon is an expensive operation. 450 00:34:48,240 --> 00:34:51,000 To not reduce the performance, 451 00:34:51,000 --> 00:34:56,000 IIS caches all tokens for password based authentications 452 00:34:56,700 --> 00:34:57,633 by default. 453 00:34:59,100 --> 00:35:02,820 The implementation uses the LKRHash 454 00:35:02,820 --> 00:35:05,190 instead of the tree hash table 455 00:35:05,190 --> 00:35:08,610 and configures a scavenger to delete 456 00:35:08,610 --> 00:35:12,243 and use the record every 15 minutes. 457 00:35:15,660 --> 00:35:20,163 As we mentioned, LKRHash is highly customized. 458 00:35:21,150 --> 00:35:26,150 During initialization, the module define several functions, 459 00:35:27,240 --> 00:35:29,970 such as the hash function, 460 00:35:29,970 --> 00:35:34,860 the logic of how to extracting the key from the record 461 00:35:34,860 --> 00:35:39,273 and how to decide which one is the correct record 462 00:35:39,273 --> 00:35:41,283 when the collision happened. 463 00:35:44,760 --> 00:35:46,980 And this is the hash function 464 00:35:46,980 --> 00:35:50,490 defined by the token cache module. 465 00:35:50,490 --> 00:35:54,790 It simply uses the DJB to hash the username 466 00:35:55,710 --> 00:36:00,123 and the password, and then makes them together by XO. 467 00:36:04,620 --> 00:36:08,760 And this is the function used to decide 468 00:36:08,760 --> 00:36:13,683 which one is the correct record when a collision happens. 469 00:36:15,510 --> 00:36:17,580 The function first checks 470 00:36:17,580 --> 00:36:22,240 whether the local method of both record are equals or not 471 00:36:23,280 --> 00:36:25,090 and then compare the username 472 00:36:27,030 --> 00:36:29,523 and compare the username again. 473 00:36:31,290 --> 00:36:32,733 You may be wondering, 474 00:36:34,380 --> 00:36:38,763 why did this function compare the user name twice? 475 00:36:40,140 --> 00:36:43,920 I guess the original intent of IIS 476 00:36:43,920 --> 00:36:46,143 was to compare the password, 477 00:36:47,130 --> 00:36:51,600 however, the developer copy and paste the code, 478 00:36:51,600 --> 00:36:55,473 but forgot to replace the name to the password. 479 00:36:57,240 --> 00:36:58,323 It's the big fail. 480 00:37:02,910 --> 00:37:06,690 The failure could add an inconsistency 481 00:37:06,690 --> 00:37:10,923 between the hash calculation and the cache comparison. 482 00:37:12,690 --> 00:37:14,820 The hash calculation involve 483 00:37:14,820 --> 00:37:18,180 both the username and the password. 484 00:37:18,180 --> 00:37:21,390 However, when a collision occurs, 485 00:37:21,390 --> 00:37:23,830 the table only compare the username 486 00:37:24,810 --> 00:37:27,513 to get the correct entry. 487 00:37:28,830 --> 00:37:32,730 Since we can adjust the field of the password 488 00:37:32,730 --> 00:37:34,383 to change the hash, 489 00:37:35,280 --> 00:37:40,080 if the hash hits a record that is already in the table, 490 00:37:40,080 --> 00:37:44,757 the module will return that to it's directory. 491 00:37:48,840 --> 00:37:50,400 So the result is that 492 00:37:50,400 --> 00:37:54,660 you can reuse another users log in token 493 00:37:54,660 --> 00:37:56,103 with random passwords. 494 00:37:58,110 --> 00:38:01,053 However, they are still a few prerequisites. 495 00:38:02,100 --> 00:38:05,280 First, each password attempt 496 00:38:05,280 --> 00:38:09,653 only has the success rate of 42 billion 497 00:38:09,653 --> 00:38:13,263 because the hash is a 32 bit integer. 498 00:38:15,210 --> 00:38:17,250 The other prerequisite is that, 499 00:38:17,250 --> 00:38:21,933 there must be a successful login before our attack, 500 00:38:23,280 --> 00:38:26,370 but once the log in is done 501 00:38:26,370 --> 00:38:28,860 and the token is cached in the memory, 502 00:38:28,860 --> 00:38:31,050 you have unlimited attacks 503 00:38:31,050 --> 00:38:33,933 during the 15 minutes time window. 504 00:38:35,597 --> 00:38:40,597 Both of the above prerequisites makes this bug unusable. 505 00:38:41,767 --> 00:38:45,060 It is just like playing the lottery 506 00:38:45,060 --> 00:38:48,303 in the space of the 32 bit integer. 507 00:38:53,640 --> 00:38:57,723 So to make this bug a more severe vulnerability, 508 00:38:58,800 --> 00:39:02,403 we have developed several ways to win the lottery. 509 00:39:03,450 --> 00:39:05,250 The first enhancement 510 00:39:05,250 --> 00:39:08,763 is to increase the probability of the collision. 511 00:39:11,010 --> 00:39:16,010 A vulnerability that requires user interaction is too late. 512 00:39:16,590 --> 00:39:18,690 So for the second, 513 00:39:18,690 --> 00:39:23,323 we must find a way to exploit without user interaction. 514 00:39:26,160 --> 00:39:28,650 The last is to defeat the restriction 515 00:39:28,650 --> 00:39:31,710 of the 15 minutes time window, 516 00:39:31,710 --> 00:39:34,683 we figure out a way to cache the token forever. 517 00:39:39,450 --> 00:39:42,933 Okay, the first is to increase the probability. 518 00:39:44,130 --> 00:39:47,427 As we mentioned that the four billion password records 519 00:39:47,427 --> 00:39:49,593 are a ridiculous number. 520 00:39:50,820 --> 00:39:55,820 The LKRhash even use an LCG to make the result more random, 521 00:39:58,290 --> 00:40:03,290 but just because of this LCG we can lower the key space 522 00:40:03,840 --> 00:40:07,740 because the LCG is not one to one mapping 523 00:40:07,740 --> 00:40:11,133 under the key space of 32 bit integer. 524 00:40:13,410 --> 00:40:17,973 So there must be results that will never appear. 525 00:40:19,380 --> 00:40:24,380 So we can precompute a dictionary that excludes the password 526 00:40:24,570 --> 00:40:28,200 whos hash is not in the results. 527 00:40:28,200 --> 00:40:32,253 This development can reduce a number of the key space. 528 00:40:33,900 --> 00:40:37,200 Also, there are still billions of password records, 529 00:40:37,200 --> 00:40:42,200 we have increased our success rate by 13% at the least. 530 00:40:46,140 --> 00:40:49,533 The second enhancement is to regain the initiative. 531 00:40:50,910 --> 00:40:54,450 There's a feature called "Connect As" 532 00:40:54,450 --> 00:40:57,630 that is usually used in the virtual hosting 533 00:40:57,630 --> 00:41:01,150 because the vendor has to separate IIS process 534 00:41:02,280 --> 00:41:03,903 for their customers. 535 00:41:05,340 --> 00:41:06,540 With this feature, 536 00:41:06,540 --> 00:41:11,540 each IIS process can be under a different user context. 537 00:41:15,450 --> 00:41:20,450 Under the feature, IIS will auto logon the user you specify 538 00:41:20,460 --> 00:41:23,550 while spawning the new process. 539 00:41:23,550 --> 00:41:26,460 This token will also be cached, 540 00:41:26,460 --> 00:41:29,950 that means we can reuse the customer's identity 541 00:41:30,810 --> 00:41:34,323 and no longer to wait for user interaction. 542 00:41:35,910 --> 00:41:39,063 In this case, we have regained the initiative. 543 00:41:42,270 --> 00:41:46,713 To prove it works, we did a test in our lab environment. 544 00:41:47,790 --> 00:41:49,890 Windows server can handle 545 00:41:49,890 --> 00:41:54,423 about 1800 login attempts per second. 546 00:41:55,830 --> 00:42:00,830 Because every attack cost nothing, you can run this all day 547 00:42:00,900 --> 00:42:04,373 and the success spread is about 4.2%. 548 00:42:07,710 --> 00:42:12,543 This is already higher than the SSR in your Gacha games. 549 00:42:14,940 --> 00:42:18,390 And you can also run it for longer, 550 00:42:18,390 --> 00:42:22,063 five days for 20%, 12 days for 50% 551 00:42:23,790 --> 00:42:28,790 and the success rate of running for 24 days can get 100%. 552 00:42:33,180 --> 00:42:36,780 We have reduced in our lab environment 553 00:42:36,780 --> 00:42:40,893 and can get a password in about five days. 554 00:42:44,730 --> 00:42:49,080 The last enhancement is to defeat the time window. 555 00:42:49,080 --> 00:42:53,640 Our idea is simple, in modern software architecture 556 00:42:53,640 --> 00:42:57,690 it's common to see the patent of a background daemon, 557 00:42:57,690 --> 00:43:00,510 monitors the system's health 558 00:43:00,510 --> 00:43:05,510 or several cron-jobs assess the internal APIs regularly. 559 00:43:08,700 --> 00:43:11,250 So we can assume a situation 560 00:43:11,250 --> 00:43:15,510 that a credential is attached with the cron-job 561 00:43:15,510 --> 00:43:20,090 and the gap between each access is less than 15 minutes. 562 00:43:22,530 --> 00:43:27,033 In this assumption, the token will be cached forever. 563 00:43:29,520 --> 00:43:32,130 Okay, I know it's very ideal, 564 00:43:32,130 --> 00:43:33,783 Is there any real case? 565 00:43:37,020 --> 00:43:40,413 Sure, let's talk about the exchange server again. 566 00:43:43,680 --> 00:43:47,400 There is a service called active monitoring, 567 00:43:47,400 --> 00:43:50,010 which is enabled by default 568 00:43:50,010 --> 00:43:54,933 and responsible for monitoring all services, 569 00:43:56,230 --> 00:44:01,230 HX to OWA and active sync service every 10 minutes 570 00:44:02,370 --> 00:44:04,353 with the test credential. 571 00:44:05,971 --> 00:44:08,040 That's for the health check, 572 00:44:08,040 --> 00:44:12,063 the token of the credential will be cached forever. 573 00:44:15,780 --> 00:44:19,230 So you can try as many as you like 574 00:44:19,230 --> 00:44:21,910 until you get a successful login 575 00:44:25,050 --> 00:44:29,407 and the password is also usable to log into the OWA. 576 00:44:33,240 --> 00:44:38,240 The account for the health check has its own mailbox too, 577 00:44:38,550 --> 00:44:42,000 this is useful for further exploitations, 578 00:44:42,000 --> 00:44:43,980 such as phishing 579 00:44:43,980 --> 00:44:47,973 or training another post office RCE together, 580 00:44:49,050 --> 00:44:50,673 that's our last case. 581 00:44:54,420 --> 00:44:57,723 Let's talk about the mitigations and future works. 582 00:45:00,677 --> 00:45:02,760 For the design of the hash table, 583 00:45:02,760 --> 00:45:06,270 it's recommended to use the pseudo random function 584 00:45:06,270 --> 00:45:09,090 such as the SipHash or HighwayHash 585 00:45:10,290 --> 00:45:12,780 that can reduce the collision 586 00:45:12,780 --> 00:45:16,203 and make the attack more custom. 587 00:45:17,580 --> 00:45:21,903 For the design of the cache, inconsistency is still the key, 588 00:45:22,740 --> 00:45:25,350 just like our case today, 589 00:45:25,350 --> 00:45:30,350 the cache poisoning due to the different password behaviors 590 00:45:30,360 --> 00:45:34,653 and those indication bypass due to the unkeyed password. 591 00:45:36,120 --> 00:45:41,010 Since the hash-flooding attack is by the side attack, 592 00:45:41,010 --> 00:45:45,600 there are several workarounds to mitigate the problem 593 00:45:45,600 --> 00:45:48,870 such as the input size limitation 594 00:45:48,870 --> 00:45:52,710 or a state to randomize the hash. 595 00:45:52,710 --> 00:45:55,620 Each solution has its limitation, 596 00:45:55,620 --> 00:45:58,380 so the last recommendation is 597 00:45:58,380 --> 00:46:02,733 to learn attack and defense from the history. 598 00:46:06,300 --> 00:46:10,290 There are still several cool future works in my mind, 599 00:46:10,290 --> 00:46:13,440 such as using timeless timing attack 600 00:46:13,440 --> 00:46:15,603 to reduce the key space. 601 00:46:16,590 --> 00:46:19,470 However, since I am lazy, 602 00:46:19,470 --> 00:46:22,743 welcome to pick them up if you are interested, 603 00:46:25,680 --> 00:46:28,590 this is the end of my presentation, 604 00:46:28,590 --> 00:46:33,510 if you have any questions, here is my contact information. 605 00:46:33,510 --> 00:46:36,573 Thank you again for being here, thanks.