Yêu cầu đặc quyền root từ trong tập lệnh


23

Tôi có một kịch bản có thể chạy như sudo script.shhoặcpkexec script.sh

Sẽ tốt hơn nhiều từ quan điểm của người dùng nếu tập lệnh yêu cầu mật khẩu từ người dùng khi chỉ chạy nó theo tên script.sh.

Làm cách nào tôi có thể "nhúng" yêu cầu pkexechoặc sudochạy toàn bộ tập lệnh với quyền root?

Lưu ý rằng chạy mọi thứ với sudo sh -ccó thể không phải là giải pháp tốt nhất vì tôi có các chức năng trong tập lệnh.

Câu trả lời:


55

Điều này sẽ làm việc:

echo "$(whoami)"

[ "$UID" -eq 0 ] || exec sudo "$0" "$@"

thí dụ:

./test.sh 
blade
[sudo] password for blade: 
root

3
Điều tốt về điều này là đệ quy với exec- gọi chính nó nhưng đồng thời thay thế quá trình, vì vậy chúng tôi không sinh ra nhiều phiên bản của kịch bản
Sergiy Kolodyazhnyy 15/03/2016

1
Đệ quy giải cứu !!! Nhắc tôi để thêm một tiền thưởng cho cái này trong một vài ngày!
Fabby

6
Một điều cần lưu ý khi làm điều này là sự leo thang đặc quyền; về cơ bản, càng nhiều lệnh bạn chạy với quyền root, càng có nhiều cơ hội cho một hacker độc hại khai thác thứ gì đó để có quyền truy cập vào tài khoản root. Tôi không nói rằng luôn luôn sai khi làm cho toàn bộ tập lệnh chạy bằng root, nhưng đáng để suy nghĩ một chút về nó trước khi bạn quyết định làm như vậy. Tôi nghĩ rằng nó sẽ tốt đẹp (mặc dù không cần thiết) nếu câu trả lời sẽ chạm vào đó.
David Z

Nếu bạn có một giá trị thời gian chờ khá được đặt trong / etc / sudoers, thì bạn có thể tùy ý đặt sudo trước mỗi lệnh trong tập lệnh thực sự cần quyền truy cập root và nó sẽ chỉ yêu cầu một lần. Một điều tôi thường làm phiền là việc gọi một đoạn script như vậy từ gui sẽ không hoạt động vì sudo được / dev / null để nhập mật khẩu và không thành công. Đó là những gì gksudo và kdesudo được thiết kế để xử lý vì họ sẽ sử dụng gui để hỏi mật khẩu.
Joe

1
@ Coder256: Tôi không nghĩ chỉnh sửa của bạn là đúng. "$@"sẽ mở rộng ra nhiều từ, một từ cho mỗi tham số.
jwodder

12

Nếu bạn thích một hộp thoại đẹp, hãy thử một cái gì đó như thế này. Tôi đã loại bỏ thứ này ra khỏi thứ khác mà tôi đã viết, vì vậy nó có thêm những thứ bạn có thể không cần hoặc không muốn, nhưng nó cho thấy ý tưởng chung:

brand="My Software"

# Check that the script is running as root. If not, then prompt for the sudo
# password and re-execute this script with sudo.
if [ "$(id -nu)" != "root" ]; then
    sudo -k
    pass=$(whiptail --backtitle "$brand Installer" --title "Authentication required" --passwordbox "Installing $brand requires administrative privilege. Please authenticate to begin the installation.\n\n[sudo] Password for user $USER:" 12 50 3>&2 2>&1 1>&3-)
    exec sudo -S -p '' "$0" "$@" <<< "$pass"
    exit 1
fi

hộp thoại sudo

Cái này sử dụng whiptail, cái mà bạn có thể cài đặt nếu bạn chưa có nó:

sudo apt-get install whiptail

1
Tại sao bạn lưu mật khẩu trong một biến?
heemayl

