Saya memiliki proses yang dimulai dengan damon berjalan sebagai root, sekarang saya ingin "menurunkan" hak istimewa proses ini ke orang-orang dari pengguna rata-rata Anda. Apakah ini mungkin? Jika ya, bagaimana?
PS: Menjalankan unix di mac
Saya memiliki proses yang dimulai dengan damon berjalan sebagai root, sekarang saya ingin "menurunkan" hak istimewa proses ini ke orang-orang dari pengguna rata-rata Anda. Apakah ini mungkin? Jika ya, bagaimana?
PS: Menjalankan unix di mac
Jawaban:
Prosesnya sendiri harus memanggil setuid (2). Anda juga harus menyelidiki menjalankannya di dalam chroot (8) jika Anda belum melakukannya. Sejauh yang saya tahu, tidak ada cara bagi root untuk mengubah cairan proses lain.
Jika alasan Anda menjalankannya sebagai root adalah untuk mengikat port, saya sarankan menjalankannya sebagai pengguna normal pada port yang lebih tinggi dan menggunakan ipfw (8) pada OS X untuk meneruskan port 80/443 / etc ke port yang lebih tinggi:
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
seorang diri sama sekali tidak cukup.
sudo tcpdump -Z
menggunakan initgroups (3), setgid (2) dan setuid (2) untuk menghentikan hak root dari prosesnya sendiri.
# code taken from:
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c
/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
username,
(unsigned long)pw->pw_uid,
(unsigned long)pw->pw_gid,
pcap_strerror(errno));
exit(1);
}
...
}
initgroups
, setgid
, setuid
(Terakhir!) Justru paradigma yang tepat pada unix, dan harus selalu diikuti. Selain itu, fungsi "droproot" yang bertanggung jawab memeriksa apakah uid dan gidnya benar-benar telah disetel, meskipun ketiga fungsi utama tersebut mengembalikan kesuksesan.
Anda dapat menjalankan perintah sebagai pengguna lain menggunakan su
:
su USERNAME -c COMMAND
Akan berjalan COMMAND
dengan hak istimewa turun ke USER
.
Perhatikan bahwa, secara default, su
akan menggunakan penerjemah shell pengguna target untuk menjalankan perintah. Sebaliknya, perilaku default sudo
adalah memperlakukan COMMAND
program mandiri, yang menjalankan lingkungan saat ini. Tentu saja perilaku default ini dapat diubah dengan berbagai sakelar dan variabel lingkungan.
su
tidak berfungsi jika USERNAME tidak memiliki shell yang ditentukan (atau /bin/false
) sedangkan sudo tidak berfungsi.
su
akan mencerminkan hal itu. Namun, kita selalu bisa menimpanya menggunakan -s
sakelar. Perhatikan bahwa tujuannya su
adalah untuk meniru perilaku pengguna tertentu - yang biasanya dipengaruhi oleh cangkangnya. Sebaliknya, sudo
akan (secara default) mengabaikan pengaturan shell pengguna target.
Untuk melepaskan hak istimewa, Anda perlu pengguna non-root untuk berpindah. Maka itu hanya masalah beralih ke pengguna itu:
#define UNPRIV_UID 48
#define UNPRIV_GID 48
if (getuid() == 0) { // we are root
// setting UID/GID requires root privileges, so if you don't set
// the GID first, you won't be able to do it at all.
if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}
ASSERT(getuid() != 0);
Perhatikan bahwa ini dilakukan dalam program itu sendiri, bukan dalam skrip pembungkus. Banyak program memerlukan hak akses root untuk beberapa tujuan tertentu (misalnya untuk mengikat ke port bernomor rendah), tetapi tidak perlu root setelah itu. Jadi program-program ini akan mulai sebagai root, tetapi kemudian menjatuhkan hak istimewa begitu mereka tidak lagi diperlukan.
Jika Anda sama sekali tidak memerlukan hak akses root, maka jangan jalankan sebagai root. Misalnya:
# Change this:
myprog -C /my/config/file
# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
setuid
Fungsi hanya menetapkan efektif UID, bukan UID nyata. Anda harus menggunakan setreuid
jika Anda tidak ingin prosesnya bisa mendapatkan hak istimewa kembali. (Dan kode di atas juga tidak berhubungan dengan hak istimewa kelompok tambahan. Ini hanya cocok untuk meluncurkan kode yang sebagian besar tepercaya.)
setuid()
mengatur pengguna yang nyata dan disimpan; Anda mungkin berpikir seteuid()
. Tidak semua sistem memiliki setreuid()
, jadi itu tidak dapat digunakan di mana-mana. Semantik yang tepat dari setuid()
yang terlibat, tetapi jika Anda memiliki euid 0, Anda akan dapat meninggalkan semua hak pengguna-id tradisional dengan setuid()
. Kelalaian terbesar dalam jawaban ini adalah bahwa initgroups
atau setgroups
harus dipanggil juga setgid
dan setuid
, dan bahwa pernyataan yang lebih menyeluruh harus dilakukan pada akhirnya.
Jika Anda menjalankan executable yang berbeda, yaitu Anda memanggil execve
atau exec
fungsi keluarga lainnya, mungkin secara tidak langsung melalui fungsi seperti system
atau popen
, dan proses anak harus dijalankan tanpa hak istimewa sejak awal, maka cara paling sederhana adalah untuk mendapatkan shell yang terlibat, dan telepon su
. Berikut ini gambaran umum tentang bagaimana kode tersebut terlihat di Perl, menunjukkan kutipan yang diperlukan untuk:
$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;
Jika proses anak perlu memulai sebagai root tetapi kemudian menghapus hak istimewa, lihat kode dalam jawaban ini , yang mengilustrasikan cara menurunkan peringkat hak istimewa dalam suatu proses.