Excessive privileges - Access Mode - TypeScript

Excessive privileges - Access Mode - TypeScript

Need

Restriction of access privileges to system files and directories

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and APIs
  • Usage of fs for file system operations

Description

Non compliant code

        import express from 'express';
import fs from 'fs';

const app = express();

app.get('/readFile', (req, res) => {
  fs.readFile('/path/to/file', 'utf8', (err, data) => {
    if (err) {
      console.error(err);
      return res.status(500).send('Internal Server Error');
    }
    res.send(data);
  });
});

app.post('/writeFile', (req, res) => {
  const content = req.body.content;
  fs.writeFile('/path/to/file', content, 'utf8', (err) => {
    if (err) {
      console.error(err);
      return res.status(500).send('Internal Server Error');
    }
    res.send('File written successfully');
  });
});

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

The vulnerability in the given code is excessive privileges in accessing files. This vulnerability arises from the fact that the code does not properly restrict the access mode of the files being read or written.

In the app.get('/readFile') route handler, the code uses the fs.readFile() function to read a file from the specified path. However, it does not specify any custom permission mask to restrict the access mode of the file. This means that the file being read may have a permissive access mode, allowing anyone to read, write, or execute it.

Similarly, in the app.post('/writeFile') route handler, the code uses the fs.writeFile() function to write content to a file. Again, there is no custom permission mask specified, which means that the file being written to may have a permissive access mode, allowing anyone to modify or execute it.

These excessive privileges can have serious security implications. An attacker could potentially read sensitive information from system files or modify important files, leading to unauthorized access or data breaches. It can also allow an attacker to create potentially harmful files on the system.

To mitigate this vulnerability, it is recommended to restrict the access mode of system files and directories by using a custom permission mask, such as an access mode of 0600. This will ensure that only the owner of the file has read and write permissions, while others have no access.

Steps

  • Identify the system files or directories that need to be restricted by a custom permission mask.
  • Set the appropriate permission mask for the files or directories. For example, an access mode of 0600 can be used to restrict read, write, and execute permissions to the owner only.
  • Update the file paths in the code to point to the correct system files or directories.
  • Modify the code to use the fs.access() function to check the access mode of the files or directories before performing any read or write operations.
  • Handle the case where the access mode check fails by returning an appropriate error response.
  • Test the updated code to ensure that the access mode restrictions are enforced correctly.

Compliant code

        import express from 'express';
import fs from 'fs';

const app = express();

const filePath = '/path/to/file';

app.get('/readFile', (req, res) => {
  fs.access(filePath, fs.constants.R_OK, (err) => {
    if (err) {
      console.error(err);
      return res.status(500).send('Internal Server Error');
    }

    fs.readFile(filePath, 'utf8', (err, data) => {
      if (err) {
        console.error(err);
        return res.status(500).send('Internal Server Error');
      }
      res.send(data);
    });
  });
});

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

  fs.access(filePath, fs.constants.W_OK, (err) => {
    if (err) {
      console.error(err);
      return res.status(500).send('Internal Server Error');
    }

    fs.writeFile(filePath, content, 'utf8', (err) => {
      if (err) {
        console.error(err);
        return res.status(500).send('Internal Server Error');
      }
      res.send('File written successfully');
    });
  });
});

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

The fixed code addresses the vulnerability by implementing proper access control for system files and directories.

In the code, the fs.access function is used to check the access mode of the file specified by the filePath variable. The fs.constants.R_OK flag is passed to check if the file is readable, and the fs.constants.W_OK flag is passed to check if the file is writable.

For the /readFile route, the code first checks if the file is readable using fs.access. If the file is not readable, it logs an error and sends a 500 Internal Server Error response. If the file is readable, it then uses fs.readFile to read the file content and sends it as a response.

For the /writeFile route, the code first checks if the file is writable using fs.access. If the file is not writable, it logs an error and sends a 500 Internal Server Error response. If the file is writable, it uses fs.writeFile to write the content received from the request body to the file and sends a success response.

By performing access checks before reading or writing files, the code ensures that only files with appropriate access modes can be accessed or modified. This helps to prevent unauthorized access or modification of system files, reducing the risk of potential security vulnerabilities.

References