Skip to content

Secure Arguments and Environment Variables

We show how to pass arguments and environment variables in a secure fashion to an application with the help of CAS.

SCONE CAS Overview

SCONE CAS manages the keys of an application. The keys are unter complete control of the application: only services given explicit control by the application get access to the keys.

Prerequisites

We assume that you already

Simple Example

We create a simple C program to print the arguments as well as the environment variables:

cat > print-arg-env.c <<EOF
#include <stdio.h>

extern char **__environ;

int main (int argc, char **argv) {
    printf("argv:");
    for (int i = 0; i < argc; i++) {
        printf(" %s", argv[i]);
    }
    printf("\n");

    char** envp = __environ;
    printf("environ:\n");
    while (*envp != NULL) {
        printf("%s\n", *envp);
        envp++;
    }
    return 42;
}
EOF

We can compile this natively as follows:

gcc print-arg-env.c -g -O3 -o print-arg-env

And we can now run this with some some arguments and some environment variables:

ENV2=World ENV1=! ./print-arg-env Hello

This results in an output similar to this:

argv: ./print-arg-env Hello
environ:
ENV2=World
ENV1=!
...

Let's cross-compile this program to run inside of enclaves as follows. We determine which SGX device to mount with function determine_sgx_device.

determine_sgx_device
docker run $MOUNT_SGXDEVICE  --network=host -it -v `pwd`:/work registry.scontain.com/sconecuratedimages/crosscompilers bash
# in the container compile the program:
scone-gcc /work/print-arg-env.c -g -O3 -o /work/scone-print-arg-env

We can now determine MRENCLAVE as follows:

export MRENCLAVE=`SCONE_HASH=1 ./scone-print-arg-env`
echo MRENCLAVE of scone-print-arg-env is $MRENCLAVE

We can now run the program inside of an enclave but not under the control of CAS as follows:

ENV2=World ENV1=! ./scone-print-arg-env Hello

This will result in the same output as before:

argv: ./print-arg-env Hello
environ:
ENV2=World
ENV1=!
...

Without CAS: No Confidentiality and Integrity of Arguments and Environment Variables

Note that neither the integrity nor the confidentiality of these arguments are protected. To protect these and to ensure that the program is indeed executed inside an enclave, we need to run the program in the context of CAS.**

Secure Arguments and Environment Variables

In the next step, we control the environment variables and the arguments with the help of CAS.

When does the SCONE runtime use CAS?

When environment variable SCONE_CONFIG_ID is not set, the SCONE runtime will not contact CAS. If it is set, we will contact SCONE_CAS_ADDR. If SCONE_CAS_ADDR is not set, we contact by default host „cas“. The SCONE runtime will also contact SCONE_LAS_ADDR for local attestation. If SCONE_LAS_ADDR is not set, we contact by default host „las“.

You can use a our public CAS instance at domain scone-cas.cf:

export SCONE_CAS_ADDR=scone-cas.cf

We also assume that you already started a LAS in the background via docker-compose up -d las on the local machine:

export SCONE_LAS_ADDR=... # Address of your local LAS instance, e.g., 172.17.0.1

We can now create a new session on cas as follows. We first create a unique session name:

export SESSION=secure-arguments-example-$RANDOM-$RANDOM

We create a policy (aka session) as follows:

cat > session.yaml <<EOF
name: $SESSION
digest: somedigest

services:
   - name: scone-print-arg-env
     mrenclaves: [$MRENCLAVE]
     tags: [thisissometag1]
     command: ./scone-print-arg-env arg1 arg2 arg3
     environment:
        SCONE_MODE: hw
        env1: running
        env2: in
        env3: enclave
     pwd: /
EOF

Let's make sure that we have a client certificate to identify this client:

Next, we will upload this session to CAS. To do so, we first attest CAS as follows.

scone cas attest $SCONE_CAS_ADDR

Actually, this will fail for the public CAS scone-cas.cf since it runs in DEBUG mode:

Error: Error during attestation of CAS
Caused by: Remote attestation report verification failed
Caused by: The program enclave is not trustworthy
Caused by: Debug mode is enabled. Enclave protection is turned off, all secrets can be extracted with a debugger

Hence, we need to attest CAS such that we permit debug mode:

scone cas attest $SCONE_CAS_ADDR --only_for_testing-trust-any --only_for_testing-debug  --only_for_testing-ignore-signer -C -G -S

