How to prevent data leaks with HTTPS
Your company's cybersecurity team has just reached out to you. Your financial data has been compromised. It is currently for sale on the net. Why are they calling you? Well, it turns out that the billing management application you developed for them with GraphQL was at fault.
Although the application has been in use for a while without causing any problem, it appears that a recent change in your company's organization facilitated this data leak. Indeed, the recent and massive deployment of remote work increased the number of your employees working from home. This is not an issue if applications are secure. But in this case, your financial application did not benefit from any particular protection since it was usually used directly from your company premises, without any exchange with the outside world. One of the problems pointed out by the cyber team was the unencrypted mode of exchange between the server and the users, via plain HTTP.
Why is HTTP a security problem?
As you probably know, HTTP is one protocol that allows the exchange of text (HyperText Transfer Protocol) between a client and a server. This protocol allows the exchange of data in clear text, which could at one time be interesting for a website but which nowadays quickly finds its limits when it comes to exchanging potentially sensitive information.
It is now widely depreciated in favor of its secure version: HTTPS (HyperText Transfer Protocol Secure). The advantage of the latter is that it uses TLS (SSL) to secure exchanges between the client and the server. This involves encrypting the data exchanged, which can only be read by the client and the server. The server and client use an asymmetric encryption algorithm and a certificate to prove that the server is the one it claims to be.
These protocols can be used for web browsing, but also for all types of GET/POST/PUT requests that are used by GraphQL. Not securing these requests means giving access to the content of the data sent to any individual who is able to intercept the message in question. In our case study, since the application uses HTTP, all the financial exchanges made by the users could be intercepted on their way to the company's servers.
Data transmitted in clear text is particularly vulnerable to man-in-the-middle attacks, where a malicious person only needs to capture the exchange to know its content. It is to guard against these attacks that encryption mechanisms exist, coupled with certificates. They make it possible to encrypt exchanges while ensuring that the chosen server is contacted rather than an intermediary seeking to spy on the traffic.
- This is also the reason why most Internet browsers highlight (negatively) unsecured sites and why their ranking on search engines is lower! It is, therefore in your interest to secure your various applications.
If you want to catch DoS vulnerabilities and 100+ other GraphQL security vulnerabilities before it's too late, check out Escape. Run hundreds of security scans in your CI/CD 🚀
How to force HTTPS on GraphQL APIs
Use the HTTPS protocol
If you don't want your data to be transmitted in clear text, this is one of the safest ways to ensure that it isn't. As mentioned above, HTTPS is based on SSL (TLS) and, therefore requires that you dispose of a certificate and keys for asymmetric encryption (public and private keys). You can easily get the whole package from sites such as Let's Encrypt. If you want to go through the full process with your chosen Certificate Authority (CA), the process is detailed here.
You then need to configure your GraphQL implementation to take your certificate into account and encrypt your exchanges.
Apollo GraphQL
Here is the first example using Apollo GraphQL, which is based on Node (Express) and the HTTP and HTTPS modules:
import express from "express";
import {ApolloServer} from "apollo-server-express";
import typeDefs from "./graphql/schema";
import resolvers from "./graphql/resolvers";
import fs from "fs";
import https from "https";
import http from "http";
async function startApolloServer(){
const configurations = {
// Note: you may need sudo to run on port 443
production: {
ssl: true,
port: 443,
hostname: "example.com"
},
development: {
ssl: false,
port: 4000,
hostname: "localhost",
},
};
const environment = process.env.NODE_ENV || "production";
const config = configurations[environment];
const app = express();
const server = new ApolloServer({ typeDefs, schema });
let httpServer;
if (config.ssl) {
// Assumes certificates are in a .ssl folder off of the package root.
// Make sure these files are secured.
httpServer = https.createServer({
key: fs.readFileSync(`./ssl/${environment}/server.key`),
cert: fs.readFileSync(`./ssl/${environment}/server.crt`),
}, app);
} else {
httpServer = http.createServer(app);
}
await new Promise<void>(resolve => httpServer.listen({ port: config.port }, resolve));
console.log("🚀 server ready at", `http${config.ssl ? 's' : ''}://${config.hostname}:${config.port}${server.graphqlPath}`);
return {server, app};
}
Hasura
Hasura does not directly allow secure requests via SSL/TLS. The configuration must be done at the level of the server that hosts Hasura. Here is an example of the configuration file ( nginx.conf
) for NGINX:
server {
listen 80;
listen 443 ssl;
server_name hasura.example.com;
location/{
proxy_pass http://localhost:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Graphene
Again, you will need to manage this setting at the server level.
If you are using Graphene with Django, additional settings may be required to ensure that Django knows that HTTPS is being used rather than HTTP. It is recommended that you read the official Django documentation so that you do not put yourself at further risk by performing this manipulation.
Use a VPN
If your applications carry sensitive data, you can add an extra layer of security by setting up or using a VPN.
The advantage of a VPN is that it allows data to pass in encrypted form between the VPN server (on-premises or not) and the user's computer. This can be an additional asset for the security of your applications. Indeed, HTTPS and VPN do not intervene at the same level of the transport chain and are therefore fully compatible!
To sum up, as long as no encryption mechanism is in place, your data will circulate in plain text and will, therefore be accessible to anyone who manages to intercept it.
Implementing these mechanisms is not complex and allows you to significantly improve the security of your applications in a context where more and more employees are required to work remotely.
What to learn more?
- Interactive lesson to configure HTTP Headers for User Protection
- Using HTTPS with Apollo GraphQL
- Why is HTTP not secure
- Understanding the man-in-the-middle attacks and derivatives
More from our GraphQL vulnerabilities series:
- Access Control Best Practices for GraphQL
- Cross-Site Scripting (XSS) in GraphQL
- Avoid GraphQL Denial of Service attacks
- Understanding and Dealing with Cross-Site Request Forgery Attacks (CSRF)
Wanna know more about GraphQL Security? Check out our blog post "9 GraphQL Security Best Practices" or start your lessons with our API Security Academy focused on GraphQL and learn how to build safe GraphQL APIs.