← All talks

2015 - James Kettle - Server Side Template Injection: RCE for the Modern Web App

BSides Manchester38:381.9K viewsPublished 2015-09Watch on YouTube ↗
About this talk
White paper - https://portswigger.net/knowledgebase/papers/ServerSideTemplateInjection.pdf Simple inputs can conceal an {expansive} attack surface. Feature-rich web applications often embed user input in web templates in an attempt to offer flexible functionality and developer shortcuts, creating a vulnerability easily mistaken for XSS. In this presentation, I’ll discuss techniques to recognise template injection, then show how to take template engines on a journey deeply orthogonal to their intended purpose and ultimately gain arbitrary code execution. I’ll show this technique being applied to craft exploits that hijack four popular template engines, then demonstrate RCE on two corporate web applications. This presentation will also cover techniques for automated detection of template injection, and exploiting subtle, application-specific vulnerabilities that can arise in otherwise secure template systems.
Show transcript [en]

Welcome back everyone. We've got Jake's coming up from Port Swigger. He's the only thing that stands between you and lunch.

Just a quick, at lunch time, NWR, who are the after party, will start giving out wristbands. So you can go there, you can get a wristband and then you can go, it's at Revolutions, Rebs is it? Yep. Up on Oxford's, Oxford Road. Just up there. So if you want to go to the party and get your face, then at the cost of them, you have to do so. Also, after lunch, in track three, the rookies will start talking. These are all the guys and girls who are speaking for the first time at a conference. Go along, show you support. They might not be the... most polished speakers, a bit like me, but they have something interesting to say normally, unlike me. So, go and ask them, that's

really good. And with that, I won't eat into any more of your time because I was going to be waiting for lunch soon. So, over to James. Thank you. Welcome to server-side template injection. You may be familiar with being so focused on exploiting an application that you missed something that was staring you in the face, or with feeling tired of seeing report after report containing nothing to do in cross-site scripting, or with simply really wanting to get a shell on a box. In this session, I'll introduce to you a vulnerability that looks a lot like cross-site scripting, but isn't, and share with you a six-step process for hijacking template engines and getting shells on boxes. My first

encounter with turnpane injection was around 80 months ago. It was on a client site, on a client engagement. And it was quite a stressful environment. People were crammed into this tiny room and there was a white product with a tally of the number of shelves that each person had got within the last few weeks. You can imagine what that felt like. And the application that I was testing had some slightly strange behavior. It let you customize emails that will be sent out to users. And these emails had some dynamic content. So where the template that I could edit said, dear, user.firstname, the user would see their actual name. And I thought, well, that's interesting. I wonder how I can exploit this. Clearly, there's

some kind of dynamic data lookup going on. I know what to do. I'll change it from user.name to user.password. And it will tell me everyone's password. It's brilliant. So I tried that and it failed completely. But what it did tell me was that this input was being processed as a free marker template by the server. And I looked up the free marker documentation and in the frequently asked questions section it said, should I allow users to submit templates? And the answer that they gave was, no, don't do this, it's really dangerous and it listed the most terrible things that Hacker could do to your server with free market templates. Which was brilliant. It was exactly what I needed. And then on a trail of

breadcrumbs through their documentation to a fully working exploit that got me a show on their server and access to a sizable amount of sensitive financial information. And that was cool. But it was really just quite a lucky one-off event. It was lucky that the application made it so obvious that my input was being processed as a template, and it was lucky that the free market documentation is so forthcoming to potential happens. Nine months ago, though, at Portsrigger, we received a report that BurpSuite was failing to find a blatant cross-site scripting vulnerability, which isn't something that happens very often. So I investigated this manually and found, once again, a server that was behaving in a slightly odd way, not what

you'd really expect, And thanks to my previous encounter with template injection, I realized that that's what the issue really was. So although the client who contacted us thought they only had a cross-site scripting issue, they actually had something a lot more serious. Actually, potentially, anyone could just walk up and get code execution on their publicly accessible, quite well-known web server. And this left me with a couple of questions. Exactly how common is template injection? How many times has someone found cross-site splitting and not realised that it's a symptom of a much more serious issue? And secondly, how serious is template injection? Is it only a free marker that can be used to take complete control over the server? Or does that apply to other popular template engines as well?

So I investigated and the results are what I'll be sharing with you now.

