Làm thế nào để ngăn chặn trình gọi của người dùng không được sử dụng trong sudo


8

Tôi đang chạy sudo-1.8.6 trên CentOS 6.5. Câu hỏi của tôi rất đơn giản: Làm cách nào để ngăn SHELL lan truyền từ môi trường của người dùng sang môi trường sudo?

Thông thường mọi người đang đi theo một cách khác - họ muốn bảo tồn một biến môi trường. Tuy nhiên, tôi gặp sự cố khi người dùng của tôi "zabbix" có vỏ đang /sbin/nologincố chạy lệnh thông qua sudo. Sudo đang bảo tồn /sbin/nologinđể root không thể chạy subshells. (Cập nhật: Phần này là đúng, nhưng nó không phải là biến môi trường SHELL. Đó là giá trị shell đang được kéo từ / etc / passwd mới là vấn đề.)

Tôi bao gồm một bài kiểm tra minh họa vấn đề; đây không phải là trường hợp sử dụng trong thế giới thực của tôi mà chỉ đơn giản minh họa rằng SHELL của người dùng được bảo tồn. Tôi có một chương trình chạy như người dùng zabbix. Nó gọi /usr/bin/sudo -u root /tmp/doit(chương trình đang chạy như zabbixmột daemon, vì vậy /sbin/nologinshell trong tệp mật khẩu không ngăn được nó). /tmp/doitlà một tập lệnh shell chỉ đơn giản là có:

#!/bin/sh
env > /tmp/outfile

(chế độ của nó là 755, rõ ràng). Trong outfiletôi có thể thấy đó SHELL/sbin/nologin. Tuy nhiên, tại thời điểm này, tập lệnh đang chạy dưới quyền root, thông qua sudo, vì vậy nó không nên có các biến môi trường của người dùng trước đó, phải không?

Đây là / etc / sudoers của tôi:

Mặc định Yêu cầu
Mặc định!

Mặc định luôn_set_home
Mặc định env_reset
Mặc định env_keep = "MÀU SẮC HIỂN THỊ HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
Mặc định env_keep + = "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Mặc định env_keep + = "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Mặc định env_keep + = "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Mặc định env_keep + = "LC_TIME LC_ALL NGÔN NGỮ LINGUAS _XKB_CHARSET XAUTHORITY"
Mặc định safe_path = / sbin: / bin: / usr / sbin: / usr / bin: / usr / local / bin: / usr / local / sbin

## Cho phép root chạy bất kỳ lệnh nào ở bất cứ đâu 
root ALL = (ALL) ALL

#includedir /etc/sudoers.d

Và đây là /etc/sudoers.d/zabbix:

Mặc định: zabbix! Yêu cầu

zabbix ALL = (root) NOPASSWD: / tmp / doit

Chỉnh sửa: Thêm một chút thông tin:

Quá trình chạy sudo là zabbix_agentd, từ phần mềm giám sát Zabbix. Có một mục trong /etc/zabbix/zabbix_agentd.d/userparameter_disk.conftệp trông giống như:

UserParameter = example.disk.discovery, / usr / local / bin / zabbix_ston_discovery

/usr/local/bin/zabbix_raid_discoverylà một kịch bản Python. Tôi đã sửa đổi nó để làm điều này:

in sub process.checkDefput (['/ usr / bin / sudo', '-u', 'root', '/ tmp / doit'])

/tmp/doit chỉ đơn giản là làm điều này:

#! / thùng / sh
env >> / tmp / outfile

Tôi chạy phần sau trên máy chủ Zabbix của mình để chạy /usr/local/bin/zabbix_raid_discoverytập lệnh:

zabbix_get -s client_hostname -k 'example.disk.discovery'

Sau đó, tôi kiểm tra /tmp/outfilevà tôi thấy:

SHELL = / sbin / nologin
HẠN = linux
NGƯỜI DÙNG = root
SUDO_USER = zabbix
SUDO_UID = 497
USERNAME = root
PATH = / sbin: / bin: / usr / sbin: / usr / bin: / usr / local / bin: / usr / local / sbin
MAIL = / var / mail / root
NKT = /
LANG = en_US.UTF-8
SHLVL = 1
SUDO_COMMAND = / tmp / doit
TRANG CHỦ = / root
ĐĂNG NHẬP = root
SUDO_GID = 497
_ = / bin / env

