Few ways I could hijack your node.js applications

Published Feb 26, 2018Last updated Mar 21, 2018
Few ways I could hijack your node.js applications

Building a secure application is paramount to building an app with clean and responsive user interface, this is the main reason I always make sure I analyze possible ways I can protect my applications from attackers. The details I will outline in this tutorial will try to cover the few bugs an attacker can use to manipulate through your application in-order to access data beyond their reach.

This is a slightly longer article, grab a seat and a pack of popcorn to follow me all through.

As security researchers, we think of every possible ways we can penetrate an application and also possible ways by which the security flaws can be fixed. Buzzing around is the Node-Express thingy but some developers using them seem to omit some serious security flaws that an attacker could use to inject through the application, probably make themselves an administrator or just modify some resources they are unauthorized to do.

I will start the tutorial by explaining the few ways I can possibly inject your API endpoints built on NODEJS and what you can do to stop me.

Request Body Injection: Request body injection is a vulnerability where you don't filter exactly what the user passed in to the application, an instance is: You built an E-commerce application where users can purchase items and also pay online, whenever the payment process is complete, you have an end-point where you send some POST request from the payment gateway through, as an attacker, I can get the API by purchasing an item that is less expensive, monitoring my network logs to see the end points been triggered, the method used to trigger the request and the type of payload the end point is expecting.
After getting those details I could simulate my previous purchase but this time by purchasing a more expensive item and then injecting the end point expecting the payment status with the appropriate method and then sending the exact data it is expecting through it, this time, the application is fooled into believing I have paid, thereby generating me an invoice that I have purchased the item! easy right? Well, That’s it but a simple process could have prevent such a disastrous effect.

What can I do silly?
Now, I see you are eager to learn wink, fasten your seat-belt let’s move! to prevent an issue like this, I will encourage you to generate a unique identification key that is not visible during the transaction process, did I hear you say, how do I make that possible? Well, you can do that by storing the Identification key in the browser’s cookies, encrypting it with a secret key that is known only by your application, this way, even if someone forged the token, you can be certain that they can't get the key even if they try to brute-force through, your application will lock them out!

I have done that what next? Very good, the next step is to make sure whenever the payment process is complete and the response code is 200 or 201, Whichever one your payment gateway returns, you need to send the data from the payment gateway to your web application then during the storing process, you verify the token in your browser’s cookies, decode it to make sure it passed through, and is not yet expired or forged by an attacker. You also need to invalidate the token as soon as the process is complete 😃.
That’s very straight-forward enough and certainly you can be sure your payment system is not fooled into believing an item was paid for when truly it was only forced to believe the lie.

Request Body Injection 2:
I won’t want to waste your time here, I can already see you asking why do I need the part two when I can fold everything in the first explanation, take a chill pill! I am only trying to make things more explanatory, I want to be sure you get my message and you are doing your best to prevent me from hacking through your application.
Request body injection is a name I give to vulnerability where an API endpoint can be deceived to accept data it wasn’t suppose to or perform operation beyond it’s system of functionality.

Let me give you an instance of how I can penetrate through your application, an instance is when I tried creating an account on your website and I inspect my network logs to see the list of data your application is inspecting. I will check my localStorage or Browser cookies to see if you are using a token like JWT, I will decode the token online using any online JWT decoder, after seeing your sample output, I will note them down in my magic book 😃.
You ask me how the information can help me penetrate through your application? read on! Let say after decoding your JWT token it looks like the below json Object.