Now we can create the policy on CAS as follows:

export PREDECESSOR=$(scone session create session.yaml)

This results in an output similar to this:

echo $PREDECESSOR
1215b15a4968c970aa7012c9e3193e619f40e87df6d017bf0ad6d333230b54e3

Note that if you try to upload to a session that already exists, you will get an error code like this:

Error: Creating session failed
Caused by: CAS at 'https://scone-cas.cf:8081/' returned HTTP error status code 400 Bad Request
Caused by: Session already exists, please specify predecessor hash

In other words, if you want to update a session, you need to define a predecessor key in the policy that specifies the current session. This is to ensure that a client does not overwrite a just updated session, i.e., it permits to detect write/write conflicts.

Executing Print-Arg-Env

Let us now execute scone-print-arg-env in the context of session secure-arguments-example. To do so, we need to pass in environment variable SCONE_CONFIG_ID which contains the name of the session and we need to set SCONE_CAS_ADDRas well as SCONE_LAS_ADDR as we have shown above.

SCONE_CONFIG_ID=$SESSION/scone-print-arg-env ./scone-print-arg-env

This will print the following output:

argv: ./scone-print-arg-env arg1 arg2 arg3
environ:
SCONE_MODE=hw
env2=in
env1=running
env3=enclave

Note that the environment variables - except those expected by the SCONE runtime to locate LAS, CAS and the session - are ignored. This means even if we pass additional arguments and environment variables, the output does not change. The execution of

IRGNORED_ENV=1 SCONE_CONFIG_ID=$SESSION/scone-print-arg-env ./scone-print-arg-env IGNORED1 IGNORED2

results in the same output:

argv: ./scone-print-arg-env arg1 arg2 arg3
environ:
SCONE_MODE=hw
env2=in
env1=running
env3=enclave

The SCONE variables provided by the environment are not protected in any way and we designed SCONE assuming that an attacker could modify these environment variables. This could lead to denial of service attacks but not to the exposure of any secrets.

Integrity of SCONE environment variables

An adversary could change SCONE_CONFIG_ID, SCONE_CAS_ADDR and SCONE_LAS_ADDR but in this case, the application does not start (attestation fails) up or it does not get access to the secrets and configuration variables to do its job.

Changing the policy

If we want to change the arguments or the environment variables of the program, we can change the policy as follows:

cat > session1.yaml <<EOF
name: $SESSION
version: 0.3
predecessor: $PREDECESSOR

security:
  attestation:
    tolerate: [debug-mode, hyperthreading]

services:
   - name: scone-print-arg-env
     mrenclaves: [$MRENCLAVE]
     command: ./scone-print-arg-env new_arg1 new_arg2 new_arg3
     environment:
        SCONE_MODE: hw
        env1: version
        env2: 2
        env3: enclave
     pwd: /
EOF

Update the session as follows:

export PREDECESSOR1=$(scone session update session1.yaml)
echo $PREDECESSOR1

Note that in case you do not know the predecessor hash, you can compute the predecessor hash as follows:

scone session read $SESSION > session0.yaml  # download the current policy
export PREDECESSOR=$(scone session verify session0.yaml)
echo $PREDECESSOR

When executing the program now, we see the new values of the arguments and the environment variables:

SCONE_CONFIG_ID=$SESSION/scone-print-arg-env ./scone-print-arg-env 

When executing on out-of-date trusted computing base (TCB), this will fail despite being in debug mode:

[SCONE|WARN] src/enclave/dispatch.c:197:print_version(): Application runs in SGX debug mode.
    Its memory can be read from outside the enclave with a debugger! This is not secure!
