我正在实施一些 CTF 挑战。这些标志位于一些从程序中读取的文本文件中。为了保护标志,我更改了文件的所有者,但将其设置setuid
为可执行文件以便能够读取文件。当我在 gdb 外部运行程序并且读取标志时,它会起作用,但在 gdb 内部我会得到Permission denied
.我正在 VirtualBox 中的 Linux 虚拟机中运行练习。我创建了一个不在 sudoers 文件中的普通用户,并且标志文件属于 root。
-rwsr-xr-x 1 root user 15260 Mar 13 13:22 exercise6
-rw-r--r-- 1 user user 3270 Mar 13 06:10 'Exercise 6.c'
-rwsr-xr-x 1 root user 15700 Mar 14 03:28 exercise7
-rw-r--r-- 1 user user 4372 Mar 13 06:10 'Exercise 7.c'
-rwS------ 1 root root 28 Mar 13 06:10 admin_flag.txt
-rwS------ 1 root root 20 Mar 13 06:24 exercise1.txt
-rwS------ 1 root root 27 Mar 13 06:24 exercise2.txt
-rws------ 1 root user 18 Mar 13 10:34 exercise3.txt
-rwS------ 1 root root 22 Mar 13 06:24 exercise4.txt
-rwS------ 1 root root 19 Mar 13 06:10 user_flag.txt
答案1
setuid1 的安全契约是它授予可执行程序额外的权限。这些权限仅授予该程序。它们不得允许调用用户执行程序不会执行的任何操作。
这使得 setuid 与跟踪(ptrace
大多数 Unix 变体上的系统调用)不兼容。如果调用用户可以观察程序的内部操作,那么他们就可以访问该程序有权访问的任何机密数据。但这可能是不允许用户查看的机密数据,程序通常不会透露这些数据。也许更明显的是,如果调用用户可以更改程序正在执行的操作(也可以ptrace
),这可以让他们完全拥有 setuid 用户的所有权限,这完全违背了仅授予运行一个特定程序的权限的目标。跟踪是 GDB 等调试器用来检查和控制程序执行的功能。
例如,考虑程序unix_chkpwd
,其工作是检查调用用户的密码。该程序必须能够读取机密数据(密码哈希数据库)。但不得允许调用用户读取整个数据库。调用用户必须只能查询该用户的条目,并且只能回答是/否(不提取密码散列本身),并且具有速率限制以防止暴力破解。如果您可以运行gdb unix_chkpwd
并打印出密码哈希数据库的内容,它将完全破坏该数据库的安全性。
为了维护安全:
- 当程序在启动时已被跟踪时,setuid 位将被忽略。可执行文件启动时没有额外的权限。
- 仅允许 root 跟踪以额外权限启动的程序。
1这也适用于 setgid、setcap 或任何其他类似的机制来运行具有提升权限的程序。