如何保护 sudo 支持的脚本的安全

如何保护 sudo 支持的脚本的安全

以非特权用户身份执行 root 命令的解决方案 -sudo 脚本- 很容易出现安全漏洞以及意外行为和结果的可能性(对于任何其他解决方案(例如带有 的二进制包装器)也是如此setuid);

很明显,脚本是使用 visudo 添加的,如下所示

www-data ALL=(ALL) NOPASSWD: /usr/local/sbin/mycommand
  • 应该可读的,可写只能由 root 执行- 既是所有者又是组 ( chown root:root mycommand; chmod 700 mycommand)
  • 应该有它的父目录所有权 root:root755模式
  • 应该验证输入- 参数和标准输入 - 并拒绝并中止执行任何无效/意外的提供的数据
  • 应该使用绝对路径而不是相对路径/别名(?)
  • Defaults env_reset应该/etc/sudoers设置(?这里需要帮助)

还可以采取什么措施来保护 sudo 支持的脚本?

答案1

最好的事情之一是使用sudoers文件中的“Digest_Spec”可能性来验证可执行文件的校验和

手册页摘录:

如果命令名称以 Digest_Spec 为前缀,则仅当可以使用指定的 SHA-2 摘要进行验证时,该命令才会成功匹配。

使用 openssl 生成校验和:

$ openssl dgst -sha224 /usr/local/sbin/mycommand
 SHA224(/usr/local/sbin/mycommand)=
         52246fd78f692554c9f6be9c8ea001c9131c3426c27c88dbbad08365 

然后在你的 sudoers 文件中(在同一行):

 www-data ALL=(ALL) NOPASSWD: 
    sha224:52246fd78f692554c9f6be9c8ea001c9131c3426c27c88dbbad08365
    /usr/local/sbin/mycommand

答案2

我会稍微修改一下您保护脚本的标准列表。鉴于此 - 或类似的 - 条目/etc/sudoers

www-data ALL=(ALL) NOPASSWD: /usr/local/sbin/mycommand

