ขอสิทธิ์รูทจากภายในสคริปต์


23

ฉันมีสคริปต์ที่สามารถทำงานเป็นsudo script.shหรือpkexec script.sh

script.shมันจะดีกว่ามากจากจุดที่ผู้ใช้มุมมองว่าสคริปต์ถามรหัสผ่านจากผู้ใช้เมื่อเพียงแค่ใช้มันโดยใช้ชื่อ

ฉันจะ "ฝัง" คำขอไปยังpkexecหรือsudoเรียกใช้สคริปต์ทั้งหมดด้วยสิทธิ์พิเศษได้อย่างไร

โปรดทราบว่าการรันทุกอย่างด้วยsudo sh -cอาจไม่ใช่วิธีที่ดีที่สุดเนื่องจากฉันมีฟังก์ชั่นในสคริปต์

คำตอบ:


55

สิ่งนี้จะได้ผล:

echo "$(whoami)"

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

ตัวอย่าง:

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

3
สิ่งที่ดีเกี่ยวกับเรื่องนี้คือการเรียกซ้ำexec- เรียกตัวเอง แต่ในเวลาเดียวกันการแทนที่กระบวนการดังนั้นเราจึงไม่วางไข่สคริปต์หลายครั้ง
Sergiy Kolodyazhnyy

1
ขอความช่วยเหลืออีกครั้ง !!! เตือนฉันให้เพิ่มค่าหัวนี้ในอีกไม่กี่วัน!
Fabby

6
สิ่งที่ต้องระวังเมื่อทำเช่นนี้คือการเพิ่มระดับสิทธิ์ โดยทั่วไปยิ่งคุณใช้คำสั่งเป็นรูทมากเท่าไหร่โอกาสที่แฮ็กเกอร์ที่เป็นอันตรายจะยิ่งใช้ประโยชน์จากบางสิ่งมากขึ้นเพื่อเข้าถึงบัญชีรูท ฉันไม่ได้บอกว่ามันผิดเสมอไปที่ทำให้สคริปต์ทั้งหมดทำงานในฐานะรูท แต่มันก็คุ้มค่าที่จะนำความคิดมาก่อนที่คุณจะตัดสินใจทำ ฉันคิดว่ามันจะดี (แม้ว่าจะไม่จำเป็น) ถ้าคำตอบนั้นแตะที่
David Z

หากคุณมีค่าการหมดเวลาที่เหมาะสมตั้งอยู่ใน / etc / sudoers คุณสามารถเลือกที่จะใส่ sudo ต่อหน้าแต่ละคำสั่งในสคริปต์ที่ต้องการเข้าถึงรูทและจะถามเพียงครั้งเดียว สิ่งหนึ่งที่ฉันมักจะสับสนคือการเรียกสคริปต์ดังกล่าวจาก gui จะไม่ทำงานเพราะ sudo ได้รับ / dev / null สำหรับการป้อนรหัสผ่านและล้มเหลว นั่นคือสิ่งที่ gksudo และ kdesudo ถูกออกแบบมาเพื่อจัดการเพราะพวกเขาจะใช้ gui เพื่อขอรหัสผ่าน
Joe

1
@ Coder256: ฉันไม่คิดว่าการแก้ไขของคุณถูกต้อง "$@"จะขยายเป็นหลายคำโดยหนึ่งคำสำหรับแต่ละพารามิเตอร์
jwodder

12

หากคุณต้องการบทสนทนาที่น่ารักลองทำสิ่งนี้ ฉันฉีกสิ่งที่ฉันเขียนออกมาตรงนี้ดังนั้นมันจึงมีสิ่งพิเศษที่คุณอาจไม่ต้องการหรือต้องการ แต่มันแสดงให้เห็นถึงแนวคิดทั่วไป:

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

กล่องโต้ตอบ sudo

สิ่งนี้ใช้แส้ซึ่งคุณสามารถติดตั้งได้หากคุณยังไม่มี:

sudo apt-get install whiptail

1
ทำไมคุณถึงบันทึกรหัสผ่านในตัวแปร?
heemayl

10
อย่าโทรexec echo [PASSWORD]! มันจะวางกระบวนการด้วยรหัสผ่านบนบรรทัดคำสั่งที่ผู้ใช้สามารถเห็นได้ ทั้งใช้คำสั่งในตัวecho(บังคับรุ่นในตัวด้วยbuiltin echo) หรือ bashism <<<(like so :) sudo ... <<< "$pass"; SH และเชลล์อื่น ๆ มีเอกสารที่นี่สำหรับกรณีเหล่านี้ นอกจากนี้อ้างรหัสผ่านในกรณีที่มีตัวอักษรพิเศษ
David Foerster

อีกวิธีหนึ่งคือใส่whiptailคำสั่งเป็นสคริปต์และการใช้งานที่แยกต่างหากสิ่งที่ต้องการSUDO_ASKPASS=/path/to/askpass-with-whiptail.sh sudo -A -p "My password prompt" -- "$0" "$@"ที่จะมีsudoข้อตกลงกับสอบถามรหัสผ่านที่กำหนดเอง
David Foerster

