
thank you so for the last nine years we've underestimated the impact of a common class of wonder abilities in PHP applications hundreds probably thousands of instances of this issue have been found we've overlooked a simple behavior in PHP which exposes them to exploitation through on serialization my name salmon one way or another I spend a lot of my time exploiting web applications while attacking web applications so what I tend to do is ask myself what vonner abilities does this app have and what's the impact of exploiting those issues the research I'm gonna talk about today doesn't have much impact on the first part of that question so I'll be talking about vulnerabilities that you've probably
thought you already knew about but I'll be giving you a different answer than you might have expected for what the impact of exploiting them is so before I talk about my own research I think it's really important to say that this is really just a tiny addition to some wonderful research done by a man called Stephan Esther about ten years ago so he discovered this issue in PHP with on serialization and so our serialization is for those of you who don't know really basically it's basically a process by which PHP converts internal objects into a string representation that can be stored in a database or passed over the wire and then converted back to an object in PHP the examples on
the slide are really simple so I've just given like an integer and a string but it can deal with much more complicated objects and what Stefan SR realized was that there's a technique quite closely related to return orientated programming called property orientated programming whereby you can construct sort of a malicious objects that if you get everything right upon being unsterilized will sort of cause a chain of methods to be caught and cause something malicious to happen so as the issue is additionally understood there's a function called uncie realized on PHP and that's called on some data and as I mentioned basically certain methods are automatically invoked upon unsee realization so there's a method called wakeup which is called whenever an
object is unsee realized and there's also a method called destruct which is called whenever an object is destroyed if we get things just right basically we can sort of chain together certain objects so that something nasty happens if you're not familiar with that issue I can't encourage you enough to sort of read Stephanie's research I gave a talk myself here three years ago I think sort of covering a lot of the same material but for the rest of this presentation you'll just have to accept that serialization is bad okay so what am I going to go through today I'm going to start by talking about something called stream wrappers which is a functionality in PHP which basically can be triggered
on any file operation and I'll go through a bunch of those and we'll end up focusing in on the what's called the fast dream wrapper which deals with a type of archive called a far archive which is sort of supposed to be the PHP equivalent of jar archives I'll talk about something called file planting so we're going to need to get one of these archives on to our target system the easiest way is just to upload one if we've got that functionality in the app but there's a couple of other things we could look at if we can't do that identifying the type of vulnerabilities that are affected by this issue then I'm going to talk about there's a really
nice tool called PHP GGC the GGC is for generic gadget chains by a guy called Charles Fong who works for handy onyx I think and that's sort of why say serial foe PHP if you're familiar with white so serial in Java exploitation and he's kindly given me permission to release a branch sort of alongside this talk which uses some of the techniques I'm talking about to embed some of the payloads that are already included with that tool in a in a far archive then I'll go through a number of case studies talk briefly about how we could defend against this issue and then a few things to take away okay so the first part of this talk is
essentially adventures in going in reading the PHP manual and I came across this cartoon which might not make that much sense at the moment but we'll go back to it after I've shown you some stuff from the manual and then it will hopefully make more sense okay so this is the page in the PHP manual which describes Stream wrappers so essentially it comes with lots of these built in Stream wrappers and there's a list at the bottom of the ones which are enabled by default and they're triggered by all sorts of different file operations so opening a file or checking your for file exists copying a file that kind of thing these have been used to other stream
wrappers have been used in lots of different sort of exploit techniques so you'll hopefully be quite familiar with the remote stream wrappers which I've grouped here file HTTP FTP and data data is not strictly remote but it does require this setting allow you are LF open to be true to use it so it sort of falls neatly into that category so these are these stream wrappers that essentially you use to access external files from PHP so it can turn a local file include into a remote file included if you can provide like a HTTP URL it will go off and grab that file and include it as code often these are the things behind server side request
forgery issues so for instance if we've got a call to file get contents and we control the argument we can give it an HTTP or an FTP argument and it will go off and get that file and finally they're activated by X X Z so X and our external entity issues the next stream wrapper I wanted to talk about is the PHP stream wrapper so that's often used for instance in local file included exploits we can use PHP code on such that input to grab standard i/o which will be what we've posted to a page if we're you know if PHP is running as a as a web server there's a quite a neat technique you can use to read the source
code of a file with a local file include because this stream wrapper includes some filtering functionality so if we included a PHP file from another PHP file it's going to try and run that but if we want to read the source code we can base 64 encode that then include it and then on our end we can basics defrauding code that and read the source code Stephan essay used a really neat sort of variation of this on one of his early on serialization exploits so he was able to put together a chain which would write arbitrary data to a file but there was a prefix on the file which was PHP Die which would stop any code after
that from running well what he managed to do was essentially base 64 decode everything before it was written to the file and that sort of nullifies this header and then he could prepare his other data to write anything to the file the next stream wrapper is glob whenever I come across this I think it's going to be really useful but it works differently from the others so you can for instance call file get contents glob and then a path and get a listing of files this is the example from the manual of how it's used so it's used with the directory iterator there and there's a page in the manual that lists all the operations supported by any
stream wrapper and the glob stream wrapper literally supports none of them so there's two stream wrap has left as they deliver and four which are both related to archives so if we're looking to exploit those what we could think about is if there's issues in the native code so maybe we could supply sort of a malicious archive and try and trigger some memory corruption or something like that that's going to be quite difficult to exploit sort of in the presence of modern mitigations like a SLR and Det now obviously there's something else there otherwise I wouldn't be giving this talk so we'll focus in on the far wrapper and within the manual it lists everything that's in a far archive and
the first thing it lists is quite interesting so there's something called a stub and the stub contains PHP code so immediately as an attacker we think what can we get it to run that code through the stream wrapper so I wrote a simple test program to set the stub to just echo something out and then to access the file through the stream wrapper and unsurprisingly it doesn't trigger that code and just to sort of confirm that everything was working as I expected we can execute that archive and the stub does get executed now as best as I can tell essentially that's the only circumstance in which that code gets run if we access that file as an executor
not wanting to be desired we move on to the next element of the file and there's something called a manifest in all four archives and if we look at the manual page which lists what within a manifest there's something very interesting in there so we can have metadata in this archive which is contained in the manifest which is in the standard serialized format so sort of again not expecting it to work but we may as well try I constructed a simple sort of test program so we define a class called test object and we set the metadata to an instance of this class and then another test program which again defines this class but also has a destructor defined
this time so that if the object gets unsterilized and destroyed it should trigger this code and we're going to access a file in the archive and surprise surprise it actually does work so if we can put serialized data within an archive and then access it through the stream wrapper that will be unsee realized and if it hadn't been so obvious you would have done something like that okay so just to sort of confirm that everything is working as I expected I made a couple more test programs so instead of getting the contents of a file within that archive we'll just check whether the file exists and also we can check whether a file that clearly doesn't exist exists and
both times the destructor still gets called so hopefully now that makes a little bit more sense so from this sort of obvious attack methodology emerges with sort of two parts so we had need to get one of these archives onto the target and then we need to reference it through the stream wrapper to cause our payload to be unsee realized and this is quite similar to local file include vulnerabilities so in that case we need to get a file onto the target and then include the source code so if you are familiar with the sort of standard on serialization issue there's a couple of differences to be aware of so when a normal uncie realization issue occurs
the application is very deliberately uncie realized something and then does something with it so it's often easy to access a number of magic methods so not just this destruct and wake up for instance there's one called two string so we could you know try and trigger a chain that way in this case the applications not really had any intention to one serialize anything so we only have destruct and wake up to start our chain from and there's a sort of a quirk that means it within a destruct chain we've lost the current paths or anything any file operations we do within that chain we need to use absolute birth okay are the I showed you
a lot of copies of this slide with the different elements of a fire archive the third element is the file contents which I hope is obvious the fourth element is a signature which it says is optional but by default PHP will only access one of these archives if it has a valid signature so that's not optional to us as an attacker okay that you've probably seen enough of the manual now so I'm going to take a few things out of it and hopefully you can trust me that this is what the manual says there's three valid formats for a fire file sort of the base file format tar format and zip format for now I'm going to ignore the zip format so
that might be useful if we were attacking a system which had some legitimate functionality which allowed us to upload a zip file but fahren tar both have some sort of interesting flexibilities in their format that could be exploitable to us so we'll start off with the base file format I've done has sort of a little hex dump with all the different elements in it and if I can from here the green is the serialized metadata in the sort of standard format so that's probably the most interesting thing to us but what I wanted you to actually notice is for the stub so that stub never got run but we can set it to essentially anything we want as long as
it includes this small segment of code and that means we can prefix a valid archive with anything we want we can put it in the stub and that will be the start of the file so we can fake a lot of file formats by simply putting data into the stub now sometimes that might not be quite enough for us and there's some interesting flexibilities in the tar file format that allow us to do something else I'm not going to go sort of into the full details of that file format but these are sort of the the important points and these two in particular so the first 100 bytes of a tar archive is the file name of the
first file in the r-mo so that's quite flexible to us we can change that and we're simply changing the name of the file and the end of the archive is marked 1,024 zero bytes and anything after that is ignored so this is quite useful for us to sort of make files that might pose as two different formats so to just to go through it really simply here's here's another hex dump this is at the start of a tar archive what I can do is change the name of that first file to what looks like gibberish but if I go through I said the first two bytes to a JPEG header the next two bytes say
basically this is a comment within the JPEG file and the next two bytes to the length of that comment now we can set that length to encompass the whole of the archive and then just carry on a JPEG file afterwards and because we've got those 1,024 null bytes the PHP when it's dealing with the archive will ignore everything after that and something dealing with the image will see the archive essentially as a comment and everything else is the image so hopefully I've got one of these in the distant so this is just a picture of my cat you're missing some good pictures of my cat prepared like a song-and-dance routine
so make sure so HDMI so I meant to strike finish a PC right back to the important stuff a picture of my cat if I change the file name of the picture might go and open it with an archive program we can see it's recognized as a tower right so it's got this unusually named fun in it but it's also got all the elements of a file file which I mentioned earlier so it's got the stub and the metadata which is in the standard PHP serialized format and it's got the signature which isn't really sort of human readable but so we can see that it's essentially a perfect polyglot so the you know depending on which
application is using it it views it as a perfectly legitimate sort of file of that format so I mentioned earlier about our sort of fall planting so is there anything beyond just uploading a file to the target application we can do to get one on there so there's a couple of tricks from local file inclusion that we could use I've referenced them there so Brett Moore came up with a really cool technique with PHP Mpho whereby basically if you upload a file to a PHP page it gets saved to the temporary folder and the dollar underscore files array gets populated and if I'm PHP info outputs this so it will tell us where that temporary file is but as soon as
PHP info has finished outputting it will delete that file but what we can do is sort of store PHP info by refusing to receive its output once we've got what we need and that will cause the fire to persist for some time Jimmy ran smart demonstrated that there's basically really low entropy in the names of these files on windows so a bit of feedback I've had after I gave this talk last week if black cat has made me realise that one of the things I put up here isn't really feasible so the session file stuff you can only trigger this on a file which has an extension so in Windows the temporary files will have
the TMP extension but in Linux they won't and as far as I know in both session files won't have an extent you can't trigger this issue on a file with no extension and then finally up but sort of mentioned log files there I've not managed to pull it off but in theory it's possible it's quite difficult too we need to know the entire contents of the file to calculate a valid signature for whatever we're going to append on the end of that file or you know in the middle of it okay so in terms of identifying the vulnerabilities that are affected by this it's essentially all X X E and a number of SS are F issues on PHP applications I
thought it was worth mentioning that there's an option which is sometimes used to protect against exit C which is the no net option which says no network because this is dealing only with local files that doesn't protect against this if we're looking to sort of detect the fact that we can use Stream wrappers you know in a black box way it's much more preferable to use the FTP wrapper than the HTTP wrapper because it supports a lot more operations and I'll demonstrate that shortly if we've got no way to sort of connect our band with ourselves we can try using the file stream wrapper and observing the behavior of the application so essentially if it behaves
a certain way with a valid path and we can chuck file colon slash slash in front of it then that probably means that stream wrappers are working ok so PHP GAC is basically why so serial for PHP I've just taken all the good bits and written a couple of lines of code to basically put the the palos which are already included with that into a fire archive using the techniques are discussed a quick note on the payload so so to have them work with the demos I'm doing today I'm doing most of them against the latest version of PHP and there's kind of a defense-in-depth change that's been made so you used to be able to dynamically call a function
called the sir which would evaluate as PHP our strengths but they've prevented you from doing that now so I'm simply calling a function called passed which calls out to a system command and spits the output out if we're sort of attacking a hardened system and it has functions that pass through our exit you know banned most applications seem to use this library manager called composer and that includes a simple function which wraps include so we could abuse that to include PHP code from another file so all the case studies I'm going to go through today were found with manual analysis two of them could have been easily found with this sort of FTP kernel such techniques I talked about
earlier and they all use just a simple uploading a file onto the target to place it there okay so the first one I'm going to look at is a CMS called typo3 many things to a developer called Oliver Haider who helped to fix the issue so the the code path from user input to where the vulnerability is is fairly complicated but the the vulnerability is hopefully fairly clear from here so where we end up is with file exists being called on a URL decoded value so when it's trying to work out what type of path were giving it it's issues when it processes links but when it's trying to work out how to process the but it
does things like check if it's got colons or slashes in it and says I know that's a remote file but it does that before then URL decoding so as long as we encode for instance the colon we can trick it into thinking it's dealing with a local file and it will call file exists on a path completely under our control
they say the first thing we need to do is generate a payload like any sensible person but lots of pictures of my cat and my pictures further if at first if I run PHP did you see - yeah that this will list the payloads it's not formatted very nice so I mentioned some of these are so some of them were two string payloads so we can't use them you know with this exploit but what I'm going to do is so I'm taking as the input cat one dot jpg I'll output ip3 dot jpg I'm going to use a payload of brother Loki one and I'm going to try and run the command do you name - I ok
so that's written into my pictures directory type it's reader jpg so I'm running this demo just as admin this CMS of implements of fine grained access model and it doesn't come with any standard roles or anything like that the functionality I'm abusing would be accessible to lots of non admin users
[Music]
so I'm going to upload the payload that I generated earlier and actually what I'm going to do I'm just going to listen on port 443 on me so I'm listening on port 443 on another server and I'm going to try and trigger the FTP stream wrapper to sort of demonstrate that Stream wrappers are being activated so if I go to any page and add some content
add an image is element that has a link as long as I encode that colon so that's connected back to us and we can see that the FTP stream app has been activated I can do my poor impression of an FTP server and we can see that it's trying to access xxx why why why
so if instead of using the FTP Stream wrapper we access that payloads through the faster a mapper hopefully
[Music]
try again I thought I was so clever when I fixed the damage to work not online that's that's what this turns me right that's right this is the request
so somewhere down here this be saying that the link to that far and if we intercept the response at the top there and see it's triggered the pilot and yeah that's the end of that demo there's not okay so the next step over is in WordPress and when I first found this issue so that you know they ultimately the issue is in PHP but we need to find vulnerabilities in applications to exploit it so I found this issue in WordPress and thought how that'd be a you know a good one to demonstrate it and thought they would fix it fairly quickly you can see when I reported it and it hasn't been fixed yet so you know
I've ended up feeling that the only responsible thing is to disclose it as it is so this is this is my favorite of the vulnerabilities because it's slightly more subtle and this is ultimately where the vulnerability is so it calculates this variable thumb file and it ends up calling file exists on it but the way it calculates this variable is it takes this value file calculates the base name of that and it replaces every occurrence of that with this value thumb and there's no guarantee that the base name of the file only occurs once so what we're going to do is try and get it to replace the start of the file rather than just the end so write this
value file comes from this function get attached file and in most cases that prepends the applications sort of upload directory to to the file name but in certain circumstances it doesn't so if the file starts with a slash then it's a Linux absolute path but if it starts with a single character then a codon then a forward slash then it's a Windows absolute part so despite the fact that we're attacking a Linux system we're going to give it a file path that looks like a Windows absolute path and as you know abused this functionality to end up replacing the start of the file name and therefore activating the stream wrapper in terms of the payload I'm
going to use today until fairly recently so November 2017 there was a payload that I presented here three years ago which went from two string two code execution they've made some changes since then and that payload is no longer valid so we have to try and find another one WordPress is quite limited in what classes you can use to construct these kind of payloads so sort of looking through the the classes that are there there's a one that really stands out which is this requests utility filtered iterator which is an array iterator so this essentially backs an array and when you iterate through an array this is the code that gets executed and this uses a
property defined for bet so if we control the object we control this callback and we can call any function we want with any argument we want now this is obviously only triggered by iterating through the array so we need to find something else to iterate through the array I looked around you know both the classes that are already loaded and WordPress and a few system classes and couldn't find anything to do this so the natural sort of next step is to look if there's any common plugins that have anything like this and there's a very common plug-in for the word commerce and that includes a class which has a fairly benign looking destructor because it's
just for closing files but the thing that it does that's useful for us is it iterates through one of its properties so we can use that to trigger the other part of the payload let's have a look at this turn now for this demo I sort of scripted it because there's quite a lot of you know grabbing various values from various places WordPress seems to run horribly slowly on my computer so apologies so I was just this is the one case where WordPress has sort of predefined roles and stuff like that so it's quite clear what user we can do this asked if I can log in the server right so this is the latest version of WordPress and has the
latest version of WooCommerce installed on it one of these should be users users and so I've set up a user called author which is a member of the earth or Alf so WordPress goes of anonymous subscribers authors editors admins so you know this issue is only exposed to authenticated users but they're certainly not supposed to be able to execute code
this should hopefully do everything for me so the first thing it does is upload the file is doing it through XML RPC so the value is base 64 encoded but we can have a look at that file in here it's basically got sort of a JPEG header on it but not much more and then it goes straight into the stub and has are serialized payload in the metadata exception so it'll upload the file slowly so it's uploaded to file and then we need to just log in to the normal user interface to grab a cookie basically all right so it's logged in and got his cookies we're gonna use this one here is the admin cookie or the you know the backend
cookie so using that cookie it's then going to access the page to edit the post that represents the file that we just uploaded we need to access that page to get something called the nonce which we're going to need to do the next stuff that we need to do so it's grabbing the value of this non sear and then it's using that and it's setting the file name to Zed colon slash said so when the code that we looked at earlier replaces the base file it's going to replace the said at the end but it's also going to replace the Zed at the start because the start of the file is the same as the basepart
but eventually go through so now it's going to set the thumb value to a fire path to access the payload that we just uploaded and now finally when it triggers the it triggers the thumbnail functionality through this XML RPC call to work press get meteor item so hopefully if I intercept the response to that down on the bottom we've called you name - a again we'll see how fast it sphere
it's just to say you know we can call any girl my [ __ ] is closer I'll leave that running in the background okay so the final case study is in a library called TC PDF I'm going to exploit it through CMS could console but really the important point is this is that this is in quite a widespread library so as far as I know this is the standard library and PHP applications to convert HTML to PDFs and in quite a simple way of sort of exposes the issue so in this sort of standard application scenario there's some situations where we might be deliberately given access to the HTML that's being sent to a PDF but also we
often find we can sort of cross-site script into some code that's then being rendered into a PDF and the vulnerability is like I said quite straightforward essentially it's it you know runs a tag handler through all the tags at the HTML and if it encountered an image tag it calls this function image with the source attribute and that does a few things but you know full story to a file exists called with with the value as we supplied it so let's look at that
so we need to generate a payload again
and try cutting ezc faster this time [Music]
again the same as the first demo it's a you wouldn't need to be an admin to access all this functionality but I haven't set up a bunch of users with the various different parameters so the CMS includes this article functionality and there's a setting you can have on articles to allow them to be exported as PDF which then uses the library so I've got this article set up I've just got the contents there's xxx yyy that should generate PDF latex yyy if I edit the content of that
so first I'm just going to put an image tag that literally references the image with no stream wrapper so I'm just using a relative path to the image in the code now if I save this the HTML view of the article won't work properly because that's the browser is looking for that relative path and not finding it but the PDF asked me did I upload the image
we try that again we got a PDF with the image and define try that so you can see it's still breaking you know in the browser but if I put the father in front of this see even more broken in the browser because that doesn't understand the file you are a little if we send it to the PDF Janerio triggers the failure
okay so in terms of defending against this issue obviously it would be ideal to avoid those types of vulnerabilities altogether but bearing in mind that they were already nine types of vulnerabilities and we're still finding them in applications now that might not be that realistic sort of IPS is IDS's antivirus software should be able to detect this quite easily you know with signatures and things like that it doesn't seem possible to disable that the sort of behavior of that stream wrapper from the command line or PHP dot ini' but you could potentially you know a disable it during compilation I've spoken to PHP about the issue a couple of months ago I haven't heard back but hopefully in the long term as
they will address this issue so what do I want you to take away from the presentation more broadly than just PHP we're seeing a lot of unsee realization issues in multiple languages and they're made a lot worse by you know I've said complexity there but bloat is probably the right words you know people are adding libraries to applications and not worrying about whether they're used anymore or not not removing them we're starting to see some libraries implement sort of defensive codes they're trying to you know remove behaviors that are very useful for on serialization exploits by abusing this streem wrapper you know we can exploit a number of different vulnerabilities so xxe yes srf you know certainly if certain settings
are set so for instance allow URL F open is set to false on PHP some of these issues you probably wouldn't even pick up and you would certainly report them as very low impact on the pen test now hopefully you realize they can be used to trigger code execution and yeah hopefully I've made it clear sort of easy ways to identify the issues either looking at source code or with black box methods so I've added one slide from the talk that I gave last week because a couple of people have pointed out to me that somebody else discovered this behavior and used it in a CTF so a guy called orange side sort of said it
as a CTF challenge I think towards the end of 2017 you know I think as far as we're both aware we both just discovered the same thing independently and and yeah you know you often find that in security people have the same ideas around the same time so that's me all finished are there any questions anyone got a question for Sam yep when you were basically injecting your injection into the JPEG there's no possibility to actually insert a reverse shell so you cannot get a shot back out of it yeah so what you could do I mentioned about the the assert stuff so previous to PHP 7.2 it was really easy to with these kind of
an serialization payloads to run arbitrary PHP code which obviously you could write a whole reverse shell and and contain it within that JPEG I mentioned the composers got a wrapper for include file so if you were looking to execute sort of more complicated code than just running one command what you could do is embed in that jpay your whole PHP source file as part of the archive and then include that with the sort of composer wrapper function and then you know you'd be running a whole whatever you wanted but you reverse shell would probably be the funny things yes anyone else know don't give it up first Sam you