Tư cách thành viên nhóm và quy trình setuid / setgid


10

Quá trình mà de-leo thang đặc quyền thông qua setuid()setgid()dường như không kế thừa các thành viên nhóm của uid / gid họ thiết lập.

Tôi có một quy trình máy chủ phải được thực thi như root để mở một cổng đặc quyền; sau đó, nó giảm xuống mức uid / gid không riêng tư cụ thể, 1 - ví dụ: của người dùng foo(UID 73). Người dùng foolà thành viên của nhóm bar:

> cat /etc/group | grep bar
bar:x:54:foo

Do đó, nếu tôi đăng nhập foo, tôi có thể đọc một tệp /test.txtcó các đặc điểm sau:

> ls -l /test.txt
-rw-r----- 1 root bar 10 Mar  8 16:22 /test.txt

Tuy nhiên, chương trình C sau (biên dịch std=gnu99), khi chạy root:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main (void) {
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}   

Luôn báo cáo Quyền bị từ chối . Tôi tưởng tượng điều này có liên quan đến nó là một quá trình không đăng nhập, nhưng nó cản trở cách thức các quyền được cho là hoạt động.


1. Thường là SOP cho máy chủ và tôi nghĩ phải có cách giải quyết vấn đề này khi tôi tìm thấy một báo cáo về ai đó làm điều đó với apache - apache đã được thêm vào nhóm âm thanh và sau đó rõ ràng có thể sử dụng hệ thống âm thanh. Tất nhiên, điều này có thể xảy ra trong một ngã ba chứ không phải quá trình ban đầu, nhưng trên thực tế trường hợp này giống nhau trong bối cảnh của tôi (đó là một quá trình con được chia rẽ sau cuộc gọi setuid).


Chuyển setuid()/ setgid()cuộc gọi xung quanh.
vonbrand

@vonbrand haha Tôi nghĩ rằng tôi đã ở trong một facepalm đó - nhưng kết quả tương tự, vì vậy tôi sẽ chỉnh sửa các câu hỏi để loại bỏ những cá trích đỏ.
goldilocks

1
Nếu bạn sử dụng setgid(54)thay vì setgid(73)(như trong /etc/groups, nhóm barcó gid 54), nó có hoạt động không?
lgeorget

@lgeorget Chắc chắn, nhưng điều đó đánh bại mục đích. Quá trình cần GID riêng vì những lý do khác và tương tự, những tệp đó phải có quyền mà họ có. Đó là lý do tại sao thành viên trong nhóm số nhiều là cần thiết - ví dụ: nếu bạn có hai người dùng cần thực hiện việc này. Lưu ý rằng bạn không thể setuid()một lần nữa sau khi bạn làm điều đó ... nhưng, hmmm ... Tôi nghĩ rằng bạn có thể với seteuid()...
goldilocks

1
Câu hỏi của tôi là chắc chắn không có vấn đề tinh tế ẩn giấu nào khác ở đâu đó. :-)
lgeorget

Câu trả lời:


14

Vấn đề là điều đó setuidsetgid không đủ để cung cấp cho quá trình của bạn tất cả các thông tin cần thiết. Việc ủy ​​quyền của một quy trình phụ thuộc vào

  • UID của nó
  • GID của nó
  • nhóm bổ sung của nó
  • khả năng của nó.

Xem man 7 credentialsđể có được một cái nhìn tổng quan chi tiết hơn. Vì vậy, trong trường hợp của bạn, vấn đề là bạn đặt chính xác UID và GID, nhưng bạn không đặt các nhóm bổ sung của quy trình. Và nhóm barcó GID 54, số 73 nên không được công nhận là nhóm mà quy trình của bạn tham gia.

Bạn nên làm

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <grp.h>

int main (void) {
    gid_t supplementary_groups[] = {54};

    setgroups(1, supplementary_groups);
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}  

1
Đó là một câu hỏi thú vị xứng đáng nhận được nhiều sự ủng hộ hơn bởi vì nó thực sự có thể hữu ích cho nhiều người ngoài kia. :-)
lgeorget

Vì vậy, tôi đã có một vấn đề tương tự với các cổng nối tiếp. Tôi đã thực hiện điều này cho dialoutnhóm và nó hoạt động lần đầu tiên.
tl8

0

OK, truy tìm mạng một chút. Lúc đầu tôi nghĩ rằng APUE sẽ giữ tất cả các câu trả lời, nhưng đã nhầm. Và bản sao của tôi (phiên bản cũ) đang hoạt động, vì vậy ... Chương 5 của Sổ tay Quản trị Unix và Linux có vẻ đầy hứa hẹn, nhưng tôi không có nó (chỉ là một bản sao của hai phiên bản đầu tiên, cũng đang hoạt động).

Tất cả các tài nguyên nhỏ mà tôi đã tìm thấy (google cho "daemon viết unix") đều nói về các bước quan trọng, như cách phân tách khỏi tty, v.v. Nhưng không có gì về UID / GID. Thật kỳ lạ, ngay cả bộ sưu tập HOWTO rộng lớn tại http://tldp.org dường như cũng có chi tiết. Chỉ excetion là của Jason Ngắn Hãy viết một Daemon Linux - phần I . Chi tiết đầy đủ về cách SUID / SGID và tất cả những thứ lộn xộn đó hoạt động là sự phá hủy SUID của Chen, Wagner và Dean (một bài báo trong USENIX 2002). Nhưng hãy cẩn thận, Linux có thêm một UID, FSUID (xem Ghi chú không tương thích Unix của Wolter : Các chức năng thiết lập UID để thảo luận).

Daemonizing một quá trình chắc chắn không dành cho người yếu tim. Các cân nhắc bảo mật chung được đưa ra trong D. Lập trình bảo mật của D. Wheeler cho Linux và Unix HOWTO - Tạo phần mềm bảo mật . Systemd hứa sẽ đơn giản hóa hầu hết điều đó (và do đó giảm khả năng xảy ra lỗi dẫn đến các vấn đề bảo mật), xem hướng dẫn sử dụng daemon .


1
Câu hỏi không phải là về daemonization. Bạn đã nhầm lẫn bit SUID (cung cấp cho một quy trình quyền của chủ sở hữu thực thi của nó) với setuid(), cho phép quá trình thay đổi tùy ý UID của nó. SUID thường được dự định để cho phép leo thang các quyền (không riêng tư -> riêng tư), trong khi setuid()chỉ có thể làm ngược lại.
goldilocks
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.