Skip to main content

Insecure object reference - Personal information

Need

Protection of personal information from unauthorized access and modification

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and APIs

Description

Non compliant code

import express from 'express';

const app = express();

let users = [
{ id: 1, name: 'Alice', email: '[email protected]' },
{ id: 2, name: 'Bob', email: '[email protected]' },
];

app.get('/users/:id', (req, res) => {
const id = parseInt(req.params.id);
const user = users.find((user) => user.id === id);

if (user) {
res.json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
});

app.put('/users/:id', (req, res) => {
const id = parseInt(req.params.id);
const user = users.find((user) => user.id === id);

if (user) {
user.name = req.body.name;
user.email = req.body.email;
res.json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The vulnerability in this code is an insecure object reference. This vulnerability allows an attacker to bypass authentication mechanisms and modify other users' information by altering the unique identifiers that distinguish each user.

In the code, there are two routes defined: /users/:id for retrieving user information and /users/:id for updating user information. The id parameter in the routes is used to identify the user.

The issue lies in the fact that there is no validation or authorization check to ensure that the user accessing or modifying the information is authorized to do so. Any user can potentially access and modify the information of any other user by simply altering the id parameter in the request.

For example, an attacker can send a GET request to /users/2 and retrieve the information of user with id 2. Similarly, they can send a PUT request to /users/2 and modify the information of user with id 2.

To fix this vulnerability, the code should implement proper authentication and authorization mechanisms. It should validate that unprivileged users can only access and modify their own information. Additionally, user operations should be managed using session objects to ensure that the user performing the operation is authenticated and authorized to do so.

Steps

  • Implement authentication mechanism to ensure that only privileged users can access and modify user information.
  • Validate the user's identity before allowing them to access or modify user information.
  • Use session objects to manage user operations and ensure that each user can only access and modify their own information.
  • When retrieving user information, validate that the user is authorized to access that specific user's information.
  • When updating user information, validate that the user is authorized to modify that specific user's information.
  • Consider using a more secure method for identifying users, such as using a unique token or encrypted identifier instead of plain integers.

Compliant code

import express from 'express';

const app = express();

let users = [
{ id: 1, name: 'Alice', email: '[email protected]' },
{ id: 2, name: 'Bob', email: '[email protected]' },
];

// Authentication middleware
const authenticateUser = (req, res, next) => {
// Implement your authentication logic here
// Example: Check if the user is logged in and has necessary privileges
const isAuthenticated = req.session && req.session.userId;

if (isAuthenticated) {
next();
} else {
res.status(401).json({ message: 'Unauthorized' });
}
};

app.get('/users/:id', authenticateUser, (req, res) => {
const id = parseInt(req.params.id);
const userId = req.session.userId;

if (id === userId) {
const user = users.find((user) => user.id === id);

if (user) {
res.json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
} else {
res.status(403).json({ message: 'Forbidden' });
}
});

app.put('/users/:id', authenticateUser, (req, res) => {
const id = parseInt(req.params.id);
const userId = req.session.userId;

if (id === userId) {
const user = users.find((user) => user.id === id);

if (user) {
user.name = req.body.name;
user.email = req.body.email;
res.json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
} else {
res.status(403).json({ message: 'Forbidden' });
}
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The fixed code addresses the vulnerability by implementing proper authentication and authorization mechanisms to ensure that users can only access and modify their own information.

  1. The code uses the Express framework to create a server.
  2. The users array represents a simplified database of user information.
  3. The authenticateUser middleware function is added to the routes that require authentication. It checks if the user is logged in by verifying the presence of a userId in the session object.
  4. The /users/:id route is protected by the authenticateUser middleware. It retrieves the id parameter from the request and compares it with the userId from the session. If they match, it finds the corresponding user in the users array and returns the user's information in the response. If the user is not found, it returns a 404 status code.
  5. The /users/:id route also handles the PUT request to update user information. It follows the same authentication and authorization process as the GET request. If the user is authorized, it finds the user in the users array and updates their name and email with the data from the request body. It then returns the updated user information in the response.
  6. If the user is not authorized to access or modify the requested user's information, the code returns a 403 status code indicating forbidden access.
  7. The server listens on port 3000 for incoming requests.

By implementing proper authentication and authorization checks, the fixed code ensures that unprivileged users can only access and modify their own information, mitigating the insecure object reference vulnerability.

References