อนุญาตให้ setuid บนเชลล์สคริปต์


184

setuidบิตได้รับอนุญาตบอกลินุกซ์ที่จะเรียกใช้โปรแกรมที่มีรหัสผู้ใช้ที่มีประสิทธิภาพของการใช้แทนการปฏิบัติการที่:

> cat setuid-test.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv) {
    printf("%d", geteuid());
    return 0;
}

> gcc -o setuid-test setuid-test.c
> ./setuid-test

1000

> sudo chown nobody ./setuid-test; sudo chmod +s ./setuid-test
> ./setuid-test

65534

อย่างไรก็ตามสิ่งนี้ใช้กับไฟล์ที่เรียกทำงานได้เท่านั้น เชลล์สคริปต์ละเว้นบิต setuid:

> cat setuid-test2

#!/bin/bash
id -u

> ./setuid-test2

1000

> sudo chown nobody ./setuid-test2; sudo chmod +s ./setuid-test2
> ./setuid-test2

1000

Wikipedia พูดว่า :

เนื่องจากความน่าจะเป็นที่เพิ่มขึ้นของข้อบกพร่องด้านความปลอดภัยระบบปฏิบัติการหลายระบบจึงเพิกเฉยต่อคุณลักษณะ setuid เมื่อนำไปใช้กับเชลล์สคริปต์ที่รันได้

สมมติว่าฉันยินดีที่จะยอมรับความเสี่ยงเหล่านั้นมีวิธีใดที่จะบอก Linux ให้จัดการ setuid bit เหมือนกันในเชลล์สคริปต์เช่นเดียวกับที่ใช้กับโปรแกรมปฏิบัติการหรือไม่?

ถ้าไม่มีวิธีแก้ปัญหาทั่วไปสำหรับปัญหานี้หรือไม่? โซลูชันปัจจุบันของฉันคือการเพิ่มsudoersรายการเพื่ออนุญาตให้ALLเรียกใช้สคริปต์ที่กำหนดในฐานะผู้ใช้ที่ฉันต้องการให้เรียกใช้ด้วยNOPASSWDเพื่อหลีกเลี่ยงการแจ้งรหัสผ่าน ข้อเสียเปรียบหลักที่จำเป็นสำหรับsudoersรายการทุกครั้งที่ฉันต้องการทำเช่นนี้และความต้องการให้ผู้โทรมาsudo some-scriptแทนที่เพียงแค่some-script

คำตอบ:


202

