Node.js Security
Security of Node.js applications:
Node.js applications need to be secured against common vulnerabilities and attacks. The following are the most common security vulnerabilities in Node.js applications and best practices to mitigate them.
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