在CentOS系统中,setuid和setgid是极具价值的权限提升机制,它们允许普通用户以文件所有者或所属组的身份执行程序。像passwd、sudo这样的命令正是依赖此机制才能让非特权用户完成密码修改等操作。然而,这种能力也是一把双刃剑,攻击者常常利用错误配置的setuid/setgid二进制文件进行权限提升,或者通过植入恶意setuid程序来维持后门访问。要捕捉系统中所有此类调用事件,最直接有效的手段就是配置Linux审计子系统auditd,通过内核级监控记录每一次setuid和setgid系统调用。
理解setuid和setgid系统调用在着手配置之前,我们需要明确内核层面到底发生了什么。当程序调用setuid相关功能时,实际上会触发几个关键的系统调用。setuid()用于设置实际用户ID、有效用户ID和保存的设置用户ID,setgid()则对应组ID的设置。除此之外,还有setreuid()、setregid()、setresuid()和setresgid()等更精细的调用。我们要监控的正是这一系列系统调用族。auditd的强大之处在于,它不仅能记录谁调用了这些函数,还能捕获调用是否成功、进程的原始身份、目标身份以及完整的执行路径。这意味着即便攻击者试图通过某些手段隐藏行踪,内核层面的审计记录依然会留下铁证。
安装并启用auditd服务在CentOS 7及更高版本中,auditd通常已经预装。如果系统中尚未安装,执行以下命令即可完成安装。
yum install audit -y
安装完成后,需要确保auditd服务设置为开机自启动并立即运行。使用systemctl命令进行管理。
systemctl enable auditd systemctl start auditd
验证服务状态,确认没有异常报错。
systemctl status auditd
此时审计系统已经在后台运行,但默认规则集并不包含对setuid和setgid系统调用的监控。我们需要手动添加自定义规则。值得一提的是,auditd的配置文件位于/etc/audit/auditd.conf,其中定义了日志轮转、磁盘空间处理等重要参数。对于高安全需求的环境,建议检查log_format参数是否设置为ENRICHED,这样日志中会包含更丰富的上下文信息。同时要确保max_log_file和num_logs的值足够大,因为系统调用审计产生的日志量可能相当可观。
编写审计规则捕获setuid事件auditd的规则通过auditctl命令动态添加,但永久规则应写入/etc/audit/rules.d/目录下的规则文件中。我们创建一个名为setuid-monitor.rules的文件。
vi /etc/audit/rules.d/setuid-monitor.rules
针对setuid系统调用,我们需要监控syscall 105(在x86_64架构上setuid的系统调用号)以及相关的setreuid和setresuid。不过更推荐的做法是使用系统调用名称而非数字,这样可读性更强且跨架构兼容。以下是核心规则。
# 监控所有setuid系统调用,记录成功和失败事件 -a always,exit -F arch=b64 -S setuid -S setreuid -S setresuid -S seteuid -F key=setuid-events -a always,exit -F arch=b32 -S setuid -S setreuid -S setresuid -S seteuid -F key=setuid-events
规则解释:-a always,exit表示在系统调用退出时总是记录事件。arch=b64和arch=b32分别对应64位和32位程序,确保两种架构的调用都被覆盖。多个-S参数指定了要监控的系统调用名称。key字段设置为setuid-events,这是一个自定义标签,方便后续使用ausearch工具按关键词检索日志。always,exit模式的优势在于,它能在系统调用完成时记录返回值,我们可以据此判断调用是成功还是失败,这对于安全分析至关重要。
编写审计规则捕获setgid事件setgid的监控逻辑与setuid完全一致,只是系统调用名称不同。继续编辑同一个规则文件,追加以下内容。
# 监控所有setgid系统调用,记录成功和失败事件 -a always,exit -F arch=b64 -S setgid -S setregid -S setresgid -S setegid -F key=setgid-events -a always,exit -F arch=b32 -S setgid -S setregid -S setresgid -S setegid -F key=setgid-events
这里使用了setgid-events作为独立的关键词标签。分开设置标签是有意为之,因为在实际安全运维中,setuid事件通常比setgid事件更具威胁性,分开标记便于分级告警和查询。如果你希望将所有权限变更事件统一管理,也可以使用相同的标签名。至此,规则文件包含了四条规则,分别覆盖64位和32位环境下的setuid和setgid调用。
应用规则并使其永久生效保存规则文件后,需要让auditd重新加载配置。在CentOS 7及更新版本中,推荐使用augenrules工具将rules.d目录下的规则合并生成主规则文件,然后重启服务。
augenrules --load systemctl restart auditd
验证规则是否成功加载,使用auditctl -l命令列出当前活动规则。
auditctl -l
输出中应该能看到刚才添加的四条规则。如果规则没有出现,检查/var/log/audit/audit.log中是否有规则语法错误的相关记录。常见问题包括系统调用名称拼写错误、arch参数与系统不匹配等。在纯64位CentOS系统上,32位规则可能显示为不可用状态,这属于正常现象,不影响64位规则的正常工作。
深入理解规则的高级选项上述基础规则已经能够记录所有setuid和setgid事件,但在生产环境中,我们往往需要更精细的控制。比如,某些系统守护进程会频繁进行合法的setuid调用,产生大量噪音日志。我们可以通过添加条件过滤来排除特定进程。假设要排除sshd服务的setuid调用,规则可以这样写。
-a always,exit -F arch=b64 -S setuid -F comm!=sshd -F key=setuid-events
comm字段对应进程的可执行文件名。更严格的过滤可以使用exe字段指定完整路径,或者使用uid字段限定只记录特定用户的操作。另一个实用的选项是记录进程的初始用户身份。默认情况下,审计日志会包含auid(审计用户ID)和uid(当前用户ID),auid代表登录用户的原始身份,即使进程通过su或sudo切换了用户,auid也不会改变。这对于追踪提权行为的真正源头非常有价值。确保在auditd.conf中启用了相关字段记录,日志中就会自动包含这些信息。
测试审计规则的实际效果规则生效后,我们需要验证它是否能正确捕获事件。创建一个简单的测试脚本,执行setuid调用。
# 编写一个C语言测试程序 cat > /tmp/test_setuid.c << 'EOF' #include#include int main() { setuid(0); return 0; } EOF # 编译 gcc /tmp/test_setuid.c -o /tmp/test_setuid # 以普通用户身份运行 /tmp/test_setuid
执行完毕后,使用ausearch命令查询相关审计记录。
ausearch -k setuid-events
输出会显示一条或多条记录,每条记录包含时间戳、进程ID、用户身份、系统调用名称、调用参数以及退出状态。重点关注type=SYSCALL这一行,其中success=no表示调用失败(因为普通用户无法直接setuid到root),exit字段包含具体的错误码。如果看到success=yes,说明调用成功,这在安全审计中需要特别关注。同样的方法可以测试setgid事件,只需将测试程序中的setuid改为setgid即可。
日志分析与实时告警审计日志的价值在于分析。原始日志位于/var/log/audit/audit.log,直接阅读较为晦涩。ausearch工具提供了丰富的过滤选项。按关键词查询是最常用的方式,此外还可以按时间范围、用户、进程名等条件筛选。例如,查看最近10分钟内所有失败的setuid尝试。
ausearch -k setuid-events --success no -ts recent
对于需要实时响应的场景,可以配置audisp插件将事件转发到SIEM系统或自定义脚本。audisp是auditd的事件分发守护进程,它支持将审计事件通过syslog输出,或者调用自定义程序处理。在/etc/audisp/plugins.d/syslog.conf中启用syslog插件后,所有审计事件会同步写入/var/log/messages,这样就可以被日志集中管理平台采集。更进一步,可以编写一个简单的Python脚本,订阅auditd事件流,当检测到setuid成功事件时立即发送邮件或企业微信告警。这种主动防御能力是单纯依赖文件完整性检查工具无法提供的。
处理日志增长与存储优化setuid和setgid调用在正常系统中并不频繁,但如果部署了大量使用这些机制的应用,日志量仍可能快速增长。auditd内置了日志轮转和空间管理机制。在/etc/audit/auditd.conf中,max_log_file定义了单个日志文件的最大大小(单位MB),num_logs定义了保留的日志文件数量。当磁盘空间紧张时,可以调整space_left_action参数,将其设置为rotate或syslog,让系统在空间不足时自动轮转日志或切换到syslog记录。更极端的做法是设置disk_full_action为halt或single,在磁盘满时保护系统完整性,但这通常只适用于极高安全要求的环境。建议定期将审计日志归档到远程存储,并在本地保留至少30天的历史数据,以满足合规性要求。
排查常见问题与故障处理在实际部署中,可能会遇到规则不生效的情况。首先检查auditd服务是否真正在运行,使用systemctl status auditd确认。如果服务状态正常但规则未加载,查看/var/log/audit/audit.log中是否有规则语法错误提示。另一个常见问题是内核审计子系统被禁用,可以通过检查/proc/cmdline确认启动参数中是否包含audit=0,如果是,需要在GRUB配置中移除该参数并重启系统。在某些虚拟化环境中,宿主机可能限制了审计功能,需要联系云服务提供商确认。如果日志中出现了大量预期之外的记录,使用auditctl -D先清空所有规则,然后逐步添加,逐条验证,以定位是哪条规则导致了噪音。
将审计范围扩展到相关系统调用除了直接的setuid和setgid调用,一些相关系统调用也值得纳入监控范围。execve系统调用在执行setuid程序时,内核会自动处理权限提升,但execve本身并不直接触发setuid系统调用。如果希望完整记录所有通过setuid位执行的程序,需要额外添加对execve的监控,并结合文件属性过滤。不过这会显著增加日志量,需要根据实际安全需求权衡。另一个值得关注的调用是capset,它用于设置进程的权能集,在现代Linux系统中,部分原本需要完整root权限的操作可以通过细粒度的capability完成,监控capset能弥补单纯监控setuid的不足。
合规性要求与最佳实践许多安全合规标准,如PCI DSS、等级保护,都明确要求对特权操作进行审计。配置auditd监控setuid和setgid事件是满足这些要求的关键措施。在审计记录中,确保包含以下要素:操作时间、执行用户、原始登录用户、目标用户或组、进程名称和路径、调用是否成功。定期审查这些日志,重点关注非工作时间的事件、来自非系统账户的成功setuid调用、以及异常进程执行的权限变更。将审计日志的完整性保护也纳入考虑,使用远程日志服务器或写入一次性存储介质,防止攻击者在入侵后篡改本地日志。
通过以上配置,CentOS系统已经具备了全面监控setuid和setgid使用事件的能力。这套机制从内核层面提供了不可绕过的审计轨迹,无论攻击者使用何种手段进行权限提升,只要触发了相关系统调用,就会被记录下来。结合定期的日志审查和实时告警,可以极大提升对潜在入侵行为的感知速度和溯源能力。