First, I'll introduce what template injection is, how it happens, and then I'll walk through this process for identifying and building an exploit for template injection vulnerabilities and show this process being applied to five of the most popular template inputs. Then I'll demonstrate code execution zero days in two web applications that you may have heard of but hopefully don't have installed on your own now.

Then I'll just have five minutes for questions at the end. So what is template injection? It's where user input is unsafely embedded into a template so that the user can put a template expression in their input and this will be evaluated by the server. So with this example here, the custom greeting user input is being concatenated directly into the template. So if the user puts a template expression in there, it will be evaluated. Just for clarity, this second example is not vulnerable to template rejection. This is what I would say is correct use of a template. So there is user input being passed in by the user.firstName variable, but it's being passed in as an argument rather than concatenated into a template. any expressions in

the user input won't be evaluated. This looks quite a lot like SQL injection, in that you've just got user input being concatenated into somewhere where it shouldn't be. And like SQL injection, it can happen just by accident. However, I've also seen it occur intentionally quite a few times. So developers want to let users customize templates within their application, and they maybe don't realize what the security risks are.

So the first step to dealing with this is simply to find out if a given input is being processed as a template. Then you need to figure out which template engine is in use, and then finally build an expert for it to prove that it's actually a notable issue. So to find template, injection might sound really quite easy until you realise that there are scores of different template engines out there and they all have different syntax. The way that I've found to locate it is to inject a really generic mathematical expression like 7x7 and then look at the output of the server. And the reason this is the most efficient way is because almost all template engines that support the double

curly syntax will be able to cope with that expression and will evaluate it fine. So if you repeat that payload for each of the different common types of syntax, which are shown along the bottom, then you should get decent coverage. You'll find most template engines out there. If you're just testing something manually, then you can just

just inject any old crap and see if there are some error messages that tell you which template engine is in use. But as far as automating this attack goes, that won't work. There's actually a second harder to spot way in which template injection can happen. So here, the user input is being embedded directly into a template expression itself. So it will be something like a variable name. And so if you change this value in any way, then the application will either give you the mp string back or just error out. So this example here isn't even vulnerable to cross-site scripting until you realize that you need to close the template expression using the double curly syntax or whatever the syntax of the template engine is. If you

find that when you inject that syntax after the base input and then put something off it, and the bit after it gets reflected unmodified, that's a decent sign that you've got code injection here.

Having figured out that there's some kind of processing going on with a really generic template, you then need to narrow down to find out exactly which template engine is being used. And this can be done using a decision tree based on the behavior of the server. So if this seven times seven payload works, then we know that the template engine is one of a set of template engines, and one engine in that set is Smarty. So we can follow up with this A comment B payload, which uses syntax specific to Smarty. And if that works, that tells us this is Smarty, and if it fails, then we've ruled it out. And we can just apply this technique intuitively to narrow down exactly which template

engine is being used in a fairly efficient way. If you were a Burksware user, then you will have received an update earlier this month, which will automate both of those steps for you. It will try and find template injection and tell you which template engine is being used. What it won't do is build an exploit for you, because here things start to get really quite involved. First course step,

building an expert is simply to read the documentation. That might sound really quite lame, but a lot of the time, reading the documentation is all you need to do to build a working expert. And you save yourself a lot of time if you don't skip that. If you're really lucky, like I was, then the template engine you're targeting will have a security consideration section which lists out all the most dangerous functions, and you can just use those. Some template engines are less forthcoming. And then you need to fall back to looking for lists of built-in functions and variables and such like. Just to get an idea of what the attack surface is. You almost always need to read the for template author

section because that will just tell you what the basic syntax of the template engine is. So you'll be able to do things like loop over the passwords that you'll be stealing from the server. Next step is to fully map the attack surface. Most template engines have some kind of a self object. It may or may not be documented, but this object will contain everything in scope, everything you have access to. So if you find that, and you have a way to loop around this object's attributes and methods, then you can iteratively find everything in scope. In cases where this object isn't documented, or where it simply doesn't exist, then you can fall back to running a variable report

just using a word list of variable names to see if you get any hits. And you often find a self object that does exist, but just wasn't documented. I built a word list for this express purpose and released it publicly by a set list. So you can just go and download that if you need to. Finally, you know what you've got access to, just attack it. Here you've just got the standard objectives that you would have in any web application assessment. Can I find methods that read and write files? Can I find things that are vulnerable to SQL injection? And so on. It's a bit like on the serializer, you're going to have quite a large attack service there. There may

