Skip to main content

Non-encrypted confidential information - Local data

Need

Secure storage of confidential information on local devices

Context

  • Usage of Dart 2.0 for building high-performance web and mobile applications
  • Usage of dart:io for handling input and output operations in Dart programming
  • Usage of the shelf package in Dart for building web applications and HTTP middleware

Description

Non compliant code

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

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

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

shelf.Response _echoRequest(shelf.Request request) {
var firebaseData = 'Confidential Firebase Data';
File('local.txt').writeAsString(firebaseData);
return shelf.Response.ok('Data Saved!');
}

In the above Dart code, we are using the Shelf framework to create a backend server. The server is set up to listen to requests on localhost at port 8080.

The function _echoRequest is designed to handle incoming requests. It takes a shelf.Request as a parameter and returns a shelf.Response.

The vulnerability lies in the way we are handling the confidential Firebase data. We are storing this data in a local file named local.txt using the writeAsString method. This method writes a string to a file, creating the file if it doesn't already exist.

However, the data is being written as plain text, without any form of encryption. This means that anyone who gains access to the device and bypasses its security mechanisms can easily read the confidential Firebase data. This is a serious security concern as it can lead to data breaches and unauthorized access to sensitive information.

In the case of theft or loss of the device, the attacker can easily access and exploit this confidential information. Therefore, it is crucial to encrypt any sensitive data before storing it in the device's local storage.

Steps

  • Import a library that provides encryption functionality such as 'encrypt' in Dart.
  • Create an encryption key and an initialization vector. The key should be securely generated and stored, not hardcoded in the application.
  • Before writing the firebase data to the file, encrypt it using the encryption key and initialization vector.
  • When reading the data from the file, decrypt it using the same key and initialization vector.
  • Ensure that the encryption and decryption processes are correctly implemented and that the data is not exposed in its plain form at any point.

Compliant code

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

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

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

shelf.Response _echoRequest(shelf.Request request) {
var firebaseData = 'Confidential Firebase Data';

// Create an encryption key and an initialization vector
final key = encrypt.Key.fromLength(32); // example of generating a secure random key
final iv = encrypt.IV.fromLength(16); // example of generating a secure random initialization vector

// Create an encrypter
final encrypter = encrypt.Encrypter(encrypt.AES(key));

// Encrypt the data
final encryptedData = encrypter.encrypt(firebaseData, iv: iv);

// Write the encrypted data to the file
File('local.txt').writeAsString(encryptedData.base64);

return shelf.Response.ok('Data Saved!');
}

The updated code now includes the 'encrypt' library, which is used to encrypt the confidential Firebase data before it is stored in the local file.

An encryption key and an initialization vector are generated using the Key.fromLength and IV.fromLength methods respectively. These are used to create an Encrypter object, which is then used to encrypt the Firebase data.

The encrypted data is then written to the local file. This ensures that even if an attacker gains access to the physical device and bypasses the device security mechanism, they will not be able to view the confidential data without the encryption key and initialization vector.

Please note that the encryption key and initialization vector should be securely generated and stored, not hardcoded in the application as shown in this example. This is to prevent an attacker from easily obtaining these values and decrypting the data.

Also, when reading the data from the file, it should be decrypted using the same key and initialization vector. This ensures that the data is not exposed in its plain form at any point.

References