POSIX兼容的方式告诉系统是否重启?

时间:2013-08-30 18:54:22

标签: security time posix clock exploit

我正在编写一些高度可移植的安全代码。我试图避免某些版本的sudo中的this one等实用程序中的安全漏洞:

  

...可以通过运行sudo -k然后将系统时钟重置为01-01-1970来成为超级用户。

这是因为sudo依赖于绝对(即日历)时间来确定访问是否已超时。

我的想法是使用CLOCK_MONOTONIC

中定义的time.h.

来自POSIX standard

  

[CLOCK_MONOTONIC]被定义为一个时钟,其值不能通过clock_settime()设置,并且不能有后向时钟跳转。最大可能的时钟跳转应由实现定义。

问题是,在许多(大多数?)系统上,CLOCK_MONOTONIC在重启时重置。 是否有任何保证符合POSIX标准的方式来确定自上次运行程序以来系统是否已重新启动?

一种(坏)方法是检查存储的时钟值是否大于当前时钟值,但这只会改变问题。在CLOCK_MONOTONIC重新启动时重置的系统上,可能会有一个长度为TIMEOUT的短窗口,允许访问。

我错过了什么可以避免这个问题?

2 个答案:

答案 0 :(得分:10)

在我看来,使用POSIX shared memory对象很简单:

  

POSIX共享内存对象具有内核持久性:共享内存   对象将存在,直到系统关闭,或直到所有   进程已取消映射该对象,并已将其删除   shm_unlink

每当您的程序启动时,它都可以shm_open一个具有一致名称的新对象,并将所有者设置为root。该对象不需要包含任何特定值。 POSIX要求所有共享内存对象一直持续到重启,除非手动销毁(只有它的所有者或创建者可以做...在这种情况下是root用户)。

每当程序启动时,它首先检查是否已存在以root作为所有者的共享内存对象。由于只有root可以创建这样的对象,并且只有root或重启可能会破坏它,因此您可以确定自上次重启后您的程序是否已经启动,保存唯一可能的规避是root用户调用{{1}手动对象。

我在下面写了一个测试和设置函数,应该完全按照你的需要做。它的工作原理除了所有权设置/检测之外:由于某些未知原因,对shm_unlink的两次调用都在我的系统上失败,说“无效参数”。 shmctl的{​​{1}}页面显示man错误表示无效的内存对象标识符或无效的命令。但shmctlEINVAL命令肯定是有效的,您可以观察程序的输出以查看每次创建和/或打开的有效对象标识符。

IPC_SET

如果有人有任何线索,我很难过。 POSIX共享内存here的一些信息和示例。

答案 1 :(得分:1)

this python library中,他们在utmp中查找最后一个BOOT_TIME条目。从技术上讲,POSIX中的是utmpx(文件格式)和用于访问它的libc函数。我认为这可以保持在POSIX内。