ทำไม“ sudo su” ในเชลล์สคริปต์ไม่ทำงานส่วนที่เหลือของสคริปต์เป็นรูท


36

สคริปต์ตัวอย่างสามารถเป็นด้านล่าง:

#!/bin/bash
sudo su
ls /root

เมื่อใช้./test.shในฐานะผู้ใช้ปกติแทนที่จะเรียกใช้lsในฐานะผู้ใช้ขั้นสูงและออกจากระบบจะเปลี่ยนเป็นรูท และเมื่อฉันออกจากระบบจะดำเนินการls /rootในฐานะผู้ใช้ปกติ

ใครสามารถบอกฉันเกี่ยวกับกลไกเกี่ยวกับเรื่องนี้ได้บ้าง


13
sudo suทำให้ดวงตาของฉันเจ็บ
Gelraen

มันถูกใช้เพราะคนไม่รู้จัก sudo ดีพอและดังนั้นพวกเขาจึงต้องการวิธีการรัน su บนระบบที่รูตนั้นปลอดภัยด้วยรหัสผ่านที่เสียหายโดยเจตนา แต่ใช่ sudo "redundifies" การใช้ su
Johan

1
คุณใช้sudo -sไม่ได้เหรอ?
Joe Z.

@Johan ผมมักจะใช้sudo suเพราะผมใช้มากขึ้นในตัวเลือกของกว่าฉันของบรรดาsu sudoฉันรู้ว่าตัวเลือกของ sudo ดีพอ แต่ฉันสามารถพิมพ์ su ได้เร็วขึ้น แต่ใช่ฉันเดาว่านั่นแปลว่าฉันไม่รู้จัก sudo ดีพอ
user606723

1
ฉันเพิ่งตรวจสอบหน้าคน sudo แต่ดูเหมือนว่ามันsudo -iจะคล้ายกับsu -ในขณะที่sudo -sดำเนินการเช่นsu(ไม่มีขีด)
โจฮาน

คำตอบ:


49

คำสั่งในสคริปต์ดำเนินการหนึ่งต่อหนึ่งโดยอิสระ สคริปต์เองเป็นพาเรนต์ของคำสั่งทั้งหมดในสคริปต์เป็นกระบวนการอิสระอื่นและคำสั่ง su ไม่สามารถและไม่สามารถเปลี่ยนเป็นรูทได้: คำสั่ง su สร้างกระบวนการใหม่ด้วยสิทธิ์พิเศษของรูท

หลังจากคำสั่ง su เสร็จสิ้นกระบวนการหลักซึ่งยังคงทำงานในฐานะผู้ใช้เดียวกันจะดำเนินการกับสคริปต์ที่เหลือ

สิ่งที่คุณต้องการทำคือเขียนสคริปต์ตัวคลุม คำสั่งที่มีสิทธิใช้งานจะเข้าสู่สคริปต์หลักตัวอย่างเช่น~/main.sh

#!/bin/sh
ls /root

สคริปต์ตัวตัดคำเรียกสคริปต์หลักพร้อมสิทธิ์รูทเช่นนี้

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

เพื่อเปิดใช้งานกระบวนการนี้ให้คุณเรียกใช้ wrapper ซึ่งจะเปิดใช้งานสคริปต์หลักหลังจากเปลี่ยนผู้ใช้เป็นผู้ใช้รูท

เทคนิค wrapper นี้สามารถใช้เปลี่ยนสคริปต์เป็น wrapper ได้ โดยทั่วไปตรวจสอบเพื่อดูว่ามันทำงานเป็นรูทหรือไม่ถ้าไม่ใช้ "su" เพื่อเรียกใช้งานตัวเองอีกครั้ง

$ 0 เป็นวิธีที่สะดวกในการสร้างสคริปต์ที่อ้างถึงตัวมันเองและคำสั่ง whoami สามารถบอกเราได้ว่าเราเป็นใคร

ดังนั้นสคริปต์หลักที่มี wrapper ในตัวจึงกลายเป็น

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

หมายเหตุการใช้งานของ exec มันหมายถึง "แทนที่โปรแกรมนี้ด้วย" ซึ่งสิ้นสุดการดำเนินการอย่างมีประสิทธิภาพและเริ่มโปรแกรมใหม่ที่เปิดตัวโดย su ด้วยรูทเพื่อเรียกใช้จากด้านบน อินสแตนซ์การแทนที่คือ "รูท" ดังนั้นจึงไม่เรียกใช้ทางด้านขวาของ ||