Linux จะเพิกเฉยต่อบิต setuid on ที่ executables ที่ถูกตีความทั้งหมด (เช่น executables ที่เริ่มต้นด้วย#!บรรทัด) comp.unix.questions คำถามที่พบบ่อยอธิบายปัญหาด้านความปลอดภัยที่มีเชลล์สคริปต์ setuid ปัญหาเหล่านี้มีสองประเภท: ที่เกี่ยวข้องกับ shebang และที่เกี่ยวข้องกับเชลล์ ฉันไปดูรายละเอียดเพิ่มเติมด้านล่าง

หากคุณไม่สนใจเกี่ยวกับความปลอดภัยและต้องการอนุญาตสคริปต์ setuid ใน Linux คุณจะต้องแก้ไขเคอร์เนล ในฐานะของเมล็ด 3.x ฉันคิดว่าคุณต้องเพิ่มการเรียกไปinstall_exec_credsยังload_scriptฟังก์ชันก่อนเรียกใช้open_execแต่ฉันยังไม่ได้ทดสอบ


ตั้งค่า shebang

มีสภาพการแข่งขันที่เป็นไปตามวิธีที่ shebang ( #!) ถูกนำไปใช้โดยทั่วไป:

  1. #!เคอร์เนลเปิดปฏิบัติการและพบว่ามันเริ่มต้นด้วย
  2. เคอร์เนลปิดการปฏิบัติการและเปิดล่ามแทน
  3. เคอร์เนลแทรกเส้นทางไปยังสคริปต์ไปยังรายการอาร์กิวเมนต์ (ตามargv[1]) และดำเนินการล่าม

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

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

ไม่กี่ระบบยูนิกซ์ (ส่วนใหญ่ OpenBSD, NetBSD และ Mac OS X ซึ่งทั้งหมดนี้จำเป็นต้องมีการตั้งค่าเคอร์เนลที่จะเปิดใช้งาน) ใช้shebang setuid ที่เชื่อถือได้โดยใช้คุณสมบัติเพิ่มเติม: เส้นทางหมายถึงไฟล์ที่เปิดอยู่แล้วในไฟล์อธิบายN (เพื่อเปิดเป็น เทียบเท่ากับ) ระบบยูนิกซ์หลายระบบ (รวมถึง Linux) มีแต่ไม่มีสคริปต์ setuid/dev/fd/N/dev/fd/Ndup(N)/dev/fd

  1. #!เคอร์เนลเปิดปฏิบัติการและพบว่ามันเริ่มต้นด้วย สมมุติว่าไฟล์ descriptor ของไฟล์สั่งการเป็น 3
  2. เคอร์เนลเปิดล่าม
  3. เคอร์เนลแทรก/dev/fd/3รายการอาร์กิวเมนต์ (ตามargv[1]) และดำเนินการล่าม

หน้า shebang Sven Mascheck ของมีจำนวนมากของข้อมูลเกี่ยวกับ shebang ทั่ว Unices รวมทั้งการสนับสนุน setuid


ล่าม Setuid

สมมติว่าคุณมีการจัดการเพื่อให้โปรแกรมของคุณทำงานเป็นรูทไม่ว่าจะเป็นเพราะระบบปฏิบัติการของคุณรองรับ setuid shebang หรือเพราะคุณใช้โปรแกรมแปลงไฟล์ไบนารีดั้งเดิม (เช่นsudo) คุณได้เปิดช่องรักษาความปลอดภัยหรือไม่? บางที ปัญหาที่นี่ไม่เกี่ยวกับการแปลโปรแกรมที่คอมไพล์แล้ว ปัญหาคือว่าระบบรันไทม์ของคุณทำงานอย่างปลอดภัยหรือไม่หากดำเนินการด้วยสิทธิ์พิเศษ

  • ปฏิบัติการไบนารีเนทีฟแบบไดนามิกใด ๆ ที่เชื่อมโยงแบบไดนามิกอยู่ในวิธีที่ตีความโดยตัวโหลดแบบไดนามิก (เช่น/lib/ld.so) ซึ่งโหลดไลบรารีแบบไดนามิกที่โปรแกรมต้องการ ในหลาย ๆ unices คุณสามารถกำหนดค่าพา ธ การค้นหาสำหรับไลบรารีแบบไดนามิกผ่านสภาพแวดล้อม ( LD_LIBRARY_PATHเป็นชื่อทั่วไปสำหรับตัวแปรสภาพแวดล้อม) และแม้แต่โหลดไลบรารีเพิ่มเติมลงในไบนารีที่ดำเนินการทั้งหมด ( LD_PRELOAD) ทรงของโปรแกรมสามารถรันโค้ดในบริบทของโปรแกรมนั้นโดยการวางเป็นพิเศษที่สร้างขึ้นlibc.soใน$LD_LIBRARY_PATH(ในหมู่กลยุทธ์อื่น ๆ ) ระบบมีสติทั้งหมดละเว้นLD_*ตัวแปรในไฟล์เรียกทำงาน setuid

  • ในเชลล์เช่น sh, csh และอนุพันธ์ตัวแปรสภาพแวดล้อมจะกลายเป็นพารามิเตอร์ของเชลล์โดยอัตโนมัติ ผ่านพารามิเตอร์เช่นPATH, IFSและอื่น ๆ อีกมากมายทรงของสคริปต์มีโอกาสมากมายที่จะรันโค้ดในบริบทเชลล์สคริปต์ของ เชลล์บางตัวตั้งค่าตัวแปรเหล่านี้ให้เป็นค่าเริ่มต้นที่มีเหตุผลหากตรวจพบว่าสคริปต์นั้นได้รับการเรียกใช้ด้วยสิทธิ์ แต่ฉันไม่รู้ว่ามีการใช้งานเฉพาะที่ฉันเชื่อถือ

  • สภาพแวดล้อมรันไทม์ส่วนใหญ่ (ไม่ว่าจะเป็น native, bytecode หรือตีความ) มีคุณสมบัติคล้ายกัน ไม่กี่ข้อควรระวังพิเศษใน setuid executables แม้ว่าคนที่เรียกใช้รหัสพื้นเมืองมักจะไม่ทำอะไรที่น่าสนใจกว่าการเชื่อมโยงแบบไดนามิก (ซึ่งจะใช้ความระมัดระวัง)

  • Perlเป็นข้อยกเว้นที่น่าสังเกต มันชัดเจนสนับสนุนสคริปต์ setuidในทางที่ปลอดภัย ในความเป็นจริงสคริปต์ของคุณสามารถเรียกใช้ setuid แม้ว่าระบบปฏิบัติการของคุณจะละเว้นบิต setuid ในสคริปต์ นี่เป็นเพราะ Perl มาพร้อมกับผู้ช่วยรูท setuid ที่ดำเนินการตรวจสอบที่จำเป็นและเรียกใช้ล่ามในสคริปต์ที่ต้องการด้วยสิทธิ์พิเศษที่ต้องการ นี่คือคำอธิบายในคู่มือperlsec มันเคยเป็นสคริปต์ Perl setuid ที่จำเป็น#!/usr/bin/suidperl -wTแทน#!/usr/bin/perl -wTแต่ในระบบที่ทันสมัยส่วนใหญ่#!/usr/bin/perl -wTก็เพียงพอแล้ว

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

native wrapper แบบไบนารีสามารถสร้างเชลล์สคริปต์ให้ปลอดภัยหาก wrapper สร้างสภาวะแวดล้อมที่เหมาะสม สคริปต์จะต้องระมัดระวังไม่ให้สมมติฐานมากเกินไป (เช่นเกี่ยวกับไดเรกทอรีปัจจุบัน) แต่สิ่งนี้จะเกิดขึ้น คุณสามารถใช้ sudo สำหรับสิ่งนี้หากว่ามันถูกตั้งค่าเพื่อฆ่าเชื้อในสภาพแวดล้อม ตัวแปรการขึ้นบัญชีดำนั้นเกิดข้อผิดพลาดได้ง่าย ด้วย sudo ตรวจสอบให้แน่ใจว่าenv_resetมีเปิดตัวเลือกที่setenvจะปิดและที่env_fileและenv_keepมีเพียงตัวแปรที่ไม่มีพิษมีภัย


TL, DR:

  • Setuid shebang ไม่ปลอดภัย แต่มักจะเพิกเฉย
  • หากคุณรันโปรแกรมที่มีสิทธิ์ใช้งาน (ไม่ว่าจะผ่าน sudo หรือ setuid) ให้เขียนโค้ดเนทีฟหรือ perl หรือเริ่มโปรแกรมด้วย wrapper ที่ฆ่าเชื้อสภาพแวดล้อม (เช่น sudo พร้อมenv_resetตัวเลือก)

¹ การสนทนานี้ใช้อย่างเท่าเทียมกันถ้าคุณแทน“setgid” สำหรับ“setuid”; ทั้งคู่ถูกละเว้นโดยเคอร์เนล Linux บนสคริปต์


2
@Josh: เชลล์สคริปต์ setuid ที่ปลอดภัยนั้นเป็นไปได้ แต่เฉพาะในกรณีที่ผู้ใช้เชลล์และผู้เขียนสคริปต์นั้นระมัดระวัง ฉันขอแนะนำ Perl ซึ่งผู้ใช้งานได้รับการดูแลว่าสคริปต์ setuid ควรปลอดภัยด้วยความพยายามเพียงเล็กน้อยในส่วนของผู้เขียนสคริปต์
Gilles

3
เห็นได้ชัดว่าsuidperlสิ่งที่ได้รับการคัดค้านและทำเครื่องหมายสำหรับการกำจัดมานานหลายปี (แต่ยังคงไม่น้อย)
jmtd

7
ที่จริงแล้วsuidperlถูกลบออกเป็นของ perl 5.11 (5.12 เสถียร): perl5110delta:> "suidperl" ถูกลบแล้ว มันใช้เพื่อให้กลไกในการเลียนแบบบิตสิทธิ์ setuid บนระบบที่ไม่สนับสนุนอย่างถูกต้อง perl5120delta:> "suidperl" ไม่ได้เป็นส่วนหนึ่งของ Perl อีกต่อไป มันใช้เพื่อให้กลไกในการเลียนแบบบิตสิทธิ์ setuid บนระบบที่ไม่สนับสนุนอย่างถูกต้อง
Randy Stauner

5
ให้สังเกตบรรทัดนี้จากเอกสาร Perl 5.6.1 (เกือบสิบปีที่แล้ว) ... perl561delta:> โปรดทราบว่า suidperl ไม่ได้ถูกสร้างหรือติดตั้งโดยปริยายใน perl รุ่นล่าสุด ใช้ suidperl เป็นกำลังใจอย่างมาก หากคุณคิดว่าคุณต้องการลองใช้ทางเลือกอื่นเช่น sudo ก่อน ดูcourtesan.com/sudo
Randy Stauner

3
ฉันไม่เข้าใจ: นี่เป็นคำอธิบายถึงสาเหตุของปัญหา แต่มีคำตอบที่แท้จริงสำหรับคำถามของ OP หรือไม่ มีวิธีบอก OS ให้รันเชลล์สคริปต์ setuid หรือไม่?
Tom

55

วิธีหนึ่งในการแก้ไขปัญหานี้คือการเรียกเชลล์สคริปต์จากโปรแกรมที่สามารถใช้ setuid บิต
มันเหมือนกับ sudo ตัวอย่างเช่นนี่คือวิธีที่คุณจะทำสิ่งนี้ให้สำเร็จในโปรแกรม C:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    setuid( 0 );   // you can set it at run time also
    system( "/home/pubuntu/setuid-test2.sh" );
    return 0;
 }

บันทึกเป็น setuid-test2.c
รวบรวม
ตอนนี้ทำ setuid ในโปรแกรมนี้ไบนารี:

su - nobody   
[enter password]  
chown nobody:nobody a.out  
chmod 4755 a.out  

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


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

39
โปรดทราบว่านี่ไม่ปลอดภัยแม้ว่าเส้นทางแบบเต็มไปยังสคริปต์จะถูกเข้ารหัส เชลล์จะรับช่วงตัวแปรจากสภาพแวดล้อมและหลาย ๆ ตัวอนุญาตให้ผู้เรียกใช้แทรกรหัสโดยพลการ PATHและLD_LIBRARY_PATHเป็นเวกเตอร์ที่ชัดเจน เปลือกหอยบางส่วนดำเนินการ$ENVหรือ$BASHENVหรือ~/.zshenvแม้กระทั่งก่อนที่จะเริ่มดำเนินการสคริปต์ที่เหมาะสมดังนั้นคุณจึงไม่สามารถปกป้องจากสิ่งเหล่านี้ที่ทุกคนจากภายในสคริปต์ เพียงวิธีที่ปลอดภัยเพื่อเรียกสคริปต์เปลือกที่มีสิทธิ์คือการทำความสะอาดสภาพแวดล้อม Sudo รู้วิธีการทำอย่างปลอดภัย ดังนั้นไม่ได้เขียนกระดาษห่อเองใช้ sudo
Gilles

28
ฉันรู้สึกแย่ที่เขาถูกลดระดับลงอย่างกระทันหัน - ฉันบอกว่าฉันต้องการฟังเวอร์ชันที่ไม่ปลอดภัยด้วยเช่นกันและฉันก็จินตนาการถึงไฟล์ปฏิบัติการที่ใช้อาร์กิวเมนต์ของสคริปต์เชลล์เมื่อฉันพูดถึงมัน เห็นได้ชัดว่ามันไม่ปลอดภัยอย่างหนาแน่น แต่ฉันอยากรู้ว่ามีความเป็นไปได้อะไรบ้าง
Michael Mrozek

8
@Gilles: FYI, Linux ไม่แน่ใจLD_LIBRARY_PATHในสิ่งอื่น ๆ เมื่อพบบิต setuid
grawity

3
แทนการใช้systemคุณอาจพบว่ามันง่าย (และมีประสิทธิภาพมากขึ้น) เพื่อใช้เป็นหนึ่งในexecครอบครัว - execveมีโอกาสมากที่สุด ด้วยวิธีนี้คุณไม่ได้สร้างกระบวนการใหม่หรือเริ่มเชลล์และคุณสามารถส่งต่อข้อโต้แย้ง (สมมติว่าสคริปต์ที่ได้รับการยกเว้นของคุณสามารถจัดการกับข้อโต้แย้งได้อย่างปลอดภัย)
Toby Speight

23

ฉันนำหน้าสคริปต์บางตัวที่อยู่ในเรือนี้:

#!/bin/sh
[ "root" != "$USER" ] && exec sudo $0 "$@"

โปรดทราบว่านี้ไม่ได้ใช้แต่เพียงรันไฟล์ปัจจุบันด้วยsetuidsudo


4
สิ่งนี้ไม่ได้ใช้ setuid แต่ให้คุณsudoพร้อมท์ (สำหรับฉันจุดทั้งหมดของ setuid คือการอนุญาตให้สิ่งต่าง ๆ ทำงานเป็นรูตโดยไม่จำเป็นต้องใช้ sudo)
Luc

12

หากคุณต้องการหลีกเลี่ยงการโทรsudo some_scriptคุณสามารถทำได้:

  #!/ust/bin/env sh

  sudo /usr/local/scripts/your_script

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

  • เชลล์เป็นซอฟต์แวร์ชิ้นใหญ่ที่โต้ตอบกับผู้ใช้อย่างหนัก แทบเป็นไปไม่ได้เลยที่จะตรวจสอบทุกอย่างอย่างมีสติ - โดยเฉพาะอย่างยิ่งเนื่องจากรหัสส่วนใหญ่ไม่ได้มีวัตถุประสงค์เพื่อให้ทำงานในโหมดดังกล่าว
  • สคริปท์เป็นคำตอบที่รวดเร็วและส่วนใหญ่มักจะไม่ได้รับการจัดเตรียมอย่างระมัดระวังเพื่อให้ setuid พวกเขามีคุณสมบัติที่อาจเป็นอันตรายมากมาย
  • พวกเขาพึ่งพาโปรแกรมอื่นมาก มีการตรวจสอบเชลล์ไม่เพียงพอ sed, awkฯลฯ จะต้องมีการตรวจสอบเช่นกัน

โปรดทราบว่าsudoมีการตรวจสอบสติ แต่ไม่เพียงพอ - ตรวจสอบทุกบรรทัดในรหัสของคุณเอง

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


2
ฉันเข้าใจที่ควรจะเป็น/ust/bin/env /usr/bin/env
บ๊อบ

4

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

แต่ถ้าคุณไม่รังเกียจความเสี่ยงด้านความปลอดภัยที่น่ากลัวให้ใช้ setuid shell เป็นล่ามสำหรับเชลล์สคริปต์ ไม่ทราบว่าจะใช้งานได้กับคุณหรือไม่ แต่ฉันคิดว่ามันน่าจะ

ให้ฉันบอกว่าฉันไม่แนะนำให้ทำเช่นนี้ ฉันแค่พูดถึงมันเพื่อวัตถุประสงค์ทางการศึกษา ;-)


