Node.js Applicative DoS Through MongoDB Injection

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let me just put my timer and welcome everyone thank you a lot for coming this talk will be about no sequel injection and how to exploit them to obtain an applicative dose and I've decided to subtitle it talk how to find exploits by reading the doc because you will thank that just by having a hacky mind when reading the doc you can actually find exploit and create new attacks against applications so my name is Vladimir the chalk em you can call me Vlad I'm the lead node.js guy at screen will security company so maybe you want to talk about that with me but I'm also part of the jas security working group and I'm an address collaborator so if you've got question regarding nodejs security feel free to ping the working group reruns here make up their army and we are hiring a screen so if you want to move to Paris we will catch you and that's cool but let's go through serious business right now so just a quick poll who in the room is already familiar with secret injections yeah pretty much everyone so I will go quickly on the first part because the first part is mostly remainders about secret injection then I will explain how to obtain no secret injections and I have a confession to make so you all come to see problem in the sequel databases we will only focus on MongoDB so sorry for the scam I guess but after the first introductory part we'll go to the serious business as known as the cool part because I will exploit a MongoDB injection to great application and that's fan and of course because I'm a serious person I will teach you how to protect yourself against that because I'm not unconscious please don't do evil so let's start right away with sequel injection and not secret injections so as most of you already familiar with sequel injection I won't spend too much time on that so let's check this piece of code that's an express controller that except get requests on URL that ends up with slash past slash ID and ID being a parameter and when there is a request that gets into the application we create a sequel queries select from a tennis YT equals and then we put the parameter and we ran that on the database so as a result if the ID in the HTTP request is 1 the query becomes select star from a times when ID equal 1 and the out kernel that is eventually the document which has an ID 1 in this table if it exists and I realize that the name item is terrible for a database table so I try to do better next time but as most of you so it is injectable meaning it's terrible so if instead of an integer I put 1 or true the sequel query becomes select star from items where I'd equals 1 or true right and at this point every documents in that table are returned as a result of the HTTP request and that's called data rich and if you don't think that's a big deal just ask Yahoo because it almost kills em recently a couple years ago and obviously we can do even more a velar stuff is that a world if you know we can be more evil than that with using an Union query to hit another table so you can do one Union select username password from users so the sequel query becomes static stuff from ATMs r ID equals 1 Union select username password from users and since I'm a terrible developer when I created this app the password I'm not even hashed so basically it's a backdoor to everything in my app and I should feel bad but not as bad as those people who all have been having secret injections in production in the last for three years and please don't sue me I check the slides each time I do the presentation and there is a reference at the bottom of the page so please usually I will write this website if you did agree with that and most people tell me secret injection are things of the past you know now we've got our rounds we've got big frameworks and we don't have secret injections anymore right yeah I'm not sure Instagram as legacy code in their code buzz so I'm not sure secret injection legacy attacks so long story short you want to care about them but that's not the topic of the talk because I hear someone in the room being like yeah he spends too much time talking about secret injections I want to hear about manga Delhi and you're totally right but before I talk about MongoDB injection maybe we should remember together how MongoDB works compared to compared to sequel databases so in MongoDB you don't have a single string to formalize your query you've got what's called a collection which is more or less equivalent of a sequel table and then you've got a method you call on that collection and then you've got a query object that describes what the method should do so in that example we want to go we want to go through collection and items once again is a terrible name and we want to operate the method name find that obviously allows you to find documents in your collection and since we don't want to find all the documents in the collection we use a query object so this can be for instance a month 0 and the outcome of this request will be getting all the items in that collection which have a field name amount that is the integer 0 and it will be extremely limited if the only request you could do is I want something that has a value with that value it has a field with that value so MongoDB has a query language query language as you can see on the last line of this slide you can use for instance dollar JT for greater than which is obvious now if I feel the exist language is the most cryptic one in the world and isn't understandable for anyone but in that case if you want every document which has a field amount whose value is greater than 0 and that's equal to you we can use the lab JT 0 and of course a lot of other operators like issue for equals and not mean for not in and you can see that exists I'm not sure what it does it seems way too straightforward to be fair and you've got other methods to do stuff on your database because you could also insert document remove documents or update documents and I think the chief is telling me is that this light is boring as heck so I prude move forward at this point so who knows about no sequel injection in the room all right so you come to the right talk because I will show you to perform that so we've got another Express controller this time it's a post route we'll see later that you can do the same with a gate route but let's start with an easy one and we've got a query it's made with Mongoose so Mongoose does not protect you against that when you get a queries at document that find and then the query is created based on the content of the HTTP payload so it's type and then we take the field desired type in the HTTP payload right so let's say I want to fetch all the documents that have the type blog in my collection so my request that body would be desired type blog the string blog and the query becomes document that find type blog at this point it must treat mostly straightforward because the outcome of this request is all the documents in the collection that has a field name type which value exactly is blog and what word developer did not think through when he did that is that hey there is no thing to prevent anyone for injecting unibit really object in that controller so if an attacker would just craft a request and put desired type not equal 0 0 the query becomes document that find type not equal 0 and since in this connection we can assume perfectly that the type is always a string this will return all the documents which have a field type or not that is not equal to 0 basically everything so once again we've got a massive data reach and let's ask all the company will be at bankrupt because of that kind of attack how they feel about that yeah I mean person I know now we will talk a bit about denial of service and MongoDB because I've showed you that MongoDB injection can be dangerous it's mostly the newest for data leak but if you can inject a delete statement and update statement it can be even worse because you could remove arbitrary data from the database or update a literary documents in the database but now I will show I will demonstrate how to obtain an appellee an applicative denial of service but before showing you how to get an applicative denial of service maybe I should talk about what is a denial of service so it's a very fun attack because everything is in the name so let's say you have a website and at one point it's not giving service to your legitimate users right sure you have a chat application and people cannot chat anymore you are not in a situation where service is denied to your users or you are in situation of denial of service so the question is how can a bad Mauritius attacker put an application into this state so you've got the very famous DDoS attacks that we are extremely popular a few years ago and that's basically a caveman attack it's basically hitting an application so ad and so often that it stopped responding so to do that you can for instance have 1,000 of billions of of machines that do HTTP requests a lot of them at the same time on the same endpoint and the CPU will get hired and hip really explode and at one point your application will crash and will not respond to anyone and don't say I told that but you can use low EQ for that it's eventual and you can have also an other network based denial of service if you trick like x out in TCP stack such riffin to do and there is awesome literature about that if you want to know more pinging about that and in the node.js world we also have the regex the denial of service so another application is mono threaded rights meaning that if you do something synchronous like forever the application cannot do anything else at this bunch of blocking the event loop and regex are really fun way to obtain that so I had a client of mine who actually regex those themself because they were having a marriage of a glass not to mention but a poorly crafted ratings app and with a huge payload at one point of regex took seconds to execute so it's not a permanent denial of service because your app is not crashing but for all the time of the regex is computing your application is not responding anymore and that's pretty bad because it costs you money because you have to scale and sometimes you get up to your scale limit and you cannot do anything anymore and your business is bankrupt in 23 hours but what else what else can we do to obtain a denial of service so to be honest I was trying to obtain regex dos in MongoDB because MongoDB has a regex operator right that allows you to search document based on reg X and I failed miserably because there is a protection in MongoDB for that so Hey but then I was browsing the blog and I saw this code sample and at once the light came to me because there is this parameter when you use the MongoDB driver full size I was like wait white if it has a pool size that means there is a connection pool from your application from your node.js process through the MongoDB database and if you go through MongoDB documentation you learn that there is only one query in the car in each connection in the pool at a time meaning if you've got five connection in your pool connections in your pool you can only perform five queries to MongoDB at the same time so the new one will have to wait for the other ones to finish and I think people you can see where I'm going there so I was looking at that a lot I actually spent he was looking at this chunk of code and was like can we exhaust the pool size I mean if I am able to have five very slow requests at the same time in parallel from my application to MongoDB then there wouldn't be any connection left for the legitimate traffic and the application will not be responding on the endpoints that means going to be basically all of them if you use MongoDB after as your primary database so then I did what every hacker should do I went back to MongoDB Dutch because MongoDB dog showed me something extremely interesting once again is that the door aware operator still aware operator allows you to run arbitrary JavaScript on MongoDB side so it's cool when you've got a complex query to perform you can of the arbitrary expression that returns a boolean and as I said this JavaScript code will run against each element in the collection one by one and return all the elements that returns truth against that expression and MongoDB I don't know why has a sleep method in its standard JavaScript feed meaning that if you type sleep with a parameter in your shell or in a Mungo query you will wait for this number of milliseconds I'm not sure what it's for because often MongoDB is already slow about itself but if you want to add slowness artificially be my guest and do it and now let's see how to take that all together to perform an applicative DOS so at the beginning of the talk I said that items was boring as a collection name so basically now we'll use dogs dogs these are really important shoes because our two kind of people on earth murderers and people who like those so I hope everyone is on the right side here and this endpoint basically allows you to fetch a dog by its name let's show that work so that's a get end point because we have the query based on the query string here and when we've got a request we do dog dot find and then we take the HTTP query string and we return the result of that current but this time we will not focus on the injection so as you can see at the on the second half of the slide the the outlet the outcome is a bit different as usual so we've got a line in a B a B is a truly an Apache bench that allows you basically to perform load testing on an application it allows you to run a lot of HTTP requests in a small amount of time against an application so a B will be impersonating our attacker the attackers that want to exhaust the pool size we want to make the application and responsive so a B is a bad part in our scenario and the query is the query Python by a B and the curl and at the bottom we've got time to time tchau represents the legitimate users meaning to perform this test we ran the a B command to have an attack flow happening against the app and then we during the attack flow we're an actual commands that represent the legitimate traffic and we measure the time it takes to answer to that calculon and the goal of this game is to make this calculon as inefficient as possible as slow as possible so let's start with not that bad attack so we'll perform ten HTTP requests in parallel up to 100 of them without any special injection so in that case the good legitimate traffic takes two seconds to be performed which is already terrible but that's because my code is terrible and because there is 10,000 documents in the collection we have to return in that query that way it takes time so we do that and we see that that the legitimate user get access to the service so there is no denial of service at this point now let's see what happens if we fetch only one dog so I can show you how the query actually performs so I fetch wonder by its name with a query string so I chose dog named Lulu because Lu is the best name for a dog it was my name of my dog when you don't care that I do you can see her on the right left hand side of the picture of the slide but so let's say we fetch only one dog at once so we've got our attacks against the a B part and we've got our witness legitimate traffic as a last line secure comment and this time since we are only fetching one record over 10,000 because there is only one loser in the universe it's much faster it takes 600 milliseconds to perform the legitimate traffic which is somehow alright and now let's do the fan thing let's inject that so instead of adding a query in the filename and a legitimate dog name we'll have a query in the hamdullah where and sleep 1 which means for each document in that collection will ask MongoDB to pose its execution for 1 milliseconds and I started this test shoot with my usual setup and it took time it took a lot of time I mean it was never stopping so at one point I just interrupted the treatment and the two minutes it took for the legitimate call is actually the time after which I stopped the treatment meaning that until I was tapping the attack parts the legitimate user we are not having any access to the application at all altogether so we actually performed a denial of service through a MongoDB injection on a node.js app and it's not only working from the GS apps because no secret injection are available in all applications we protect that in Java PHP Python and we see that in real life in all these languages meaning that this attacks is not tied to node J as if you've got back containers or technologies you might want to check if you're vulnerable to that and sorry for the anxiety I created in the room that's not my goal but yeah app is not responding we managed to get what we wanted but the real question because we are two deaf conference tonight at a black hat conference is how do we protect against that so you've got a bad way to protect against that some people told me yeah you just have to experience a pool size yeah but you know the pool size by default is 5 you expand it to 10 we will just have to do 10 requests in parallel to fluid it you will expand to 100 we will do 100 requests in parallel to flood it I mean having a lot of HTTP requests hitting an application is not expensive especially now that everyone can spawn a lot of machines in the cloud within seconds so don't think that it is a power game because you cannot win you will rate limits maybe you can weight limit access to your application but sometimes some endpoints of your application as slow as another sometimes you do some endpoint in your application needs to be called more than others so how will you rate limits exactly what you've got to single and paint application waiting me a rate limiting it is not really a good strategy because it will create a bad developer experience for your team and the bad user experience for your clients so you should not go that way either so maybe we should present no secret injection all together maybe as half of the security talk in the world so conclusion is don't trust the external inputs in your app so that it ate everything that goes into your app and be extremely conservative with that don't accept anything you don't know the shape of so if you were crooked you're basically using --happy as a framework and there's already something in line in too happy to do that if you're using Express you can use joy which is a very cool library from the happy project and there is a middleware generator and celebrate to use Vijay and that's a very very easy to use pattern matching libraries that propose you to validate everything that gets into your application without a lot of pain so you might have fun with that thanks a lot for your attention I have a favor to ask you please scan this QR code or go to this URL and provide me feedback about this talk that's really important so I can experiment feel free to ping me and if you want to talk note security or application security feel free to contact me [Applause]
Info
Channel: node.js
Views: 1,616
Rating: undefined out of 5
Keywords:
Id: xJWZsoYmsIE
Channel Id: undefined
Length: 22min 21sec (1341 seconds)
Published: Fri Oct 19 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.