โปรแกรมสามารถบอกได้หรือไม่ว่ากำลังทำงานภายใต้ sudo


27

ฉันมีโปรแกรมที่ควรทำงานต่างออกไปหากกำลังทำงานภายใต้ "sudo" มีวิธีที่จะดูว่ามันทำงานภายใต้ sudo หรือไม่?

อัปเดต: มีคนถามว่าทำไมฉันถึงต้องการทำเช่นนี้ ในกรณีนี้บน Mac ที่ใช้ MacPort มีเอาต์พุตที่บอกให้คุณตัดและวางคำสั่งเฉพาะ หากคำสั่ง MacPorts รันด้วย "sudo" คำสั่งนั้นควรรวม sudo ไว้ในคำสั่งตัวอย่าง:

$ sudo port selfupdate 
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.2.1 installed,
MacPorts base version 2.2.1 downloaded.
--->  Updating the ports tree
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

^^^^^^^^^ it would be really sweet if it output "sudo port upgrade outdated" instead.  It would be even better if it just did it for you :-)

ฉันอยากรู้: คุณสามารถอธิบายได้อย่างไรว่ามันควรมีพฤติกรรมแตกต่างกันอย่างไร
sciurus

1
@sciurus โดยทั่วไปแล้ว use-case จะอยู่ในสคริปต์การติดตั้งที่ต้องการสิทธิ์พิเศษ หากคุณไม่ได้มีพวกเขาเพียงแค่ตายทันที
Nick T

3
เสียงเหมือนmeta.stackexchange.com/questions/66377/what-is-the-xy-problem/... คุณคืออะไรจริงๆต้องการจะทำอย่างไร
เจนนี่ D พูดว่า Reinstate Monica

ฉันจำคำสั่งบางอย่างที่คลุมเครือโดยไม่รู้ตัวว่ามันทำงานเหมือนรูทหรือไม่ ... ฉันคิดว่าคำตอบคือ "ใช่"
Rolf

คำตอบ:


48

ใช่มีตัวแปรสภาพแวดล้อม 4 ชุดเมื่อโปรแกรมทำงานภายใต้ sudo:

$ sudo env |grep SUDO
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tal
SUDO_UID=501
SUDO_GID=20

โปรดทราบว่าสิ่งเหล่านี้สามารถปลอมได้โดยเพียงแค่ตั้งค่า อย่าไว้ใจพวกเขาในสิ่งที่สำคัญ

ตัวอย่างเช่น: ในโปรแกรมนี้เราต้องบอกผู้ใช้ให้เรียกใช้โปรแกรมอื่น หากหนึ่งปัจจุบันทำงานด้วย sudo อีกคนหนึ่งจะเกินไป

#!/bin/bash

echo 'Thank you for running me.'

if [[ $(id -u) == 0 ]]; then
  if [[ -z "$SUDO_COMMAND" ]]; then
    echo 'Please now run: next_command'
  else
    echo 'Please now run: sudo next_command'
  fi
else  echo 'Error: Sadly you need to run me as root.'
  exit 1
fi

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


2
ฉันจะใช้สำหรับ "สิ่งใดที่สำคัญ"
Kevin - Reinstate Monica

3
@ เควินหากใครบางคนยึดติดกับสภาพแวดล้อมของพวกเขาเพื่อปลอมเป็นสิทธิ์ระดับสูงแล้วพวกเขาหวังว่าจะรู้ว่าพวกเขากำลังทำอะไรและจะยอมรับผลที่ตามมา
Nick T

Downvoted เพราะคำตอบใด ๆ ที่ต้องผ่านการรับรองโดย "ไม่ไว้ใจพวกเขาสำหรับสิ่งที่สำคัญ" ไม่ใช่คำตอบเลย แต่เป็นการแฮ็คที่น่าเกลียด
สตีเฟ่นซี

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

11

นี่ไม่ได้ตอบคำถามโดยตรง แต่ฉันไม่คิดว่าคำถามที่ถูกถามจะถูกถามที่นี่ ดูเหมือนว่าผู้ถามต้องการโปรแกรมที่จะทำหน้าที่แตกต่างกันอย่างน่าเชื่อว่าถ้ามีสิทธิ์บางอย่างหรือไม่ แต่ฉันจะยืนยันการตรวจสอบ sudo ไม่ใช่วิธีที่จะทำเช่นนั้น ประการแรกระบบจำนวนมากอาจไม่ใช้ "sudo" มันไม่จำเป็นต้องใช้บน Linux หรือ Unixes จำนวนมาก