5
มันจะทำงาน. อย่างที่คุณพูด บิต SETUID อนุญาตให้ดำเนินการกับเจ้าของสิทธิ์ เชลล์ Setuid (ยกเว้นว่ามันถูกออกแบบมาเพื่อทำงานกับ setuid) จะทำงานเป็นรูทสำหรับผู้ใช้ใด ๆ คือทุกคนสามารถเรียกใช้rm -rf /(และคำสั่งอื่น ๆ จากซีรีส์ไม่ได้อยู่ที่บ้าน )
Maciej Piechotka

9
@MaciejPiechotka โดยไม่ทำที่บ้านคุณหมายถึงคุณรู้สึกอิสระที่จะทำอย่างนั้นเหรอ? :)
peterph

4

คำสั่ง super [-r reqpath] [args]

Super อนุญาตให้ผู้ใช้ที่ระบุเรียกใช้สคริปต์ (หรือคำสั่งอื่น ๆ ) ราวกับว่าพวกเขาเป็นรูท; หรือสามารถตั้งค่ากลุ่ม uid, gid และ / หรือเสริมบนพื้นฐานต่อคำสั่งก่อนที่จะดำเนินการคำสั่ง มันมีไว้เพื่อเป็นทางเลือกที่ปลอดภัยในการสร้างสคริปต์ setuid Super ยังอนุญาตให้ผู้ใช้ทั่วไปสามารถส่งคำสั่งให้ดำเนินการโดยผู้อื่น สิ่งเหล่านี้รันด้วย uid, gid และกลุ่มของผู้ใช้ที่เสนอคำสั่ง

