จะส่งตัวแปรไปยังสคริปต์ที่เปิดใช้งานรูทได้อย่างปลอดภัยได้อย่างไร


13

คำถามนี้เป็นคำถามทั่วไปและไม่เพียง แต่ใช้กับสถานการณ์ของฉันเท่านั้น แต่ ... ฉันมีเครื่องมือ busybox ขนาดเล็กที่ฉันต้องการให้ผู้ใช้ที่ไม่ใช่รูทสามารถรันสคริปต์เฉพาะกับสิทธิ์พิเศษของรูทได้ ตัวอย่างเช่นบางสิ่งบางอย่างเช่นสคริปต์ขนาดเล็กนี้เพื่อเปิดใช้งาน DHCP โดยที่ตัวแปรเดียว ( $1) เพื่อส่งเข้าสู่ cmdline (!!) คือชื่อโฮสต์ที่จะส่งออก:

#!/bin/bash
udhcpc -b -i eth0 -h $1

การเรียกใช้ udhcpc เช่นนี้ต้องใช้การเข้าถึงรูทดังนั้นฉันวางแผนที่/etc/sudoersจะแก้ไขเพื่อให้มีบรรทัดนี้:

joe ALL = NOPASSWD: /path/to/enable_dhcp.sh

ซึ่งควรเปิดใช้งาน "joe" เพื่อให้เรียกใช้สคริปต์นั้นได้อย่างง่ายดายด้วยสิทธิ์พิเศษของรูทเพียงแค่เรียกใช้:

sudo /path/to/enable_dhcp.sh

และไม่ถูกถามหารหัสผ่าน (ซึ่งเป็นสิ่งที่ฉันต้องการเนื่องจากฉันต้องการให้โจสามารถเขียนสคริปต์นี้ได้)

ตอนนี้ .. ฉันรู้แล้ว (หรืออย่างน้อยฉันก็คิดว่า) การใช้$1สคริปต์ที่สามารถรันได้อย่างง่ายดายด้วยสิทธิ์พิเศษของรูทเป็นแนวคิดที่น่ากลัวเพราะคุณสามารถฉีดสิ่งที่คุณต้องการได้

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

คำตอบ:


14

เล่นเชลล์สคริปต์ภายใต้sudoความปลอดภัยระบุว่าsudoการกำหนดค่าการตั้งค่าสภาพแวดล้อม ในทางกลับกันหากsudoไม่รีเซ็ตสภาพแวดล้อมการรันเชลล์สคริปต์ไม่ปลอดภัยแม้ว่าสคริปต์ของคุณจะไม่ใช้พารามิเตอร์ (ดูที่อนุญาตให้ setuid สำหรับเชลล์สคริปต์ ) ตรวจสอบให้แน่ใจว่าคุณมีDefaults env_resetใน/etc/sudoersหรือว่าตัวเลือกนี้เป็นค่าเริ่มต้นเวลารวบรวม ( sudo sudo -V | grep envควรมีReset the environment to a default set of variables)

ไม่มีอันตรายใด ๆ ในการใช้พารามิเตอร์สคริปต์ $1เป็นสตริงสิ่งที่คุณต้องแน่ใจก็คือคุณใช้มันเป็นสตริง (ตัวอย่างเช่นอย่าทำeval "$1") เห็นได้ชัดว่ามันสำคัญอย่างยิ่งที่นี่ที่จะไม่ตั้งสมมติฐานเกี่ยวกับเนื้อหาของตัวแปรและใส่เครื่องหมายคำพูดคู่รอบการแทนที่ตัวแปรทั้งหมด (เช่นเขียน"$1"ไม่ใช่$1) โปรดทราบว่าการใส่เครื่องหมายอัญประกาศล้อมรอบการแทนที่ตัวแปรนั้นไม่เฉพาะเจาะจงกับสคริปต์ที่รันด้วยสิทธิ์ แต่เป็นสิ่งที่คุณต้องทำตลอดเวลา

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

#!/bin/sh
case "$1" in
  *[!:-.0-9A-Za-z]*|-*) echo 1>&2 "Badly formed host name!"; exit 3;;
esac
udhcpc -b -i eth0 -h "$1"

สิ่งอื่น ๆ ที่ควรพิจารณาที่อาจมีผลกระทบต่อพฤติกรรมของคำสั่งนั้น: ไดเรกทอรีการทำงานปัจจุบันและสิ่งที่ stdin, stdout, stderr ชี้ไปที่ตัวจัดการสัญญาณและ ulimits ตัวอย่างเช่นโดยการอนุญาตให้ทิ้งแกน (บน <kbd> Ctrl- \ </kbd>) คุณสามารถอนุญาตให้ผู้ใช้ทำการทิ้งขยะ / เรียกใช้ / ล็อคซึ่งในระบบของฉันเป็น tmpfs ที่มีขนาด จำกัด มากและสามารถอนุญาตให้ DoS
Stéphane Chazelas

5

คุณควรจับคู่อินพุตที่ส่งผ่านกับรูปแบบที่ดีที่รู้จัก

ตัวอย่างเช่นดูเหมือนว่าที่อยู่ IP อาจเป็นอินพุตที่ถูกต้องสำหรับคุณ ดังนั้นคุณสามารถใช้สิ่งนี้:

if [[ "$1" =~ ^[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9]$ ]]
then
  udhcpc -b -i eth0 -h "$1"
else
  echo "Don't mess with me pork chop."
fi

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

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