[SCONE|FATAL] src/process/init.c:476:__scone_prepare_secure_config(): Could not initialize enclave state: Attestation failed
  Caused by: CAS sent an attestation/configuration error: SCONE quote verification failed
  Caused by: Failed to verify SCONE remote attestation report
  Caused by: The enclave's TCB is not trustworthy
    Caused by: Security risks:
    - The TCB is outdated and may be vulnerable
    - See advisory INTEL-SA-00076 (https://www.intel.com/content/www/us/en/security-center/advisory/INTEL-SA-00076)
    - See advisory INTEL-SA-00088 (https://www.intel.com/content/www/us/en/security-center/advisory/INTEL-SA-00088)
    - ...

The error message will provide you a list of security announcements that are violated. You can tolerate these by changing the policy:

cat > session2.yaml <<EOF
name: $SESSION
version: 0.3
predecessor: $PREDECESSOR1

security:
  attestation:
    tolerate: [debug-mode, hyperthreading, outdated-tcb]
    ignore_advisories: "*"

services:
   - name: scone-print-arg-env
     mrenclaves: [$MRENCLAVE]
     command: ./scone-print-arg-env new_arg1 new_arg2 new_arg3
     environment:
        SCONE_MODE: hw
        env1: version
        env2: 2
        env3: enclave
     pwd: /
EOF

Update the session as follows:

export PREDECESSOR2=$(scone session update session2.yaml)
echo $PREDECESSOR2

Let us try to execute this again:

SCONE_CONFIG_ID=$SESSION/scone-print-arg-env ./scone-print-arg-env 

Access Control to Confidential Application

Everybody that knows the SCONE_CONFIG_ID and has access to CAS instance and the program, can execute ./scone-print-arg-env. In some cases, we would only permit authorized users to start a confidential application. We can use OTPs (One Time Passwords) to limit access to applications (see https://sconedocs.github.io/CAS_session_lang_0_3/#2fa-with-time-based-one-time-passwords).

Let us generate an OTP secret as follows:

export OTPSECRET=... # base32 encoded without trailing =

Please use this secret in your authenticator. For testing, you can use an online authenticator like https://jwessel.github.io/totp-gauth-token/QR_generator.html.

cat > session3.yaml <<EOF
name: $SESSION
version: 0.3
predecessor: $PREDECESSOR2

security:
  attestation:
    tolerate: [debug-mode, hyperthreading, outdated-tcb]
    ignore_advisories: "*"
    one_time_password_shared_secret: $OTPSECRET

services:
   - name: scone-print-arg-env
     mrenclaves: [$MRENCLAVE]
     command: ./scone-print-arg-env need to pass your OTP
     environment:
        SCONE_MODE: hw
        env1: version
        env2: 3
        env3: otp-variant
     pwd: /
EOF

Update the session as follows:

export PREDECESSOR3=$(scone session update session3.yaml)
echo $PREDECESSOR3

When executing the program

SCONE_CONFIG_ID=$SESSION/scone-print-arg-env ./scone-print-arg-env 

will now result in an fatal error:

[SCONE|FATAL] src/process/init.c:476:__scone_prepare_secure_config(): Could not initialize enclave state: Attestation failed
  Caused by: CAS sent an attestation/configuration error: Failed to retrieve service attestation configuration
  Caused by: An One-time Password is required to access this session

With your authenticator, please determine the current OTP and store this in environment variable OTP:

export OTP=...

and now execute with the right OTP:

SCONE_CONFIG_ID=$SESSION/scone-print-arg-env@$OTP ./scone-print-arg-env 

We see the following output:

[SCONE|WARN] src/enclave/dispatch.c:197:print_version(): Application runs in SGX debug mode.
    Its memory can be read from outside the enclave with a debugger! This is not secure!
[SCONE|WARN] src/syscall/syscall.c:31:__scone_ni_syscall(): system call: membarrier, number 324 is not supported
[SCONE|WARN] src/process/init.c:722:__scone_apply_secure_config(): Ignoring `SCONE_PWD` environment variable and host provided process working directory.
    Applying process working directory from service's session configuration (/)
argv: ./scone-print-arg-env need to pass your OTP
environ:
SCONE_MODE=hw
env1=version
env2=3
env3=otp-variant

An OTP - as the name says - is a one time password. When executing the command again, this will always fails (even if one would be in the right 30 seconds time period):

[SCONE|WARN] src/enclave/dispatch.c:197:print_version(): Application runs in SGX debug mode.
    Its memory can be read from outside the enclave with a debugger! This is not secure!
[SCONE|FATAL] src/process/init.c:476:__scone_prepare_secure_config(): Could not initialize enclave state: Attestation failed
  Caused by: CAS sent an attestation/configuration error: Failed to retrieve service attestation configuration
  Caused by: The given One-time Password is invalid. Please try again.
Note: Connecting to CAS at scone-cas.cf (port 18765) using service ID secure-arguments-example-8230-28245/scone-print-arg-env@307608