Node.js Security

Common Security Vulnerabilities:

  • Injection Attacks: for example, SQL Injection, Command Injection etc.
  • Cross-Site Scripting (XSS): Embedding harmful scripts into web pages.
  • Cross-Site Request Forgery (CSRF): Faking requests from logged-in users.
  • Insecure Deserialization: Executing random code during deserialization process.
  • Broken Authentication and Session Management: Wrong handling of user authentication and sessions.
  • Security Misconfiguration: Security settings misconfigured wrongly.
  • Sensitive Data Exposure: Insecurely managing sensitive information.

Implementing Security Measures:

Input Validation:

  • To prevent injection attacks, sanitise and validate user inputs.
  • Use validator libraries for input validation
                                    
const validator = require('validator');

// Validate email
if (validator.isEmail(userInput)) {
    // Process valid email
} else {
    // Handle invalid email
}
                                    
                                

Parameterized Queries:

  • Use parameterized queries or prepared statements to prevent SQL Injection.

Using 'mysql':

                                    
const mysql = require('mysql');
const connection = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'mydatabase'
});

const userId = 1;
connection.query('SELECT * FROM users WHERE id = ?', [userId], (err, results) => {
    if (err) throw err;
    console.log(results);
});
                                    
                                

Using mongoose (MongoDB):

                                    
const mongoose = require('mongoose');
const User = mongoose.model('User', new mongoose.Schema({ name: String, age: Number }));

User.findOne({ name: 'John' }, (err, user) => {
    if (err) throw err;
    console.log(user);
});
                                    
                                

  • Use HTTPS:
    • Use HTTPS to encrypt data in transit and prevent eavesdropping and man-in-the-middle attacks.
                                    
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();

const options = {
    key: fs.readFileSync('server.key'),
    cert: fs.readFileSync('server.cert')
};

https.createServer(options, app).listen(443, () => {
    console.log('Server running on https://localhost:443');
});
                                    
                                

Secure Authentication and Session Management:

  • Use strong passwords & multi-factor authentication
  • Use secure session cookies (HttpOnly, Secure, SameSite)
  • Hash passwords with a 'bcrypt' library
                                    
const bcrypt = require('bcrypt');
const saltRounds = 10;

// Hashing a password
bcrypt.hash('myPlaintextPassword', saltRounds, (err, hash) => {
    // Store hash in your password DB.
});

// Verifying a password
bcrypt.compare('myPlaintextPassword', hash, (err, result) => {
    // result == true
});
                                    
                                

Prevent XSS:

Use libraries like 'xss' to sanitize user inputs.

                                    
const xss = require('xss');
const safeString = xss(userInput);
                                    
                                

  • Use template engines that automatically escape output (e.g., Handlebars, Pug).

Prevent CSRF:

  • Use CSRF protection tokens.
  • Use libraries like 'csurf' for CSRF protection in Express.js.
                                    
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
const parseCookies = require('cookie-parser');

app.use(parseCookies());
app.use(csrfProtection);

app.get('/form', (req, res) => {
    res.render('send', { csrfToken: req.csrfToken() });
});

app.post('/process', (req, res) => {
    res.send('Data is being processed');
});

                                    
                                

Secure Deserialization:

  • Avoid deserializing data from untrusted sources.
  • Use safe libraries and validate the data being deserialized.

Security Headers:

  • Using security headers to protect the application.
  • Set security-related HTTP headers using helmet libraries.
                                    
const helmet = require('helmet');
app.use(helmet());
                                    
                                

Regular Security Audits:

  • Always be checking your code for vulnerabilities on a regular basis.
  • Use tools like npm audit to scan for vulnerabilities in dependencies..
                                    
                                    npm audit