ตัวอย่างเช่นผู้ใช้อาจเข้าสู่ระบบในฐานะ root แล้วทำให้ sudo ไร้ความหมายหรืออาจเป็นระบบที่มีผู้ใช้ที่ไม่ใช่รูทที่ยังคงมีความสามารถในการดำเนินงานดูแลระบบที่โปรแกรมอาจต้องการทำ ในที่สุดระบบอาจไม่มีรูทหรือ sudo เลยและใช้ระบบควบคุมการเข้าถึงที่จำเป็นซึ่งมีความสามารถแตกต่างกันและไม่มีการใช้ superuser ทั้งหมดในการ sudo หรือผู้ใช้อาจถูก sudoed แต่เข้าสู่บัญชีที่ไม่มีสิทธิ์มากกว่าบัญชีของตนเองเพื่อความปลอดภัย (ฉันมักจะเรียกใช้รหัสที่ไม่น่าเชื่อถือกับผู้ใช้ที่ไม่มีสิทธิ์ชั่วคราวที่สามารถเขียนลง ramdisks ได้เท่านั้นไม่สามารถเพิ่มสิทธิ์ของฉันได้ ) โดยรวมแล้วเป็นความคิดที่ไม่ดีที่จะสมมติว่ารูปแบบการอนุญาตเฉพาะเช่น sudo หรือการมีอยู่ของ root หรือสมมติว่าผู้ใช้ sudoed มีสิทธิ์พิเศษใด ๆ

หากคุณต้องการทราบว่าคุณมีสิทธิ์ในการดำเนินการตามปกติวิธีที่ดีที่สุดคือการลองและทำมันจากนั้นตรวจสอบ errno สำหรับปัญหาการอนุญาตหากล้มเหลวหรือหากเป็นการดำเนินการหลายขั้นตอนที่ต้องล้มเหลวทั้งหมดหรือประสบความสำเร็จทั้งหมด คุณสามารถตรวจสอบว่าการทำงานจะทำงานกับฟังก์ชั่นเช่นฟังก์ชั่นการเข้าถึง POSIX หรือไม่ (โปรดระวังสภาวะการแข่งขันที่เป็นไปได้ที่นี่หากสิทธิ์มีการเปลี่ยนแปลงอย่างแข็งขัน)

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

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


7

มีสองกลไกที่สามารถใช้ได้

  • การตรวจสอบตัวแปรสภาพแวดล้อมสามารถปลอมได้ด้วยวิธีใดวิธีหนึ่ง แต่เป็นวิธีที่ง่ายที่สุด growisofsไม่ชอบทำงานภายใต้ SUDO ดังนั้นฉันจึงยกเลิกการตั้งค่าตัวแปร SUDO ในสคริปต์ที่ฉันใช้ มันสามารถแกล้งวิธีอื่น (ตัวแปร SUDO จะถูกนำไปยังสภาพแวดล้อมสำหรับสคริปต์ที่ทำงานภายใต้คำสั่ง at และ batch)
  • อีกวิธีในการดูว่าคุณกำลังทำงานภายใต้ sudo หรือไม่คือการเดินรายการกระบวนการจากกระบวนการหลักของคุณเพื่อค้นหา sudo มันคงเป็นการยากที่จะซ่อนตัวว่าคุณกำลังวิ่งอยู่ภายใต้ sudo ด้วยวิธีนี้ แต่มีความซับซ้อนมากขึ้น ยังคงเป็นไปได้ที่จะปลอมว่าคุณกำลังทำงานภายใต้ sudo

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


1
> เป็นการยากที่จะซ่อนว่าคุณทำงานภายใต้ sudo ด้วยวิธีนี้คุณไม่สามารถเปลี่ยนชื่อsudoไบนารีเป็นอย่างอื่นได้หรือไม่? หรือชื่อคนอื่นปฏิบัติการsudoเพื่อปลอมตรงข้าม? ไม่ว่าผมคาดหวังว่าทุกคนมีเหตุผลที่จะทำ ...
บ๊อบ

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

