ViewState not encrypted - Dart

ViewState not encrypted - Dart

Need

Secure encryption of ViewState

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing and organizing data in a Node.js application

Description

Non compliant code

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

class AppState {
  String userName;
}

void handle(shelf.Request request) {
  var appState = AppState();
  appState.userName = 'John Doe';
  var viewState = appState.toString();
  var response = shelf.Response.ok(viewState);
}
        
        

In the above code, we have the AppState class, which holds the state of the application
- in this case, a userName. This is a simple representation of a stateful object in a backend application.

In the handle function, we create an instance of AppState, set its userName property, and then convert it to a string to be sent in a response. This string represents the ViewState of the application.

The vulnerability here is that the ViewState is not encrypted. This means that anyone who intercepts the response could potentially read and manipulate the state of the application. This could lead to unauthorized access or other security breaches.

Steps

  • Import a library that provides encryption functionality.
  • Create an encryption key that will be used to encrypt the ViewState.
  • Before storing the ViewState, encrypt it using the encryption key.
  • When retrieving the ViewState, decrypt it using the same encryption key.
  • Ensure that the encryption key is stored securely and is not exposed to potential attackers.

Compliant code

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

class AppState {
  String userName;
}

void handle(shelf.Request request) {
  var appState = AppState();
  appState.userName = 'John Doe';

  // Create an encryption key
  final key = encrypt.Key.fromLength(32);
  final iv = encrypt.IV.fromLength(16);

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

  // Encrypt the ViewState
  final encryptedViewState = encrypter.encrypt(appState.toString(), iv: iv);

  var response = shelf.Response.ok(encryptedViewState.base64);
}
        
        

The above code fixes the vulnerability by encrypting the ViewState before it is stored.

Firstly, we import the encrypt package which provides encryption functionality.

Next, we create an encryption key and an initialization vector (IV) which will be used to encrypt the ViewState. The key is generated from a length of 32 and the IV from a length of 16.

We then create an encrypter using the AES algorithm provided by the encrypt package and the key we generated.

Before storing the ViewState, we encrypt it using the encrypter and the IV. The encrypt method of the encrypter returns an Encrypted object which we convert to a base64 string before storing it.

When the ViewState is retrieved, it will need to be decrypted using the same key and IV.

Please note that the encryption key and IV should be stored securely and not exposed to potential attackers. In a real-world application, you would not generate a new key and IV every time, but rather use a securely stored key and IV.

References