10
Đừng gọi exec echo [PASSWORD]! Nó sẽ sinh ra một quy trình với mật khẩu trên dòng lệnh mà bất kỳ người dùng nào cũng có thể nhìn thấy. Hoặc sử dụng lệnh tích hợp echo(buộc phiên bản tích hợp sẵn builtin echo) hoặc bashism <<<(như vậy sudo ... <<< "$pass":); Sh và các shell khác có Tài liệu ở đây cho các trường hợp này. Ngoài ra, trích dẫn mật khẩu trong trường hợp nó chứa các ký tự đặc biệt.
David foerster

Ngoài ra, đặt whiptaillệnh vào một tập lệnh riêng biệt và sử dụng một cái gì đó như SUDO_ASKPASS=/path/to/askpass-with-whiptail.sh sudo -A -p "My password prompt" -- "$0" "$@"để sudođối phó với lời nhắc mật khẩu tùy chỉnh.
David Foerster

@DavidFoerster Điều đó có thể hoạt động, nhưng sau đó bạn cần hai tập lệnh hoặc bạn viết tập lệnh hỏi của bạn vào một tệp tạm thời và sau đó chuyển nó sang sudo.
Michael Hampton

Ok tuy nhiên những người khác đã lưu ý rằng việc chuyển mật khẩu cho một biến là điều không mong muốn. Cách id tiếp cận điều này là để chuyển đầu ra của hộp thoại cho đường ống có tên như tôi đã trình bày ở đây, Askubfox.com/a/704643/295286
Sergiy Kolodyazhnyy

11

Câu trả lời của blade19899 thực sự là con đường để đi, tuy nhiên người ta cũng có thể gọi sudo bashtrong shebang:

#!/usr/bin/sudo bash
# ...

Nhắc nhở rõ ràng là điều này sẽ chỉ hoạt động miễn là tập lệnh được gọi với ./scriptvà sẽ thất bại ngay khi tập lệnh được gọi với bash script.


5
Đây là một trong những lý do tại sao bạn không bao giờ nên gõ bash scriptvào dòng lệnh để gọi một tập lệnh. Nếu kịch bản quy định cụ thể bất cứ điều gì khác hơn là bashtrong #!dòng, sau đó gọi nó với bash scriptlà sẽ thất bại. Nếu tôi cố gắng gọi một kịch bản python bằng cách sử dụng bash script.pynó cũng sẽ thất bại.
kasperd

1
Bạn có thể chạy nó với perl script, mặc dù. Perl, trong một nỗ lực để thực sự thực sự tốt đẹp, hãy kiểm tra dòng shebang và nếu nó không gọi perl thì nó chạy chương trình chính xác.
tbodt

Điều này là xấu vì nó đang chạy mọi lệnh trong kịch bản với sudo. Tốt hơn là cô lập một vài lệnh thực sự cần sudo và thêm chúng vào khi cần thiết. Không bao gồm việc đánh giá các chức năng trong các cuộc gọi sudo này; chúng phải rõ ràng và tối thiểu nhất có thể.
Douglas Held

@DoumundHeld Trong khi tôi có thể đồng ý với điều đó, đây là câu hỏi được đặt ra: "Làm thế nào tôi có thể" nhúng "yêu cầu pkexec hoặc sudo để chạy toàn bộ tập lệnh với đặc quyền gốc?". Khá chắc chắn rằng sẽ có trường hợp sử dụng trong đó có thể làm điều này sẽ hữu ích.
kos

6

Tôi mở đầu các lệnh trong tập lệnh cần quyền truy cập root sudo- nếu người dùng chưa có quyền, tập lệnh sẽ nhắc mật khẩu tại thời điểm đó.

thí dụ

#!/bin/sh 
mem=$(free  | awk '/Mem:/ {print $4}')
swap=$(free | awk '/Swap:/ {print $3}')

if [ $mem -lt $swap ]; then
    echo "ERROR: not enough RAM to write swap back, nothing done" >&2
    exit 1
fi

sudo swapoff -a && 
sudo swapon -a

Kịch bản này có thể được chạy như sudo <scriptname>hoặc <scriptname>. Trong cả hai trường hợp, nó sẽ yêu cầu mật khẩu, chỉ một lần.


