Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at some best practices we should follow when writing Node apps.
Setting Cookies
We can set cookies with Express.
We can use the cookie-session to send the cookies.
For example, we can write:
const cookieSession = require('cookie-session');
const express = require('express');
const app = express();
app.use(cookieSession({
name: 'session',
keys: [
process.env.COOKIE_KEY1,
process.env.COOKIE_KEY2
]
}));
app.use((req, res, next) => {
const n = req.session.views || 0;
req.session.views = n++;
res.end(n);
});
app.listen(3000);
We use the cookie-session package to set the cookies.
CSRF
Cross-site requests forgery is an attack where a user does unwanted actions in the app that they’re logged in as.
These attacks target state-changing requests since they can’t see the response of the forged request.
To protect us from CSRF attacks, we can use the csrf
module.
And in Express, we can use the csurf
module.
For example, we can write:
const cookieParser = require('cookie-parser');
const csrf = require('csurf');
const bodyParser = require('body-parser');
const express = require('express');
const csrfProtection = csrf({ cookie: true });
const parseForm = bodyParser.urlencoded({ extended: false });
const app = express();
app.use(cookieParser());
app.get('/form', csrfProtection, (req, res) => {
res.render('send', { csrfToken: req.csrfToken() });
});
app.post('/process', parseForm, csrfProtection, (req, res) => {
res.send('submitted');
});
Then we can add the form in our template:
<form action="/process" method="POST">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
Name: <input type="text" name="name">
<button type="submit">Submit</button>
</form>
We add a hidden input with the csrfToken
in the form so that we can only submit the form when a CSRF token is present.
Data Validation
We should validate our data so that it prevents cross-site scripting.
Cross-site scripting occurs when attackers object HacaSruot code into HTML with specialty crafted links.
Stored cross-site scripting occurs when the app stores the user input which isn’t correctly filtered.
It runs within the app.
To prevent these kinds of attacks, we should always filter and sanitizer user input.
SQL Injection
Another kind of attack to prevent is SQL injection.
We run SQL statements in our code dynamically so that we can read data and do malicious actions.
To prevent these attacks, we should use parameterized queries or prepared statements.
Some modules like node-postgres module will let us create a parameterized query as follows:
const q = 'SELECT name FROM books WHERE id = $1';
client.query(q, ['1'], (err, result) => {});
sqlmap lets us automate the testing of detecting and exploring SQL injection flaws in our app.
We can use it to test for SQL injection vulnerabilities.
Command Injection
Another security flaw that can arise is command injection.
We can put commands in a query string to run shell commands.
To prevent these attackers, we should always sanitize user input.
We can write code like:
https://example.com/downloads?file=%3Bcat%20/etc/passwd
Also, child_process.exec
runs /bin/sh
so it’s a bash interpreter rather than a program launcher.
A new command can be injected by the attacker with this with a backtick or $()
.
We can overcome this with child_process.execFile
.
Conclusion
We can set cookies and run various commands security.
Also, we need to protect against malicious inputs.