@DavidFoerster ที่สามารถใช้งานได้ แต่จากนั้นคุณต้องใช้สองสคริปต์หรือเขียนสคริปต์ askpass ของคุณไปที่ไฟล์ชั่วคราวแล้วส่งต่อไปยัง sudo
Michael Hampton

ตกลง แต่คนอื่นสังเกตแล้วมันไม่พึงประสงค์ที่จะส่งรหัสผ่านไปยังตัวแปร วิธี id วิธีนี้คือการส่งออกของการโต้ตอบไปยังท่อที่มีชื่อตามที่ฉันได้แสดงไว้ที่นี่askubuntu.com/a/704643/295286
Sergiy Kolodyazhnyy

11

คำตอบของ blade19899 นั้นเป็นหนทางไปอย่างแน่นอน แต่ใคร ๆ ก็สามารถโทรหาได้sudo bashใน shebang:

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

ข้อแม้ที่ชัดเจนคือนี้จะทำงานเฉพาะตราบใดที่สคริปต์ที่เรียกว่ามีและจะล้มเหลวทันทีที่สคริปต์ที่เรียกว่ามี./scriptbash script


5
นี่คือหนึ่งในเหตุผลที่คุณไม่ควรพิมพ์bash scriptบนบรรทัดคำสั่งเพื่อเรียกใช้สคริปต์ หากสคริปต์ระบุสิ่งอื่นนอกเหนือจากbashใน#!บรรทัดการเรียกใช้สคริปต์ด้วยbash scriptจะล้มเหลว ถ้าฉันพยายามเรียกใช้สคริปต์ไพ ธ อนbash script.pyมันก็จะล้มเหลวเช่นกัน
kasperd

1
คุณสามารถเรียกใช้มันด้วยperl scriptแม้ว่า Perl ในความพยายามที่จะเป็นคนดีจริง ๆ ตรวจสอบบรรทัด shebang และถ้ามันไม่ได้เรียก perl มันรันโปรแกรมที่ถูกต้อง
tbodt

สิ่งนี้ไม่ดีเพราะมันรันทุกคำสั่งในสคริปต์ด้วย sudo เป็นการดีกว่าที่จะแยกคำสั่งไม่กี่คำที่ต้องการ sudo จริงๆและเพิ่มคำสั่งที่จำเป็น อย่ารวมการประเมินฟังก์ชั่นในการเรียก sudo เหล่านี้ ควรมีความชัดเจนและน้อยที่สุดเท่าที่จะทำได้
Douglas Held

@DouglasHeld แม้ว่าฉันจะเห็นด้วยกับสิ่งนี้คำถามก็คือ: "ฉันจะ" ฝัง "คำขอไปยัง pkexec หรือ sudo เพื่อเรียกใช้สคริปต์ทั้งหมดด้วยสิทธิ์ root ได้อย่างไร? ค่อนข้างแน่ใจว่าจะมีกรณีการใช้งานที่สามารถทำสิ่งนี้ได้จะเป็นประโยชน์
kos

6

ฉันนำหน้าคำสั่งภายในสคริปต์ที่ต้องการการเข้าถึงรูทด้วยsudo- หากผู้ใช้ยังไม่ได้รับการอนุญาตสคริปต์จะถามรหัสผ่าน ณ จุดนั้น

ตัวอย่าง

#!/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

สคริปต์นี้ก็จะสามารถทำงานเป็นหรือเป็นsudo <scriptname> <scriptname>ในทั้งสองกรณีมันจะถามรหัสผ่านเพียงครั้งเดียว


2
ปัญหาที่นี่คืออาจมีหลายคำสั่งที่จำเป็นต้องเข้าถึงรูตซึ่งหมายถึงการเรียกsudoใช้คำสั่งที่แตกต่างกัน 25 คำสั่งซ้ำซ้อน - เรียก sudo ได้ง่ายขึ้นครั้งเดียว อย่างไรก็ตามที่นี่เหตุผลที่สคริปของคุณเรียกใช้ sudo เพียงครั้งเดียวก็คือเพราะ sudo มีเวลาหมด 15 นาที - คำสั่งที่ใช้เวลานานกว่านั้นจะต้องได้รับการปรับปรุงใหม่ วิธีการทำงานของคุณเพียงแค่ . . ไม่ใช่วิธีที่ฉันต้องการให้มันใช้งานได้
Sergiy Kolodyazhnyy

@Serg สำหรับสคริปต์ขนาดเล็กวิธีที่ฉันใช้ง่ายและรวดเร็ว - ฉันไม่ใช่โปรแกรมเมอร์ที่สง่างามจริงๆ!
ชาร์ลส์กรีน

