GNU/Linux >> Belajar Linux >  >> Linux

Izinkan Setuid Pada Skrip Shell?

setuid izin bit memberitahu Linux untuk menjalankan program dengan id pengguna yang efektif dari pemilik bukan pelaksana:

> 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

Namun, ini hanya berlaku untuk file yang dapat dieksekusi; skrip shell mengabaikan bit 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 mengatakan:

Karena kemungkinan peningkatan kelemahan keamanan, banyak sistem operasi mengabaikan atribut setuid saat diterapkan ke skrip shell yang dapat dieksekusi.

Dengan asumsi saya bersedia menerima risiko tersebut, apakah ada cara untuk memberi tahu Linux agar memperlakukan bit setuid sama pada skrip shell seperti halnya pada executable?

Jika tidak, apakah ada solusi umum untuk masalah ini? Solusi saya saat ini adalah menambahkan sudoers entri untuk mengizinkan ALL untuk menjalankan skrip yang diberikan sebagai pengguna yang saya inginkan, dengan NOPASSWD untuk menghindari permintaan kata sandi. Kelemahan utama dari itu adalah kebutuhan akan sudoers entri setiap kali saya ingin melakukan ini, dan kebutuhan penelepon untuk sudo some-script alih-alih hanya some-script

Jawaban yang Diterima:

