Hello and welcome to secure JavaScript programming with Vladimir de Turckheim. This video is about exploiting a prototype pollution. We have a prototype pollution under node.js server and we will exploit it in two ways. In one way to obtain a denial of service, this one will actually makes a lot of sense for things that happens also in the browser. We will also use an exploit that has been found in older version of Kibana and reproduce it on another app to show how a prototype pollution can lead to other results than denial of service. Lets not go through the source code for now and just check our app. We've got an application which has two endpoints. One endpoint is fibo slash number, and actually you give it a number and it returns the nth number of Fibonacci, so fibo7 is 13. Also, it has another endpoint that is items, that is passed endpoints. That will be used to insert item into a fictional database, for instance, hello world. We have something with a timestamp, an ID and it is inserted into our database. Let's start with a fun thing. If you remember the previous video about prototype injections and if you haven't watched it, I recommend highly you watch it before the current one. As you remember in the theoretical video for prototype pollution, the main way to get a prototype pollution is through some things that will be JSON.parse. We are lucky here, we've got an endpoint that takes JSON as inputs. Lets try already a first prototyping pollution. We will pollute the prototype and we will actually overwrite some methods on the global objects prototypes, so hasOwnProperties. Let's put null here and let's do the same for hasOwnProperty. Should be better if I write it property null and let's do setPrototypeOf, that's whole work will do. We just run multiple ones and see if one of them go through. We have run that once and if we run it again, we actually get an error. Let's try to run that with a legitimate payload. We still get an error. So whatever we run on these endpoints now result in 500 sever error. We have actually broken a code path in the app. If we test a fibo number it will still work, but these code path for each item in session has been fully broken and we are in a state of denial of service. It can also happen in a front-end application if you are able to prototype pollution and break some original methods of the JavaScript language. Well, the application won't be able to do some stuff. So for instance, if you remove the method that I used to write under DOM because you have access to the right prototypes, real pollution. Well, you would break actually the DOM for someone. All of that based on JSON.parse [inaudible] Let's see how we broke the object upload endpoint of this app. But just checks a code. Let me kill it and restart it just for later use or let's even go to debug. What happens? Here we've got the endpoint for uploading files, it's here. It just calls a method name storing DB, takes the body and pass it to the method and if there is an error, returns an error and otherwise returns the items that has been inserted. Let's check the content of storing DB. It calls getid. Getid basically returns an ID. We get an ID for the item we want to insert and as mentioned, this is like a virtual database. The idea just created by incrementing them and instead of actually writing something into the database, I just added, like virtually insert. If we check the code as a method that checks that the item already doesn't have an ID to prevent collision between that and an item that might already existing into DB and in that case would return an error. What it does is it creates the timestamp, the ID per data in an object and then merge the item we got from the HTTP request over the object we want to insert in database and return that into callback function. That's pretty much it. Hoek.merge as we have seen in the previous video, is when you are able to prototype pollution. Let's put a debug point here and rerun immediately a well-made issue spot. Not that one. Should be this one, yeah. Here, when we check what's merged, we see that this object has two proto properties. That's the thing we got when we had the side effect of the pre-prototype pollution or at least of passing an object as a proto entry. A JSON is a proto key and it has own properties null, has own property null set prototype of null. Here, the prototype pollution as explained in the previous video of that [inaudible] first video about prototype pollution, actually removes the hazard property method from the global prototype and replaces it by null and that's it. The error we got next time is each time we run something on this end point, what we get is this throws an error and express catches this error because we are in a synchronous programming airflow. If we uncomment those two things because of the way JavaScript works because JavaScript is single threaded, each time there is an asynchronous operation, the stack trace is lost. You cannot know from the code except when you read the code as a human being, but engine V8 doesn't know, can't know where the asynchronous operation comes from if it's not a primase [inaudible]. In that case when we increment the process the next tick, we have an asynchronous operation and the error cannot be caught by a try-catch anymore. If I rerun the server and runs a prototype pollution, let's run the prototype pollution and then I re-run a query. This time actually, the server crashes because of the asynchronous operation. It was not able to find the stack trace and then to find the right try-catch. That's detailed in our case, what we are interested in is prototype pollution. That's already pretty bad. But now let's try to do something even more nasty. I will run a payload that goes that way and now we see that nothing has changed. But when I get on fibo/10 well, now I get an error because it's a get endpoint. That's not the one I wanted to do. I wanted to do be a case. Sorry about this. Now it just hangs. It should just hang. What's happening? Yes. I'm not on the right end point. Let me start again. If I do my past with my prototype pollution with inspect PRK, nothing changes. Stash items. Now if I get unslash, fibo/10, it just hangs forever. If I check what's debuggable locally, I can see that I have actually the ability to debug a target on my machine. I open it and when I'm on this debugger basically, I can do whatever I want. For instance, I will do require child process and then I will do execSync and then I will do ls and I will add a two string because I'm a nice person. Basically, we are actually running commands through the debugger on the target machines that's running as a server. But that case is not actually really realistic so they just go through these and these have also debugger. Now we've got the result. What happened? Well, we ran a prototype pollution that created a property NODE_OPTIONS on basically all objects inside the application. On object, if you ask for NODE_OPTION, it will go towards the prototype chain, and find that the value is inspect break. When we compute a Fibonacci number in this case, what we do is we actually run a child process. That's a hack that's usually very used in Node.js for CPU intensive operation, you spawn a child process or walker thread on the most recent version of Node.js. In that case, the process is spawn with what's inside process that end as environment variable. There is a special environment variable in node that is NODE_OPTION, that can be used when you want to pass command line parameters to node. If I want to start node with the debugger, I can do either node --inspect exploitable.js. I add too many dash and it opens with the debugger, but if I want to do NODE_OPTIONS equals --inspect, and I remove this, it doesn't work because I probably forgot S and options. That's called the demo effect and now it starts the debugger. When you start the node process, it actually just change process to compute the Fibonacci number. It will actually look for the value into NODE_OPTION, and since we had put inspect brake, which opens the debugger on wait, that's how we started a debugger. We could also have used something else like -r, and I would say log.js, and let's restart the server now because it's broken. Let's run that in a post command, and now when we compute a Fibo number, it's doesn't work because it cannot find logs.js, so that's probably me who poorly wrote my exploits. Let's rerun it and see how it goes, and this times you see it writes ''Hello World'', because we actually used a commanding node that requires a file before it reads, and we actually executed the content of this logged file that prints ''Hello World''. The goal of this course and video is to show you that prototype pollutions can have a lot of effects. It changes the value you can expect from the JavaScript engine to give you, but it can go even further. Let's say when you have an administrator account you put is admin on it, and if you don't have an administrator account, you don't put this value. Well, a prototype pollution can be used to make all the user administrators. Let's say you have a front-end application, well, the prototype pollution can be used to break it, because through a prototype pollution, you will disable some methods that are either used by your code or by your framework, and make that an accessible, replaced by null, and just crashing loops, and you have a denial of service, and you don't have any business yet. Prototype pollution might be stored in a database to, if you remember or if you will watch the course about stored XSS. Well, it's possible to store them in a database, as long as it's some things that will be JSON.parsed at one point. Remember what we said in the previous course, freeze your objects, you can, if you use nodes, there is a via key to disable prototype pollutions altogether by freezing the global prototype and disabling proto. Use safe objects, maybe use map instead of dicts. Thanks so much for watching this video, see you soon in another one and until then take care of yourself.