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 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
- started a LAS instance on the local host.
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_ADDR
as 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