Locking Down the Command Line with Intel® SGX

One avenue that an attacker may use to collect sensitive data from an application is by hijacking control of command-line arguments. If an attacker can choose the arguments to give to a command then it can ask the command to perform unauthorized operations or return sensitive data. The Anjuna SGX Runtime can protect against such attacks by imposing requirements on the command line arguments that a program can accept.

An attacker with access to the secured host might run an application in the terminal, passing arguments that cause it to read input files, process them, and generate output that leaks secrets. By restricting the command-line arguments that the application can receive, the secure enclave can prevent such attacks.

This section shows how to configure the Anjuna SGX Runtime to lock down an application command line to protect it against this class of attacks. We’ll show how to configure a secure encalve that runs OpenSSL to decrypt input payloads, while preventing an attacker from exposing private keys.

This section assumes that you’re using Ubuntu 18.04, and that OpenSSL and the Anjuna SGX Runtime are installed and configured.

To ensure that OpenSSL is installed, execute the following command:

$ sudo apt install openssl

For information about installing the Anjuna SGX Runtime, see Getting the Anjuna Runtime.

Create a Key Pair

Begin by creating a working directory to contain the files we’ll be working with:

$ mkdir lockdown

$ cd lockdown

Next, create a public/private key pair to use for encrypting and decrypting data:

$ openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048

$ openssl rsa -in private_key.pem -pubout > public_key.pem

OpenSSL creates the files private_key.pem and public_key.pem.

Now use anjuna-sgxrun to generate a manifest template file. We’ll edit the template to configure the Anjuna SGX Runtime to run OpenSSL.

Generate the manifest template with the following command:

$ anjuna-sgxrun --setup openssl

anjuna-sgxrun creates the file manifest.template.yaml, the manifest template. Edit this file and add the following entries:

keys:
- id: input_key
  source: enclave_generated

encrypted_files:
- path: private_key.pem.sealed
  key: input_key

Now use anjuna-sgxrun to generate a key pair for the secure enclave:

$ anjuna-sgxrun --provision openssl

We can now use anjuna-encrypt to encrypt the private key so that no cleartext copy of it exists, and it can be read only by OpenSSL running inside the secure enclave.

Encrypt the key:

$ anjuna-encrypt  --public-key provision/openssl.pubkey private_key.pem

anjuna-encrypt creates the file private_key.pem.sealed, a copy of the private key that is encrypted so that it can be read only from within the secure enclave.

In normal use, you could now delete the private_key.pem file to make it completely inaccessible to any attacker, but for this example you should not delete it. We’ll keep it and use it again to make further changes to the secure enclave’s configuration.

In the normal case, after you’ve deleted the private_key.pem, there is no longer a cleartext copy of the private key anywhere, which means that the only process that can possibly read it is openssl, and then only when it runs inside the secure enclave.

Encrypt an Example File

Let’s use the public key we created to encrypt an example file.

First, create a file containing some example data:

$ echo Secret message > message.txt

This command creates a file named message.txt that contains the text Secret message.

Now use the public key we created to encrypt it:

$ openssl rsautl -encrypt -inkey public_key.pem -pubin -in message.txt > message.txt.encrypted

OpenSSL creates a file named message.txt.encrypted that contains an encrypted copy of message.txt.

We can now run OpenSSL in its ecure enclave to decrypt the encrypted message:

$ anjuna-sgxrun openssl rsautl -decrypt -inkey private_key.pem.sealed -in message.txt.encrypted

anjuna-sgxrun runs OpenSSL inside its secure enclave, which enables it to automatically decrypt the data in the file private_key.pem.sealed. That decrypted key enables OpenSSL to decrypt message.txt.encrypted, so that it can then display the cleartext message: Secret message.

Without the private key, it would not be possible to decrypt message.txt.encrypted, and if we delete private_key.pem, the only way to get the privte key is through OpenSSL running inside the proper secure enclave.

Command-line Attacks

There’s a weakness in our protection, though: if an attacker can gain access to the command line and run OpenSSL in its secure enclave it becomes possible to retrieve the cleartext of the public key by passing the right parameters to OpenSSL:

$ anjuna-sgxrun openssl rsa -in private_key.pem.sealed -check

Even if we delete the cleartext private_key.pem, an attacker with the right access and permissions can use this method to recover the private key, and our sensitive data are no longer secure. How can we protect against this class of attacks?

The Anjuna SGX Runtime protects against such attacks by enabling us to specify strict requirements on the command lines that a command may accept when run inside the secure enclave. To lock down the command line is this way, we must configure the secure encalve using its manifest file.

Configure the Allowed Command Line

Edit the manifest.template.yaml file and add the following entries:

command_arguments:
- openssl
- rsautl
- -decrypt
- -inkey
- private_key.pem.sealed
- -in
- message.txt.encrypted

These entries specify a literal command line that then becomes the only command line that the secure enclave allows. If we try to run OpenSSL in the secure encalve with any other arguments, the secure enclave will prevent it from running.

To test the new configuration, run these commands:

$ anjuna-sgxrun --provision openssl
$ anjuna-encrypt --public-key provision/openssl.pubkey private_key.pem
$ anjuna-sgxrun openssl

OpenSSL can still decrypt the encrypted message, but any attempt to pass command-line arguments to OpenSSL results in an error. We can no longer use the OpenSSL command line to exfiltrate the cleartext of the private key.

We can test that protection by trying to run OpenSSL in the secure enclave with the command-line arguments needed to retrieve the private key:

$ anjuna-sgxrun openssl rsa -in private_key.pem.sealed -check

The secure enclave no longer allows us to run OpenSSL with command-line arguments.