Web security. Am I protecting my REST api correctly? (node.js express)

I have a MEAN stack application with REST, like api. I have two types of users: user and admin. To sign the user and save the session, I use jsonwebtoken jwt, like this (simplified):

const jwt = require("jsonwebtoken"); //example user, normally compare pass, find user in db and return user let user = { username: user.username, userType: user.userType }; const token = jwt.sign({ data: user }, secret, { expiresIn: 604800 // 1 week }); 

To protect my express routes, I do this:

in this example, this is the "get user" route, the administrator is allowed to receive information about any given user. A "normal" user is allowed to receive information about him himself, why I compare the requested username with the username decoded using the token.

 let decodeToken = function (token) { let decoded; try { decoded = jwt.verify(token, secret); } catch (e) { console.log(e); } return decoded; } // Get one user - admin full access, user self-access router.get('/getUser/:username', (req, res, next) => { let username = req.params.username; if (req.headers.authorization) { let token = req.headers.authorization.replace(/^Bearer\s/, ''); decoded = decodeToken(token); if (decoded.data.userType == 'admin') { //do something admin only } else if (decoded.data.username == username) { //do something user (self) only } else{ res.json({ success: false, msg: 'not authorized' }); } } else { res.json({ success: false, msg: 'You are not logged in.' }); } }) 

So my question is: how safe is this? Can someone manipulate a session token to change the username to a different username? or even change userType from user to administrator?

My suggestion. Only if they know the "secret", but is there enough security? a secret is, like a plain text password, stored in code. What is the practice?

+5
source share
5 answers

the secret is, after all, the same as the plain text password stored in the code.

It is right. If secret not kept secret, then an attacker can fake user objects and sign them using this secret, and verify cannot distinguish this information.

Inclusion of secrets in the code risks a secret leak. It may leak through your code repository because a misconfigured server serves the JS source files as static files or because an attacker finds a way to use the child_process call to generate the echo source files on the server. The safety of your users should not depend on the fact that no one makes such common mistakes.

What is the best practice?

Use Key Management System (KMS) instead of collapsing your own or embedding secrets in code. Wikipedia says

Key Management System (KMS), also known as Cryptographic Key Management System (CKMS), is an integrated approach for generating, distributing and managing cryptographic keys for devices and applications.

Often, how you do it depends on your hosting. For example, Google Cloud and AWS provide key management services.

https://www.npmjs.com/browse/keyword/kms can help you find something suitable for your stack.

+2
source

This is extremely safe, especially if sent via HTTPS - then the attacker does not know what your request payload looks like.

The only real danger is to make sure that you keep SECRET safe, do not keep git in public repositories blocked access to any mailbox in which the secret is stored. Use a secret secret.

There are other ways to streamline your server. Consider using the npm popular helmet .

+1
source

It is safe if your data packets are sent via HTTPS. If you want to add another layer of security that you can do, you can first encrypt user data with iron , which uses 'aes-256-cbc' for encryption, and then use this encrypted text and generate a token via JWT . Thus, if the user somehow gets access to your token and goes to the JWT website. He will not be able to recognize what is inside this sign.

Again, this is simply the addition of an additional level of security, and it is impossible for a person to get information, because it is very time-consuming, but at the same time adds additional security for our application.

Also make sure all your secrets (private keys) are private.

+1
source

To answer his initial question: "Can someone manipulate a session token to change the username to a different username or change the user type from user to administrator?"

JWT points are encrypted on the server side and sent to the client in the form of a response. There are two things to keep in mind with this marker:

  • Token is encrypted using a private key that only the server knows about
  • The token contains, as you know, a signature that checks the contents of the JWT payload (for example, userType , etc.)

For more information about the first point, see the following.

For a better visual presentation of JWT tokens and signatures, consider the following URL: https://jwt.io/


With this in mind, you must ensure that:

  • Your private key is never opened at any time to external services / clients. Ideally, this key is not even hardcoded in your code base (ask if you want me to dwell on this in detail).

  • You have no logical flaws in your endpoints.

From a design point of view, I would much better divide any endpoints associated with the admin space into my endpoints, but by looking at them quickly, your code seems beautiful. :-)


On the side that can help you if you do not have much experience in the field of web application security, I would recommend checking some automated scanners, such as Acunetix , Burp (hybrid) and so on. Despite the fact that they are not perfect in any way, they are quite capable of detecting a sufficient number of behavioral vulnerabilities (such as an attacker).

+1
source

Some potential vulnerabilities in the code above:

  • The username variable comes from the URL, but usertype asserted from the token in the router action. For example, the audit log may be corrupted if it takes the user ID from the username variable, as this is not authentic and can be anything sent by the user.

  • Repetition is a problem. Since the token is valid for one week, it is not possible to revoke administrator rights, for example, before the token expires. (An attacker could play back the previous admin token.)

  • Similarly, you cannot terminate (force log out) any session before the tokens expire. This is a common problem in such stateless designs.

  • Null reference after decoding a token, as pointed out by others. In node.js, which is more like weakness than vulnerability, I would say I think it is not used.

  • The secret on the server is extremely valuable and can be used to impersonate any user. It is very difficult to protect such a secret in systems with high security requirements.

Thus, contrary to another answer, it is far from being "extremely safe", but can be safe enough for many purposes.

+1
source

Source: https://habr.com/ru/post/1274732/


All Articles