be quite a few methods you can call. but you might have some restrictions on the arguments you can pass in. This talk is really about getting code execution. But I should mention at this point, template engines are really effective for information disclosure. Because they're being evaluated right in the heart of the server. They may well have access to environment variables and the like, which can contain all sorts of useful things like AWS secret keys. And the cool thing about grabbing those is you aren't using any fancy exploits. There's no real work. You just go, can I loop over everything and read it out and see if there's anything sensitive there. It's absolutely true. So that's the theory.

Now we're going to look at five template engines that I've selected because it shows the different ways in which the exploit development process can play out. Firstly, free market. So this is the one where the frequently asked questions section tells you what the most dangerous features are. And it says new is one of the most dangerous features. And there's quite a lot of fluff because the documentation wasn't written for hackers really. The key thing is we can use Nuke to create arbitrary Java objects provided that they implement template model. So let's have a look at template model.

When I was reading this, I was thinking, well, these sound fairly boring. But one of these classes really jumped out at me. Can anyone tell which one of those classes might be particularly useful to me? Yes, execute. Wonder what that does? Well, it executes a shell command, and it gives me the output, which is exactly what I need. So all I have to do is use this class as designed with the new built-in to execute the ID command highlighted in blue. And I've got a shell on the server. And the cool thing about that is that's using purely intended functionality, documented functionality. It isn't going to get patched. It isn't going anywhere. If you get a free

market template injection, you've got a pretty good chance of that working. Venocity is another popular Java template engine. And the documentation is nowhere near as helpful. It doesn't even mention any kind of self object that has everything in scope. So I ran, I fell back to running a variable name group force. And I found when you refer to the class variable, highlighters, you get a generic Java object back, which is interesting. I googled from that and found it's part of class tool. Class tool is not part of core velocity, but it's bundled with it by default, and it's enabled by default. So it might as well be, but that's why I didn't find it in

my original read through of the documentation. And the purpose of this tool is for Java reflection in templates. So using those two methods, we can really easily make an arbitrary Java object and use it to execute a shell demand on the server. This payload simply makes it sleep for five seconds, so you can time the response to confirm that it didn't work. And that's cool, but we really want the output of our shelter mark, right? And because this is Java, we're gonna have to do quite a lot more work together. However, there's nothing that complex here. I'm just using intended functionality to look around some variables and using the reflection to get some more helper classes that I need to get the

output of the shelter. So once again, I built an exploit using functionality days, not well documented at all, but there's no real exploit there. You just walk up and get shut. Smarty is a PHP template engine, and by default it's so trivial to exploit that it's not worth talking about here, but it offers a secure mode, and the entire purpose of this secure mode is to let untrusted people supply templates without giving them a shell on the server. And this is implemented using a whitelist of PHP functions. So I can't call something like system because it's not on the whitelist, right? And however, Smarty has a self object. And the self object has a method called getStream variable which can easily be used

to read an arbitrary file. So that's nice. But it's not really a shell on the server. Even better though, it lets us call arbitrary static classes. And there's a static class called Smarty Internal Write File, with a method called Write File. And what this does is it lets you write arbitrary contents to arbitrary locations, and you can also overwrite files. The only catch is that the third argument to this function has to be of type Smarty. But fortunately, using the clear config method, on the self object, we can get a reference to an object of that type, so we can effectively use that to get past that check. So we can chain those two methods onto each other and use the script name variable,

which helpfully is available by default and tells us the location of the current PHP file, to overwrite the current PHP file with a back dot.

And that's not intended to function out. Now, you might be thinking, well, for sandbox break out, that was kind of easy. It's not exactly Chrome sandbox, right? And I would agree, I get the impression that a lot of these template engines that offer a secure mode or sandbox mode haven't really been audited by anyone. So this exploit has now been patched. But the patched version, you may be able to get an exploit in there still. I think I would be very careful about trusting template engines claims about how secure their sandbox mode is. It's a technically challenging thing to implement.

Twig is another popular PHP template engine. And by default, oh wait, and it's used by Symfony. And by default, it's more secure than the smarty secure mode. So there's a PHP function like this, yes. And also we can't call static classes and we can't get object references out of functions because they just get flattered into strings. So things get a bit trickier here. There is a self object, it's not documented but you can find it by reporting it. And it doesn't have any very interesting methods itself but it has an attribute called env which is an instance of Twig environment which has some cool methods. It has a method which as a call to PHP's call user func, which is like a default PHP

