Bagaimana mencegah shell dari penelepon digunakan dalam sudo

8

Saya menjalankan sudo-1.8.6 pada CentOS 6.5. Pertanyaan saya sangat sederhana: Bagaimana cara mencegah SHELL dari merambat dari lingkungan pengguna ke lingkungan sudo?

Biasanya orang pergi ke arah lain - mereka ingin melestarikan variabel lingkungan. Namun, saya mengalami masalah ketika pengguna saya "zabbix" yang shellnya /sbin/nologinmencoba menjalankan perintah melalui sudo. Sudo menjaga /sbin/nologinagar root tidak bisa menjalankan subshell. (Pembaruan: Bagian ini benar, tetapi itu bukan variabel lingkungan SHELL. Ini adalah nilai shell yang ditarik dari / etc / passwd yang menjadi masalah.)

Saya menyertakan tes yang menggambarkan masalah; ini bukan kasus penggunaan dunia nyata saya tetapi hanya menggambarkan bahwa pemanggil SHELL pengguna dipertahankan. Saya memiliki program yang berjalan sebagai pengguna zabbix. Itu panggilan /usr/bin/sudo -u root /tmp/doit(pemrograman berjalan seperti zabbixadalah daemon, jadi /sbin/nologinshell di file kata sandi tidak mencegahnya). /tmp/doitadalah skrip shell yang hanya memiliki:

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

(Modenya adalah 755, jelas). Dalam outfileSaya dapat melihat bahwa SHELLadalah /sbin/nologin. Namun, pada titik ini skrip berjalan sebagai root, melalui sudo, jadi seharusnya tidak memiliki variabel lingkungan pengguna sebelumnya, kan?

Inilah saya / etc / sudoers:

Persyaratan default kecil
Default! Visiblepw

Default selalu always_set_home
Default env_reset
Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
Default env_keep + = "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Default env_keep + = "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults env_keep + = "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults env_keep + = "LC_TIME LC_ALL LANGING LINGUAS _XKB_CHARSET XAUTHORITY"
Secure_path = / sbin: / bin: / usr / sbin: / usr / bin: / usr / local / bin: / usr / local / sbin

## Izinkan root untuk menjalankan perintah apa pun di mana saja 
root ALL = (ALL) ALL

#includedir /etc/sudoers.d

Dan ini milik saya /etc/sudoers.d/zabbix:

Default: zabbix! Requiretty

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

Sunting: Sedikit informasi lebih lanjut:

Proses menjalankan sudo adalah zabbix_agentd, dari perangkat lunak pemantauan Zabbix. Ada entri dalam /etc/zabbix/zabbix_agentd.d/userparameter_disk.conffile yang terlihat seperti:

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

/usr/local/bin/zabbix_raid_discoveryadalah skrip Python. Saya telah memodifikasinya untuk melakukan ini:

print subprocess.check_output (['/ usr / bin / sudo', '-u', 'root', '/ tmp / doit'])

/tmp/doit cukup lakukan ini:

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

Saya menjalankan yang berikut ini di server Zabbix saya untuk menjalankan /usr/local/bin/zabbix_raid_discoveryskrip:

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

Lalu saya periksa /tmp/outfile, dan saya melihat:

SHELL = / sbin / nologin
JANGKA = linux
USER = 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
PWD = /
LANG = en_US.UTF-8
SHLVL = 1
SUDO_COMMAND = / tmp / doit
HOME = / root
LOGNAME = root
SUDO_GID = 497
_ = / bin / env

Itu SHELLgaris benar-benar mengganggu saya. File ini dimiliki oleh root, jadi saya tahu itu sedang dibuat oleh pengguna root, tetapi shell dari pemanggil pengguna ( zabbix).

Mike S
sumber
Apakah sudo env SHELL=/bin/sh shmemberikan prompt dengan / bin / sh yang ditetapkan sebagai variabel SHELL di sistem Anda?
@adonis - Lihat pertanyaan saya yang diperbarui. BTW, kamu sangat tampan.
Mike S
@ Binzebra - Ya saya tahu env_delete, tapi saya setuju inti masalahnya adalah bahwa perilaku default env_reset ...causes commands to be executed with a new, minimal environment.Kami memiliki sistem linux dengan PAM, jadi menurut halaman manual The new environment contains the ... SHELL ... (variable),. Seperti yang Anda lihat dari /etc/sudoersfile saya di atas, kami tidak mengizinkan SHELLdi env_keep. Jadi SHELLseharusnya tidak dilestarikan; kita harus memiliki pengguna root SHELL.
Mike S
@ Binzebra - Saya telah menambahkan zabbix ALL=(root) NOPASSWD: /bin/env SHELL=/bin/sh /tmp/doit *ke /etc/sudoers/zabbixfile saya , dan memiliki shell yang tepat. Terima kasih, saya sekarang punya solusi. Pertanyaannya adalah, mengapa saya harus memasukkannya? Tampaknya berbahaya (dan rusak) untuk melewati SHELL penelepon tetapi saya tidak dapat menemukan tempat di mana sudo diatur untuk memodifikasinya. Saya telah berlari find /etc/sudoers /etc/sysconfig -type f -exec grep env_ {} \;dan tidak menemukan bendera merah; /etc/sudoershanya berisi env_string. Jadi saya tidak berpikir ada bendera sudo yang mengganggu ...
Mike S
Mike: Pada level pertama: Sederhana sudo bashharus memulai bash shell sebagai root dan HARUS memiliki variabel SHELL yang disetel ke nilai dari / etc / password. Anda melaporkan bahwa SHELL diatur ke (atau dipertahankan sebagai) /sbin/nologin. Itu adalah masalah keamanan, shell yang dimulai oleh root tidak boleh dikontrol oleh variabel lingkungan yang ditetapkan oleh pengguna. Itu adalah sesuatu yang harus Anda selidiki.