คุณก็สามารถดาวน์โหลดไบนารี sudo จากที่ไหนสักแห่งและให้สิทธิ์ ...
Jens Timmerman

@JensTimmerman คุณต้องมีสิทธิ์รูทเพื่อให้ได้สิทธิ์ที่ถูกต้อง หากคุณสามารถเปลี่ยนชื่อหรือฮาร์ดลิงก์ได้ ไม่จำเป็นต้องดาวน์โหลด หากคุณติดตั้ง SUID ให้กับ ID ผู้ใช้เป้าหมาย (หากจะใช้งานได้) คุณต้องประนีประนอมรหัสผู้ใช้เป้าหมายแล้ว
BillThor

อาขวาก็ปฏิเสธที่จะทำงานได้โดยไม่ต้อง setuid ไม่ดีของฉัน ...
Jens Timmerman

2

คุณสามารถเปรียบเทียบประสิทธิภาพกับ ID ผู้ใช้จริง

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


2
ไม่sudoตั้งค่ารหัสที่มีประสิทธิภาพและแท้จริง ซึ่งตรงข้ามกับ suid ซึ่งไม่ได้ นี่คือโปรแกรม C เล็กน้อยที่คุณสามารถใช้ในการทดสอบ (ขออภัยความคิดเห็นจะลบบรรทัดใหม่คุณจะต้องเพิ่มพวกเขากลับ):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
Derobert

... หรือมิฉะนั้นperl -E 'say $<, "\n", $>'
derobert

2

คุณสามารถตรวจสอบตัวแปร UID ที่มีประสิทธิภาพ (EUID) ได้ดังนี้:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi

นี่ไม่ได้ตอบคำถาม โค้ดจะให้เอาต์พุตเดียวกันเมื่อรันเป็น root เช่นเดียวกับเมื่อรันเป็น sudo
สตีเฟนซี

@StephenC - ฉันคิดว่าสำหรับวัตถุประสงค์ของ OP ไม่มีความแตกต่าง IMHO เป้าหมายของพวกเขาคือการระบุการดำเนินการ sudo หรือการดำเนินการจากเชลล์รูทของแท้โดยไม่มีความแตกต่าง
Eliran Malka

1
ฉันคิดว่าคุณอาจพูดถูก ฉันมาที่นี่เพราะฉันไม่เข้าใจว่าทำไมsudo echo $USERพิมพ์ชื่อผู้ใช้ที่ไม่มีสิทธิพิเศษ (ตัวแปรถูกแทนที่ก่อน sudo) จริงๆแล้วฉันใช้รหัสของคุณในสคริปต์ ขอขอบคุณ!
สตีเฟนซี

ส่วนใหญ่ยินดีต้อนรับ :)
Eliran มาลกา

-1

คุณสามารถสัมผัสไฟล์ใน/rootแล้วif -eมัน และหาก -e เป็นจริงrm(ตรวจสอบรหัสข้อผิดพลาด) เพื่อให้การทดสอบของคุณใช้งานได้ในครั้งต่อไป

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


4
คำตอบนี้ตรวจสอบว่ากระบวนการได้รับอนุญาตให้เขียน/root(ซึ่งไม่จำเป็นต้องเหมือนกับการใช้งานเป็น UID 0) แต่ไม่ได้ตรวจสอบว่าได้รับสิทธิ์เหล่านั้นโดยใช้sudoหรือไม่
Ladadadada

ใช่ "วิธีพันผิวแมว"; ขณะที่ฉันเขียนคำตอบฉันคิดถึงสิ่งอื่น 4 หรือ 5 อย่างดังนั้นฉันจึงสรุป
Chris K

-2

ฉันพบว่ามันใช้งานได้ดีสำหรับสิ่งนี้

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]

สิ่งนี้ไม่ทำงานเมื่อฉันลองใช้ FreeBSD, Centos7 หรือ MacOS X ฉันคิดว่าคุณหมายถึง "/ proc" แทนที่จะเป็น "/ etc" แต่ถึงแม้จะมีการเปลี่ยนแปลง แต่ก็ไม่ได้ผลกับทั้งสามอย่างนี้ "$ USER" ถูกรีเซ็ตโดย sudo คุณหมายถึง $ SUDO_USER หรือเปล่า นอกจากนี้คุณหมายถึง "[[" แทน "["?
TomOnTime

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