2011-12-14 40 views
32

Đây là một chương trình thiết root-uidRealUID, UID đã lưu, UID hiệu quả. Chuyện gì vậy?

$ls -l 
-rwsr-sr-x 1 root root 7406 2011-12-13 22:37 ./x* 

Mã nguồn:

int main(void) { 
    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

seteuid(600); 
    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

setuid(1000); 

    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

setuid(0); // HOW DOES THIS SUCCEED IN SETTING THE EUID BACK TO 0 
    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

    return 0 ;  
} 

OUTPUT

  UID   GID 
Real  1000 Real  1000 
Effective 0 Effective 0 
     UID   GID 
Real  1000 Real  1000 
Effective 600 Effective 0 
     UID   GID 
Real  1000 Real  1000 
Effective 1000 Effective 1000 
     UID   GID 
Real  1000 Real  1000 
Effective 0 Effective 1000 

Câu hỏi của tôi

Các trang người đàn ông khẳng định rằng ý chí setuid thay đổi uid thực, được lưu và hiệu quả. Vì vậy, sau khi gọi setuid(1000), cả ba thay đổi thành 1000. Làm thế nào là setuid(0) hãy để tôi thay đổi euid thành 0?

Trả lời

24

Có hai trường hợp,

  1. Bạn muốn tạm thời thả đặc quyền gốc trong khi thực hiện setuid chương trình
  2. Bạn muốn vĩnh viễn thả đặc quyền gốc trong khi thực hiện chương trình setuid ...
  • Bạn có thể tạm thời làm điều đó bằng cách thiết lập euid cho người sử dụng id sản và sau đó thay đổi uid để bất cứ điều gì bạn want.And sau khi bạn cần đặc quyền gốc lại bạn có thể setuid để rễ và userid hiệu quả sẽ thay đổi trở lại root. Điều này là do id người dùng đã lưu không bị thay đổi.
  • Bạn có thể thả đặc quyền vĩnh viễn bằng cách thay đổi uid ngay lập tức đến một id người dùng đặc quyền thấp hơn. Sau này không có vấn đề gì bạn không thể lấy lại đặc quyền root.

Trường hợp 1:

Sau một chương trình setuid bắt đầu thực hiện

1.seteuid(600); 
2.setuid(1000); 
3.setuid(0); 

Đối với trường hợp này đặc quyền gốc có thể đạt được trở lại một lần nữa.

   +----+------+------------+ 
       | uid|euid |saved-uid | 
       |----|------|------------| 
      1.|1000| 0 | 0   | 
      2.|1000| 600 | 0   | 
      3.|1000| 1000 | 0   | 
      4.|1000| 0 | 0   | 
       | |  |   | 
       +------------------------+ 

Trường hợp 2:

Sau một chương trình setuid bắt đầu thực hiện,

1.setuid(1000); 
2.setuid(0); 



       +----+------+------------+ 
       | uid|euid |saved-uid | 
       |----|------|------------| 
      1.|1000|0  | 0   | 
      2.|1000|1000 | 1000  | 
       | |  |   | 
       +------------------------+ 

Trong trường hợp này bạn không thể lấy lại đặc quyền root. Điều này có thể được xác minh bằng lệnh sau,

cat/proc/PROCID/task/PROCID/status | ít

Uid: 1000 0  0  0 
Gid: 1000 0  0  0 

Lệnh này sẽ hiển thị một UID và GID và nó sẽ có 4 lĩnh vực (ba lĩnh vực đầu tiên là người chúng tôi đang quan tâm). Một cái gì đó giống như ở trên

Ba trường đại diện cho uid, euid và id người dùng đã lưu. Bạn có thể giới thiệu tạm dừng (đầu vào từ người dùng) trong chương trình setuid của bạn và kiểm tra từng bước lệnh cat /proc/PROCID/task/PROCID/status | less. Trong mỗi bước bạn có thể kiểm tra uid đã lưu thay đổi như đã đề cập.

