
okay welcome everybody to the Gold Room we are gonna start this is Robert's Accord Java serialization the serial killer without further ado thanks so that's that's me and my fully evolved form for those of you who watch anime I guess I'm a technical director NTC group I spend my time sort of split between three activities one of those activities is developing delivering secure coding training classes in Java C C++ C sharp the material presenting today is sort of cut down from a full day I developed on serialization which is a you know sort of an interesting idea cuz now I'm trying to figure out who wants to listen to me talk about serialization for full
day but a few people have I also do secure coding research which at NCC group mainly publishing white papers there's actually is a white paper on Java serialization on are on the NCC group website people like to have a look at that and the third thing I do is code security reviews so try to keep keep my hands in it and you know make sure I sort of maintain the skillset not just you know teach so how many of you here do you Java serialization okay just David's forboden maybe three or four of you how many of you are Java developers how many of you just like came in the wrong room by accident so I'll give a
quick intro into Java serialization I I try to trim this down to fit the available time and I decided to focus on demos because I thought people liked demos so I had to kind of eliminate some of the overview stuff but Java C rosacea in general supports transformation of a graph of objects into a stream of bytes which can be stored or transmitted so you have objects which are serialized the serialized data can then be stored a file and a database or just maintain a memory and then the the objects can be reconstituted from the serialized data so of course the serialize form has to identify and verify the class information there's no source code that gets transmitted it's
just information about the actual object so to reconstitute these objects the source code has to be available to the JVM that's you know deserializing the objects and so the source code will be loaded just as Java normally loads classes you know looking through the class path and so forth so let's say we have a simple class a bicycle class we want to see I realize it it's it's exceedingly simple so we create an output stream which in this case is a file output stream to receive the bytes so basically we're creating a file called temp then we create an object output stream to decorate the file output stream object and then we call the write method on object output stream
we create a new instance of this object and call write object on it that serializes the object and then we just flush the stream to then DC realize that we just do the opposite process we create input stream which is a file input stream to leave read in the temp file and then we create a new object input stream object and then we call the read object method on object input stream to deserialize the object so read object just returns a generic object because it can be used to deserialize any type of object so typically what the developer does here is they cast the return by a read object to the anticipated type of the object
that's being deserialized so in this particular case the developers anticipating a bicycle object so there are series of callbacks that can be used to customize how objects are serialized so I a lot of times people think that if these callbacks are used that indicates that there's a problem with the code but it turns out that sort of creating these custom methods is is really sort of a necessary part of implementing serialization securely and for more details on that probably come to the six-hour class because that gets gets in the weeds so there's a write replace method which replies provides a replacement object to serialize that's basically for use with proxy objects the right object method gives full control
over writing the stream so if when if you implement right object you can either accept sort of the default serialize form or you can decide I want to only see realize these fields or you could decide that you want to write information that has nothing at all to do with the object that you're serializing you have complete control during the serialization of course you need to implement a read object method that corresponds to your write object method so you actually read in the data that was written out and the read resolve is called T replace a deserialized object with another one again basically to take a proxy object and use that proxy object to create the
actual object that you're you're trying to serialize and deserialize and then finally there's a valid object method that's called after after the objects have been created and also after it's sort of too late to ensure the security of the transaction so during serialization the write replace methods execute it first and then if it's present the right object method will operate on the replacement object not on the original object during d serialization read object is called potentially to work on a proxy object if it is a proxy object then there'll be a read resolve method invoked and then finally the call to validate the object so the validation methods executed on the replacement object not on the proxy
object that silently discarded so if you look at a UML sequence diagram here you see we have the application code and it's it's implementing those four lines of code I showed earlier to you know just read the bytes from the file or any stream initialize the object input stream then read the object from the stream with the read object method call that transfers control to the object input stream which resolves the classes the stream using resolve class so that's just the normal process of looking up the definition of the class corresponding to the object that's being deserialized and you know that could already be loaded into memory or it can be loaded by you know looking
at the bootstrap loader and looking at the class path and just the normal process by which classes are loaded so then we go to deserialize the objects and you know there can be any number of objects in the serialization stream even even serializing a single object typically that object references other objects so in order to serialize a single object that typically serializes a entire graph of objects and also you could have multiple objects in a single stream so for each object discovered in the stream object input stream is going to call the read object read resolve and validate object methods if they're if they've been implemented if not they'll call basically default versions of default version of read object so it
finally returns control to the application code which again a cast the deserialize object to the expected type in the previous example that was a bicycle and then goes and uses deserialized object and eventually these objects are finalized which people forget about and a lot of Java serialization researchers don't talk about but that that finalized call might actually be the most dangerous thing up on the slide so the security issues and here's my here's a kind of classic understatement naive use of objects serialization may allow malicious party with access to the serialization byte stream to read private data or create objects within ballot or dangerous and and the security issue in in a nutshell is that this this guy down here
who accidentally cut his hand off while slicing a sandwich he could probably implement serialization right it's just those three or four lines of code I showed you earlier but to get it right you have to be extremely knowledgeable and so this sort of gap here is is basically the security problem you know this ability to people to deploy systems that use serialization without kind of understanding how these things can be attacked so default serialization of object rates all the fields the serialization stream that includes private fields package private fields protect it public and so there's there's no there's really no attempt at all at protecting the serialized data right so the the first mistake you can
make is just to serialize some sensitive information and make that available to someone who shouldn't have access to it because there's no protection at all you can look at the files and basically you'll see the ASCII right in the file and if that's inadequate there's a there's a specification which fully defines all the fields and there's some tools which will you know convert them into human readable form for you so there's there are no protections and and you can see here that the private data is also written out right so any private field you have is gonna be exposed malicious code can even basically access private fields within a serialized object by just serializing the object
and then you know kind of manually going through the resulting byte stream to extract the private information that's yet another way sensitive information can get leaked out all these are covered by a single cwe d serialization of untrusted data the consequences of these vulnerabilities vary widely we talked already about leaking private fields it's it's able your attackers can also modify the objects so you know if you get a cookie which is a serialized data that's got your bank account name on it and you decide that there's not enough money in your bank account you rather have bill gates bank account you could just modify the object and send that modified object to the service these can be very
simply exploited for denial of service tax and also remote code execution so these these problems have been around for a long time but in the last couple years they sort of blew up quite a lot when people you know we're able to figure out that serialization is using our my and and you know our my and C realizations used in WebSphere and Cisco products and JMS and and you know 15 or 20 other popular you know software infrastructures that people regularly deploy so so this these vulnerabilities are sort of out there in spades and there are they're not at all difficult to exploit so here's a very simple unrealistic remote command execution example and when I say simple and
unrealistic I mean you know I can guarantee we found this in code right but I have to say it's simple enough listing because you know it looks kind of dumb but so here we've got a gadget the serializable and it's got a private field here called command and it's got a reader so let me talk about this this command right so so the purpose of this you know the what the developer was thinking here was probably you know I want to I want to write a class that's gonna invoke commands in a safe way so gonna have command field which is a private field and this is this is gonna be set you know we're gonna have
restricted access to this by making it private so we're only being set that through methods defined interface to safe secure commands that can be executed but what happens is we have a read object method which then calls runtime exec on the command and the problem of course here is that the attacker and attacker who can access this serialized data and very simply edit or you know modify the serialized form of this to put any come and here they want right and when this object gets deserialized this command is gonna be executed so this is a very simple version of this but the principle is largely the same right so what happens is the attacker can identify it
can provide whatever objects really they want in the serialization stream it doesn't have to be the one the developers into expecting and then they can basically invoke code in these objects using attacker supplied data so it's a form of almost a form of kind of you know return or into programming with invocation of gadgets so here's a quick list of some of the protocols that use serialization so if you use any design you could likely be affected by these class of vulnerabilities okay so the further problem with D serialization is his code is susceptible to vulnerability even when the code really appears to be correct right so the the code I showed you before is more or less correct
that's how keep deserialize but it is completely vulnerable to these exploits so again an attacker could provide an instance of an unexpected class and send it to a service that will then decirles that malicious object and and and likely cast it's the expected type so when the cast occurs you'll get a you'll get a cast exception right but by the time that exception occurs it's already too late because the entire exploit has already completed so so here's our again T serialization process and during this you know the deserialization of each object in the stream it's going to VOC these methods read object read resolve and validate object so basically the attacker you know provides a list of
objects and for each object it's gonna call these methods with the data they supply and so what they can do is they can basically you know specify a program that's going to execute in your JVM driven by this data right so they can run any existing code and there's enough code there that you know it's not too hard to piece together you know you know a program that's gonna have some malicious impact such as calling runtime exec on a on a command ok so let's do a demonstration this demonstration uses the Apache Commons collection invoker transformer got a lot of bad press so I didn't use that I use a different gadget you know common
solution to this problem is black listing gadgets that solution is I'm gonna use the ill-informed because there is not a there is not a known set of dangerous gadgets this is sort of an unknown unlimited set of dangerous gadgets out there so blacklisting is not appropriate approach I'll show you some code everyone excited about seeing code thank you so this is I'm gonna show you a CRO five let me debug this a little bit and said just running it so we're going to call basically this RC 8 RC e payload method I'll step into that this is going to create a command exploit that we're gonna you know this is the payload so our payload here's gonna be the cow
program someone asked me once you know Kent can you also call command with parameters and yes you can that was what this was for so going through this quickly we're gonna create a constant transformer object we're gonna create an instantiation sperm object get some of the parameters create a chain transformer and a priority queue add a couple things q activate the attack and now we're going to serialize this gadget chain that I'm using for this exploit I'll step into the serialization code real quick this is the equivalent to what I showed you on the slide earlier we're just creating an object output stream and a try with resources block and then we called the right object
method and here we're just converting it in memory to a byte array so that's the serialized attack and now the next thing we're going to do is going to take that serialized payload and we're going to deserialize it so again I'll step into that so again we have an object input stream now and a try with resources block and this this read object here as soon as I execute the read object that entire exploit is going to get triggered so so this this whole exploit will occur before read object returns meaning that any cast you have here to detect an invalid type is coming too late so I'm just gonna hit single step here and
you'll see that there's a calculator and you can use this to figure out how much everyone should pay for lunch including a 15% tip and all works just fine okay so that's the end of that demo go back to the slides so there's your remote command execution I had some I gave this class once and someone right at this point raised a hand and said so what's the danger and I I just kind of Joe kind of fell open and someone else the audience had to explain to them I want attackers running code on your systems it seemed obvious to me okay so here's another demo which is a boss attack develop by this guy vote
Tuco carrots at least I think that's how his name's pronounced haven't anyone tried to correct me yet so seems like a close approximation at least so he defined a half set with cycles and it's it's actually particularly devious because it doesn't exhaust memory which eventually will cause an out of memory exception what this does is just recursos indefinitely consuming CPU and you know runs forever so I'll show you this one real quick the let me show you the code so so here's the dose the dose payload we're just gonna create a half set and then we're gonna loop and basically create new half sets and assign them to other half sets and sort of create this cyclic
structure so that's all there is to it it's very simple the demo is this one's a little bit cerebral cerebral sir you know what word I'm trying to say like in the mind yeah sorry one of the things that goes when you get older so your vocabulary home from NCC group you know so one of the things I did early on was I I put a sign on my front door that says put pants on you know so that that doesn't happen again cuz so anyway so so this example I'm gonna create a thread and in that thread I'm gonna deserialize the das payload then I'm gonna wait 10 seconds so in computing terms 10 seconds
is basically infinity because we don't want to wait until the Sun burns out to see if this returns so I'm just gonna run this and basically if you see exiting appear in the console it means that this this thread never completed because of the das attack if you see das has been deserialized my you know my demo would have ended in an embarrassing fashion but instead you know this this never completes so that's a wonderful little attack just using a hash table deserializing hash table which obviously is part of the java runtime environment okay moving on so I want to mention also patchy Commons a file upload which is another kind of dangerous gadget so this
has a class called just file item which handles file uploads a serializable has custom write object and read object methods and this also allows remote execution and file manipulation using the the all to finalize and you know the interesting thing about the call to finalise is it runs as part of a separate thread so this called a you know it's called from the garbage collectors part of a separate thread so this call is not in the same security context as the normal deserialization right so it's outside of the security context which makes it even more dangerous sort of you know eliminates any mitigation you might have attempted by removing privileges so in this really there's just in the finalized method
there's some code which goes and deletes a file right and so the risk here is that the name of the file is supplied by the attacker right so the attacker can you know modify the serialized data specify whatever file they want to you know blow way on your system and when this object gets finalized that file is as file is removed okay so risk factors and all this so so the biggest risk factor is you know are you deserializing untrusted data you know and a lot of people do this right people will serialize a cookie on their client system and then deserialize it and of course that's untrusted because it got to the to the end user you know if you
if you're just doing serialization with within your trusted computing boundary within your trusting computer base it might not be so bad so does it take place before authentication sort of makes it worse it's nice to know at least the email of the person who's attacking you not that it's real and is there any attempt to limit what ties can be serialized which is a common effective mitigation you know basically whitelisting mitigation and also there's always this question does the deserialization host of gadgets that can be utilized and attack anyone want to hazard a guess at that question you think the host has gadgets that can be used in the attack there's couple people nodding so the answers
yes yeah yes it does don't even think that well I haven't installed patchy comm and so I'm not at risk you know there are a number of you know dangerous gadgets but they've been identified but I think it's very clear that there are many more which have not been identified so I wanted to touch briefly on a mitigation so the the primary mitigation again is you know just don't do this don't do serialize untrusted data but the problem here I mean I I would describe this as the most difficult problem and software security because basically the problem you're trying to solve by deserializing untrusted data is how do i execute attacker supplied code securely in my environment right that's
basically what you're doing so it's a really really really tough problem to solve so if you decide to try to solve this problem you know look ahead deserialization can be used for white listing or black listing now I've already put most people use it for black listing and I've also pointed out that black listing is 100% ineffective so if you're WebLogic whatever you know there's blacklist invoke or transformer you are still completely vulnerable to attacks just not the most popular one so there are a bunch of existing office off-the-shelf solutions bizzy's even one that kind of has the name of my my talk but my favorite has become the JDK the jp2 90 which was implemented by
Oracle and and shipped starting with Java 9 and also portions of it were back ported to Java 6 7 & 8 so so the way this Java serialization filtering works is basically allows filtering of the classes before they are deserialize before the read object method starts to these various callback methods so we can we can narrow the set up deserialize with classes to a context appropriate set of classes you can also filter for a graph size and complexity to try to eliminate the denial of service attacks I'll show you in a minute that that doesn't work so it's very well basically that that well voltar Co carats attack Gossett AK I showed you is exceptionally
tiny and there are no limits small enough to be set that would prevent that particularly das attacks so the you know the the limits that a lot of these tools implement is not particularly effective at preventing Gauss attacks so so they're starting in Java 9 and now I guess Java 9 is already obsolete it's kind of a fast-moving world so Java 10 you have processed wide filters custom filters and built-in filters the core mechanism upon which all these things is built is a filter interface which is set on the object input stream the process wine filters they're kind of the big hammer solution those were back port it to JDK 8 7 & 6 as of these versions so
if you're using you know an older version of Java and many people are still using JDK 8 because it's sort of the long term supported version right now of of Java you can at least use this process wide filter so the process wide filters configured via system property or configuration file so the system properties JDK serial filter and security properties the same but in the con security job of properties and the and it's basically kind of a string I'll show you what it looks like so custom filters can be written by implementing the object input felt interface and overriding the check input method you need to be using Java 9 or later to take advantage of this there's
two methods add it to object input stream there's a set object input filter and a get object input filter and you can also set filters using config set 0 filter which affect every object input stream that doesn't otherwise have a filter if there's no filter then a global filters use if it's defined so let me do a demo of this and might sort of cut this down a little bit in the interest of time I think I have 20 minutes left which is I could show more of this yeah I've got two slides left it's been pretty fast I mean you eliminate more slides than I needed to okay so let me demo this and you know
now that I'm less afraid of the time I'll say ask questions so this is this is down here I haven't a different project because I need it to use Java 9 or now I'm up to Java 10 and I guess what I'll show first is I'll show the vulnerable code so I'm gonna take out the mitigation here and start to debug this so one of the things I did here which I I mostly think was a good idea was I I swapped out okay I swapped out the default Java compiler and I used the Google compiler which is called me cheating look Oh error prone an error prone is kind of cool I mean it
just diagnose so usually here David could back me up on this you know you you run into the Sun Java guys one so on you say could you please flag you know like no how about no and they're like well it's too many false pauses we're not gonna flag that and so what error-prone did was you know every one of those requests to flag something they implemented so so error-prone actually Flags all these sort of dangerous pieces of code and you know if you don't like false positives I guess don't use error-prone go back to using just a normal Oracle compiler okay so in this example we're going to serialize a bicycle ensure this is
working
okay so we're gonna see you realize a bicycle I'm gonna serialize a file object the idea here is that the bicycle is what we want to serialize deserialize and the files what we do not as it's the misuse case so we're gonna deserialize the bicycle and that there's the call to read object and so that works just wonderfully and now we're going to deserialize our file and there's a call to read object and that also works wonderfully and what I've done here is instead of sort of casting this expected type i just assigned it to an object that eliminates the actual cast exception that you should receive this seems like a stupid thing to do but
again it's not uncommon for us to find this in source code that we evaluate okay so let me modify this code and we'll show the mitigations so we're gonna do here is we're gonna we're gonna add a custom filter this bike filter to the object input stream let's go ahead and debug that the bicycle filter well I guess you'll see it start to look at it okay so we're going to serialize the bicycle we're going to serialize the file and now we're going to deserialize the bicycle there's the read object method and now the read object method invokes the custom filter that we've installed so here's the custom filter it makes a call to check input and you can
see here in the output that I just printed out some of the data that's passed here right so you can see the number of references the depth you know the depth of the object graph the number of bytes and the actual name of the class being deserialized which is bicycle so we check the limits and none of the limits are exceeded so we're good there then we get the name of the class we find out it's a bicycle and this is sort of interesting you ever change your coat just before the night before you give a demo and they forgot to change it back so that's what I did so so what this was supposed to say here
was accept it reject it and undecided but now it says undecided because I was wondering what would happen if it just returned undecided now the interesting thing here let me show you so we're going to return undecided if you return undecided it will actually deserialize the object so that will actually succeed but my next one is not gonna work because it's supposed to be rejected so I guess let's fix it Oh bicycle doctor so this should be accepted
my spelling except it wrong
and here we're gonna do reject it that shows up and go back here
okay now what I just do undecided for now because it does work it turns out I was off looking at the you know Oracle source code and they never do a test on anything beside rejected which means that in their code that handles this accept it and undecided or handled exactly the same normally this should be accept it and this should be undecided here but let's go ahead and try this again going to you I'm gonna stop the code from running and then I'm sorry go ahead and debug this again
yeah so the problem with air prone is it compiles a little slower which makes it not perfect for demos but okay so we're gonna create the bicycle object we're gonna create the file object we're gonna deserialize the bicycle object now we're we're still returning undecided it still works and now we're going to do you see realize the file objects that we call read object we're into the filter method and you can see here now we're dealing with deserializing a file object again the all the all the limits are quite small so that's not going to trigger the rejection but the class now is is a file it's not bicycle so based on that this will be rejected and that will cause
that will cause an exception to be thrown so you'll see here that we end up with a invalid class exception so the D serialization is prevented let me just well stop twelve minutes I'll show the whole demo that I normally show so here I'm going to disable the custom filter and I'm going to show the process wide filter so the advantage of this one is that you know it sets for everything in your JVM and also it's available in Java 6 7 & 8 so this is something you could use today if you're using Java 8 so let me start to compile this just think lack of interest in process Y filters I thought these were
sort of more interesting than that so here's the filter basically that's being set and it takes a little practice to get this right so the first time I did this I said you know don't serialize anything and then serialize bicycle and it turned out that basically said don't serialize anything because that first filter would catch everything so you have to put sort of the more specialized filters here so what I'm saying now is to serialize by scope but don't Syria deserialize anything else and then set some limits for no good reason because this this does not work I've been successful so if I go ahead and debug this let me just run it okay you'll see that the filter snags okay
so this filter that we set this process white filter snags that you know based on this filter it says hey bicycle is allowed but nothing else is allowed so it rejects the the file class okay so one last example and then we're done with this and then I'll wrap up so for the last example I'm gonna go back to the custom alright everybody we're trying to get life set up for you all so please make sure to keep room in the hallways for the lunch people to get the food back for you and also it's not quite the time to get in line for lunch yet so just hold off there's plenty of food for everybody and it's gonna be
starting at noon so and the booths will be open at noon - so form two lines one for the booze and one for the food thank you freeze Georgia being here say how woot that's the first time I did Georgia Binks in first nation works ok yes ok so I just made that last change and then I ran this and what I can show you here is that this daus attack at the end this ultra curse attack lines up getting defeated now the interesting thing about this is it's not to feed it because of the limits right so you see the voter Koko's attack has has one reference it's it's less bytes than the bicycle attack
is 36 bytes and there's there's really nothing here that you can detect with the lemon the only reason it gets caught is because hash set wasn't in my whitelist and so it turns out that you really don't to serialize hash anyway so it's a good it's a good object to leave out of your your white list of objects okay so going back to the slides the so the primary mitigation for this stuff again is do not serialize untrusted data it's really a tough thing to get right you know if you need to do that you can look at this look ahead object input streams to use whitelisting to to serialize only only those necessary classes and then
basically you know you should come to my full-day course and then I'll teach you how to write those whitelisted classes so they're secure right because it's also very easy to make an error in implementing those classes so you can apply a custom filter with a whitelist for each use of deserialization that lets you be more precise about you know which objects can be to serialize in which context and then I didn't talk about this at all but makes sense to have a Security Manager with the security policy so you can sort of limit the potential damage that might be done if your deserializing untrusted objects so that's said for my talk this is me this is my email address I answer email
7:24 I know it sounds weird but I will wake up at 2:45 a.m. on a Saturday morning and have this instinct that someone just sent me an email and you'll get a response within five minutes so and you know there's a I have a live lessons out with Pearson which is a video series on Java series and feel free to enjoy that it's open also available on Safari books online or contact us and we can come to your organization and spend a whole day training your developers up on how to use Java sedation securely okay that's it for me any questions yes sir
yeah
yeah it's just any any field in in the serialized object is open to you tampering right because the format's fully defined so you know an attacker can just get it get it and you know edit the the contents of the object and replace one file name with another typically the way most attackers do this is they just they just write D serialization code and so to create their own objects with their you know their specific values in order to create sort of specially crafted malicious serialization stream but that tampering is really straightforward I have normal you know my normal training I showed an example of popping open a file the series asian file and editing it and then saving it and the
date has changed
yeah if you can get to the you know if you can get to the proxy object right so the proxy object is typically designed to be the perfect serialize form of the object right so it it's only purpose is to store the information and retrieve it whereas the actual object you know it's mostly designed to be efficient at runtime ring functionality but but the proxy will make a copy of really the arguments constructor and pass that data to the objects constructor during so that data is gonna be serialized David next she's smart used to work for me at certain he knows all about sterilization but it's nice to know that there's like two people who understood yeah
any other questions okay yeah yeah uh no I don't think there's any way to fix it and furthermore it's hash tables that are not really designed for serialization because but even without the attacker in the picture because when you when you deserialize at the different JVM the keys aren't guaranteed to work anymore so so there's kind of multiple reasons not to serialize and deserialize those sort of collections what you could try is to use a proxy you know I know all the details of every but I guess in general I met the highly suspicious point where I wouldn't use any of these unless and you know a lot of experts in this area basically just
kind of say that attack streams any other questions okay I think there's a lot [Applause]