Super ให้คำปรึกษาไฟล์ `` super.tab '' เพื่อดูว่าผู้ใช้ได้รับอนุญาตให้ดำเนินการตามคำสั่งที่ร้องขอ หากได้รับอนุญาต super จะดำเนินการ pgm [args] โดยที่ pgm คือโปรแกรมที่เกี่ยวข้องกับคำสั่งนี้ (รูทได้รับอนุญาตให้ดำเนินการตามค่าเริ่มต้น แต่ยังสามารถถูกปฏิเสธได้หากกฎไม่รวมรูทผู้ใช้ทั่วไปจะไม่ได้รับอนุญาตให้ดำเนินการตามค่าเริ่มต้น)

หากคำสั่งเป็นลิงก์สัญลักษณ์ (หรือฮาร์ดลิงก์เช่นกัน) ไปยังโปรแกรมสุดแล้วพิมพ์คำสั่ง% args เทียบเท่ากับการพิมพ์% คำสั่ง args (คำสั่งต้องไม่เป็น super หรือซุปเปอร์จะไม่รับรู้ว่ามันถูกเรียกผ่าน การเชื่อมโยง.)

http://www.ucolick.org/~will/RUE/super/README

http://manpages.ubuntu.com/manpages/utopic/en/man1/super.1.html