SHELLDòng đó thực sự làm phiền tôi. Tệp được sở hữu bởi root, vì vậy tôi biết nó được tạo bởi người dùng root, nhưng shell là từ người dùng gọi ( zabbix).


sudo env SHELL=/bin/sh shcung cấp lời nhắc với / bin / sh được đặt làm biến SHELL trong hệ thống của bạn không?

@adonis - Xem câu hỏi cập nhật của tôi. BTW, bạn rất đẹp trai.
Mike S

@BinaryZebra - Có tôi biết env_delete, nhưng tôi đồng ý mấu chốt của vấn đề là hành vi mặc định của env_reset ...causes commands to be executed with a new, minimal environment.Chúng tôi có một hệ thống linux với PAM, vì vậy theo trang man , The new environment contains the ... SHELL ... (variable). Như bạn có thể thấy từ /etc/sudoerstập tin của tôi ở trên, chúng tôi không cho phép SHELLtrong env_keep. Vì vậy SHELLkhông nên bảo tồn; chúng ta nên có người dùng root SHELL.
Mike S

@BinaryZebra - Tôi đã thêm vào tệp zabbix ALL=(root) NOPASSWD: /bin/env SHELL=/bin/sh /tmp/doit *của mình /etc/sudoers/zabbixvà nó có vỏ phù hợp. Cảm ơn, bây giờ tôi có một cách giải quyết. Câu hỏi là, tại sao tôi cần phải bao gồm nó? Có vẻ nguy hiểm (và bị hỏng) khi vượt qua SHELL của người gọi nhưng tôi không thể tìm thấy nơi nào sudo được đặt để sửa đổi nó. Tôi đã chạy find /etc/sudoers /etc/sysconfig -type f -exec grep env_ {} \;và tôi không tìm thấy cờ đỏ nào; /etc/sudoerschứa env_chuỗi duy nhất . Vì vậy, tôi không nghĩ rằng có một lá cờ sudoers can thiệp ...
Mike S

Mike: Ở cấp độ đầu tiên: Một đơn giản sudo bashnên bắt đầu một bash shell là root và nó PHẢI có biến SHELL được đặt thành giá trị từ / etc / password. Bạn báo cáo rằng SHELL đang được đặt thành (hoặc được bảo tồn là) /sbin/nologin. Đó là một vấn đề bảo mật, shell bắt đầu bằng root không được kiểm soát bởi một biến môi trường được đặt bởi người dùng. Đó là điều bạn phải điều tra.

Câu trả lời:


5

Sau đó, câu trả lời là sudocó một lỗi. Đầu tiên, cách giải quyết: Tôi đặt cái này vào /etc/sudoers.d/zabbix file:

zabbix ALL = (root) NOPASSWD: / bin / env SHELL = / bin / sh / usr / local / bin / zabbix_ston_discovery

và bây giờ các tiểu ban được gọi từ zabbix_raid_discoverycông việc.

Một bản vá để sửa lỗi này sẽ có trong sudo 1.8.15. Từ người bảo trì, Todd Miller:

Đây chỉ là một trường hợp "nó luôn như vậy". Không có
thực sự là một lý do tốt cho nó Khác biệt dưới đây sẽ làm cho hành vi
phù hợp với các tài liệu.

 - chập chững