1
fwiw ภาคผนวกมาถึงจุดนี้ หากฉันกำลังเขียนสคริปต์เช่นนั้นฉันก็จะทำคำสั่ง if ที่จุดเริ่มต้นที่ตรวจสอบ $ EUID และถ้ามันไม่ได้เป็นศูนย์ sudo ตัวเองและออกจากนั้นมิฉะนั้นดำเนินการต่อสคริปต์
Bratchley

ตกลงและฉันจะอัปเดตคำตอบเพื่ออธิบายสิ่งนี้
Johan

2
อาจจะค่อนข้างเก่า แต่ฉันรักเส้นทางที่แน่นอนสำหรับทุกคนที่ทำงานได้ดังนั้นบางคนไม่สามารถเปลี่ยนสคริปต์ ~ / main.sh เป็นสิ่งที่เลวร้ายได้ โจมตีส่วนหนึ่งของสคริปต์ USER
artifex

2
คุณอาจต้องการที่จะรับฟังข้อโต้แย้งที่ถูกส่งผ่านไปโดยรวมถึงการอ้างอิงถึง $ *
Bratchley

@JoelDavis ฉันมักจะวิ่งเข้าไปในกำแพงของ "จะเกิดอะไรขึ้นถ้ามีอักขระช่องว่างในการขัดแย้ง" ฉันไม่เคยพบทางออกที่น่าพอใจ เมื่อฉันเขียนสคริปต์ที่ใส่อาร์กิวเมนต์ของมันลงในไฟล์ temp หนึ่งอาร์กิวเมนต์ต่อบรรทัดจากนั้นเรียกสิ่งที่ต้องการและส่งผ่านไปยังสคริปต์สุดท้ายนั้นอาร์กิวเมนต์ของไฟล์ที่อ่านเพื่อหาข้อโต้แย้งเดิม
Johan

20

ใช้สคริปต์ต่อไปนี้

sudo su <<HERE
ls /root
HERE

รหัสระหว่างบล็อกที่นี่จะถูกเรียกใช้ในฐานะรูท


6
sudo suกำลังเรียกสองโปรแกรม ใช้sudo -s <<HEREDOCหรือsu user <<HEREDOC... จำกัด โง่ 5 นาที
Johan

6

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


ใช่ฉันรู้ว่าฉันสามารถทำได้lsแต่นี่เป็นเพียงตัวอย่าง ในความเป็นจริงฉันต้องทำสิ่งต่าง ๆ มากมายด้วยสิทธิ์ของรูท :-) ดังนั้นฉันชอบคำตอบของ @ Ankit
Hongxu Chen

1

เมื่อคุณยิงsudo suกระบวนการใหม่ที่มีประสิทธิภาพuserid (euid=EUID)ของผู้ใช้ super คดเคี้ยวด้วยเหตุนี้เรามีทุบตีใหม่ที่ใช้ในกระบวนการ id ที่แตกต่างกันที่เกี่ยวข้องกับขั้วเดียวกัน(pid=PID)(tname=TTY)

คำอธิบาย

สมมติว่าหลังจากการยิงps -A | grep bashคุณมี21460 pts/2 00:00:00 bashเอาต์พุต ตอนนี้เมื่อคุณรัน./test.shคำสั่งทั้งสองsudo suและls /rootจะได้รับการสปูPID 21460ล หลังจากการดำเนินการเมื่อคุณมีrootเป็นผู้ใช้ที่ใช้งานตีอีกครั้งคุณจะสังเกตเห็นทุบตีใหม่ที่ทำงานบนps -A | grep bash PID say, 21570การออกจากroot bashจะฆ่า bash ที่ถูกแยกใหม่แล้วกลับไปที่user's bashและดำเนินการคำสั่งสพูลls /rootก่อนปล่อยพร้อมต์


หากใช้ su หรือ sudo คือ "ถาวร" ใน bash (หรือที่อื่น ๆ ) มันจะสร้างปัญหามากกว่าที่มันจะแก้ไข คุณต้องทำอย่างน้อยที่สุดเท่าที่เป็นไปได้เพื่อความปลอดภัย ประเด็นหลักของการมี su และ sudo (นอกเหนือจากความปลอดภัย!) คือการทำให้คุณคิดอย่างรอบคอบเกี่ยวกับสิ่งที่ต้องการสิทธิพิเศษของรูท
Joe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.