คุณเป็นโปรแกรมเมอร์ที่เก่งที่สุดในหน้านี้ คุณใช้ sudo อย่างที่ควรจะเป็น - เฉพาะในกรณีที่จำเป็นและคาดหวังผลลัพธ์ที่ชัดเจนมาก
Douglas Held

4

ดูเหมือนว่าไม่มีใครสนใจความกังวลที่เห็นได้ชัดที่นี่ วางsudoอยู่ภายในสคริปต์ของคุณที่คุณแล้วแจกจ่ายส่งเสริมพฤติกรรมของผู้ใช้ที่ไม่ดี (ฉันสมมติว่าคุณเผยแพร่เพราะคุณพูดถึง "จากมุมมองของผู้ใช้")

ความจริงก็คือมีแนวทางในการใช้แอปพลิเคชันและสคริปต์ที่คล้ายกับหลักการความปลอดภัยในการธนาคารของ: อย่าให้ข้อมูลส่วนบุคคลของคุณกับคนที่โทรหาคุณและบอกว่าพวกเขากำลังเรียก "จากธนาคารของคุณ"และที่มีอยู่ ด้วยเหตุผลที่คล้ายกัน

กฎสำหรับแอปพลิเคชันคือ:

อย่าพิมพ์รหัสผ่านของคุณเมื่อได้รับแจ้งเว้นแต่คุณจะแน่ใจในสิ่งที่กำลังทำอยู่ สิ่งนี้ใช้ได้กับทุกคนที่sudoเข้าถึง

หากคุณพิมพ์รหัสผ่านของคุณเพราะคุณทำงานsudoในบรรทัดคำสั่งที่ดี หากคุณพิมพ์เพราะคุณใช้คำสั่ง SSH ได้ หากคุณพิมพ์ลงไปเมื่อคุณลงชื่อเข้าใช้ในคอมพิวเตอร์

หากคุณเพียงแค่เรียกใช้สคริปต์ต่างประเทศหรือเรียกใช้งานได้และป้อนรหัสผ่านของคุณเมื่อได้รับแจ้งคุณก็ไม่รู้ว่าสคริปต์กำลังทำอะไรอยู่ มันอาจจะเก็บไว้ในไฟล์ temp ในเท็กซ์สำหรับทุกสิ่งที่คุณรู้และอาจล้มเหลวในการทำความสะอาดหลังจากนั้น

เห็นได้ชัดว่ามีความกังวลแยกต่างหากและเพิ่มเติมเกี่ยวกับการทำงานที่ไม่รู้จักชุดของคำสั่งที่เป็นrootแต่สิ่งที่ผมพูดถึงนี่คือการรักษาความปลอดภัยในการใช้รหัสผ่านของตัวเอง แม้ว่าสมมติว่าแอปพลิเคชัน / สคริปต์ไม่เป็นอันตรายคุณยังต้องการให้จัดการรหัสผ่านของคุณอย่างปลอดภัยเพื่อป้องกันไม่ให้แอปพลิเคชันอื่น ๆระงับการใช้งานและใช้งานโดยประสงค์ร้าย

ดังนั้นการตอบสนองส่วนตัวของฉันต่อสิ่งนี้คือสิ่งที่ดีที่สุดที่จะใส่ไว้ในสคริปต์ของคุณหากต้องการสิทธิพิเศษคือ:

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

# do privileged stuff, etc.

ในขณะที่ฉันเห็นด้วยกับคุณอย่างสมบูรณ์ผู้ใช้ที่ทำงานบางอย่างโดยไม่ทราบว่ามันทำอะไรได้บ้างก็sudo script_nameมีจุดอ่อนเหมือนกัน บางทีความคิดนี้อาจส่งเสริมนิสัยที่ไม่ดี - ฉันจะไม่พูดอะไรเกี่ยวกับเรื่องนั้น แต่ที่สำคัญคือรู้ว่าโปรแกรมทำอะไรและนั่นคือความรับผิดชอบของผู้ใช้ นั่นเป็นความคิดทั้งหมดที่อยู่เบื้องหลังซอฟต์แวร์โอเพ่นซอร์ส สำหรับสคริปต์ของฉันเอง . . สคริปต์เป็นข้อความธรรมดา - ผู้ใช้สามารถอ่านได้หากพวกเขาต้องการทราบว่ามันทำอะไร
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy มันคล้ายกัน แต่ถ้าคุณพิมพ์รหัสผ่านของคุณลงในสคริปต์โดยตรงมันยิ่งแย่ลง สคริปต์ทำงานด้วย sudo ยังไม่ทราบรหัสผ่านของคุณ
Wildcard

1

ฉันทำอย่างนี้:

echo -n "Enter password for sudo rights: "
read -s pass

echo $pass | sudo -S [your command here]

4
อย่างน้อยก็อ้างตัวแปรของคุณ
muru

และการอ้างอิงตัวแปรของคุณอาจไม่ช่วยถ้ารหัสผ่านของคุณเริ่มต้นด้วยเครื่องหมายขีดคั่น
Wildcard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.