diff -r adb927ad5e86 plugin / sudoers / env.c
--- a / plugin / sudoers / env.c Thứ ba ngày 06 tháng 10 09:33:27 2015 -0600
+++ b / plugin / sudoers / env.c Thứ ba ngày 06 tháng 10 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2 ("USERNAME", runas_pw-> pw_name,
                ISSET (didvar, DID_USERNAME), đúng);
        } khác {
- nếu (! ISSET (didvar, DID_SHELL))
- CHECK_SETENV2 ("SHELL", sudo_user.pw-> pw_shell, sai, đúng);
            / * Chúng tôi sẽ đặt LOGNAME sau trong trường hợp def_set_logname. * /
            if (! def_set_logname) {
                if (! ISSET (didvar, DID_LOGNAME))
@@ -984,6 +982,8 @@
            if (! env_should_delete (* ep)) {
                if (strncmp (* ep, "SUDO_PS1 =", 9) == 0)
                    ps1 = * ep + 5;
+ if if (strncmp (* ep, "SHELL =", 6) == 0)
+ SET (didvar, DID_SHELL);
                khác nếu (strncmp (* ep, "PATH =", 5) == 0)
                    SET (didvar, DID_PATH);
                khác if (strncmp (* ep, "TERM =", 5) == 0)
@@ -1039,7 +1039,9 @@
     nếu (reset_home)
        CHECK_SETENV2 ("TRANG CHỦ", runas_pw-> pw_dir, đúng, đúng);

- / * Cung cấp các giá trị mặc định cho $ TERM và $ PATH nếu chúng không được đặt. * /
+ / * Cung cấp các giá trị mặc định cho $ SHELL, $ TERM và $ PATH nếu không được đặt. * /
+ if (! ISSET (didvar, DID_SHELL))
+ CHECK_SETENV2 ("SHELL", runas_pw-> pw_shell, sai, sai);
     if (! ISSET (didvar, DID_TERM))
        CHECK_PUTENV ("TERM = không xác định", sai, sai);
     if (! ISSET (didvar, DID_PATH))

Tuyệt vời Mike!, Cảm ơn cho công việc thám tử.

Mike, có thể là bạn đặt một liên kết đến bản vá (tương lai?).

@BinaryZebra Diff có ở đây: sudo.ws/repose/sudo/rev/b77adbc08c91 Tôi chưa thấy một bản vá nào.
Mike S

Mike: Tôi tin rằng bạn đang sủa sai cây. Điểm mấu chốt ở đây: Provide default values for $SHELL, $TERM and $PATH if not set.là : ... if not set.. Bất kỳ giá trị được thiết lập sẽ được bảo tồn bởi sudo. Ai đang thiết lập SHELL?

@BinaryZebra - Đó không phải là cách tôi đọc nó. SHELL không được đặt (theo env_reset, theo mặc định). Vì nó không được đặt, mã cũ nói sử dụng mục nhập pw của sudo_user. Mã mới nói sử dụng mục nhập pw của người dùng runas.
Mike S

4

Câu hỏi là về nơi tôi nghĩ vấn đề là ở đâu, nhưng hóa ra vấn đề không phải là điều gì xảy ra với biến SHELL, mà là sudo thực sự làm gì. Ví dụ:

-bash-4.1 $ whoami
kiểm tra
-bash-4.1 $ grep testdude / etc / passwd
testdude: x: 1001: 10: Anh chàng kiểm tra: / tmp: / bin / bash
-bash-4.1 $ sudo env
[sudo] mật khẩu cho testdude: 
...
CHIA SẺ = / bin / bash
...

Càng xa càng tốt. ... nhưng vấn đề là sudo sử dụng vỏ của người gọi thay vì callee, trái với các tài liệu. Thật vậy, nếu tôi thay đổi shell của mình bằng cách chỉnh sửa / etc / passwd, bạn có thể thấy sudo theo vỏ của người gọi chứ không phải SHELL:

-bash-4.1 $ grep root / etc / passwd
root: x: 0: 0: root: / root: / bin / bash
-bash-4.1 $ sudo sed -i -e '/ testdude / s / bash / sh /' / etc / passwd
-bash-4.1 $ grep testdude / etc / passwd
testdude: x: 1001: 10: Anh chàng kiểm tra: / tmp: / bin / sh
-bash-4.1 $ sudo env
...
CHIA SẺ = / bin / sh
...
-bash-4.1 $ export SHELL = / hoàn toàn / vô nghĩa / đường dẫn
-bash-4.1 $ sudo env
...
CHIA SẺ = / bin / sh
...

Tôi không thể sử dụng sudo -ivì tôi không muốn mô phỏng đăng nhập ban đầu. sudo -ssẽ hoạt động, miễn là tôi có lệnh thích hợp trong tệp sudoers. Tuy nhiên, hành vi dự kiến ​​(như được phản ánh trong trang man: " The new environment contains the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables") là cho vỏ là của callee. Nếu bạn nhìn vào PATH, HOME, LOGNAME, và USERcác biến cho sudo ENV bạn sẽ thấy những thứ root. SHELLnên là vỏ của root.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.