1 00:00:09,460 --> 00:00:10,580 Hi, welcome. 2 00:00:10,580 --> 00:00:11,840 Thanks for attending our talk. 3 00:00:11,840 --> 00:00:16,100 This is Room for Escape, Scribbling Outside the Lines of Template Security. 4 00:00:16,460 --> 00:00:20,140 So, my name is Alvaro Munoz, also known as Pwntested in the social media. 5 00:00:20,420 --> 00:00:23,520 I'm a security researcher with the GitHub security lab. 6 00:00:23,560 --> 00:00:27,960 And with me, my colleague, Alexander Mirosh, also known as Oleg Mirosh in Twitter. 7 00:00:27,960 --> 00:00:31,760 And he is a security researcher with Micro Focus Fortify team. 8 00:00:31,840 --> 00:00:36,600 So, today, we will be reviewing the security of content management systems, or CMS. 9 00:00:36,600 --> 00:00:44,440 And, basically, we will be focusing on the security of the template systems that are used by CMSs. 10 00:00:44,460 --> 00:00:56,320 So, a content management system is basically an application that is used to manage different types of web content, so that users can actually create, upload, and publish different types of content. 11 00:00:56,320 --> 00:01:07,600 So, normally, this content is based on some structures and some kind of documents called templates, which are used to generate and create dynamic content. 12 00:01:07,600 --> 00:01:13,820 So, these templates normally allow a subset of different programming language capabilities. 13 00:01:13,820 --> 00:01:18,900 So, they are powerful in the sense that they can be used to run arbitrary code. 14 00:01:18,900 --> 00:01:25,100 Because of that, they are normally sandboxed in order to prevent arbitrary code execution and remote code execution. 15 00:01:25,980 --> 00:01:37,340 So, our research will focus on both .NET and Java-based content management systems, because these are the languages that are more prevalent across enterprises. 16 00:01:37,460 --> 00:01:42,140 And our assumption is that the attacker can control the templates, right? 17 00:01:42,140 --> 00:01:59,100 So, we don't really care about how the attacker gets control of these templates in the first place, if it's through a server-side template injection, or if it's maybe through our cross-site scripting that allows him to submit arbitrary templates in behalf of someone else. 18 00:01:59,100 --> 00:02:10,380 Or maybe they have permissions, like if you are a user, for example, in SharePoint, if you have an account in SharePoint, you are allowed to create your own sites and content. 19 00:02:10,380 --> 00:02:24,700 So, no matter how the attacker can edit the content of a template, our research will focus on escaping and breaking all the mitigations put in place to prevent arbitrary code execution. 20 00:02:25,000 --> 00:02:29,060 So, we will first start with .NET. 21 00:02:29,060 --> 00:02:31,680 Basically, we will focus on SharePoint. 22 00:02:31,680 --> 00:02:39,100 We will present five different ways we were able to break the sandbox used by SharePoint to prevent arbitrary code execution. 23 00:02:39,100 --> 00:02:49,320 And then we will move into the Java part, where we will present four different template engines, including the most popular ones, such as Velocity and FreeMarker. 24 00:02:49,420 --> 00:02:55,200 And then we will present 10 different content management systems, and we will try our bypasses on them. 25 00:02:55,200 --> 00:02:59,480 So, we will wrap up with some takeaways and conclusions, and then open the floor for Q&A. 26 00:02:59,580 --> 00:03:02,120 So, let's start with the .NET part. 27 00:03:02,580 --> 00:03:03,720 Thank you, Alvaro. 28 00:03:03,720 --> 00:03:12,520 In this part of our presentation, we will present different types of security problems in content management systems, and give examples of them in SharePoint. 29 00:03:12,520 --> 00:03:17,580 But before that, we need to explain some basics of SharePoint security. 30 00:03:17,900 --> 00:03:21,540 SharePoint has two types of ASPx pages. 31 00:03:21,540 --> 00:03:24,120 The first type is application pages. 32 00:03:24,120 --> 00:03:30,340 Each of these pages are the part of SharePoint server and implement some application logic. 33 00:03:30,340 --> 00:03:33,460 They are stored in specific folders on the file system. 34 00:03:33,460 --> 00:03:35,920 Of course, users are not able to change them. 35 00:03:35,920 --> 00:03:41,500 They are regular ASPx pages and are processed by server without any restrictions. 36 00:03:41,620 --> 00:03:44,220 In opposite to them, there are side pages. 37 00:03:44,220 --> 00:03:48,520 They are stored in database and they can be customized even by users. 38 00:03:48,520 --> 00:03:52,580 SharePoint parses them in special mode, also known as safe mode. 39 00:03:52,580 --> 00:03:57,060 Actually, they are more like some sort of templates for presenting dynamic content. 40 00:03:57,100 --> 00:04:02,880 On this slide, we can see a diagram how server works with these pages. 41 00:04:02,900 --> 00:04:07,680 Virtual provider can fetch content from file system or database. 42 00:04:08,020 --> 00:04:22,580 Based on the virtual path of the current page, ASP page parse filter will decide either it is side page and safe mode should be applied, or it is an application page and it will be processed without any restrictions. 43 00:04:22,660 --> 00:04:26,720 So, page filter is a critical element from security design. 44 00:04:27,760 --> 00:04:33,280 Let's have a look on a simple ASPx page. 45 00:04:33,280 --> 00:04:37,300 For our attacks, we are only interested in server-side components. 46 00:04:37,300 --> 00:04:38,900 For example, directives. 47 00:04:38,900 --> 00:04:43,320 There are special instructions on how server should process the current page. 48 00:04:43,320 --> 00:04:46,580 Often, they have some number of attributes. 49 00:04:46,600 --> 00:04:53,220 We can include server-side code either in special blocks or as embedded server-side code. 50 00:04:53,220 --> 00:04:58,600 To be processed by server, control should have the runout server attribute. 51 00:04:58,640 --> 00:05:02,540 The next element is server-side common block. 52 00:05:02,540 --> 00:05:04,480 It is ignored by server. 53 00:05:04,540 --> 00:05:09,890 And server-side include directives allow us to include raw content of arbitrary file. 54 00:05:10,760 --> 00:05:14,640 Now, we can better understand what safe mode means. 55 00:05:14,680 --> 00:05:18,960 Side page will not be compiled, so we cannot use server-side code. 56 00:05:18,960 --> 00:05:22,640 We are not able to include files from file system. 57 00:05:22,640 --> 00:05:24,980 We can only use allowed controls. 58 00:05:24,980 --> 00:05:29,380 This list is defined in safe control section of web config file. 59 00:05:29,580 --> 00:05:36,620 Page filter also applies an allow list for directives and even for attributes of most of them. 60 00:05:36,620 --> 00:05:38,460 There are many other restrictions. 61 00:05:38,460 --> 00:05:41,740 For example, event binding is blocked as well. 62 00:05:41,840 --> 00:05:48,940 As we can see, it is a set of quite strong restrictions how it can be bypassed. 63 00:05:48,940 --> 00:05:52,480 As we know, safe mode is enforced by page filter. 64 00:05:52,820 --> 00:05:58,800 So, our first question was, is there any place where SharePoint does not use it? 65 00:05:58,800 --> 00:06:01,460 And answer yes, there are such places. 66 00:06:01,460 --> 00:06:15,000 Page filter will not be applied for the content argument of the parse control method if it's called only with one argument or if the second one that actually has name ignoreParseFilter is true. 67 00:06:15,160 --> 00:06:21,860 In addition, page filter is used at rendering time but is ignored at design time. 68 00:06:22,320 --> 00:06:30,220 But even if page filter is not applied, SharePoint uses another way to verify the input. 69 00:06:30,580 --> 00:06:43,900 It is a verify control on safe list method from editing page parse type that aims to do the same task at the original page filter, block markup with unsafe elements. 70 00:06:44,720 --> 00:06:50,200 But let's imagine for a second that we are able to bypass either this method or page filter. 71 00:06:50,260 --> 00:06:55,760 By the way, each such bypass is separate vulnerability and we will present them in a few minutes. 72 00:06:55,760 --> 00:07:01,100 So, how could we get remote code execution after escaping the safe mode? 73 00:07:01,200 --> 00:07:11,980 Remember, since parse control method never calls compilation, we are not able to use server-side code or perform any other attack that require compilation. 74 00:07:12,340 --> 00:07:18,180 But if we escape safe mode, we can use unsafe controls or directives. 75 00:07:18,180 --> 00:07:20,080 Let's review several of them. 76 00:07:21,000 --> 00:07:26,160 One of the most interesting unsafe controls is object data source. 77 00:07:26,160 --> 00:07:30,860 It allows us to invoke public methods from arbitrary public type. 78 00:07:30,860 --> 00:07:36,540 We can see an example of payload that uses start method from process type to launch calculator. 79 00:07:36,600 --> 00:07:39,640 So, actually, it is arbitrary code execution, jackpot. 80 00:07:39,640 --> 00:07:43,100 But let's review a couple other unsafe controls. 81 00:07:43,520 --> 00:07:49,420 XML data source and XML controls allow us to get content of arbitrary XML files. 82 00:07:49,540 --> 00:07:55,660 The similar results we can get by server-side include directives that return us content of any text files. 83 00:07:55,960 --> 00:08:01,460 Let's see how we can escalate from arbitrary file read to arbitrary code execution. 84 00:08:01,660 --> 00:08:08,940 If we can access web.config file, we will be able to get validation key from machine key section. 85 00:08:09,140 --> 00:08:15,460 By the way, this value may be present in other places such as internal SharePoint properties. 86 00:08:15,460 --> 00:08:17,980 We will see this example a bit later. 87 00:08:18,280 --> 00:08:27,580 With validation key, we can generate a valid view state that will execute arbitrary code commands on the target server. 88 00:08:27,580 --> 00:08:31,540 We can use tools such as userserial.net for this. 89 00:08:32,580 --> 00:08:42,400 Now, when we know what safe mode is and how we can compromise SharePoint server if it is bypassed, we can move to our next part of this talk. 90 00:08:42,400 --> 00:08:47,220 Here we will present five different types of security problem in content management system. 91 00:08:47,540 --> 00:08:51,020 We will show examples of each type in SharePoint. 92 00:08:51,200 --> 00:08:56,580 We would like to stress here that our target is SharePoint server with default configuration. 93 00:08:56,580 --> 00:09:04,440 All vulnerabilities allowed us to execute arbitrary code on the target and all attacks were performed by regular user. 94 00:09:04,440 --> 00:09:06,300 No admin rights were needed. 95 00:09:06,860 --> 00:09:08,220 Let's start. 96 00:09:08,840 --> 00:09:13,780 The first type of security problems is access to resources with sensitive information. 97 00:09:13,780 --> 00:09:20,520 It can be configuration or business information in various files, logs, database, or even process memory. 98 00:09:20,520 --> 00:09:25,880 Of course, proper sandbox should prevent this problem, but it is not always the case. 99 00:09:26,220 --> 00:09:35,820 We already mentioned that page filter blocks server-side includes directives and verify control on safe list method should do this as well, and actually it does. 100 00:09:35,980 --> 00:09:42,360 But if it's called with false in block server-side includes argument, it will not block them. 101 00:09:42,540 --> 00:09:45,320 And we found such usage of this method. 102 00:09:45,320 --> 00:09:47,220 It was used for design mode. 103 00:09:48,060 --> 00:09:53,520 The next building block for our talk, how we can provide our markup for this mode. 104 00:09:53,520 --> 00:10:01,480 We can send it in web part XML parameter of the render web part for edit method of the web page services. 105 00:10:01,480 --> 00:10:04,500 So we can try to include web config file there. 106 00:10:05,080 --> 00:10:10,660 Here we can see the full payload for the mentioned parameter and address to relevant web services. 107 00:10:11,020 --> 00:10:14,580 Server returned us the entire web config with validation key. 108 00:10:14,660 --> 00:10:21,120 We use it for view state-based deserialization attack, which led us to executing arbitrary OS command on the server. 109 00:10:22,740 --> 00:10:27,180 Time for our next type of security problems in content management system. 110 00:10:27,640 --> 00:10:30,500 Allow dangerous element that can be used for attacks. 111 00:10:31,600 --> 00:10:39,880 We have found an example in SharePoint safe control list, or should we call it not so safe control list in this case. 112 00:10:42,100 --> 00:10:46,420 It is contact link suggestion micro view control. 113 00:10:46,420 --> 00:10:54,060 We can see snippet with interesting code from implementation where request parameter is passed to data set read XML method. 114 00:10:54,160 --> 00:11:00,500 If we can control input for this method, we can get our data deserialized by XML serializer with control type. 115 00:11:00,500 --> 00:11:06,500 We already showed in one of our previous work that in this case we can get arbitrary code execution. 116 00:11:06,560 --> 00:11:11,240 Unfortunately, this payload is too big for slides, but you can find it in our white paper. 117 00:11:11,960 --> 00:11:17,580 The last piece of the puzzle is our site page with this dangerous control. 118 00:11:17,580 --> 00:11:19,820 You can see it on this slide. 119 00:11:19,820 --> 00:11:28,370 For the attack, we just need to place the payload into the text box and click on submit button and desired command will be executed on the SharePoint server. 120 00:11:29,820 --> 00:11:39,360 For us, the next type of security problems looks quite interesting, so we will explain it with more details and present two separate examples from SharePoint server. 121 00:11:40,200 --> 00:11:47,160 Dynamic content usually means that we will have at least read access to some properties or attributes of some objects. 122 00:11:47,580 --> 00:11:52,100 For some system like SharePoint, we can even write values there. 123 00:11:52,100 --> 00:11:57,480 Of course, some box should filter out the access to dangerous property or attributes. 124 00:11:57,900 --> 00:12:00,560 Let's review basic type of such filtering. 125 00:12:00,960 --> 00:12:05,580 The first case is when only one level of properties or attributes is allowed. 126 00:12:05,580 --> 00:12:07,700 We can see examples on the slide. 127 00:12:07,700 --> 00:12:11,360 Name property of user object of select value from menu. 128 00:12:11,360 --> 00:12:16,500 We can imagine the object and its properties like a branch with only leaves. 129 00:12:17,740 --> 00:12:21,560 If an allow list is applied, it's relatively easy to review all elements. 130 00:12:21,560 --> 00:12:25,180 And after such review, we can make sure that there is no dangerous elements. 131 00:12:25,400 --> 00:12:27,940 What if block list is used instead? 132 00:12:28,100 --> 00:12:32,320 We still need to verify available objects and it can be a bit difficult. 133 00:12:32,600 --> 00:12:37,760 So in general, we do not consider a block list a safe approach because of potential gaps there. 134 00:12:37,940 --> 00:12:41,340 We will see in Java part a couple of examples of such bypasses. 135 00:12:42,300 --> 00:12:48,720 The most interesting case for us is where access to nested properties or attributes is allowed. 136 00:12:48,720 --> 00:12:54,520 For example, request.authUser.name or menu.selectedItem.text. 137 00:12:54,700 --> 00:13:01,500 Because of branch-leaves analogy, many developers may imagine this case as branch with branches and leaves. 138 00:13:01,500 --> 00:13:05,840 And they may apply a filter only for the first level objects. 139 00:13:05,840 --> 00:13:08,040 But it is not true. 140 00:13:08,040 --> 00:13:09,400 It is a network. 141 00:13:09,400 --> 00:13:14,200 And we may jump from one branch to another branch or even to the trunk. 142 00:13:14,200 --> 00:13:20,540 For example, on this slide, we can see how we can access application instance from a new web control. 143 00:13:21,400 --> 00:13:25,140 Let's illustrate this problem by examples from SharePoint. 144 00:13:25,660 --> 00:13:27,780 There is wikiContentWebParseControl. 145 00:13:27,780 --> 00:13:33,180 It is allowed and can pass our markup into the parseControl method. 146 00:13:33,180 --> 00:13:37,640 Please note, it is called with false value in ignoreParseFilter argument. 147 00:13:37,640 --> 00:13:40,160 So, PageFilter will not be ignored. 148 00:13:41,080 --> 00:13:48,620 The following snippet shows that in this case, the virtual path will be created from AppRelativeVirtualPath property. 149 00:13:48,900 --> 00:13:53,110 And if you remember, PageFilter will apply restriction based on this virtual path. 150 00:13:53,440 --> 00:14:00,860 So, if we are able to change it, we can fool the PageFilter to not apply any restriction to our markup. 151 00:14:00,900 --> 00:14:03,280 Let's try to graph such payload. 152 00:14:03,460 --> 00:14:14,760 First snippet fails, because when ASPxParser tries to assign a new value to AppRelativeVirtualPath, the Page property of our control is not defined yet. 153 00:14:14,760 --> 00:14:17,540 So, we need to delay this assignment a little bit. 154 00:14:17,540 --> 00:14:20,160 We can do this by data binding. 155 00:14:20,160 --> 00:14:26,620 So, by the time the property is bound, the Page property will be already defined. 156 00:14:27,340 --> 00:14:29,660 Here is our final payload. 157 00:14:29,660 --> 00:14:35,860 We can notice that our new path points to application page setting ASPx. 158 00:14:36,240 --> 00:14:42,960 It is assigned to ToolTip property and later will be transferred to AppRelativeVirtualPath. 159 00:14:43,020 --> 00:14:48,360 So, the PageFilter will think that this is system page and will allow any unsafe markup. 160 00:14:48,360 --> 00:14:51,960 For example, we can use ObjectDataSource control to start calculator. 161 00:14:52,860 --> 00:14:55,480 Let's see how the real attack may look. 162 00:14:59,240 --> 00:15:02,620 We can see a site page with our payload. 163 00:15:02,820 --> 00:15:03,920 Path to system page. 164 00:15:03,920 --> 00:15:06,700 It will be assigned to AppRelativeVirtualPath. 165 00:15:07,280 --> 00:15:10,680 Unsafe markup contains ObjectDataSource control. 166 00:15:11,080 --> 00:15:17,340 We will invoke start method of the process type and we'll start calculator. 167 00:15:17,500 --> 00:15:19,400 Let's save it here. 168 00:15:20,360 --> 00:15:23,660 For our attack, we need to upload it to the target server. 169 00:15:23,660 --> 00:15:26,320 In our case, it's SharePoint with default configuration. 170 00:15:26,320 --> 00:15:33,140 That means regular users have access to their own personal sites and we can use them to host our site page. 171 00:15:33,140 --> 00:15:36,120 We are notificated as regular user with name attacker. 172 00:15:36,400 --> 00:15:37,920 Sneaky, isn't it? 173 00:15:38,020 --> 00:15:41,360 And here is his personal site. 174 00:15:41,360 --> 00:15:43,340 Let's upload our page here. 175 00:15:44,100 --> 00:15:47,080 Now, to trigger our attack, we just need to click on it. 176 00:15:47,080 --> 00:15:52,080 But before that, let's take a look on the right slide of our screen. 177 00:15:52,200 --> 00:15:57,380 We can see task manager on our SharePoint server and we will notice if calculator start. 178 00:15:57,380 --> 00:16:02,680 Now, let's start our attack and here is our calculator. 179 00:16:03,680 --> 00:16:06,700 Let's move to our next vulnerability in SharePoint. 180 00:16:06,700 --> 00:16:10,240 Now, we will try to exploit read access to nested properties. 181 00:16:10,240 --> 00:16:12,080 We will use control parameter. 182 00:16:12,080 --> 00:16:18,220 It allows to bind value of property from another control to select prop parameter. 183 00:16:18,240 --> 00:16:20,920 Also, it supports nested properties. 184 00:16:20,920 --> 00:16:24,600 We need to deliver value of target property back to us. 185 00:16:24,600 --> 00:16:33,200 To do this, we will use XML URL data source control that sends value of select parameters to external server. 186 00:16:33,280 --> 00:16:38,500 Now, we need to find accessible property with sensitive information. 187 00:16:38,600 --> 00:16:44,060 Here, we should explain a little bit configuration process of SharePoint online servers. 188 00:16:44,060 --> 00:16:47,220 Obviously, they are installed and configured automatically. 189 00:16:47,220 --> 00:16:51,620 But what about configuration parameters that are unique for each installation? 190 00:16:51,960 --> 00:16:57,580 They will be provided in special file that will be used for unintended configuration. 191 00:16:57,620 --> 00:16:59,600 What is important for our attack? 192 00:16:59,600 --> 00:17:06,040 All such parameters, including validation key, will be stored in initialization setting property. 193 00:17:06,040 --> 00:17:11,760 So, we just need to find a path of nested property to it from any allowed control. 194 00:17:11,760 --> 00:17:13,080 And here it is. 195 00:17:13,520 --> 00:17:20,620 Here is the whole page that will send value of validation key to attackers.server.com. 196 00:17:20,620 --> 00:17:26,970 With this value, we successfully got arbitrary code execution by unsafe deserialization in view state. 197 00:17:28,220 --> 00:17:31,420 Now, let's move to the next type of security problems. 198 00:17:31,420 --> 00:17:35,880 It is connected with our previous work on unsafe deserialization. 199 00:17:35,880 --> 00:17:47,120 Such kind of problem is relevant when text or binary data is converted to an object and the type or class of this object is under attacker control. 200 00:17:47,120 --> 00:17:50,680 Plus, it is not properly limited. 201 00:17:51,000 --> 00:17:54,940 Actually, it doesn't really matter what mechanism is used. 202 00:17:54,940 --> 00:18:02,060 Classical deserializers, JSON unmarshalers, type converters, or even some custom approach. 203 00:18:02,060 --> 00:18:04,500 All of them are potentially dangerous. 204 00:18:04,500 --> 00:18:09,560 For successful exploitation, attacker just may need to find proper gadget on the system. 205 00:18:10,240 --> 00:18:18,100 We have found examples of such problems in SharePoint and were able to perform arbitrary code execution attack using it. 206 00:18:18,160 --> 00:18:20,340 But patch is not available yet. 207 00:18:20,340 --> 00:18:25,380 So, we are going to publish all details of this problem when fix is released. 208 00:18:25,700 --> 00:18:33,280 The last type of security problems in this part is the classical time of check to time of use problems. 209 00:18:33,280 --> 00:18:41,000 They occur when the server invalidates some input, but this input is later changed before the server uses it. 210 00:18:41,200 --> 00:18:44,960 We have found such problem in web part editing surface page. 211 00:18:45,040 --> 00:18:58,580 User input is validated by the already mentioned verify control on safe list method, but later the server may modify the input and remove substring that match specific regex pattern. 212 00:18:59,440 --> 00:19:01,580 Let's look on the next input. 213 00:19:01,580 --> 00:19:10,920 For validation control on safe list, it is just one server-side comment block, so it will pass validation. 214 00:19:11,100 --> 00:19:18,860 But SharePoint removes the highlighted yellow substring and pass control will see two comments and some markup. 215 00:19:18,860 --> 00:19:24,540 Note, pass control has only one argument, so patch filter will be ignored. 216 00:19:24,980 --> 00:19:26,900 Time for our payload. 217 00:19:26,900 --> 00:19:31,640 We can notice our unsafe object data source control and calculator command. 218 00:19:31,940 --> 00:19:41,160 In this part of our talk, we saw multiple ways to achieve arbitrary code execution on the SharePoint server by regular user. 219 00:19:41,720 --> 00:19:48,280 These vulnerabilities revealed five different types of security problems in content management system. 220 00:19:48,700 --> 00:19:57,660 Now let's switch back to Alvaro and he will present even more vulnerabilities with templates for dynamic content in different Java frameworks and products. 221 00:19:58,240 --> 00:19:59,740 Thank you, Alexander. 222 00:19:59,740 --> 00:20:08,480 So switching to the Java part, we will be reviewing four of the most popular Java template engines, including FreeMarker, Velocity, Pebble, and GeneJava. 223 00:20:08,480 --> 00:20:19,040 And also we will be reviewing 10 different content management systems that are using these engines and then we will be trying our bypasses on these content management systems. 224 00:20:19,080 --> 00:20:22,300 So a brief introduction into what template engines are. 225 00:20:22,300 --> 00:20:25,980 Basically these are systems that take two different inputs. 226 00:20:25,980 --> 00:20:39,920 One is the template where we are mixing static and dynamic expressions and also the template context where we store objects that are required by the engine in order to resolve the dynamic expressions in the template. 227 00:20:39,920 --> 00:20:43,120 For example, here we have the user.name expression. 228 00:20:43,120 --> 00:20:50,900 In order to resolve it, we need to get access to the user object in the context and then invoke the getName method. 229 00:20:50,900 --> 00:21:03,500 So because it's invoking Java methods, it's basically dangerous in the sense that attackers can execute arbitrary Java code and that's the reason why most of them are sandboxed in order to prevent arbitrary code execution. 230 00:21:04,460 --> 00:21:22,020 So apart from the objects that are normally and directly used by the template, there are a number of other objects that are exposed as part of a template API that is normally provided by the content management systems, which basically provides objects such as, 231 00:21:22,020 --> 00:21:27,180 for example, the request, the response, the separate context, or even the HTTP session. 232 00:21:27,180 --> 00:21:34,960 So those objects are available in most of the template APIs and also many more that are part of this API. 233 00:21:35,440 --> 00:21:39,880 So we will be discussing first some generic bypasses. 234 00:21:39,880 --> 00:21:48,340 That means that are independent of which engine is used, no matter if it's FreeMarker, Velocity, Pebble, or GeneJava, right? 235 00:21:48,340 --> 00:21:58,120 So those bypasses are based on finding different objects that we can use to get arbitrary code execution. 236 00:21:58,120 --> 00:22:02,800 So we need to inspect the template context and look for this kind of objects. 237 00:22:02,800 --> 00:22:13,980 In order to do that, if we have access to the JVM, we can basically debug it or we can instrument it, dump the template context, and inspect and analyze all the objects in there. 238 00:22:14,040 --> 00:22:30,040 However, if we don't have access to the JVM, we will have to read the template API documentation, maybe do some brute forcing in order to guess names like, for example, request or rec or response resp and things like that. 239 00:22:30,040 --> 00:22:39,620 And also in some of the engines, like, for example, FreeMarker, it is possible to list all the variables or objects that are exposed in the context. 240 00:22:40,040 --> 00:22:48,080 So apart from those objects that are directly exposed to the context, we have some objects that are indirectly exposed. 241 00:22:48,080 --> 00:22:59,260 Like, for example, if we are exposing the HTTP session because it contains some attributes, all of those attributes will be available for the users and attackers to access and use. 242 00:22:59,260 --> 00:23:02,820 Same thing with the servlet request and same thing with the servlet context. 243 00:23:02,820 --> 00:23:10,820 So those are stores of attributes, stores of objects that the attacker can get access to and use to look for interesting objects. 244 00:23:11,160 --> 00:23:15,660 So let's see how many objects we can find in one simple content management systems. 245 00:23:15,660 --> 00:23:17,680 In this case, it will be LiveArray. 246 00:23:17,680 --> 00:23:40,140 And in order to do that, we will be generating this template that I'm showing you, which basically is listing all of the context variables, then all of the request attributes, then we will show all the request, sorry, the session attributes, then the servlet context attributes. 247 00:23:40,140 --> 00:23:52,740 And because the servlet context will expose the Spring framework context, we will be also listing all of the Spring bins, all the objects registered in the Spring context. 248 00:23:52,740 --> 00:24:01,500 So if we render that, you will see that we have a bunch of objects directly exposed to the context. 249 00:24:01,500 --> 00:24:03,660 Those are part of the template API. 250 00:24:03,840 --> 00:24:06,460 And some of them are very interesting. 251 00:24:06,460 --> 00:24:13,080 Others are exposed as part of the request attributes, session attributes, and servlet context attributes. 252 00:24:13,080 --> 00:24:24,200 So as we can see here, we have interesting objects like an instance manager or, for example, the web application context for Spring that we use to list and access all the Spring bins. 253 00:24:24,200 --> 00:24:28,380 So as you can see, there are hundreds and thousands of objects here. 254 00:24:28,420 --> 00:24:31,660 There is a total of almost 900 objects. 255 00:24:31,660 --> 00:24:39,060 And because some of them will have public fields that we can get access to, then this number will increase to thousands of objects. 256 00:24:39,720 --> 00:24:41,520 So back to the slides. 257 00:24:41,520 --> 00:24:55,460 This is why we call it object dumpster diving, because this is how we felt when trying to find very few interesting objects that can lead to remote code execution among, you know, thousands and thousands of objects. 258 00:24:55,460 --> 00:25:01,560 So now we will be reviewing the top three objects that we found that lead to remote code execution. 259 00:25:01,560 --> 00:25:08,700 So for example, the first one, the class loaders, was available in 10 out of the 10 content management systems that we analyzed. 260 00:25:08,940 --> 00:25:16,440 So normally you can get access to this class loader instance through the get class loader method in the class type. 261 00:25:16,860 --> 00:25:21,360 But that is normally blocked by any block list by any sandbox. 262 00:25:21,360 --> 00:25:26,640 So you can still get access if you get access to a protection domain or a servlet context as we saw before. 263 00:25:26,760 --> 00:25:36,440 So once that you get access to a class loader, you can obviously load arbitrary classes and then also load arbitrary resources from the class path. 264 00:25:36,520 --> 00:25:47,680 But apart from that, you get access to a URL object and then from there you can access any file from the file system that the application server has permissions to access. 265 00:25:47,680 --> 00:25:49,280 So here you have an example. 266 00:25:49,280 --> 00:26:00,020 You get the URL using the get resource method and then you point the URL to the password file and then you open a connection and read all the bytes from that file. 267 00:26:01,200 --> 00:26:25,320 So apart from the standard class loaders, because content management systems are normally deployed on top of servlet containers or application servers, the instance of the class loader that you will be able to access is normally an instance of a web application class loader that are slightly different because of the way that class loading delegation work, 268 00:26:25,320 --> 00:26:33,040 but also because they expose a number of additional methods that are not part of the abstract class loader class. 269 00:26:33,060 --> 00:26:34,800 So here are just some examples. 270 00:26:34,920 --> 00:26:49,240 Just mentioned because we don't have time to cover them in this talk, although it's explained in the white paper that we are publishing as part of this talk, there are different ways of using these methods in this web application class loader to get remote code execution. 271 00:26:49,260 --> 00:27:04,080 Just to mention some of the vectors, we will be able to upload web cells, instantiate arbitrary objects, perform JNDI injections, or even initialize attacker-controlled classes. 272 00:27:04,220 --> 00:27:14,860 So we were able to find web application class loaders in nine out of the ten content management systems that we analyzed. 273 00:27:14,860 --> 00:27:26,580 And then the second object, the second most easy to find object in this template context was the instance manager or the object factory. 274 00:27:26,660 --> 00:27:39,120 So this was found in nine out of the ten content management systems and is normally found as part of the self-led context attributes, but also it can be accessed through one of these web application class loaders. 275 00:27:39,120 --> 00:27:44,560 So if you get access to an instance manager, what you can do is basically instantiate arbitrary types. 276 00:27:44,660 --> 00:27:48,280 So with that, it's very easy to escalate to remote code execution. 277 00:27:48,280 --> 00:28:01,780 Here we have an example using the script engine manager, but there are a bunch of classes that can lead to remote code execution, ones that you can instantiate them and then invoke arbitrary methods on them. 278 00:28:02,400 --> 00:28:06,940 So the number three object was a Spring application context. 279 00:28:06,940 --> 00:28:12,420 It was only available in four out of the ten CMSs that we analyzed. 280 00:28:12,420 --> 00:28:16,660 Actually, the only four that were using the Spring framework underneath. 281 00:28:16,660 --> 00:28:34,780 And it's normally accessible through one of the self-led context attributes, but also if the content management system is using a Spring MVC framework for the model, controller, and view layers, then Spring will inject some additional objects in the template context, 282 00:28:34,780 --> 00:28:42,000 like this Spring macro request context that will provide access to the Spring application context. 283 00:28:42,000 --> 00:28:50,080 So once that we have access to the Spring context, we can get an instance of a class loader and initiate a class loader-based attacks like we saw before. 284 00:28:50,080 --> 00:29:01,660 We can access the Spring environment that will give us access to the system environment and also the system properties and also Spring properties, including things like encryption keys and so on. 285 00:29:01,660 --> 00:29:09,300 But probably more interesting, it will give us access to the Spring bins registered in this Spring application context. 286 00:29:09,300 --> 00:29:24,700 So being able to access and manipulate those bins, we can basically control the application logic and do things like register new users, delete users, perform transactions, anything that the application is normally doing. 287 00:29:24,700 --> 00:29:27,880 So that's normally behind an authorization layer. 288 00:29:27,880 --> 00:29:31,060 So no matter what roles we have, we will be able to perform 289 00:29:34,200 --> 00:29:36,860 this kind of application logic control. 290 00:29:37,320 --> 00:29:54,540 So apart from that, we will also be able to disable the template engine sandboxes if we are able to get access to the template engine configuration bins and also instantiate arbitrary objects, like we will see later, by accessing JSON or XML and marshalers. 291 00:29:55,840 --> 00:30:02,540 So those were like genetic bypasses, independent of what template engine was used underneath. 292 00:30:02,540 --> 00:30:09,020 And now we will be reviewing some specific sandboxes bypasses for each of these four different template engines. 293 00:30:09,020 --> 00:30:27,760 So we will start with FreeMarker because it's probably the most popular one and also because, well, it was analyzed and researched by different researchers in the Like, for example, James Kettle back in 2015, when he presented server-side template injection vulnerability class. 294 00:30:27,860 --> 00:30:31,120 By the way, if you haven't watched this talk, it's highly recommended. 295 00:30:31,120 --> 00:30:40,460 He presented a bypass that is based on a kind of add-on or module that is deployed on the default configuration of FreeMarker. 296 00:30:40,720 --> 00:30:59,900 So Tony Torralba last year presented a different bypass, but this one is not universal in the sense that it depends on a non-default configuration and also being able to find gadgets in third-party libraries that may or may not be available in a specific target. 297 00:31:00,120 --> 00:31:14,320 Then Ryan Hanson this year, probably at the same time that we were doing this research, presented a vector that leads to remote code execution by uploading a web shell, but this is not universal in the sense that it only works with Tomcat servers. 298 00:31:14,320 --> 00:31:30,440 So FreeMarker sandbox is a method-based block list, which basically means that, for example, methods like the getClassLoader method in the java.lang class is blocked and you cannot get an instance of a class loader using this method. 299 00:31:30,440 --> 00:31:36,820 But as we mentioned before, you can still use the separate context or the protection domain to get access to these class loaders. 300 00:31:36,900 --> 00:31:50,240 Once you get access to a class loader, the class loader methods are not blocked by the block list, so you can still interact with them, load classes, get resources, or initiate remote code execution attacks that we saw before. 301 00:31:50,240 --> 00:31:58,320 And also reflection is forbidden to set fields values, but is allowed to get and read field values. 302 00:31:58,960 --> 00:32:08,540 So we use that to perform an attack, but this attack is not universal in the sense that it depends on being able to find an instance of a URL class loader. 303 00:32:08,540 --> 00:32:15,280 So this is normally the case in Tomcat, GlassFish, and Jetty, but it's not universal for other application servers. 304 00:32:15,280 --> 00:32:21,640 So in this case, we are basically getting the URL class loader from the protection domain or from the separate context. 305 00:32:21,640 --> 00:32:35,060 And then we are basically instantiating, by invoking this new instance method, a new URL class loader that is pointing to the attacker control jar file, in this case the pawn.jar file. 306 00:32:35,160 --> 00:32:43,600 Once we get access to this class loader, we can load arbitrary classes from our own jar file, and we will be loading the pawn class. 307 00:32:43,600 --> 00:32:47,520 And now the class is loaded, but it's not initialized. 308 00:32:47,520 --> 00:32:51,940 If we want to run arbitrary code, we need to initialize the class. 309 00:32:51,940 --> 00:32:56,020 We cannot instantiate the class, we cannot invoke static methods. 310 00:32:56,020 --> 00:33:05,900 So those vectors, those ways of initializing the class, are not a possibility for us, but we can get access to public static fields. 311 00:33:05,900 --> 00:33:12,500 So just by adding a public static field and getting access to that, the class will be initialized and the payload will be executed. 312 00:33:13,240 --> 00:33:26,360 So that was not a universal bypass in the sense that we are required to find an instance of a URL class loader, and we want to find something that works no matter if we are able to find that kind of class loader or not. 313 00:33:26,360 --> 00:33:38,180 So we are interested in finding some classes that contains public static fields of a given type, which contains a method that we can use to instantiate arbitrary types. 314 00:33:38,180 --> 00:33:48,680 To find them, we use CodeQL, which is a language that you can use to query your source code in the same way that you use, for example, SQL to query a database. 315 00:33:48,780 --> 00:33:58,480 And what we wrote was this query that basically says, okay, find me all the public static fields which are of a given type that can instantiate arbitrary types. 316 00:33:58,600 --> 00:34:03,980 We run this query on FreeMarker source code, and we found four different results. 317 00:34:03,980 --> 00:34:17,960 Those are four different fields of different types, but all those types extend from the bins wrapper type, which contains a new instance method, which we can use to instantiate arbitrary types. 318 00:34:18,220 --> 00:34:24,520 Now, this is the universal remote code execution bypass for FreeMarker. 319 00:34:24,640 --> 00:34:38,900 Basically, we need to get us access to any type of class loader from either the protection domain, separate context, and then load the object wrapper interface and get the default wrapper field from this interface. 320 00:34:39,000 --> 00:34:42,140 And then we can use that to instantiate arbitrary classes. 321 00:34:42,320 --> 00:34:51,980 Since we want to have this payload basically contained in FreeMarker classes, we are using the execute class in order to run arbitrary system commands. 322 00:34:51,980 --> 00:34:56,540 But you can use other payloads, to get arbitrary code execution. 323 00:34:56,540 --> 00:35:00,220 This was fixed in version 2.30 of FreeMarker. 324 00:35:01,280 --> 00:35:12,780 And also, if you get access to the Spring Bins, and you can get access to the FreeMarker configuration, as we saw in some of the content management systems that we analyzed, you can basically disable the sandbox. 325 00:35:12,780 --> 00:35:24,620 For example, you can get the class resolver for the default configuration that is non-sandboxed, and then set that class resolver as the class resolver for the current and sandboxed configuration. 326 00:35:24,620 --> 00:35:33,520 So effectively disabling the sandbox and being able to execute the old payload from JamesKettle once again. 327 00:35:33,900 --> 00:35:41,500 So now we will be reviewing eight different ways to escape the sandbox and get remote code execution in LiveArray. 328 00:35:42,800 --> 00:35:44,460 So let's see 329 00:35:47,560 --> 00:35:50,220 our LiveArray instance here. 330 00:35:50,220 --> 00:35:59,630 And what we will be doing is basically using this template. 331 00:35:59,630 --> 00:36:12,770 And here, what we are going to do basically is, first of all, we are going to use the class loader payload, which will allow us to read the password file using the URL trick that we explained before. 332 00:36:13,130 --> 00:36:22,010 Then, because the instance of the class loader is a web application class loader, we will be using that class loader to upload a web cell by using the write method. 333 00:36:22,790 --> 00:36:27,910 This will be available in the shell JSP file. 334 00:36:27,910 --> 00:36:36,710 Then we will be also using the web application class loader to get access to an instance manager and then instantiate arbitrary classes. 335 00:36:36,710 --> 00:36:43,010 In this case, we are instantiating an expression language processor and then running the ID process. 336 00:36:43,010 --> 00:36:49,370 Then we will be also showing a different payload that depends on using an instance manager. 337 00:36:49,370 --> 00:36:52,530 This time is taken from the self-led context. 338 00:36:52,530 --> 00:36:56,210 And again, we are using the EL processor to run the ID command. 339 00:36:56,290 --> 00:37:05,990 And then we will be using a JSON deserializer as an instance manager in the sense that we will be using that to instantiate arbitrary types. 340 00:37:05,990 --> 00:37:11,850 We will be getting access to the JSON deserializer from the Spring application context. 341 00:37:11,850 --> 00:37:26,410 And because this JSON deserializer uses a while list and allow list here, we need to register or we can actually register any arbitrary types for us to use in the JSON payload. 342 00:37:26,410 --> 00:37:35,490 So, now by deserializing this JSON payload, we are effectively instantiating an EL processor and then again running the ID command. 343 00:37:35,490 --> 00:37:52,010 Same thing, but instead of getting the JSON deserializer from the Spring context, LiveRay directly exposed this JSON factory util, which we can use to create a JSON deserializer and then once again use that to instantiate arbitrary types. 344 00:37:52,030 --> 00:37:58,810 And then we will see the two free market specific bypasses that we explained a few minutes ago. 345 00:37:58,810 --> 00:38:05,810 The first one is using the URL class loader that is the case here because LiveRay is deployed on Tomcat. 346 00:38:05,870 --> 00:38:17,050 And then we can basically access our own jar file, load it, and then by getting a public static field, the class will be initialized and the payload will be executed. 347 00:38:17,190 --> 00:38:23,870 And we will be able to check the output of this payload by checking the standard output. 348 00:38:23,870 --> 00:38:34,490 And the last payload that worked in LiveRay, actually there's a couple more, but eight was more than enough, is this universal RC. 349 00:38:34,490 --> 00:38:47,950 So we are loading the object wrapper interface, loading the default wrapper field, and then using that field to instantiate arbitrary types, in this case the execute type that we will be using to run the ID. 350 00:38:47,950 --> 00:38:57,030 So now if we save this template and we will be showing the results of these payloads. 351 00:38:57,030 --> 00:39:05,390 The first one was reading the password file, the second one was deploying a web cell that we can now access and run arbitrary commands. 352 00:39:05,550 --> 00:39:12,930 The third one was using different methods to run the ID command, as you can see here, all of them worked. 353 00:39:13,110 --> 00:39:24,690 So also the URL class loader was basically running the static initializer block of this class, which is basically printing pound in the standard output console. 354 00:39:24,690 --> 00:39:25,990 We can check that. 355 00:39:26,410 --> 00:39:28,010 And here it is, so it worked. 356 00:39:28,190 --> 00:39:35,810 And back to the payloads, the universal RC payload also worked, as we can see here. 357 00:39:36,610 --> 00:39:42,970 So switching to the Velocity Sandbox, this one is based on a class and package-based block list. 358 00:39:42,970 --> 00:39:49,730 So things like, for example, the whole Java lang reflect package is forbidden and you can get access to it. 359 00:39:49,790 --> 00:39:55,650 All the methods in Java lang class and class loader are also blocked and you cannot use them. 360 00:39:55,650 --> 00:40:04,990 But when we reviewed the implementation, we found that there is a flaw in the way that this sandbox is checking the block list. 361 00:40:04,990 --> 00:40:19,290 So, for example, when you run the request and then you get access to a class loader and run the load class method, basically the execution of this method will be checked against the block list. 362 00:40:19,290 --> 00:40:24,670 And the class name of the current class loader will be checked against the block list. 363 00:40:24,670 --> 00:40:42,690 Instead of checking the whole hierarchy of classes, only the current object class will be checked against the block list, which means that because Java lang class loader is an abstract class, it won't never be the case that the current object class will be a Java lang class loader. 364 00:40:42,690 --> 00:40:51,150 In this case, it's a parallel web app class loader, which is not present in the block list, and therefore class loader methods are effectively allowed. 365 00:40:51,330 --> 00:40:59,210 There is a feature in Velocity, which allows you to invoke a static method from a Java lang class object. 366 00:40:59,210 --> 00:41:07,370 So once that we are able to load a class, we can just invoke any static method and use that to get remote code execution easily. 367 00:41:07,850 --> 00:41:10,390 So now moving to GeneJava sandbox. 368 00:41:10,450 --> 00:41:14,290 This one is based on a method block list. 369 00:41:14,610 --> 00:41:17,270 This is actually very short, only nine methods. 370 00:41:17,330 --> 00:41:23,190 And what it contains is a piece of code that is pretty effective in protecting the sandbox. 371 00:41:23,190 --> 00:41:30,530 So every time that method invocation happens as part of the evaluation of the template, the result type will be checked. 372 00:41:30,530 --> 00:41:38,690 And if it's an instance of a Java lang class, then it will throw an exception and it will refuse to return a Java lang class instance. 373 00:41:38,690 --> 00:41:48,450 By not being able to get in access to arbitrary classes, we are normally not able to get or to be able to instantiate arbitrary types. 374 00:41:48,450 --> 00:41:50,570 However, we found a flaw. 375 00:41:50,630 --> 00:42:02,290 As you can see here, the invocation of a class cannot return a Java lang class instance, but it can return an array of Java lang classes or a map including Java lang classes. 376 00:42:02,290 --> 00:42:08,990 So what we can do is find a method returning an array of classes and then accessing any arbitrary item of this array. 377 00:42:09,550 --> 00:42:22,110 So the second part of this bypass was basically being able to access a secret or hidden variable in the context that is called __interpreter in lit speech. 378 00:42:22,110 --> 00:42:30,570 So by using this hidden variable, we were able to access a bunch of different objects, including all the context objects. 379 00:42:30,570 --> 00:42:37,150 And we were able to use those two parts to get an instance of a class loader. 380 00:42:37,150 --> 00:42:40,930 So as you can see here, we use the interpreter to get the context. 381 00:42:40,930 --> 00:42:44,090 And from the context, we got all the functions. 382 00:42:44,090 --> 00:42:50,810 And from the functions, we got the underlying methods, which are instances of Java lang reflect method. 383 00:42:50,970 --> 00:42:58,930 And this class contains this get parameter types method, which returns an array of Java lang classes. 384 00:42:58,930 --> 00:43:07,130 So as I explained before, we are able to get an instance of any individual item of this array. 385 00:43:07,350 --> 00:43:11,670 And by doing that, we are finally getting an instance of a Java lang class. 386 00:43:11,670 --> 00:43:19,150 From there, we can get the protection domain, get the class loader, and then initiate any class loader-based attack. 387 00:43:19,850 --> 00:43:26,310 So last, Pebbles and Box, we were able to find a couple of bypasses that we reported to the maintainers. 388 00:43:26,310 --> 00:43:29,510 Unfortunately, they didn't have time to fix them on time. 389 00:43:29,510 --> 00:43:33,550 So we decided not to leak these bypasses yet. 390 00:43:33,550 --> 00:43:37,010 And we are keeping them classified for a few months. 391 00:43:37,890 --> 00:43:44,230 So with that, we will switch back to Alexander, who will wrap up the talk with some conclusions. 392 00:43:44,230 --> 00:43:45,730 Thank you, Arvara. 393 00:43:45,730 --> 00:43:49,230 First of all, let's summarize our results after this research. 394 00:43:49,230 --> 00:43:53,630 More than 30 new vulnerabilities were found and reported to the vendor. 395 00:43:53,630 --> 00:43:56,170 More than 20 different products are affected. 396 00:43:56,170 --> 00:43:59,090 We can see their names on this slide. 397 00:43:59,270 --> 00:44:03,010 Based on these results, we can make the next conclusions. 398 00:44:03,010 --> 00:44:07,930 These are not the problems of specific product or framework. 399 00:44:07,930 --> 00:44:12,270 And content management system as a class should be on Red Team radar. 400 00:44:12,630 --> 00:44:18,010 Templates for dynamic content that can be managed by user is the main target for such system. 401 00:44:18,010 --> 00:44:22,610 There are specific areas with higher risk from security point of view. 402 00:44:22,750 --> 00:44:26,850 It's a good idea to perform security review and testing for such places. 403 00:44:27,010 --> 00:44:31,910 Always try to reduce attack surface as much as you can. 404 00:44:31,990 --> 00:44:32,930 And stay safe!