这是我们发现的 Unanticipated Snapshot Attack 的原始演示。感谢 Intel 提供安全公告。
首先,任何希望运行此演示的人都必须安装 Intel SGX SDK 和 Occlum(你可以选择使用我们修改过的 SGX SDK)。我们提供了一个 Dockerfile,用于快速安装 Occlum/SDK。修改后的 SGX SDK 旨在帮助攻击者判断时机。
你也可以在宿主机上安装 Occlum。(更多安装细节请参阅 https://github.com/occlum/occlum。)无论采用哪种方式,你都需要先在宿主机上安装 Intel SGX 驱动程序,或者使用内核自带的 SGX 驱动程序。
(sudo) docker build -t $Your_Image_Name .
镜像构建完成后,运行
(sudo) docker run -it --privileged -p $Redis_Server_Port:6379 -v $Host_SGX_Driver_Path:/dev/sgx --name "snapshot-demo" $Your_Image_Name
这里,$Redis_Server_Port 是你希望为容器内 Redis 服务器暴露的宿主机端口号,而 $Host_SGX_Driver_Path 是前面提到的已安装 SGX 驱动程序的设备路径。
目标程序位于 bash_redis 文件夹中。
受害程序运行一个 bash shell 脚本(occlum_bash.sh)。它首先获取一个预置的密码,生成自定义的 Redis 配置文件,并填入 "requirepass" 条目。然后根据该自定义配置文件启动一个 Redis 服务器。
要构建配置生成程序,请运行 make。要构建 Redis 服务器,请执行以下命令。
cd bash_redis
./download_and_build_redis_glibc.sh
为受害方打开一个终端。运行 run_redis.sh,检查 Redis 服务器是否正常工作。
使用命令 redis-cli -h $Redis_Server_IP -p $Redis_Server_Port -a admin123456 验证密码(admin123456)是否已写入配置文件。
按 ctrl + C 终止 Redis 服务器。
准备 2 个终端,一个用于受害方,一个用于攻击者。如果已经为受害方打开了一个终端,你只需再打开一个终端(用于攻击者)。
在受害方终端再次运行 run_redis.sh。该脚本将启动目标程序。
攻击者需要在能够确定快照正在刷写时拍摄快照(使用 ./take_snapshot_step-1.sh)。在演示中,攻击者会从受害方终端看到如下明确提示:
...
Run ./take_snapshot_step-1.sh NOW!
line 4522: # passwords, then flags, or key patterns. However note that the additive
line 4523: # and subtractive rules will CHANGE MEANING depending on the ordering.
line 4524: # For instance see the following example:
...
在攻击者终端上启动 ./take_snapshot_step-1.sh 脚本。
如果你使用我们修改过的 SGX SDK 构建 Occlum,你会看到更多提示信息。这是因为我们修改了 Intel SGX SDK 的不可信部分,打印辅助消息以帮助攻击者判断时机。为了方便攻击者,我们预留了时间槽位,让攻击者可以运行 ./take_snapshot_step-1.sh。事实上,拥有宿主机 root 权限的攻击者可以通过修改 SGX SDK 的不可信部分来拦截 enclave 执行并捕获任意快照。
一旦 Redis 服务器启动并运行,运行 ./take_snapshot_step-2.sh 以完成快照收集。
攻击者执行 replay_redis.sh,使用我们收集的快照重放 enclave。任何客户端都可以在无需认证的情况下登录 Redis 服务器。
Redis 客户端示例命令:
redis-cli -h $Redis_Server_IP -p $Redis_Server_Port
keys *
如果提示 (error) NOAUTH Authentication required.,则表示你需要密码才能访问 Redis 服务器。输入 auth $Your_Password 通过认证。在本演示中使用 auth admin123456。
如果提示 (empty array),则表示你不需要密码即可访问 Redis 服务器。
有时演示会因 Occlum 的完整性检查而失败。你可能会看到以下消息。
Replaying ...
~/snapshot-demo/bash_redis_replay/occlum_instance ~/snapshot-demo/bash_redis_replay
In: writing meta-data in write_all_changes_to_disk
In: writing meta-data in write_all_changes_to_disk
Error: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }
[ERROR] occlum-pal: The init process exit with code: 1 (line 59, file src/pal_api.c)
[ERROR] occlum-pal: Failed to run the init process: EINVAL (line 129, file src/pal_api.c)
只需(从记录阶段开始)重新运行演示,该错误就会彻底消失。
祝好运,玩得开心!