系统调用观测-Pledge
2025-03-16 16:03:27 阿炯

Pledge是通过设定系统调用以强制当前进程进入受限服务操作模式。有几个资源子集是可用,大致为计算、内存管理、文件描述符上的读写操作、打开文件、网络(以及值得注意的单独的DNS解析)。一般来说,这些模式的选择是通过许多使用libc等接口的程序的操作,以及设置promise或execpromises来实现的。可以将其做为安全行为审计的工具来使用,用以观测程序的系统调用情况。其做为OpenBSD的原生自带功能特性被内置,有Linux操作系统的移植版本。


Linux没有真正有一个普通人可以理解的安全层。如果想在Linux上做一些事情,比如控制是否允许从Web页面下载的某个程序具有遥测功能。

使用场景:从 Internet 下载了一个名为 “prog1” 的程序。不应该轻易运行它,因为它可能是一个恶意程序。运行它,如果它内含木马,就会窃取文件,破坏系统运行,对我们造成损害。如果拥有一个工具,可以自定义程序权限,并且可以使用它来运行和测试那些不明程序,那该有多好吗?

没错,这个工具,就是Pledge - 一个可以限制程序系统调用的工具!那么如何在 Linux 系统上使用 pledge呢?

感谢 Justine Tunney 的出色工作,她是项目 Cosmopolitan Libc 背后的核心开发者。利用她主持的 Libc Cosmopolitan项目,她将Pledge从 OpenBSD 移植到了 Linux 系统。

第 1 步:下载 pledge
wget http://justine.lol/pledge/pledge-1.8.com

可以将文件重命名为
mv pledge-1.8.com pledge.com

第 2 步:使其可执行
chmod +x ./pledge.com

第 3 步:将 pledge.com 添加系统路径
sudo mv ./pledge.com /usr/local/bin

第 4 步:运行和测试
pledge.com curl http://www.freeoa.net

没有为它分配任何权限,因此它会失败。

从最后一行的“curl: (6) Could not resolve host: www.freeoa.net”,可以看到失败的原因。另外也可以看到,程序发出了哪些系统调用,是否合法?(例如,一个文件资源管理器发出DNS请求,这正常吗?)
在输出里面可以看到pledgee提示:
error: pledge inet for socket (ord=029 rip=7cc86681c2eb)
error: pledge unix for socket (ord=029 rip=7cc86681c2eb)
error: pledge dns for socket (ord=029 rip=7cc86681c2eb)
error: pledge inet for socket (ord=029 rip=7cc86681c2eb)
error: pledge unix for socket (ord=029 rip=7cc86681c2eb)
error: pledge dns for socket (ord=029 rip=7cc86681c2eb)
error: pledge stdio for ioctl (ord=010 rip=7cc86680ce4e)
error: pledge inet for ioctl (ord=010 rip=7cc86680ce4e)
error: pledge tty for ioctl (ord=010 rip=7cc86680ce4e)
error: pledge stdio for ioctl (ord=010 rip=7cc866814ded)
error: pledge inet for ioctl (ord=010 rip=7cc866814ded)
error: pledge tty for ioctl (ord=010 rip=7cc866814ded)
error: pledge inet for socket (ord=029 rip=7cc86681c2eb)
error: pledge unix for socket (ord=029 rip=7cc86681c2eb)
error: pledge dns for socket (ord=029 rip=7cc86681c2eb)

是的,curl 作为一个网络工具,它大量使用了socket这些系统调用。

上面的权限提示在测试当中即使调用成功,Pledge也会显示出来供参考。可协助使用 flag 分配 promise(规约)。将在下一节中解释这些 promise 的作用。
pledge.com -p 'stdio rpath inet dns tty sendfd recvfd' \
curl -s http://www.baidu.com

可以看到:成功了。

在上面的部分中使用了 7 个 promise(规约) 来使 curl 请求成功。以下是每个 Promise 的用途:
stdio:允许读取和写入标准输入/输出(如打印到控制台)。
rpath:允许从文件系统读取文件。
inet:允许与网络相关的作(例如,连接到服务器)。
dns:允许解析 DNS 查询。
tty:允许访问终端。
sendfd:允许发送文件描述符。
recvfd:允许接收的文件描述符。

pledge 遵循"最小权限"模型,可以防止程序滥用系统资源。只要遵循此安全模型,恶意程序造成的损害非常有限。尽管 Linux 的安全武器库中有 seccomp 和 apparmor,但pledge 更直观且易于使用。用户可以对进程可以做什么有更精细的控制,会对系统增加额外的保护。