function that lets you invoke arbitrary functions provided you control both the arguments to it. And here, the name variable is an argument to that function, so we can just pass that straight in. And the callback variable comes from the filter callbacks attribute, and using the register undefined callback, filter callback method, we can set this value. So once again, by chaining two methods onto each other, we can execute arbitrary shell commands on the server.

Twig also has a sandbox mode, and this is where things start to get really difficult. So we've got all the previous limitations, but we also can't retrieve attributes. So I can't get a hold on self.end. there's whitelisted method codes. So even if a developer passes in an object that has a vulnerable method, unless that method has been whitelisted, I can't invoke that method. Fortunately, however, there's a bit of a flaw in that whitelist. This is the whitelist. As you can see right at the start, there's a few lines of code that say actually, You can call any method on any object that implements one of these interfaces. And luckily, the self object doesn't implement that interface. So we can call

arbitrary methods on the undocumented self object. And there's this method called display block, meant for internal use only, naturally, which has this line that we'll call an arbitrary method on an arbitrary object. And both of these are taken from purely user input. So we can use this method as a kind of a gadget, as a proxy to invoke any method on any object that we can get a reference to. Like so. So we've effectively bypassed the method whitelist. You might have noticed that I haven't got a shell here. Sadly true. Because by default, the Twig environment doesn't contain any objects that you can get references to which it exploits for shell access to the server. But if a developer passes in

an object that has a vulnerable method and thinks the whitelist will save them, you can use this to get them. It's worth noting that throughout an application, if you've got multiple instances of template injection, they may have different objects passed in by developers. So it's worth fully auditing every instance of template injection within an application.

This one's a bit different. This is a publicly accessible website which has a bug bounty program and lets users submit templates in a variety of languages by design. And the language I'm targeting here is Jade which is a Node.js

and I didn't really know Node.js at all when I wrote this, so I might not have taken the most efficient room. But let's see how it works. This is completely black box. I don't have access to that code. So I looked up Node.js and I found you need to import a module to do any interesting file I host that. So my goal here is to be able to import a module. So first I've confirmed that I can execute commands on the app. on the web up there. And then I found the self object and found a way to iterate around this object to see what I have access to. And there were quite a few things and I just kind of kept on

exploring the following things that had promising sounding names. And eventually I ran into this. So Copac have detected that I'm using words that can be used to do bad things to their self. So that's quite promising, it's telling you I'm on the right track. If you look at how it's worded, you can kind of tell. It says, what does it say? It says, yeah, words. It kind of implies they might be using a regular expression to implement this. And yes, they are using a regular expression, so all I have to do is take that top line, which has triggered this warning, and split it into two statements. And I'm executing exactly the same code and it isn't even locked. And now I've got access

to require, which can be used in for modules. So all I have to do is import a module that lets me execute shell commands and then execute the commands and to quite the output to my Amazon server. The reason I've had to do it like this is because load is all that asynchronous and I couldn't figure out how to get the call back working. You get the idea. I just piped the output over TCP to my website. If you're on your phone trying to hack at this moment, they've implemented some more robust defenses now beyond regular expressions that I'm going to talk about later. OK. I think that answers the question, how exploitable is template injection?

It's pretty exploitable. It doesn't vary, but in general, it's definitely worth your time trying. But I haven't answered how common is it? And I can't tell you for sure how common this issue is. I haven't tested every application out there. But I have gone into it by chance a few times. And I had absolutely no trouble finding a couple of applications to demonstrate exploits in for you.

This is Al fresco, it's a content management system. And Al fresco uses free market templates to generate quite a few of its pages. So here we can see a free market template and it's used to generate this page here. And I can view this but unfortunately as a low privilege user I can't edit this. But an administrator can edit this. And fortunately for me, Alphesco has quite a serious, sort of scripting vulnerability that I can use to hide that and administrative account and make them do whatever I want. So the problem is, they want to let you supply safe HTML in comments on documents. And they do this by parsing your window. So they look at this piece of input here, and they go, right, there's an

image tag, that's fine. And then they see an attribute with a name of the empty string, which has not been blacklisted, and a value of that, which is fine, right? But what the browser sees is an image tag, some random crap, closing tag, SVG with an event handler. So my goal here is just to inject this free market back door that we saw earlier. So I've just been a little bit of JavaScript to simply grab the user's cross-eyed request for a new token, use it to overwrite that file that I showed with my back door, and when encoded it looks like that. So I'm now going to log in

as an administrator, and see what happens