Nếu euid của bạn là gốc và bạn thay đổi uid, các đặc quyền sẽ bị xóa vĩnh viễn.If id người dùng hiệu quả không phải là root thì id người dùng đã lưu không bao giờ được chạm và bạn có thể lấy lại đặc quyền gốc bất cứ lúc nào bạn muốn trong chương trình của bạn.

+0

Bạn có thể cho tôi biết cột cuối cùng trong Uid: 1000 0 0 0 đại diện cho –

+0

Khi tôi thử kiểm tra nó bằng mã mẫu giá trị thứ tư được hiển thị giống như id người dùng có hiệu lực hay không. Đoán nó phải là id người dùng hiệu quả, nhưng không chắc chắn tại sao nó sẽ in id người dùng hiệu quả hai lần. – Ajai

+1

Cột cuối cùng là FSUID – user368507

8

MÔ TẢ setuid() thiết lập ID người dùng hiệu quả của quá trình gọi. Nếu UID hiệu quả của người gọi là gốc, UID thực và ID người dùng thiết lập đã lưu cũng được đặt.

Trong Linux, setuid() được triển khai giống như phiên bản POSIX có tính năng _POSIX_SAVED_IDS. cho phép chương trình ID người dùng thiết lập (không phải root) để bỏ tất cả các đặc quyền của người dùng, thực hiện một số tác vụ không có đặc quyền và sau đó thay thế lại ID người dùng hiệu quả ban đầu một cách an toàn.

Nếu người dùng là người chủ hoặc chương trình là người dùng đã đặt ID người dùng, bạn phải thực hiện dịch vụ chăm sóc đặc biệt. Hàm setuid() kiểm tra ID người dùng hiệu quả của người gọi và nếu đó là superuser, tất cả người dùng liên quan đến quy trình ID được đặt thành uid. Sau khi điều này xảy ra, chương trình sẽ không thể lấy lại các đặc quyền root.

Do đó, một chương trình set-user-ID-gốc có nhu cầu tạm thời thả quyền root, giả danh tính của một người dùng không có đặc quyền , và sau đó lấy lại quyền root sau đó không thể sử dụng setuid(). Bạn có thể thực hiện điều này với seteuid (2).

(từ tay các lập trình viên Linux, 2014/09/21, trang setuid.2)

+0

Theo những gì bạn đã nói, đoạn đầu ra cuối cùng sẽ hiển thị 'Hiệu quả' =' 1000'. Nhưng nó có thể trở lại '0'. Đó chính là câu hỏi của tôi. –

+0

Tôi tin rằng đó là do lệnh gọi 'seteuid' mà bạn đang thực hiện; nó làm cho hạt nhân "bảo vệ" khả năng của bạn để lấy lại 'root' trong tương lai. Việc xóa cuộc gọi đó sẽ loại bỏ hiệu ứng "backdoor". – BRFennPocock

+0

Yep, câu trả lời của @ ajai cũng cung cấp bằng chứng. Cảm ơn câu trả lời anyway –

2

O! Các chức năng này khó sử dụng đúng cách.

Trang người dùng cho biết setuid sẽ thay đổi uid thực, đã lưu và hiệu quả. Vì vậy, sau khi setuid gọi (1000), cả ba thay đổi 1000.

Đó là trường hợp khi và chỉ khi bạn đang euid 0. Đồng thời bạn gọi setuid(0), tuy nhiên, bạn là euid 1000 và lưu uid 0 (ví dụ: getresuid(2)). Đó là lý do tại sao bạn có thể lấy lại các đặc quyền.

+0

Bạn đã đúng. Các getresuid() có vẻ là làm việc tốt. Nhưng nó không phải là 'POSIX' tuân thủ. Nhưng điều đó không quan trọng trong trường hợp này. Cảm ơn.. –

Các vấn đề liên quan