Skip to main content

Non-encrypted confidential information - DB

Need

Secure storage of confidential information in the database

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and handling HTTP requests
  • Usage of body-parser for parsing request bodies in Express
  • Usage of fs for file system operations

Description

Non compliant code

import express from 'express';
import bodyParser from 'body-parser';
import fs from 'fs';

const app = express();
app.use(bodyParser.json());

app.post('/query', (req, res) => {
const { query } = req.body;
fs.appendFile('queries.txt', query, (err) => {
if (err) {
console.error(err);
return res.status(500).json({ error: 'Internal Server Error' });
}
return res.status(200).json({ message: 'Query stored successfully' });
});
});

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

The vulnerability in this code is that it stores user queries in a text file ('queries.txt') without encrypting the information. This means that if an attacker gains access to the file, they can easily read and obtain the confidential information contained in the queries.

The code receives a POST request to the '/query' endpoint and extracts the query from the request body. It then uses the 'fs.appendFile' function to append the query to the 'queries.txt' file. However, this code does not perform any encryption on the query before storing it.

As a result, an attacker with access to the file system can simply open the 'queries.txt' file and read the contents, thus obtaining the non-encrypted confidential information.

To fix this vulnerability, the code should encrypt the sensitive information before storing it in the file. This can be done by using encryption algorithms and keys to protect the data. Additionally, it is recommended to follow the organization's policies for encryption and ensure that all sensitive information is properly protected during transport and storage.

Steps

  • Install a library for encryption, such as bcrypt or crypto-js.
  • Import the encryption library into your code.
  • Generate a secret key or passphrase to use for encryption.
  • Encrypt the sensitive information before storing it in the database.
  • Update the code to use the encrypted data when necessary.
  • Decrypt the data when retrieving it from the database.
  • Update the code to use the decrypted data when necessary.

Compliant code

import express from 'express';
import bodyParser from 'body-parser';
import fs from 'fs';
import bcrypt from 'bcrypt'; // Step 1: Install and import the encryption library

const app = express();
app.use(bodyParser.json());

const saltRounds = 10; // Step 3: Generate a salt for encryption

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

bcrypt.hash(query, saltRounds, (err, hash) => { // Step 4: Encrypt the sensitive information
if (err) {
console.error(err);
return res.status(500).json({ error: 'Internal Server Error' });
}

fs.appendFile('queries.txt', hash, (err) => {
if (err) {
console.error(err);
return res.status(500).json({ error: 'Internal Server Error' });
}
return res.status(200).json({ message: 'Query stored successfully' });
});
});
});

app.get('/query', (req, res) => {
fs.readFile('queries.txt', 'utf8', (err, data) => {
if (err) {
console.error(err);
return res.status(500).json({ error: 'Internal Server Error' });
}

bcrypt.compare(data, req.query.query, (err, result) => { // Step 6: Decrypt the data
if (err) {
console.error(err);
return res.status(500).json({ error: 'Internal Server Error' });
}

if (result) {
return res.status(200).json({ message: 'Query found' });
} else {
return res.status(404).json({ error: 'Query not found' });
}
});
});
});

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

The fixed code addresses the vulnerability by encrypting the sensitive information before storing it in the database and decrypting it when retrieving it.

  1. The code imports the necessary libraries, including bcrypt for encryption.
  2. The code sets up an Express server and configures it to parse JSON requests using the bodyParser middleware.
  3. The code defines the number of salt rounds to be used for encryption.
  4. The code handles the POST request to store the user query. It uses the bcrypt library to hash the query before appending it to the "queries.txt" file. This ensures that the sensitive information is encrypted before being stored.
  5. The code handles the GET request to retrieve the user query. It reads the contents of the "queries.txt" file and uses bcrypt to compare the stored hash with the query provided in the request. If the comparison is successful, it means that the query exists and returns a success message. Otherwise, it returns an error message.
  6. The code starts the server and listens on port 3000.

By using bcrypt to encrypt and decrypt the sensitive information, the fixed code ensures that the confidential information stored in the database is protected and not accessible to attackers.

References