Non-encrypted hard drives - Go

Non-encrypted hard drives - Go

Need

Implementation of full disk encryption

Context

  • Usage of Go 1.16 for building high-performance and efficient applications
  • Usage of io/ioutil for reading and writing files in Node.js
  • Usage of log for logging messages and information

Description

Non compliant code

        package main

import (
	"io/ioutil"
	"log"
)

func main() {
	data := []byte("sensitive customer data")
	err := ioutil.WriteFile("/tmp/dat1", data, 0644)
	if err != nil {
		log.Fatal(err)
	}
}
        
        

This Go code writes a byte array containing sensitive customer data to a file called dat1 in the /tmp directory. The ioutil.WriteFile function is used to write the data to the file. If the file does not exist, WriteFile creates it with mode 0644 (readable by the user and readable/writable by the owner), before writing the data.

The vulnerability here is that the data is written to a non-encrypted hard drive. This means that anyone with access to the hard drive can easily read the file and see the sensitive customer data. The data is not protected in any way.

To exploit this vulnerability, an attacker would simply need to gain access to the hard drive. This could be done physically, or remotely if the attacker has access to the network the hard drive is on.

In the context of a Go backend application that uses the Gin framework, this vulnerability could be even more serious if the data being written to the hard drive comes from user input or from a database. This could potentially expose a large amount of sensitive customer data.

Steps

  • Implement full disk encryption on the server or the machine where the application is running.
  • Ensure that the encryption is applied to all the hard drives or storage devices used by the application.
  • Use secure encryption algorithms and key management practices to protect the sensitive data.
  • Update the code to write the sensitive data to an encrypted storage location instead of writing it to an unencrypted location.
  • Ensure that the encrypted storage location has appropriate access controls and permissions to prevent unauthorized access.
  • Regularly monitor and update the encryption mechanisms to stay up-to-date with the latest security practices.

Compliant code

        package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"io"
	"io/ioutil"
	"log"
)

func main() {
	data := []byte("sensitive customer data")
	key := []byte("passphrasewhichneedstobe32bytes!")

	c, err := aes.NewCipher(key)
	if err != nil {
		log.Fatal(err)
	}

	gcm, err := cipher.NewGCM(c)
	if err != nil {
		log.Fatal(err)
	}

	nonce := make([]byte, gcm.NonceSize())
	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
		log.Fatal(err)
	}

	encryptedData := gcm.Seal(nonce, nonce, data, nil)

	err = ioutil.WriteFile("/tmp/dat1", encryptedData, 0644)
	if err != nil {
		log.Fatal(err)
	}
}
        
        

The updated code now includes encryption for the sensitive data before writing it to the disk. The encryption used is AES (Advanced Encryption Standard) with GCM (Galois/Counter Mode) which provides both confidentiality and authenticity assurances on the data.

Here's a breakdown of the changes:

1. A key is created for the AES encryption. The key needs to be 32 bytes long.

2. An AES cipher is created with the key.

3. A GCM is created with the AES cipher.

4. A nonce (number used once) is created with the size of the GCM nonce. This nonce is needed for the Seal function of the GCM. The nonce should be unique for each call to Seal.

5. The sensitive data is encrypted using the GCM's Seal function. The function takes in the nonce, the plaintext data and additional data to authenticate (which is nil in this case). The function returns the encrypted data with the nonce prepended.

6. The encrypted data is written to the disk.

This way, even if the hard drive is not encrypted, the sensitive data stored on it is. However, it's still recommended to use full disk encryption for an additional layer of security.

References