when I open the file.

So from the admin's perspective, nothing happens. The payload is just down there. There's nothing to see. But if I go back to this file, So if I reload this file, then with a bit of luck, right, it's been replaced by a backdoor. Excellent. So, all I have to do now is stick a nice jump command here, and it'll be executed, and I've got the output. Nice. An extra cool thing about Al fresco is that according to the documentation, if you install it on the system with SE Linux, it will disable SE Linux permanently.

So that's the point. Okay. That's enough of our test though. Let's have a look at another application.

It's up. It is up. Okay. This one randomly goes down sometimes. Nothing to do with the way it's done. This is XWiki. It's a wiki software. Not as popular as media wiki, but I believe it's quite widely used in corporate environments. And the really cool thing about this is, by default, out of the box, anyone who walks up to it can register their own account on it. So there's no initial step of hijacking someone else's account. And if I just edit a page, I can pretty easily see that in my support, velocity, we've heard of velocity. So let's just grab my velocity payload and see what happens. It doesn't work. Down. And reading the documentation, that's because they removed class, because

they don't want people doing Java reflection in their wiki pages. So what do we do now? We just go through the X-Wiki development process. We have a look at the documentation, which says, actually, X-Wiki supports a range of different languages. Velocity is special in that users with no privileges can write Velocity. So that's cool. But it's one inside a sandbox that only has access to a few safe objects. But other scripting languages, you have to have high privileges to write them. But if you can, then you've got full access to the server. So let's have a look at the few safe APIs that we have access to with Velocity. First thing on the spot, So there's quite

a few. There's masses. We've got access to tons of stuff. But, reading through them, if you get to here, you might notice there's something a bit on. So using this object, we can edit the current wiki page, and we can save the wiki page. We can effectively make a wiki page that edits itself. And the interesting thing is, there's a method called save. And there's another method called save as author. The author of a wiki page being the person who last edited it. In other words, me. And it raises the question, if save as author saves as the author, who does save save as? Turns out, it actually saves as the person viewing the page. So, what I can do is take my

Python back door that I'm not allowed to inject because I don't have programming rights, and wrap it into Velocity. It says, dear user, do you have programming rights? If you do, kindly inject this pipe in that door for me.

So I'm just going to set this here.

I have a plan. I'm just going to put that there on the front page.

So I don't see anything out of the order, right? And now if an administrator

happens to log in,

then they don't see anything out of the order either, right? Because it's all happening behind the scenes. But now, if I were to look at that file, I would see the back door is present. And if, as my load for the chuser, I stick the shoulder back to it, then you wait for a bit, fill the tension a bit. 30 seconds, now it works. It's executed. Will it? Yeah, there we go. Okay. So that is pretty much template injection. Let's talk about the defensive side a little bit, I have been told. So, let's say you want to allow user submitted templates. It's a business requirement. Obviously my default advice is just don't do it. But if you have to do it, I would go with a really simple template

engine, something like Roustache or Handlebars. They don't really support any kind of logic. They're nice and simple. If you can't do that, then, just passing the minimal number of objects into the template. Because every object that you pass into a template is extra attack surface. In fact, I would do that in general if you think there's the slightest possibility that using the code could end up being evaluated inside the template. One approach that MediaWiki has used, which has been fairly successful for writing the state and the lack of people getting code execution on Wikipedia, is that You can write arbitrary Lua code inside wiki pages on Wikipedia, but the Lua environment, like the actual code that gets

executed, has had all the dangerous functions removed from it, so it's really hard to do any decent damage. If you're code then, and you want to support a range of different template engines, then it will be quite a lot of work to sandbox everyone individually. can, using up and coming technologies like Docker, try and sandbox the operating system environment. Obviously, I'm not saying just stick something in Docker and do the file. You need to do a lot of locking down, but what they've done is things like they've used kernel capabilities to stop these templates from being able to open any file handles. And on Linux, it's really hard to do anything bad without any file handles. And you can also

make the disk read only and set your ID capabilities and so on to create a situation where someone can sort of execute arbitrary code but they're gonna have a hard time doing anything worse than wasting lots of CPU. Okay, now I'm just gonna wrap up and take five minutes of questions. So, key things to remember are template engines, server side sandboxes. Template injection is there if you look for it and please explore a chat. Don't forget to follow me on Twitter. If you've got any more questions, I'll be at the back or you can send me an email. Thank you for listening. Any questions?

Excellent. Thank you.