Jawaban:

5

Maka jawabannya adalah yang sudomemiliki bug. Pertama, solusinya: Saya menempatkan ini di /etc/sudoers.d/zabbix file:

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

dan sekarang sub-perintah dipanggil dari zabbix_raid_discoverykantor.

Sebuah tambalan untuk memperbaiki ini ada di sudo 1.8.15. Dari pengelola, Todd Miller:

Ini hanya kasus "selalu seperti itu". Tidak ada
benar-benar alasan yang bagus untuk itu. Perbedaan di bawah ini seharusnya menunjukkan perilaku
cocok dengan dokumentasinya.

 - todd

diff -r adb927ad5e86 plugins / sudoers / env.c
--- a / plugins / sudoers / env.c Sel 06 Okt 09:33:27 -0600
+++ b / plugins / sudoers / env.c Sel 6 Okt 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2 ("USERNAME", runas_pw-> pw_name,
                ISSET (didvar, DID_USERNAME), true);
        } lain {
- if (! ISSET (didvar, DID_SHELL))
- CHECK_SETENV2 ("SHELL", sudo_user.pw-> pw_shell, false, true);
            / * Kami akan menetapkan LOGNAME nanti dalam kasus 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;
+ lain jika (strncmp (* ep, "SHELL =", 6) == 0)
+ SET (didvar, DID_SHELL);
                lain jika (strncmp (* ep, "PATH =", 5) == 0)
                    SET (didvar, DID_PATH);
                lain jika (strncmp (* ep, "TERM =", 5) == 0)
@@ -1039,7 +1039,9 @@
     jika (reset_home)
        CHECK_SETENV2 ("HOME", runas_pw-> pw_dir, true, true);

- / * Berikan nilai default untuk $ TERM dan $ PATH jika tidak disetel. * /
+ / * Berikan nilai default untuk $ SHELL, $ TERM, dan $ PATH jika tidak disetel. * /
+ if (! ISSET (didvar, DID_SHELL))
+ CHECK_SETENV2 ("SHELL", runas_pw-> pw_shell, false, false);
     if (! ISSET (didvar, DID_TERM))
        CHECK_PUTENV ("TERM = tidak diketahui", false, false);
     if (! ISSET (didvar, DID_PATH))
Mike S
sumber
Bagus Mike !, Terima kasih atas pekerjaan detektifnya.
Mike, mungkinkah Anda menaruh tautan ke tambalan (masa depan?).
@BinaryZebra Diff ada di sini: sudo.ws/repos/sudo/rev/b77adbc08c91 Saya belum melihat tambalan.
Mike S
Mike: Saya percaya Anda menggonggong ke pohon yang salah. Titik kunci di sini: Provide default values for $SHELL, $TERM and $PATH if not set.adalah: ... if not set.. Nilai apa pun yang ditetapkan akan disimpan oleh sudo. Siapa yang mengatur SHELL?
@ Binzebra - Bukan itu cara saya membacanya. SHELL tidak disetel (menurut env_reset, secara default). Karena tidak disetel, kode lama mengatakan untuk menggunakan entri pw sudo_user. Kode baru mengatakan untuk menggunakan entri pw pengguna runas.
Mike S
4

Pertanyaannya adalah tentang di mana saya pikir masalahnya, tetapi ternyata masalahnya bukan apa yang terjadi pada variabel SHELL, tetapi apa yang sebenarnya dilakukan sudo. Sebagai contoh:

-bash-4.1 $ whoami
testdude
-bash-4.1 $ grep testdude / etc / passwd
testdude: x: 1001: 10: Test dude: / tmp: / bin / bash
-bash-4.1 $ sudo env
[sudo] kata sandi untuk testdude: 
...
SHELL = / bin / bash
...

Sejauh ini bagus. ... tapi masalahnya adalah sudo menggunakan cangkang penelepon alih-alih callee, bertentangan dengan dokumen. Memang, jika saya mengganti shell saya dengan mengedit / etc / passwd, Anda dapat melihat bahwa sudo mengikuti shell dari penelepon dan tidak 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: Test dude: / tmp: / bin / sh
-bash-4.1 $ sudo env
...
SHELL = / bin / sh
...
-bash-4.1 $ export SHELL = / sepenuhnya / tidak berarti / path
-bash-4.1 $ sudo env
...
SHELL = / bin / sh
...

Saya tidak dapat menggunakan sudo -ikarena saya tidak ingin mensimulasikan login awal. sudo -sakan bekerja, selama saya memiliki perintah yang tepat dalam file sudoers. Namun, perilaku yang diharapkan (seperti tercermin dalam halaman manual: " The new environment contains the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables") adalah agar shell menjadi milik callee. Jika Anda melihat PATH, HOME, LOGNAME, dan USERvariabel untuk sudo env Anda akan melihat hal-hal root. SHELLharus menjadi shell root juga.

Mike S
sumber