我们可以声明该脚本:

  • 必须只能由 root 用户写入
  • 必须可由 root 用户读取和执行
  • 必须位于只能由 root 写入的目录层次结构中
  • 必须“充分”验证其输入以供使用,并拒绝任何其他内容
  • 应具有执行其任务所需的最小权限集(不一定是 setuid root)
  • PATH应该在使用任何外部命令之前定义它
  • 在使用之前应将所有变量设置为已知值
  • 应该生成审计跟踪,不仅显示调用时间和方式,还显示结果操作(想想logger

此外,在许多情况下,脚本并不真正需要以 root 身份运行 - 它可以运行 setgid,甚至 setuid 到其他帐户。在一般情况下,请考虑这些选项以避免授予脚本的完全 root 访问权限。

对于 SELinux 环境,可以创建一个策略来防止脚本执行任何意外操作。诸如 CAP_NET_ADMIN 之类的功能比一揽子 root 权限更细粒度,也可能值得考虑。

在您概述的特定情况下,您想要验证单个 IPv4 地址并将其传递给iptables,您可能能够将 IP 地址验证为一系列非特定八位字节。在这种情况下,444.555.666.999 可能会被认为是合理的,因为iptables它本身会拒绝任何不是真实 IP 地址的内容。在一种极端情况下,您可能会认为匹配 RE/^[0-9.]+$/就足以将值传递给iptables。另一方面,还有很多答案在 StackExchange 和其他地方解决验证 IP 地址的问题。有些比其他更好。

需要考虑的特殊情况是 RFC1918 地址、多播地址和您自己的外部 IP 地址范围。哦,还有以前称为 E 类的保留块。您需要 IPv6 支持吗?

如果你的脚本每分钟被调用数百次会发生什么?您需要为这种可能性做好准备吗?你的iptables链条会溢出吗?如果您认为您的链中需要数百条规则,那么[使用ipset扩大iptables不是线性列表。这是一个很好的教程。在保护方面,它允许您构建数千个集合(如果没有成千上万)类似的规则可以运行而不会显着减慢流经规则集的流量。

突然间,您看似简单的要求变得相当复杂。

答案3

命名管道方法。以 root 身份运行

mkfifo -m 666 /tmp/foo
/tmp/readpipe.sh &

并且可以作为用户 www-data 然后写入管道

echo test >>/tmp/foo

readpipe.sh 最简单的形式(带有 taint 的 perl 会更好):

#!/bin/sh
while read A </tmp/foo
do
 echo received $A     
done

答案4

还可以采取什么措施来保护 sudo 支持的脚本:使用 PAM - 可插入身份验证模块。

PAM 管理员指南:http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html

PAM 模块编写者指南:http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_MWG.html

PAM 应用程序开发人员指南:http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_ADG.html

还要检查/usr/share/doc/packages/pam/pdf 您的系统,查找与您系统上的 PAM 版本相关的这些文档。

PAM 是 Linux 中基本的安全机制之一。它用于保护和锁定许多东西,两个例子是登录过程和密码更改过程。当您强制执行密码限制(例如最小字符长度和过期时间)时,这是通过 PAM 完成的。如果 PAM 对于核心系统进程来说足够好,那么它对于您的脚本来说当然也足够好。首先查看 PAM 系统管理指南,了解您已经可以利用的内容,例如:

  • pam_time:不对用户进行身份验证,而是限制在一天中的不同时间和特定日期或通过不同的终端线路对系统和/或特定应用程序的访问。该模块可以配置为根据(个人)用户的姓名、一天中的时间、一周中的某一天、他们正在申请的服务以及他们提出请求的终端来拒绝对(个人)用户的访问。

  • pam_env:在调用时导致环境变量的设置或取消设置,在创建 pam 模块时利用此优势

  • pam_localuser:帮助实施站点范围的登录策略,其中通常包括网络用户的子集和特定工作站本地的一些帐户。使用 pam_localuser 和 pam_wheel 或 pam_listfile 是限制对本地用户和/或网络用户子集的访问的有效方法。

  • 列表不胜枚举,请参阅系统管理员指南并根据需要使用。

您可能还会发现这很有用:http://freecode.com/projects/pam_script/

从这里您将需要阅读模块编写者指南和应用程序开发指南。这就是 PAM 的目的...可插拔的认证模块。您正在有效地编写代码,如果您还没有编写代码,那么在完成后您将成为一名程序员。这不是像 Microsoft Windows 中那样单击某些复选框启用/禁用的“IT”内容。 PAM 的原因是系统管理员可以出于安全原因插入一个模块(有时很简单,有时不需要您编写)来执行任何操作。例如,用户passwd要更改其密码,为了安全起见,会使用 PAM 来更改密码,并且您不需要键入“sudo passwd”来更改密码。根据您的脚本需要执行的操作,如果正确使用 PAM 并设置脚本的所有权和 SUID/GUID,您甚至可能不需要 sudo,就像是这样/usr/bin/passwd

当你问[自己]我还能做些什么来确保这一点......可能表明这不是做某事的最佳方式。在这种情况下,使用 sudo 授予运行脚本/可执行文件的提升权限。相反,请查看 linux 已经建立的机制如何处理类似这样的事情......例如,用户使用/usr/bin/passwd 编辑root 拥有的/etc/passwd和文件,并且需要 root 权限才能修改。/etc/shadow通过 PAM,您可以根据用户 ID、组 ID、本地用户帐户、在给定时间内等限制谁可以运行您的脚本。更进一步,非常确定您可以使用自己的密码创建一个单独的组帐户,其唯一目的是运行只有这些用户的脚本,然后您不会给出 root 密码来运行您的脚本。您将只为那些可以su 到root 的用户遵循wheel 组的方案。希望这可以帮助。

相关内容