สวัสดีและยินดีต้อนรับสู่เว็บไซต์! เราคาดว่าคำตอบจะมีรายละเอียดเพิ่มเติมที่นี่ คุณสามารถแก้ไขคำตอบของคุณและอธิบายว่าโปรแกรมนี้คืออะไรและจะช่วยแก้ปัญหา OP ได้อย่างไร
terdon

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

2

หากไม่มีเหตุผลบางอย่างsudoคุณสามารถเขียนสคริปต์ wrapper แบบบางใน C:

#include <unistd.h>
int main() {
    setuid(0);
    execle("/bin/bash","bash","/full/path/to/script",(char*) NULL,(char*) NULL);
}

และเมื่อคุณรวบรวมมันตั้งเป็นด้วยsetuidchmod 4511 wrapper_script

นี่คล้ายกับคำตอบที่โพสต์อื่น แต่เรียกใช้สคริปต์ด้วยสภาพแวดล้อมที่สะอาดและใช้อย่างชัดเจน/bin/bashแทนเชลล์ที่เรียกใช้โดยsystem()และปิดช่องโหว่ความปลอดภัยที่อาจเกิดขึ้น

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

เห็นได้ชัดว่าคุณต้องการให้แน่ใจว่าสคริปต์นั้นสามารถเขียนได้โดย root เท่านั้น


