我正在编写一些高度可移植的安全代码。我试图避免某些版本的sudo
中的this one等实用程序中的安全漏洞:
...可以通过运行
sudo -k
然后将系统时钟重置为01-01-1970来成为超级用户。
这是因为sudo
依赖于绝对(即日历)时间来确定访问是否已超时。
我的想法是使用CLOCK_MONOTONIC
time.h.
[CLOCK_MONOTONIC]被定义为一个时钟,其值不能通过clock_settime()设置,并且不能有后向时钟跳转。最大可能的时钟跳转应由实现定义。
问题是,在许多(大多数?)系统上,CLOCK_MONOTONIC
在重启时重置。 是否有任何保证符合POSIX标准的方式来确定自上次运行程序以来系统是否已重新启动?
一种(坏)方法是检查存储的时钟值是否大于当前时钟值,但这只会改变问题。在CLOCK_MONOTONIC
重新启动时重置的系统上,可能会有一个长度为TIMEOUT
的短窗口,允许访问。
我错过了什么可以避免这个问题?
答案 0 :(得分:10)
在我看来,使用POSIX shared memory对象很简单:
POSIX共享内存对象具有内核持久性:共享内存 对象将存在,直到系统关闭,或直到所有 进程已取消映射该对象,并已将其删除 shm_unlink
每当您的程序启动时,它都可以shm_open
一个具有一致名称的新对象,并将所有者设置为root
。该对象不需要包含任何特定值。 POSIX要求所有共享内存对象一直持续到重启,除非手动销毁(只有它的所有者或创建者可以做...在这种情况下是root用户)。
每当程序启动时,它首先检查是否已存在以root作为所有者的共享内存对象。由于只有root可以创建这样的对象,并且只有root或重启可能会破坏它,因此您可以确定自上次重启后您的程序是否已经启动,保存唯一可能的规避是root用户调用{{1}手动对象。
我在下面写了一个测试和设置函数,应该完全按照你的需要做。它的工作原理除了所有权设置/检测之外:由于某些未知原因,对shm_unlink
的两次调用都在我的系统上失败,说“无效参数”。 shmctl
的{{1}}页面显示man
错误表示无效的内存对象标识符或无效的命令。但shmctl
和EINVAL
命令肯定是有效的,您可以观察程序的输出以查看每次创建和/或打开的有效对象标识符。
IPC_SET
如果有人有任何线索,我很难过。 POSIX共享内存here的一些信息和示例。
答案 1 :(得分:1)
在this python library中,他们在utmp中查找最后一个BOOT_TIME条目。从技术上讲,POSIX中的是utmpx(文件格式)和用于访问它的libc函数。我认为这可以保持在POSIX内。