alg: “HS256”,
typ: “JWT”
userDetails: {
isAdmin: 0,
_id: “5a80f1ca298abc001450ba4b”,
username: “James”,
email: “name@gmail.com”,
__v: 0
exp: 1519295362,
iat: 1519208962

After looking through your userDetails object, I can see you have isAdmin value set to 0 which means modifying the token to make <isAdmin: 1> will make me an admin, I could try to encrypt the token online but I can’t get your secret key 😦. I will need a smarter way of passing through, I will try to create an account again, inspecting my browser network request, I will retrieve the endpoint that handles your signup process, I will open my postman or any HTTP client, insert your endpoint in the address bar, change the HTTP method to POST, insert the necessary details your application is expecting but this time, I will add a strange key <isAdmin: 1> giggles I will make the value of isAdmin to be 1, If you are not filtering the data from your backend, your application will accept them in and boom! I made myself an administrator.

Before going through how you can prevent issues like this, I will like to explain another possible ways I can pass through, if by any chance you have secured your signup endpoint from accepting whatever the user typed in. I will create an account on your website, try to modify my profile, if you are a lazy developer, you will just accept whatever is coming from your editProfile endpoint after your middleware has validated the necessary data, you send req.body directly to your controller, I will make sure to add the <isAdmin: 1> this time, injecting through your editProfile endpoint and woooosh, I just made myself an admin, I will just logout then login just to come in and fully enjoy my newly granted privilege, free of charge.

To prevent this from happening, you don't need to ever trust your user to input the correct details,you need to filter out exactly what you want your application to take in, an example of this can be an instance where your user wants to create an account, instead of directly storing whatever is coming from request body into your application, you can destructure it to retrieve exactly what you will be needing. An example is given below:

const { username, passord, email } = req.body

then in your application, you will store it with a code similar to below.

User.create({ username, password, email })
.then(() => {})
.catch(() => {})

Token Infiltration: Did I hear you ask where the heck I got those terminologies from? don't worry we are not here to learn terminologies, we are here to learn how to protect our web applications from attackers.

I understand that token is one of the most common ways of authentication but as true as this sound, most developer or should I say, lazy developers? no, I will just say developers 😃 usually omit some important part of securing their web application and this could cause a huge vulnerability where an attacker like me could modify the token, then perform some unauthorized operation on your web application.

Too many talks already! show me what you mean! okay, what I am trying to say is let's say you built an application that uses JWT as the method of authentication and when a user tries to perform an operation, you decoded the token and then check if the decoded user object contains the <role: admin>. As an attacker, I could sign a token to look exactly like the one signed by your application. I will store the token in my browser localStorage or the browser cookies depending on where your application is storing the token initially, I would have modified it to make me look like an admin, let's say in your token you have a key called role with the value as admin or user depending on the privilege granted to the logged in user.

Where the vulnerability will occur is when you are performing an operation like decoding the token, forgetting to use your secret key. It means, any token signed and stored for your application to pickup will be valid. An instance could be when you are using an npm package like jwt-decode which allows you to decode a token without actually passing in a secret key. I am confident that you already know how to secure against an attack like this but for better context, I will advise you to encrypt the token with a secret key that is stronger than the scariest password and also make sure don't by any means decode the token within your application without explicitly using the secret key you used when signing the token.

Cross site request forgery(CSRF): Yay! I already know about that! well, calm down, there are some people who don't know about it yet and there is a high chance your current world-class application is vulnerable to this attack. Mr. john has a forum website where millions of people share ideas, this forum is a full-time business as the income he earns through advert is able to sustain him and his family even up to living the life of his dream, Peter is a hacker from the underworld looking for his next victim to fall for the dark arts sorcery 😃.

Peter tries every of the attack mentioned above but there seems to be no way, Mr. john's website developers did a great work in fixing a whole lot of bugs and protecting the end users account from getting hijacked but Peter is a hacker and hackers are naturally inquisitive, we think of every possible scenarios to penetrate through an application, since we don't give up easily, Peter continues to inspect through the application but suddenly he gave a loud sigh of relief, sticking his gloved hands into the air and shouting yes! I got it!

Before you start asking me what the issue is, come closer let me whisper it in your ear, Peter was able to detect that the application sends sensitive data through browser requests directly to the end point. Peter created an article on the website then tried to delete it but when performing the request he noticed Mr. John's website application endpoints is expecting some data like:

userId: 87789299,
articleId: 3534645767

Peter modified the request, changed the userId to an administrator Id (He got it from visiting an admin profile). That way he was able to edit/delete an article on the website since your application checks if the incoming ID is valid and also if the ID is that of the creator of the articles or an admin's. Since Peter could perform the operation by forging the userID to that of the admin he can perform every operation relating to an admin all he needs to do is to go through the application, modify the top article to reflect his contact details and how the admin can reach him in order to pay him some ransom for him to reveal the vulnerability in the system. This is a vulnerability that occurs mostly when building endpoints but we usually forget or probably don't know a better way to secure the application against such attack.

How can I fix it? You can fix this attack by making sure you don't pass the userId or any sensitive data openly through API request, the best way I have been able to fix this on my web applications is to make sure I only send the non-sensitive data while the logged in user ID can be retrieved from decoding the authenticated token generated for the logged in user.

This is the end of the tutorial, now, don't only implement the minor bugs stated above be sure that there are still millions of ways your application can be injected but fixing the above-stated issues is a very good start to fixing every other bug. Okay, now you can stand up take a walk and meditate on the few steps I have been able to share with you.

Let me know if you have any question/feedback in the comment box below. Thanks 😃

Discover and read more posts from Abdulrasaq Nasirudeen
get started