-3

ครั้งแรกที่ฉันพบคำถามนี้ไม่มั่นใจโดยคำตอบทั้งหมดที่นี่เป็นหนึ่งที่ดีกว่ามากซึ่งยังช่วยให้คุณทำให้งงงวยสคริปต์ทุบตีของคุณอย่างสมบูรณ์ถ้าคุณมีแนวโน้ม!

ควรอธิบายด้วยตนเอง

#include <string>
#include <unistd.h>

template <typename T, typename U>
T &replace (
          T &str, 
    const U &from, 
    const U &to)
{
    size_t pos;
    size_t offset = 0;
    const size_t increment = to.size();

    while ((pos = str.find(from, offset)) != T::npos)
    {
        str.replace(pos, from.size(), to);
        offset = pos + increment;
    }

    return str;
}

int main(int argc, char* argv[])
{
    // Set UUID to root
    setuid(0);

    std::string script = 
R"(#!/bin/bash
whoami
echo $1
)";

    // Escape single quotes.
    replace(script, std::string("'"), std::string("'\"'\"'"));

    std::string command;
    command = command + "bash -c '" + script + "'"; 

    // Append the command line arguments.
    for (int a = 0; a < argc; ++a)
    {
        command = command + " " + argv[a];
    }

    return system(command.c_str());
}

จากนั้นคุณเรียกใช้

g++ embedded.cpp -o embedded
sudo chown root embedded
sudo chmod u+s embedded

ทำไมต้องโหวต
Theodore R. Smith

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