3个稳定版本
1.2.0 | 2020年3月26日 |
---|---|
1.1.0 | 2018年5月18日 |
1.0.0 | 2018年5月7日 |
#188 in 过程宏
用于 sudo_pair
71KB
1K SLoC
sudo_pair
sudo_pair
是一个 sudo插件,需要另一名人类用户批准并监控特权sudo会话。
关于
sudo
被工程师每天用来以特权用户身份运行命令。但在一些敏感系统中,您真的想确保没有个人可以完全独立行事。在Square,这包括管理我们内部访问控制系统、存储会计账簿或甚至移动真实货币的应用程序。此插件使我们能够确保在这些系统中没有任何用户可以完全独立行事。
由于我们希望在正式发布1.0之前从开源社区获得反馈,因此此插件及其组件仍处于预发布阶段。
安装
警告:sudo配置错误可能会使您无法访问自己的机器。请在可丢弃的环境中测试。
目前,sudo_pair
必须从源代码编译。它是一个标准的Rust项目,以下内容足以在Rust的任何最新版本上构建它:
git clone https://github.com/square/sudo_pair.git
cd sudo_pair
cargo build --release
一旦构建完成,该插件本身需要安装到sudo可以找到的地方。通常这位于 /usr/libexec/sudo
(在macOS主机上为 /usr/local/libexec/sudo
)。必须将适当的批准脚本安装到 PATH
中。必须创建一个目录,以便 sudo_pair
可以管理用于插件和客户端之间通信的套接字。最后,必须配置sudo以加载并使用该插件。
# WARNING: these files may not be set up in a way that is suitable
# for your system. Proceed only on a throwaway host.
# install the plugin shared library
install -o root -g root -m 0644 ./target/release/libsudopair.dylib /usr/libexec/sudo
# create a socket directory
install -o root -g root -m 0644 -d /var/run/sudo_pair
# install the approval script; as currently configured, it denies access
# to users approving their own sudo session and may lock you out
install -o root -g root -m 0755 ./sample/bin/sudo_approve /usr/bin/sudo_approve
# your `/etc/sudo.conf` may already have entries necessary for sudo to
# function correctly; if this is the case, the two files will need to be
# merged
install -o root -g root -m 0644 ./sample/etc/sudo.conf /etc/sudo.conf
# if these prompts don't work for you, they're configurable via a simple
# templating language explained later in the README
install -o root -g root -m 0644 ./sample/etc/sudo.prompt.user /etc/sudo.prompt.user
install -o root -g root -m 0644 ./sample/etc/sudo.prompt.pair /etc/sudo.prompt.pair
这只会将插件文件放置在预期位置。除非您按照以下配置步骤进行操作,否则插件将不会启用。
配置
/etc/sudoers
默认情况下,/etc/sudoers
不会指示日志插件为任何命令记录输出。您需要通过以下方式启用此功能:要么让sudo
为所有命令启用日志记录(并选择任何希望绕过的命令),要么选择个别命令进行日志记录。
示例(默认记录,排除个别命令)
Defaults log_output
%wheel ALL = (ALL) NOLOG_OUTPUT: /bin/cat, /bin/ls
示例(选择个别命令)
%wheel ALL = (ALL) LOG_OUTPUT: /usr/bin/visudo
/etc/sudo.conf
插件可以提供一些选项来修改其行为。这些选项通过添加到/etc/sudo.conf
中Plugin
行末尾来提供给插件。
示例
Plugin sudo_pair sudo_pair.so socket_dir=/var/tmp/sudo_pair gids_exempted=42,109
完整的选项列表如下
-
binary_path
(默认:/usr/bin/sudo_approve
)这是批准二进制文件的位置。批准命令本身需要以目标用户或组的权限运行,这通过sudo实现,因此它必须免于要求自己的配对批准。
-
user_prompt_path
(默认:/etc/sudo_pair.prompt.user
)这是显示给调用sudo的用户提示模板的位置;如果在此位置找不到模板,将打印一个非常基础的默认模板。有关更多详细信息,请参阅提示部分。
-
pair_prompt_path
(默认:/etc/sudo_pair.prompt.pair
)这是显示给被要求批准sudo会话的用户提示模板的位置;如果在此位置找不到模板,将打印一个非常基础的默认模板。有关更多详细信息,请参阅提示部分。
-
socket_dir
(默认:/var/run/sudo_pair
)这是此插件将存储待批准会话套接字的路径。此目录必须由root拥有,并且只能由root写入,否则插件将中止。
-
gids_enforced
(默认:0
)这是sudo_pair将限制访问的gids的逗号分隔列表。如果用户sudo到一个属于这些组之一的用户,则他们需要有一个配对批准他们的会话。
-
gids_exempted
(默认:无)这是将从sudo_pair的要求中豁免的gids的逗号分隔列表。请注意,这并非
gids_enforced
标志的相反。与gids_enforced
限制对组进入的访问不同,gids_exempted
豁免sudo从组退出的要求。例如,此设置可以用来确保oncall系统管理员无需找到配对即可响应故障。请注意,root始终豁免。
提示
此插件允许您配置显示给要求找到配对的用户和被要求批准另一个用户的sudo会话的用户提示。如果未配置(或无法在文件系统中找到)提示,将提供非常基础的默认提示。
提示文件的 内容是应该打印到用户终端的原始字节。这允许使用像ANSI转义代码着色、调整终端大小和设置窗口标题这样的有趣功能,所有这些都在提供的示例提示中被使用。
这些提示还 实现了 一种简单的 %
转义模板语言。任何以 %
字符开头的已知指令都将被替换为展开后的内容,其余的则被视为文字(例如,%%
是文字 %
,而 %a
是文字 a
)。
可用的展开
%b
:_b_inary 的名称%B
:_B_inary 的完整路径%C
:调用sudo
的完整 _C_ommand(尽可能重新创建)%d
:在sudo
下运行的命令的 cw_d_%h
:在sudo
上执行的机器的 _h_ostname%H
:调用用户终端的 _H_eight(行数)%g
:调用sudo
的用户的真实 _g_id%p
:此sudo
进程的 _p_id%u
:调用sudo
的用户的真实 _u_id%U
:运行sudo
的用户的 _U_sername%W
:调用用户终端的 _W_idth(列数)
批准脚本
提供的 批准脚本 只是一个小的(但完整的)示例。尽可能多的功能已经被移入插件中,但有(重要且临时的)一个例外:目前,脚本必须验证批准 sudo
会话的用户不是请求会话的用户。
除此之外,“协议”所需做的只有
- 连接到一个套接字(作为被
sudo
的用户或组) - 将套接字的输入和输出连接到用户的 STDIN 和 STDOUT
- 发送一个
y
以批准,或发送其他任何内容以拒绝 - 关闭套接字以终止会话
实际上,你可以用 socat
来做这件事
socat STDIO /path/to/socket
本项目附带脚本并不比这多多少。它执行了一些额外的功能(如果需要,隐式执行 sudo
,关闭终端回显,禁用 Ctrl-C,并在 Ctrl-D 上终止会话),但并不多。禁用 Ctrl-C 是为了防止用户忘记这个终端正在用于监视另一个用户的会话,而本能地使用 Ctrl-C 来终止它。
限制
sudo_pair
下的会话不能被管道传输。
允许将管道数据发送到标准输入,据我所知,这很可能导致绕过这里的整个安全模型。命令通常可以在 stdin
上接受输入,而且没有合理的方式向对偶方展示这些信息。
安全模型
此插件允许用户使用sudo -u ${user}
来成为用户,或使用sudo -g ${group}
来获得额外的组。
当用户这样做时,会创建一个由用户(或组)所有并只能由其写入的套接字(${user}
或 ${group}
)。为了连接到该套接字,审批者必须能够以该用户(或组)的身份写入文件(${user}
或 ${group}
)。换句话说,他们需要处于“严密的隔舱”的另一边。实际上,这意味着审批者也需要能够以该用户或组的身份sudo
。
为了实现这一点,插件免除了审批脚本需要成对存在的需求。示例审批脚本会自动检测需要成为的用户或组,并隐式运行sudo -u ${user}
(或sudo -g ${group}
)。
作为一个具体的例子,以下是为sudo -u root
,sudo -u nobody
,和sudo -g sys
打开的套接字。
drwxr-xr-x 3 root wheel 96 May 8 09:17 .
s-w------- 1 root wheel 0 May 8 09:16 1882.29664.sock # sudo -u root
s-w------- 1 nobody wheel 0 May 8 09:17 1882.29921.sock # sudo -u nobody
s----w---- 1 root sys 0 May 8 09:18 1882.29994.sock # sudo -g sys
只有能够以用户或组的身份执行sudo
的人才能批准对用户或组的sudo
会话。
由于POSIX文件系统权限模型的限制,用户可能可以sudo到一个新用户(并获得其组)或sudo到一个新组(保留当前用户),但不能同时进行。
项目布局
此项目由三个Rustcrate组成
sudo_plugin-sys
:与sudo_plugin(8)
接口的原始Rust FFI绑定sudo_plugin
:一组Rust结构和宏,用于简化插件编写sudo_pair
:此插件的实现
依赖项
鉴于该项目对安全的敏感性质,有一个明确的目标,即最小化依赖项集合。目前,这些是
- rust-lang/libc
- rust-lang-nursery/rust-bindgen
- rust-lang-nursery/failure
- rust-lang-nursery/error-chain(将被移除)
贡献
欢迎贡献!该项目应该很小(插件本身约500行代码,插件包装约1k行代码)且文档足够完善,以便其他人可以轻松参与。
选择一个待办事项并开始吧!
错误
请将非安全问题报告到GitHub跟踪器。安全问题由Square的错误赏金计划覆盖。
许可证
sudo_pair
在Apache许可证(版本2.0)的条款下分发。
有关详细信息,请参阅LICENSE-APACHE。
依赖项
~2.5–5.5MB
~110K SLoC