Tôi có một quy trình được bắt đầu bởi một damon chạy bằng root, bây giờ tôi muốn "hạ cấp" các đặc quyền của quy trình này cho những người dùng trung bình của bạn. Điều này có thể không? Nếu có thì thế nào?
PS: Chạy unix trên máy mac
Tôi có một quy trình được bắt đầu bởi một damon chạy bằng root, bây giờ tôi muốn "hạ cấp" các đặc quyền của quy trình này cho những người dùng trung bình của bạn. Điều này có thể không? Nếu có thì thế nào?
PS: Chạy unix trên máy mac
Câu trả lời:
Quá trình tự nó phải gọi setuid (2). Bạn cũng nên điều tra chạy nó bên trong chroot (8) nếu bạn chưa có. Theo tôi biết, không có cách nào để root thay đổi uid của một tiến trình khác.
Nếu lý do bạn chạy nó với quyền root là để liên kết các cổng, tôi khuyên bạn nên chạy nó như một người dùng bình thường trên một cổng cao hơn và sử dụng ipfw (8) trên OS X để chuyển tiếp cổng 80/443 / etc sang cổng cao hơn:
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
một mình là hoàn toàn không đủ.
sudo tcpdump -Z
sử dụng initgroups (3), setgid (2) và setuid (2) để loại bỏ các đặc quyền gốc của quy trình riêng của nó.
# 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
(! Cuối cùng) chính là mô hình ngay trên unix, và phải luôn luôn được tuân thủ. Ngoài ra, một chức năng "droproot" có trách nhiệm sẽ kiểm tra xem uid và gid của nó có thực sự đã được thiết lập hay không, ngay cả khi cả ba chức năng chính đều trả về thành công.
Bạn có thể chạy các lệnh như những người dùng khác bằng cách sử dụng su
:
su USERNAME -c COMMAND
Sẽ chạy COMMAND
với đặc quyền giảm xuống USER
.
Lưu ý rằng, theo mặc định, su
sẽ sử dụng trình thông dịch shell của người dùng đích để chạy lệnh. Ngược lại, hành vi mặc định của sudo
là coi COMMAND
chương trình độc lập, chạy môi trường hiện tại. Tất nhiên những hành vi mặc định này có thể được thay đổi với các công tắc và biến môi trường khác nhau.
su
không hoạt động nếu USERNAME không có vỏ được xác định (hoặc /bin/false
) trong khi sudo không hoạt động.
su
sẽ phản ánh điều đó. Tuy nhiên, người ta luôn có thể ghi đè lên bằng cách sử dụng công -s
tắc. Lưu ý rằng mục đích của su
là bắt chước một hành vi của người dùng - thường bị ảnh hưởng bởi lớp vỏ của anh ấy / cô ấy. Ngược lại, sudo
sẽ (theo mặc định) bỏ qua cài đặt shell của người dùng mục tiêu.
Để bỏ đặc quyền, bạn cần một người dùng không root để thả xuống. Sau đó, đó chỉ là vấn đề chuyển sang người dùng đó:
#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);
Lưu ý rằng điều này được thực hiện trong chính chương trình , chứ không phải trong một tập lệnh bao bọc. Nhiều chương trình yêu cầu quyền root cho một số mục đích cụ thể (ví dụ: để liên kết với một cổng được đánh số thấp), nhưng sau đó không cần root. Vì vậy, các chương trình này sẽ bắt đầu với quyền root, nhưng sau đó bỏ đặc quyền một khi chúng không còn cần thiết nữa.
Nếu bạn không cần quyền root, thì đừng chạy nó dưới quyền root. Ví dụ:
# 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
chức năng chỉ đặt hiệu quả UID, không phải là UID thật. Bạn nên sử dụng setreuid
nếu bạn không muốn quá trình có thể lấy lại các đặc quyền. (Và mã ở trên cũng không xử lý các đặc quyền nhóm bổ sung. Nó chỉ phù hợp để khởi chạy mã được tin cậy nhiều nhất.)
setuid()
không đặt userids thực và lưu; bạn có thể suy nghĩ của seteuid()
. Không phải tất cả các hệ thống đều có setreuid()
, vì vậy nó không thể được sử dụng ở mọi nơi. Các ngữ nghĩa chính xác setuid()
là phức tạp, nhưng nếu bạn có 0, bạn sẽ có thể bỏ tất cả các đặc quyền id người dùng truyền thống với setuid()
. Thiếu sót lớn nhất trong câu trả lời này là initgroups
hoặc setgroups
phải được gọi cũng như setgid
và setuid
, và những xác nhận kỹ lưỡng hơn nên được thực hiện ở cuối.
Nếu bạn đang thực thi một hàm thực thi khác, tức là bạn đang gọi execve
hoặc một hàm khác của exec
hàm, có thể gián tiếp thông qua một hàm như system
hoặc popen
, và tiến trình con nên chạy mà không có đặc quyền từ đầu, thì cách đơn giản nhất là lấy một vỏ liên quan, và gọi su
. Dưới đây là tổng quan về cách mã có thể trông giống như trong Perl, hiển thị trích dẫn cần thiết cho:
$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;
Nếu tiến trình con cần bắt đầu với quyền root nhưng bỏ đặc quyền sau, hãy xem mã trong câu trả lời này , minh họa cách hạ cấp đặc quyền trong một quy trình.