2
Vấn đề ở đây là có thể có nhiều lệnh cần truy cập root, có nghĩa là gọi sudo25 lệnh khác nhau dự phòng - việc gọi sudo một lần sẽ dễ dàng hơn. Tuy nhiên, ở đây, lý do tập lệnh của bạn gọi sudo chỉ một lần là vì sudo có thời gian ngoài 15 phút - các lệnh mất nhiều thời gian hơn sẽ cần phải được lặp lại. Cách của bạn chỉ hoạt động. . . không phải là cách tôi cần nó để làm việc
Sergiy Kolodyazhnyy 15/03/2016

@Serg Đối với một kịch bản nhỏ, cách tôi đã nhanh chóng và dễ dàng - Tôi thực sự không phải là một lập trình viên thanh lịch!
Charles Green

Bạn là lập trình viên tốt nhất đăng trên trang này. Bạn đang sử dụng sudo chính xác như nó nên được sử dụng - chỉ khi cần thiết và có kết quả rất rõ ràng mong đợi.
Douglas Held

4

Dường như không ai khác đã giải quyết mối quan tâm rõ ràng ở đây. Đặt sudotrong tập lệnh của bạn mà sau đó bạn phân phối sẽ thúc đẩy thói quen xấu của người dùng . (Tôi cho rằng bạn đang phân phối nó vì bạn đề cập "từ quan điểm của người dùng.")

Sự thật là có một hướng dẫn trong việc sử dụng các ứng dụng và tập lệnh tương tự như nguyên tắc bảo mật trong ngân hàng: Không bao giờ cung cấp thông tin cá nhân của bạn cho ai đó gọi cho bạn và nói rằng họ đang gọi "từ ngân hàng của bạn" và tồn tại vì những lý do tương tự.

Quy tắc cho các ứng dụng là:

Không bao giờ nhập mật khẩu của bạn khi được nhắc trừ khi bạn chắc chắn những gì đang được thực hiện với nó. Điều này áp dụng ba lần cho bất cứ ai có sudoquyền truy cập.

Nếu bạn đang nhập mật khẩu của mình vì bạn đã chạy sudotrên dòng lệnh, thật tuyệt. Nếu bạn đang gõ nó vì bạn đã chạy lệnh SSH, tốt thôi. Nếu bạn đang gõ nó khi bạn đăng nhập vào máy tính, tất nhiên rồi.

Nếu bạn chỉ chạy một tập lệnh nước ngoài hoặc có thể thực thi và nhập mật khẩu của bạn khi được nhắc cho nó, bạn không biết kịch bản đang làm gì với nó. Nó có thể được lưu trữ trong một tệp tạm thời trong bản rõ, cho tất cả những gì bạn biết, và thậm chí có thể không tự dọn sạch.

Rõ ràng có những mối quan tâm riêng biệt và bổ sung về việc chạy một nhóm lệnh không xác định như root, nhưng điều tôi đang nói ở đây là duy trì bảo mật trên chính mật khẩu . Ngay cả khi giả sử ứng dụng / tập lệnh không độc hại, bạn vẫn muốn mật khẩu của mình được xử lý an toàn để ngăn các ứng dụng khác giữ nó và sử dụng nó một cách độc hại.

Vì vậy, phản ứng cá nhân của riêng tôi về vấn đề này là, điều tốt nhất để đưa vào tập lệnh của bạn nếu nó cần đặc quyền gốc, là:

#!/bin/bash
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1;}

# do privileged stuff, etc.

Mặc dù tôi hoàn toàn đồng ý với bạn, một người dùng chạy một thứ gì đó mà không biết nó làm gì cũng sudo script_namedễ bị tổn thương, nó cũng vậy. Có lẽ ý tưởng này thúc đẩy những thói quen xấu - tôi sẽ không nói gì về điều đó. Nhưng điều quan trọng là biết chương trình làm gì và đó là trách nhiệm của người dùng. Đó là toàn bộ ý tưởng đằng sau phần mềm nguồn mở. Đối với kịch bản của riêng tôi, tốt. . . một kịch bản là văn bản đơn giản - người dùng có thể đọc nó nếu họ muốn biết nó làm gì
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy tương tự, nhưng nếu bạn nhập mật khẩu trực tiếp vào tập lệnh thì nó thực sự tồi tệ hơn. Một tập lệnh chạy với sudo vẫn không biết mật khẩu của bạn.
tự đại diện

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.