Đặc quyền quy trình thả


12

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:


5

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


Tôi đặt setuid (uid) trong chương trình của mình chạy bằng root nhưng tôi cần nó để chạy như một người dùng bình thường & không có gì xảy ra, tức là nó tiếp tục chạy như root
Samantha Catania

Bạn có thể cần phải bắt lỗi từ nó sau đó (có thể bạn đang nhận được EINVAL cho uid). Setuid không chắc chắn của nó bị hỏng trên máy của bạn, bạn có thể xác minh bằng cách xem liệu apache có chạy dưới dạng _www không. Tài liệu lập trình viên: developer.apple.com/l
đa thức

Bạn đúng, nó đưa ra lỗi cú pháp từ uid mặc dù nó đúng. Đây có phải là định dạng đúng setuid (500) không?
Samantha Catania

tìm thấy vấn đề: Tôi đã cố chạy lệnh thông qua system () nhưng tôi chỉ chạy lệnh nó hoạt động & giải quyết vấn đề của tôi; thx để được giúp đỡ
Samantha Catania

Không. Đây không phải là lời khuyên tốt: gọi setuid()một mình là hoàn toàn không đủ.
Nicholas Wilson

13

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);
            }
...
}

2
Chính xác. 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.
Nicholas Wilson

3

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 COMMANDvới đặc quyền giảm xuống USER.


Lưu ý rằng, theo mặc định, susẽ 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 sudolà coi COMMANDchươ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.


Có vẻ như sukhô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.
Aif

1
@Aif Nếu người dùng không được phép chạy các lệnh tương tác, thì hành vi mặc địnhsu 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 -stắc. Lưu ý rằng mục đích của sulà 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, sudosẽ (theo mặc định) bỏ qua cài đặt shell của người dùng mục tiêu.
rozcietrzewiacz

Không, xin vui lòng không chạy mọi thứ bằng cách sử dụng shell chỉ để bỏ đặc quyền. Điều đó để lại quá nhiều sự kiểm soát của kẻ tấn công, đọc các tệp cấu hình khác nhau mà bạn không muốn chạm vào.
Nicholas Wilson

2

Để 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"

1
Lưu ý rằng điều này cho phép quá trình phục hồi các đặc quyền nếu nó muốn! Các setuidchức năng chỉ đặt hiệu quả UID, không phải là UID thật. Bạn nên sử dụng setreuidnế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.)
David Schwartz

Mã @David Schwartz được cố ý đơn giản hóa để hiển thị cơ chế được sử dụng.
tylerl

Nếu bạn đang đi để đơn giản hóa mã bảo vệ quan trọng, bạn phải làm cho nó rất rõ ràng rằng đây là những gì bạn đang làm. Và bạn nên nói những điều như "đó chỉ là vấn đề" khi không.
David Schwartz

2
@David Trên thực 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à initgroupshoặc setgroupsphải được gọi cũng như setgidsetuid, và những xác nhận kỹ lưỡng hơn nên được thực hiện ở cuối.
Nicholas Wilson

0

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 execvehoặc một hàm khác của exechàm, có thể gián tiếp thông qua một hàm như systemhoặ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.

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.