Skip to content

Finding Secrets...

One of the main advantages of SGX technology is that it cannot only protect against external attackers but also against internal attackers that have root access. We introduce a simple approach to demonstrate that your application is indeed running inside of an enclave and that its secrets are not accessible.

Note

To ensure that your SCONE application runs inside of an enclave and to distribute secrets, please to use the SCONE configuration and attestation service.

To demonstrate how one can check that SGX/SCONE can protect against users with root access1, let's consider a simplistic example: we store some secret in a variable secret2. By default, binaries are not encrypted. Hence, do not store any secrets in a binary as it is done in this simplistic example.

Finding secret in simulation mode

If you really need to to protect your binaries - for example, since you have some legacy code with embedded secrets - SCONE can protect these secrets by permitting to encrypt shared libraries.

Example

We use the SCONE crosscompiler image and start an container with access to the SGX device:

docker pull sconecuratedimages/crosscompilers
docker run --device=/dev/isgx -it sconecuratedimages/crosscompilers

Let's create some program that stores a secret (MYBIGS) in a local variable secret:

cat > mysecret.c << EOF
#include <stdio.h>
#include <unistd.h>

const char *code_is_not_encrypted="THIS_IS_NOT_SECRET";

int main() {
    char secret[7];
    secret[0] ='M';
    secret[1] ='Y';
    secret[2] ='B';
    secret[3] ='I';
    secret[4] ='G';
    secret[5] ='S';
    secret[6] =0;
    printf("'%s' SECRET at %lx\n", secret, secret);
    printf("Kill with Ctrl-C.\n");
    for(;;)
        sleep(1); // loop forever
}
EOF

Compile this program with the SCONE crosscompiler (i.e., gcc):

gcc -g -o mysecret mysecret.c

Simulation Mode

You can run this program in SIMULATION MODE, i.e., this program does not protect your secrets:

SCONE_VERSION=1 SCONE_MODE=SIM SCONE_HEAP=128K SCONE_STACK=1K ./mysecret

Log into a different terminal on your host. Let us figure out the process ID of the mysecret program:

SPID=$(ps -a | grep -v grep | grep mysecret | awk  '{print $1}')

Now, we can dump the memory of this process via the /proc filesystem. You can determine the different memory regions of your process via cat /proc/$SPID/maps and the memory is stored in /proc/$SPID/mem. We can use the following Python program to write all pages to stdout:

cat > dumpstack.py << EOF
import sys, os, string, re

pid = sys.argv[1]
maps_file = open("/proc/%s/maps" % pid, 'r')
mem_file = open("/proc/%s/mem" % pid, 'r')
r=0

for line in maps_file.readlines():  # for each mapped region
    w=line.rsplit(None, 1)[-1] # last word
    if w != "/dev/isgx" and  w != "[vvar]" and w != "[vdso]" and w != "[vsyscall]":
        m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
        r += 1
        p = 0
        if m.group(3) == 'r':  # if this is a readable region
            start = int(m.group(1), 16)
            end = int(m.group(2), 16)
            while start < end:
                try:
                    mem_file.seek(start)  # seek to region start
                    chunk = mem_file.read(4096)  # read region contents
                    sys.stdout.write(chunk)
                    p += 1
                    if p > 1000:
                        sys.stderr.write("region = %02d, index=%x    \r" % (r,start))
                        p = 0
                    start += 4096
                except:
                    pass
sys.stderr.write("\n")
EOF

Run this program and grep for the prefix of our secret:

sudo python dumpstack.py $SPID | strings -n 5 | grep MYBI

This will take some time but eventually it will print the full secret MYBIGS.

Hardware Mode

Let us now run the program in hardware mode. First, ensure that you kill the original program by typing control-C.

Finding secret in prerelease mode

Let's start mysecret in an enclave, i.e., in hardware mode inside the container:

SCONE_VERSION=1 SCONE_MODE=HW SCONE_HEAP=128K SCONE_STACK=1K ./mysecret

Update environment variable SPID in a second terminal on your host:

SPID=$(ps -a | grep -v grep | grep mysecret | awk  '{print $1}')

and then try to find the secret:

sudo python dumpstack.py $SPID | strings -n 5 | grep MYBI

This will run for much less time and in particular, it will not print any secrets.

Note, however, that secrets stored in the binaries can be found because the binary is not encrypted: a copy of the original binary - which is used to start the enclave - stays in main memory outside the enclave.

Let's look for the string THIS_IS_NOT_SECRET in our example application. We can find this secret as follows:

sudo python dumpstack.py $SPID | strings -n 5 | grep THIS_IS_NOT_SECRET

© scontain.com, July 2018. Questions or Suggestions?


  1. Note that the enclave runs in this example runs in debug mode, i.e., one can still attach to this enclave with scone-gdb. To prevent access via the debugger, you need to run your enclave in production mode

  2. Note that an adversary could analyse the binary and figure out the secret. The standard way to provide an enclave with secrets is to use SCONE CAS