Skip to main content

Lack of data validation - Numbers

Need

Implementation of robust data validation for numbers

Context

  • Usage of TypeScript for type-checking and enhancing JavaScript development
  • Usage of Express for building web applications and handling HTTP requests

Description

Non compliant code

import express from 'express';

const app = express();

app.post('/transaction', (req, res) => {
const amount = req.body.amount;

// Insecure functionality without data validation
const transactionAmount = parseInt(amount);

// Business logic
if (transactionAmount < 0) {
// Negative impact on the business
res.status(400).json({ error: 'Invalid transaction amount' });
} else {
// Carry out the transaction
// ...
res.status(200).json({ message: 'Transaction successful' });
}
});

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

The vulnerability in this code is a lack of data validation for the "amount" field in the transaction request.

In the code, the "amount" value is obtained from the request body using req.body.amount. However, there is no validation or sanitization performed on this value before it is used in the business logic.

The vulnerable line of code is const transactionAmount = parseInt(amount);. Here, the parseInt() function is used to convert the "amount" value to an integer. However, this conversion can lead to unexpected behavior if the input is not a valid number.

This lack of data validation allows for potential abuse. An attacker could manipulate the request and provide an invalid or malicious value for the "amount" field. For example, they could set a negative value for the transaction amount, which could lead to transactions being carried out with a lower value than intended.

The impact of this vulnerability is that it could result in financial losses for the business. Transactions with incorrect or manipulated values could cause financial discrepancies and disrupt the normal flow of business operations.

To mitigate this vulnerability, it is recommended to implement proper data validation and sanitization for the "amount" field. This can be done by checking if the value is a valid number and within the acceptable range before using it in the business logic. Additionally, if the value is found to be invalid, the request should be rejected or cancelled to prevent any unauthorized or unintended transactions.

Steps

  • Implement data validation for the 'amount' field in the request body
  • Check if the 'amount' field is a valid number before performing any operations
  • Handle the case where the 'amount' field is not a valid number by returning an error response
  • Update the business logic to handle the validated transaction amount properly

Compliant code

import express from 'express';

const app = express();

app.use(express.json());

app.post('/transaction', (req, res) => {
const amount = req.body.amount;

// Data validation for the 'amount' field
if (isNaN(amount)) {
res.status(400).json({ error: 'Invalid transaction amount' });
return;
}

const transactionAmount = parseInt(amount);

// Business logic
if (transactionAmount < 0) {
res.status(400).json({ error: 'Invalid transaction amount' });
} else {
// Carry out the transaction
// ...
res.status(200).json({ message: 'Transaction successful' });
}
});

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

The fixed code addresses the vulnerability by implementing proper data validation for the 'amount' field in the transaction request.

First, the code imports the necessary modules, including the Express framework, and creates an instance of the Express application.

The app.use(express.json()) middleware is used to parse incoming requests with JSON payloads.

The vulnerable part of the code is the app.post('/transaction') route handler. In the fixed code, the amount value is retrieved from the request body using req.body.amount.

To validate the 'amount' field, the code checks if the value is not a number using the isNaN() function. If the value is not a number, it responds with a 400 status code and an error message indicating an invalid transaction amount.

If the value is a number, it is parsed into an integer using parseInt(amount). This ensures that the value is a whole number.

Next, the code applies the business logic. It checks if the transaction amount is less than 0. If it is, it responds with a 400 status code and an error message indicating an invalid transaction amount.

If the transaction amount is valid, the code proceeds to carry out the transaction logic (which is not shown in the code snippet). After the transaction is completed, it responds with a 200 status code and a success message.

The code listens for incoming requests on port 3000 and logs a message to indicate that the server is running.

Overall, the fixed code properly validates the 'amount' field, ensuring that it is a valid number and meets the business logic requirements.

References