Bagaimana cara meneruskan variabel dengan aman ke skrip yang diaktifkan root?


13

Pertanyaan ini benar-benar umum dan tidak hanya berlaku untuk situasi saya, tetapi ... Saya memiliki alat busybox kecil di mana saya ingin pengguna non-root dapat mengeksekusi skrip tertentu dengan hak akses root. Sebagai contoh, sesuatu seperti skrip kecil ini untuk mengaktifkan DHCP, di mana satu-satunya variabel ( $1) untuk dikirim pada cmdline (!!) adalah nama host yang akan dikirim:

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

menjalankan udhcpc seperti ini membutuhkan akses root, jadi untuk melakukan ini saya berencana memodifikasi /etc/sudoersuntuk mengandung baris ini:

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

yang seharusnya mengaktifkan "joe" untuk dengan mudah menjalankan skrip itu dengan hak akses root dengan hanya menjalankan:

sudo /path/to/enable_dhcp.sh

dan tidak dimintai kata sandi (yang saya inginkan, karena saya ingin joe dapat menulis skrip ini).

Sekarang .. Saya tahu (atau setidaknya berpikir saya lakukan) bahwa menggunakan $1dalam skrip yang dapat dengan mudah dijalankan dengan hak akses root adalah ide HORRIBLE karena Anda dapat menyuntikkan apa pun yang Anda inginkan ke dalamnya.

Jadi ... apa cara terbaik untuk menghadapi ini? Bagaimana saya membiarkan joe melakukan apa yang saya inginkan dengan hak akses root, mengizinkannya untuk memasukkan variabel (atau secara efektif melakukannya dengan variabel lingkungan), sementara tidak terbuka lebar untuk serangan injeksi?

Jawaban:


14

Menjalankan skrip shell di bawah sudoaman asalkan sudodikonfigurasi untuk mengatur ulang lingkungan . Sebaliknya, jika sudotidak mengatur ulang lingkungan, menjalankan skrip shell tidak aman, bahkan jika skrip Anda tidak menggunakan parameternya (lihat Izinkan setuid pada skrip shell ). Pastikan bahwa Anda memiliki Defaults env_resetdi /etc/sudoersatau bahwa pilihan ini adalah kompilasi-waktu default ( sudo sudo -V | grep envharus mencakup Reset the environment to a default set of variables).

Tidak ada bahaya khusus dalam menggunakan parameter skrip. $1adalah string, yang perlu Anda pastikan adalah bahwa Anda menggunakannya sebagai string. (Misalnya, jangan lakukan eval "$1".) Jelas, ini sangat penting di sini untuk tidak membuat asumsi tentang isi variabel, dan untuk menempatkan tanda kutip ganda di sekitar semua penggantian variabel (yaitu menulis "$1", tidak $1). Perhatikan bahwa menempatkan tanda kutip ganda di sekitar substitusi variabel tidak khusus untuk skrip yang berjalan dengan hak istimewa, itu adalah sesuatu yang harus Anda lakukan sepanjang waktu.

Anda mungkin ingin memvalidasi parameter lebih lanjut, tergantung pada apa yang udhcpcterjadi dengan sesuatu yang tidak terlihat seperti nama host. Misalnya, ini akan melakukan pemeriksaan sintaksis pertama:

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

Hal-hal lain untuk dipertimbangkan yang mungkin berdampak pada perilaku perintah itu: direktori kerja saat ini, dan apa stdin, stdout, stderr point to, penangan sinyal dan ulimits. Misalnya, dengan mengizinkan dump inti (setelah <kbd> Ctrl- \ </kbd>), Anda dapat mengizinkan pengguna untuk membuang sampah / menjalankan / mengunci yang pada sistem saya adalah tmpfs dengan ukuran yang sangat terbatas dan dapat memungkinkan DoS.
Stéphane Chazelas

5

Anda harus mencocokkan input yang lulus dengan pola yang dikenal baik.

Misalnya, sepertinya alamat IP mungkin merupakan input yang valid untuk Anda. Jadi Anda bisa menggunakan sesuatu seperti ini:

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

Catatan, bahwa regexp belum diuji, Anda bertanggung jawab untuk memastikan regexp Anda tidak mengizinkan sesuatu yang berbahaya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.