Linux mengabaikan bit setuid¹ pada semua executable yang ditafsirkan (yaitu executable yang dimulai dengan #! garis). FAQ comp.unix.questions menjelaskan masalah keamanan dengan skrip shell setuid. Masalah ini ada dua jenis:terkait shebang dan terkait shell; Saya akan membahas lebih detail di bawah ini.

Jika Anda tidak peduli dengan keamanan dan ingin mengizinkan skrip setuid, di Linux, Anda harus menambal kernel. Pada kernel 3.x, saya pikir Anda perlu menambahkan panggilan ke install_exec_creds di load_script fungsi, sebelum panggilan ke open_exec , tapi saya belum mengujinya.

Shebang mantap

Ada kondisi balapan yang melekat pada cara Shebang (#! ) biasanya diterapkan:

  1. Kernel membuka executable, dan menemukan bahwa itu dimulai dengan #! .
  2. Kernel menutup executable dan membuka interpreter sebagai gantinya.
  3. Kernel menyisipkan jalur ke skrip ke daftar argumen (sebagai argv[1] ), dan mengeksekusi penerjemah.

Jika skrip setuid diizinkan dengan implementasi ini, penyerang dapat memanggil skrip arbitrer dengan membuat tautan simbolis ke skrip setuid yang ada, mengeksekusinya, dan mengatur untuk mengubah tautan setelah kernel melakukan langkah 1 dan sebelum penerjemah melakukan membuka argumen pertamanya. Karena alasan ini, kebanyakan unice mengabaikan bit setuid saat mereka mendeteksi shebang.

Salah satu cara untuk mengamankan implementasi ini adalah dengan kernel untuk mengunci file skrip sampai penerjemah membukanya (perhatikan bahwa ini harus mencegah tidak hanya memutuskan tautan atau menimpa file, tetapi juga mengganti nama direktori mana pun di jalur). Tetapi sistem unix cenderung menghindari kunci wajib, dan tautan simbolis akan membuat fitur kunci yang benar menjadi sulit dan invasif. Saya rasa tidak ada orang yang melakukannya dengan cara ini.

Beberapa sistem unix (terutama OpenBSD, NetBSD, dan Mac OS X, yang semuanya memerlukan pengaturan kernel untuk diaktifkan) menerapkan secure setuid shebang menggunakan fitur tambahan:jalur /dev/fd/N mengacu pada file yang sudah dibuka pada deskriptor file N (jadi buka /dev/fd/N kira-kira setara dengan dup(N) ). Banyak sistem unix (termasuk Linux) memiliki /dev/fd tetapi bukan skrip setuid.

  1. Kernel membuka executable, dan menemukan bahwa itu dimulai dengan #! . Katakanlah deskriptor file untuk yang dapat dieksekusi adalah 3.
  2. Kernel membuka interpreter.
  3. Kernel menyisipkan /dev/fd/3 daftar argumen (sebagai argv[1] ), dan mengeksekusi penerjemah.
Terkait:Apa saja parameter/variabel khusus shell (Bash)?

Halaman shebang Sven Mascheck memiliki banyak informasi tentang shebang di seluruh unices, termasuk dukungan setuid.

Penerjemah yang mantap

Anggaplah Anda telah berhasil membuat program Anda berjalan sebagai root, baik karena OS Anda mendukung setuid shebang atau karena Anda telah menggunakan pembungkus biner asli (seperti sudo ). Sudahkah Anda membuka lubang keamanan? Mungkin . Masalahnya di sini adalah tidak tentang program yang ditafsirkan vs dikompilasi. Masalahnya adalah apakah sistem runtime your Anda berperilaku aman jika dijalankan dengan hak istimewa.

  • Setiap executable biner asli yang terhubung secara dinamis dengan cara yang ditafsirkan oleh loader dinamis (mis. /lib/ld.so ), yang memuat pustaka dinamis yang diperlukan oleh program. Pada banyak uni, Anda dapat mengonfigurasi jalur pencarian untuk pustaka dinamis melalui lingkungan (LD_LIBRARY_PATH adalah nama umum untuk variabel lingkungan), dan bahkan memuat pustaka tambahan ke semua binari yang dieksekusi (LD_PRELOAD ). Invoker program dapat mengeksekusi kode arbitrer dalam konteks program tersebut dengan menempatkan libc.so yang dibuat khusus di $LD_LIBRARY_PATH (di antara taktik lainnya). Semua sistem waras mengabaikan LD_* variabel dalam setuid executable.

  • Dalam cangkang seperti sh, csh dan turunannya, variabel lingkungan secara otomatis menjadi parameter shell. Melalui parameter seperti PATH , IFS , dan banyak lagi, pemanggil skrip memiliki banyak peluang untuk mengeksekusi kode arbitrer dalam konteks skrip shell. Beberapa shell menyetel variabel ini ke default waras jika mereka mendeteksi bahwa skrip telah dipanggil dengan hak istimewa, tetapi saya tidak tahu bahwa ada implementasi tertentu yang akan saya percayai.

  • Sebagian besar lingkungan waktu proses (apakah asli, bytecode atau ditafsirkan) memiliki fitur serupa. Hanya sedikit yang mengambil tindakan pencegahan khusus dalam executable setuid, meskipun yang menjalankan kode asli sering kali tidak melakukan sesuatu yang lebih menarik daripada penautan dinamis (yang memang mengambil tindakan pencegahan).

  • Perl adalah pengecualian. Ini secara eksplisit mendukung skrip setuid dengan cara yang aman. Faktanya, skrip Anda dapat menjalankan setuid bahkan jika OS Anda mengabaikan bit setuid pada skrip. Ini karena Perl dikirimkan dengan pembantu root setuid yang melakukan pemeriksaan yang diperlukan dan memanggil kembali juru bahasa pada skrip yang diinginkan dengan hak istimewa yang diinginkan. Ini dijelaskan dalam manual perlsec. Dulu skrip perl setuid membutuhkan #!/usr/bin/suidperl -wT bukannya #!/usr/bin/perl -wT , tetapi pada kebanyakan sistem modern, #!/usr/bin/perl -wT sudah cukup.

Perhatikan bahwa menggunakan biner asli wrapper tidak melakukan apa pun untuk mencegah masalah ini . Bahkan, itu bisa membuat situasi lebih buruk , karena mungkin mencegah lingkungan waktu proses Anda mendeteksi bahwa ia dipanggil dengan hak istimewa dan mengabaikan kemampuan konfigurasi waktu prosesnya.

Pembungkus biner asli dapat membuat skrip shell aman jika pembungkus membersihkan lingkungan . Script harus berhati-hati untuk tidak membuat terlalu banyak asumsi (misalnya tentang direktori saat ini) tetapi ini berjalan. Anda dapat menggunakan sudo untuk ini asalkan sudah diatur untuk membersihkan lingkungan. Variabel daftar hitam rawan kesalahan, jadi selalu daftar putih. Dengan sudo, pastikan bahwa env_reset opsi diaktifkan, setenv . itu tidak aktif, dan env_file dan env_keep hanya berisi variabel yang tidak berbahaya.

Terkait:Bagaimana cara menghindari kutipan di shell?

TL,DR:

  • Shebang setuid tidak aman tetapi biasanya diabaikan.
  • Jika Anda menjalankan program dengan hak istimewa (baik melalui sudo atau setuid), tulis kode asli atau perl, atau mulai program dengan pembungkus yang membersihkan lingkungan (seperti sudo dengan env_reset pilihan).

Diskusi ini berlaku sama jika Anda mengganti "setgid" dengan "setuid"; keduanya diabaikan oleh kernel Linux pada skrip


Linux
  1. Jalankan Skrip Shell Melalui Situs Web?

  2. Parameter baris perintah dalam skrip shell

  3. Jalankan semua skrip shell di folder

  1. Ekstensi File Untuk Skrip Unix Shell?

  2. Berbagi Variabel di Beberapa Skrip Shell?

  3. Bagaimana Menguji Kepatuhan Posix Dari Skrip Shell?

  1. Array Asosiatif Dalam Skrip Shell?

  2. Memisahkan Perintah Panjang Dalam Skrip Shell?

  3. Cara menjalankan skrip Python dari shell