Tại sao không sudo su mệnh trong một tập lệnh shell chạy phần còn lại của tập lệnh là root?


36

Một tập lệnh mẫu có thể như sau:

#!/bin/bash
sudo su
ls /root

Khi sử dụng ./test.shnhư người dùng bình thường, thay vì chạy lsnhư siêu người dùng và thoát, nó chuyển sang root; và khi tôi đăng xuất, nó thực thi ls /rootnhư người dùng bình thường.

Ai đó có thể cho tôi biết về cơ chế về nó?


13
sudo sulàm mắt tôi đau
gelraen

Nó được sử dụng bởi vì mọi người không biết sudo đủ tốt, và vì vậy họ cần một cách để chạy su trên các hệ thống mà root được bảo mật bằng mật khẩu bị lỗi có chủ ý. Nhưng có sudo "dự phòng" việc sử dụng su.
Johan

1
Bạn không thể sử dụng sudo -s, mặc dù?
Joe Z.

@Johan, tôi thường sử dụng sudo suvì tôi quen với các tùy chọn suhơn là của tôi sudo. Tôi biết các tùy chọn của sudo đủ tốt, nhưng tôi có thể gõ những cái su nhanh hơn. Nhưng vâng tôi đoán điều đó có nghĩa là tôi không biết rõ về sudo.
user606723

1
Tôi chỉ kiểm tra trang sudo man. Nó xuất hiện sudo -igần giống như su -trong khi sudo -shoạt động như su(không có dấu gạch ngang)
Johan

Câu trả lời:


49

Các lệnh trong một kịch bản thực thi từng cái một, độc lập. Bản thân Script là cha mẹ của tất cả các lệnh trong tập lệnh, là một quy trình độc lập khác và lệnh su không và không thể thay đổi nó thành root: lệnh su tạo ra một quy trình mới với quyền root.

Sau khi lệnh su hoàn thành, tiến trình cha, vẫn chạy như cùng một người dùng, sẽ thực thi phần còn lại của tập lệnh.

Những gì bạn muốn làm là viết một kịch bản bao bọc. Các lệnh đặc quyền đi vào tập lệnh chính, ví dụ~/main.sh

#!/bin/sh
ls /root

Tập lệnh bao bọc gọi tập lệnh chính có quyền root, như thế này

#!/bin/sh
su -c ~/main.sh root

Để khởi chạy quá trình này, bạn chạy trình bao bọc, lần lượt khởi chạy tập lệnh chính sau khi chuyển người dùng sang người dùng root.

Kỹ thuật trình bao bọc này có thể được sử dụng để biến tập lệnh thành trình bao bọc xung quanh chính nó. Về cơ bản kiểm tra xem nó có chạy bằng root hay không, nếu không, hãy sử dụng "su" để tự khởi chạy lại.

$ 0 là một cách tiện dụng để tạo tập lệnh tham chiếu đến chính nó và lệnh whoami có thể cho chúng ta biết chúng ta là ai (chúng ta có phải là root không?)

Vì vậy, tập lệnh chính với trình bao bọc tích hợp trở thành

#!/bin/sh
[ `whoami` = root ] || exec su -c $0 root
ls /root

Lưu ý việc sử dụng exec. Nó có nghĩa là "thay thế chương trình này bằng", kết thúc việc thực hiện nó một cách hiệu quả và bắt đầu chương trình mới, được khởi chạy bởi su, bằng root, để chạy từ đầu. Ví dụ thay thế là "root" để nó không thực thi phía bên phải của | |


1
fwiw, một phụ lục cho điểm này. Nếu tôi đang viết một tập lệnh giống như vậy, tôi sẽ chỉ thực hiện một câu lệnh if ở đầu kiểm tra $ EUID và nếu nó không bằng 0 sudo và thoát ra, nếu không thì tiếp tục thực thi tập lệnh.
Bratchley

Đồng ý, và tôi sẽ cập nhật câu trả lời để giải thích điều này.
Johan

2
Có lẽ nó hơi cổ xưa nhưng tôi thích các đường dẫn tuyệt đối đến mọi tệp thực thi để ai đó không thể thay đổi tập lệnh ~ / main.sh thành một cái gì đó bất chính. Tấn công phần USER của tập lệnh
artifex

2
Bạn cũng có thể muốn nắm bắt các đối số được truyền cho nó bằng cách bao gồm một tham chiếu đến $ *
Bratchley

@JoelDavis Tôi luôn chạy vào bức tường "nếu có các ký tự khoảng trắng trong các đối số". Tôi chưa bao giờ tìm thấy một giải pháp thỏa đáng. Khi tôi đã viết một tập lệnh đưa ra các đối số của nó vào một tệp tạm thời, một đối số trên mỗi dòng và sau đó gọi bất cứ thứ gì nó cần và chuyển đến tập lệnh cuối cùng đó là đối số của tập tin cần đọc để tìm các đối số ban đầu.
Johan

20

Sử dụng như sau trong kịch bản.

sudo su <<HERE
ls /root
HERE

Mã giữa khối TẠI ĐÂY sẽ được chạy dưới quyền root.


6
sudo suđang gọi hai chương trình. Sử dụng sudo -s <<HEREDOChoặc su user <<HEREDOC... Ngốc 5 phút giới hạn.
Johan

6

Nếu không có thêm đối số susẽ chạy shell đăng nhập cho root. Đó là những gì dòng đầu tiên của kịch bản của bạn thực sự làm. Khi bạn thoát, shell đăng nhập sẽ đóng lại, su trả về và tập lệnh của bạn tiếp tục thực thi, đó là với dòng thứ hai : ls /root. Tôi nghĩ rằng bạn có thể chỉ đơn giản là sudo ls /rootđể làm những gì bạn muốn.


Vâng, tôi biết tôi có thể làm điều này cho ls, nhưng đây chỉ là một mẫu. Trong thực tế, tôi cần phải làm nhiều thứ hơn với đặc quyền root :-) Vì vậy, tôi thích câu trả lời của @ Ankit.
Hongxu Chen

1

Khi bạn thực hiện sudo sumột quy trình mới với hiệu quả userid (euid=EUID)của siêu người dùng rẽ nhánh, do đó chúng tôi có bash mới chạy ở id quy trình khác nhau được (pid=PID)liên kết với cùng một thiết bị đầu cuối (tname=TTY).

Giải trình

Giả sử sau khi bắn ps -A | grep bashbạn có 21460 pts/2 00:00:00 bashđầu ra. Bây giờ, khi bạn thực thi ./test.shcả hai lệnh sudo suls /rootsẽ được lưu vào PID 21460. Sau khi thực hiện khi bạn có rootngười dùng hoạt động nhấn ps -A | grep bashlại, bạn sẽ thấy một bash mới đang chạy PID say, 21570. Thoát khỏi root bashsẽ giết bash mới rẽ nhánh trở lại user's bashvà do đó thực thi lệnh được lưu ls /roottrước khi phát hành dấu nhắc.


Nếu sử dụng su hoặc sudo là "dai dẳng" trong bash (hoặc bất cứ nơi nào khác), nó sẽ tạo ra nhiều vấn đề hơn nó đã giải quyết. Bạn cần phải làm tối thiểu có thể là root cho an toàn và bảo mật. Điểm chính của việc có su và sudo (ngoài bảo mật!) Là khiến bạn suy nghĩ cẩn thận về những gì cần đặc quyền root.
Joe
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.