Skip to main content

Use of an insecure channel

Need

Secure transmission of data

Context

  • Usage of Dart 2.0 for building scalable and performant applications
  • Usage of Shelf for managing data persistence and querying in Node.js applications
  • Usage of Shelf.io for managing and organizing data in Node.js applications

Description

Non compliant code

import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;

void main() {
var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
.addHandler(_echoRequest);

io.serve(handler, 'localhost', 8080);
}

shelf.Response _echoRequest(shelf.Request request) {
return shelf.Response.ok('Request for "${request.url}"');
}

The above Dart code uses the Shelf package to create a simple server that listens on localhost and port 8080. The server has a single handler, _echoRequest, which returns a 200 OK response with the URL of the request.

However, this server is insecure as it does not use any form of encryption. This means that any data transmitted between the client and server is sent in plaintext and can be intercepted and read by anyone who is able to capture the network traffic. This is a major security vulnerability, especially if sensitive data such as usernames, passwords, or personal information is being transmitted.

Steps

  • Import the 'shelf' package with SSL support to enable secure communication.
  • Generate or obtain a valid SSL certificate and private key. You can use self-signed certificates for testing, but for production, you should use a certificate issued by a trusted Certificate Authority.
  • Configure the server to use the SSL certificate and private key. This will enable the server to establish secure connections using HTTPS.
  • Ensure that all data transmission is done over the secure channel. This includes not only the main data being transmitted, but also any metadata or other auxiliary data.
  • Test the server to ensure that it is correctly encrypting data and that clients can successfully establish secure connections.

Compliant code

import 'dart:io';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;

void main() {
var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
.addHandler(_echoRequest);

var server = HttpServer.bindSecure(
'localhost',
8080,
SecurityContext()
..useCertificateChain('path/to/certificate.pem')
..usePrivateKey('path/to/private_key.pem'),
);

io.serveRequests(server, handler);
}

shelf.Response _echoRequest(shelf.Request request) {
return shelf.Response.ok('Request for "${request.url}"');
}

The updated code now uses the HttpServer.bindSecure method from the dart:io library to create a secure server. This method takes three arguments: the host, the port, and a SecurityContext object. The SecurityContext object is configured with the paths to the SSL certificate and private key files.

The useCertificateChain method of the SecurityContext object is used to specify the path to the SSL certificate file, and the usePrivateKey method is used to specify the path to the private key file. These files are necessary for establishing a secure HTTPS connection.

The io.serveRequests function is then used to start the server and handle incoming requests. This function takes two arguments: the server and the handler. The handler is the same as in the original code, and is responsible for processing incoming requests and generating responses.

This updated code ensures that all data transmitted between the server and clients is encrypted using HTTPS, thereby fixing the original vulnerability. Please replace 'path/to/certificate.pem' and 'path/to/private_key.pem' with the actual paths to your SSL certificate and private key files.

References