Security has been a problem for web developers since before the Internet existed. By this, I mean network security was a problem before the Internet—the network of networks—was created. Internet and network security has gotten a lot of play recently in the media, mostly due to some high-profile hacks that have taken place. From the personal security perspective, very little has changed. The prevalence of phishing attacks continues to increase as networks become more secure. This is because human beings remain a serious liability when securing a network. However, this type of security discussion is outside the scope of this blog.
Due to the vast breadth of this topic, I am going to focus on one specific area of web security; we will discuss securing websites and apps from the perspective of an open source developer, and I will focus on the tools that can be used to secure Node.js. This is not an exhaustive guide to secure web development. Consider this blog a quick overview of the current security tools available to Node.js developers.
A good starting point is a brief discussion on injection theory. This article provides a more in-depth discussion if you are interested. The fundamental strategy for injection attacks is figuring out a way to modify a command on the server by manipulating unsecured data. Aclassic example is the SQL injection, in which SQL is injected through a form into the server in order to compromise the server’s database. Luckily, injection is a well-known infiltration strategy and there are many tools that help defend against it.
One method of injection compromises HTTP headers. A quick way to secure your Node.js project from this attack is through the use of the helmet module. The following code snippet shows how easy it is to start using helmet with the default settings:
var express = require('express')
var helmet = require('helmet')
var app = express()
app.use(helmet())
Just the standard helmet settings should go a long way toward a more secure web app. By default, helmet will prevent clickjacking, remove the X-Powered-By header, keep clients from sniffing the MIME type, add some small cross-site scripting protections (XSS), and add other protections. For further defense against XSS, use of the sanitizer module is probably a good idea. The sanitizer module is relatively simple. It helps remove syntax from HTML documents that could allow for easy XSS.
Another form of injection attacks is the SQL injection. This attack consists of injecting SQL into the backend as a means of entry or destruction. The sqlmap project offers a tool that can test an app for SQL injection vulnerabilities. There are many tools like sqlmap, and I would recommend weaving a variety of automated vulnerability testing into your development pattern. One easy way to avoid SQL injection is the use of parameterized queries. The PostgreSQL database module supports parameterized queries as a guard against SQL injection.
A fundamental part of any secure website or app is the use of secure transmission via HTTPS. Accomplishing encryption for your Node.js app can be fairly easy, depending on how much money you feel like spending. In my experience, if you are already using a deployment service, such as Heroku, it may be worth the extra money to pay the deployment service for HTTPS protection. If you are categorically opposed to spending extra money on web development projects, Let’s Encrypt is a free and open way to supply your web app with browser-trusted HTTPS protection. Furthermore, Let’s Encrypt automates the process of using an SSL certificate. Let’s Encrypt is a growing project and is definitely worth checking out, if you haven’t already.
Once you have created or purchased a security certificate, Node’s onboard https can do the rest of the work for you. The following code shows how simply HTTPS can be added to a Node server once a certificate is procured:
// curl -k https://localhost:8000/
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('/agent2-key.pem'),
cert: fs.readFileSync('/agent2-cert.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello securityn');
}).listen(8000);
If you are feeling adventurous, the crypto Node module offers a suite of OpenSSL functions that you could use to create your own security protocols. These include hashes, HMAC authentication, ciphers, and others.
Internet security is often overlooked by hobbyists or up-and-coming developers. Instead of taking a back seat, securing a web app should be one of your highest priorities, especially as threats on the Web become greater with each passing day. As far as the topic of the blog post, what’s new and what’s not, most of what I have discussed is not new. This is in part due to the proliferation of social engineering as a means to compromise networks instead of technological methods. Most of the newest methods for protecting networks revolve around educating and monitoring authorized network users, instead of more traditional security activities. What is absolutely new (and exciting) is the introduction of Let’s Encrypt. Having access to free security certificates that are easily deployed will benefit individual developers and Internet users as a whole. HTTPS should become ubiquitous as Let’s Encrypt and other similar projects continue to grow.
As I said at the beginning of this blog, security is a broad topic. This blog has merely scratched the surface of ways to secure a Node.js app. I do hope, however, some of the information leads you in the right, safe direction.
Erik Kappelman is a transportation modeler for the Montana Department of Transportation. He is also the CEO of Duplovici, a technology consulting and web design company.