The setuid
izin sedikit menceritakan Linux untuk menjalankan program dengan user id 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 executable; shell script 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 kata:
Karena meningkatnya kemungkinan kelemahan keamanan, banyak sistem operasi yang mengabaikan setuid atribut ketika diterapkan untuk eksekusi skrip shell.
Asumsi saya'm. bersedia untuk menerima risiko tersebut, apakah ada cara untuk memberitahu Linux untuk mengobati setuid bit yang sama pada shell script seperti halnya pada executable?
Jika tidak, apakah ada solusi umum untuk masalah ini? Solusi saya saat ini adalah untuk menambahkan sudoers
entri untuk memungkinkan SEMUA
untuk menjalankan suatu script sebagai pengguna saya ingin jalankan sebagai, dengan NOPASSWD
untuk menghindari prompt password. Utama kelemahan itu adalah kebutuhan untuk sudoers
entry setiap kali saya ingin melakukan hal ini, dan kebutuhan untuk penelepon untuk sudo beberapa-script
bukan hanya beberapa script
#!
line). The comp.unix.pertanyaan FAQ menjelaskan masalah keamanan dengan setuid shell script. Masalah-masalah ini ada dua macam: peristiwa-terkait dan shell-terkait; aku pergi ke rincian lebih lanjut di bawah ini.
Jika anda don't peduli tentang keamanan dan ingin memungkinkan setuid script, di bawah Linux, anda'll perlu patch kernel. Sebagai 3.x kernel, saya pikir anda perlu untuk menambahkan panggilan ke install_exec_creds
di load_script
fungsi, sebelum panggilan untuk open_exec
, tapi saya belum't diuji. Ada kondisi balapan yang melekat dengan cara shebang (#!
) biasanya dilaksanakan:
#!
. argv[1]
), dan mengeksekusi interpreter.
Jika setuid script diperbolehkan dengan implementasi ini, penyerang dapat memanggil sewenang-wenang script dengan menciptakan link simbolik yang ada setuid script, mengeksekusi, dan mengatur untuk mengubah link setelah kernel telah melakukan langkah 1 dan sebelum penerjemah mendapat sekitar untuk membuka argumen pertama. Untuk alasan ini, sebagian besar jenis unix mengabaikan bit setuid ketika mereka mendeteksi shebang.
Salah satu cara untuk mengamankan pelaksanaan ini akan untuk kernel untuk mengunci file script sampai penerjemah telah dibuka (perhatikan bahwa ini harus mencegah tidak hanya membatalkan tautan atau timpa file, tetapi juga bisa mengganti nama direktori di jalan). Tapi sistem unix cenderung menghindar dari wajib kunci, dan tautan simbolis akan membuat kunci yang benar fitur yang sangat sulit dan invasif. Saya don't pikir siapa pun yang melakukannya dengan cara ini.
Beberapa sistem unix (terutama OpenBSD, NetBSD dan Mac OS X, yang memerlukan pengaturan kernel harus diaktifkan) menerapkan aman setuid shebang menggunakan fitur tambahan: jalan /dev/fd/N
mengacu pada file yang sudah dibuka pada file descriptor N (jadi opening /dev/fd/N
kira-kira setara dengan dup(N)
). Banyak sistem unix (termasuk Linux) memiliki /dev/fd
tapi tidak setuid script. #!
. Let's mengatakan file descriptor untuk eksekusi adalah 3. /dev/fd/3
daftar argumen (sebagai argv[1]
), dan mengeksekusi interpreter.
Sven Mascheck's shebang halaman memiliki banyak informasi tentang peristiwa di seluruh jenis unix, termasuk setuid dukungan. Let's asumsikan anda've berhasil membuat program anda jalankan sebagai root, entah karena OS anda mendukung setuid shebang atau karena anda've digunakan asli biner wrapper (seperti sudo
). Pernahkah anda membuka sebuah lubang keamanan? Mungkin. Masalah di sini adalah tidak tentang ditafsirkan vs disusun program-program. Masalahnya adalah apakah anda runtime sistem berperilaku aman jika dijalankan dengan hak istimewa.
/lib/ld.jadi
), yang memuat dynamic library yang diperlukan oleh program. Pada banyak jenis unix, anda dapat mengkonfigurasi jalur pencarian untuk perpustakaan dinamis melalui lingkungan (LD_LIBRARY_PATH
adalah nama umum untuk variabel lingkungan), dan bahkan beban tambahan ke perpustakaan semua dieksekusi binari (LD_PRELOAD
). The invoker program yang dapat mengeksekusi kode sewenang-wenang dalam program itu's konteks dengan menempatkan secara khusus dibuat libc.begitu
dalam $LD_LIBRARY_PATH
(antara lain taktik). Semua waras sistem mengabaikan LD_*
variabel dalam setuid executable. JALAN
, JIKA
, dan banyak lagi, invoker script memiliki banyak peluang untuk mengeksekusi kode sewenang-wenang dalam skrip shell's konteks. Beberapa kerang set variabel-variabel tersebut ke default waras jika mereka mendeteksi bahwa script telah dipanggil dengan hak-hak istimewa, tapi aku don't tahu bahwa ada implementasi tertentu bahwa saya akan percaya. #!/usr/bin/suidperl -wT
, bukan #!/usr/bin/perl -wT
, tapi pada banyak sistem modern, #!/usr/bin/perl -wT
sudah cukup.
Perhatikan bahwa menggunakan biner asli wrapper tidak apa-apa dalam dirinya sendiri untuk mencegah masalah ini. Pada kenyataannya, itu dapat membuat situasi buruk, karena itu dapat mencegah anda runtime environment mendeteksi bahwa itu dipanggil dengan hak dan melewati runtime nya konfigurabilitas.
Asli biner pembungkus dapat membuat sebuah shell script aman jika wrapper sanitizes lingkungan. Naskah harus berhati-hati untuk tidak membuat terlalu banyak asumsi (misalnya tentang direktori saat ini) tapi ini berjalan. Anda dapat menggunakan sudo untuk ini asalkan itu's set up untuk membersihkan lingkungan. Daftar hitam variabel rawan kesalahan, jadi selalu putih. Dengan sudo, pastikan bahwa env_reset
pilihan diaktifkan, bahwa setenv
mati, dan bahwa env_file
dan env_keep
hanya mengandung berbahaya variabel. TL DR:
env_reset
pilihan).
¹ diskusi Ini berlaku sama jika anda mengganti "setgid" untuk "setuid"; mereka berdua diabaikan oleh kernel Linux pada script Salah satu cara untuk memecahkan masalah ini adalah untuk memanggil shell script dari sebuah program yang dapat menggunakan setuid sedikit. sesuatu seperti sudo. Sebagai contoh, di sini adalah bagaimana anda akan mencapai hal ini dalam sebuah program 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;
}
Simpan sebagai setuid-test2.c. kompilasi Sekarang lakukan setuid pada program ini biner:
su - nobody
[enter password]
chown nobody:nobody a.out
chmod 4755 a.out
Sekarang, anda harus mampu menjalankan hal itu, dan anda'll melihat script yang dieksekusi dengan tidak ada izin. Tapi di sini juga anda harus hardcode script path atau lulus sebagai baris perintah arg di atas exe.
Aku awalan beberapa script yang ada di perahu ini demikian:
#!/bin/sh
[ "root" != "$USER" ] && exec sudo $0 "$@"
Catatan bahwa ini tidak menggunakan setuid
tetapi hanya mengeksekusi file saat ini dengan sudo
.
Jika anda ingin menghindari panggilan sudo some_script
anda hanya dapat melakukan:
#!/ust/bin/env sh
sudo /usr/local/scripts/your_script
SETUID program perlu dirancang dengan sangat hati-hati karena mereka berjalan dengan hak akses root dan pengguna memiliki kontrol yang besar atas mereka. Mereka perlu untuk kewarasan-cek semuanya. Anda tidak bisa melakukannya dengan script karena:
sed
, awk
, dll. akan perlu diperiksa jugaHarap dicatat bahwa sudo
menyediakan beberapa kewarasan memeriksa tetapi tidak't cukup — memeriksa setiap baris dalam kode anda sendiri.
Sebagai catatan terakhir: pertimbangkan untuk menggunakan kemampuan. Mereka memungkinkan anda untuk memberikan proses yang berjalan sebagai pengguna hak-hak istimewa yang biasanya akan memerlukan hak akses root. Namun untuk contoh, sementara ping
kebutuhan untuk memanipulasi jaringan, tidak perlu untuk memiliki akses ke file. I'm tidak yakin namun jika mereka diwariskan.
Anda dapat membuat sebuah alias untuk sudo + nama script. Tentu saja, yang bahkan lebih banyak pekerjaan yang harus diatur, karena anda kemudian harus men-setup sebuah alias, juga, tapi itu menghemat anda dari keharusan untuk mengetik sudo.
Tapi jika anda don't pikiran mengerikan risiko keamanan, menggunakan setuid shell sebagai penerjemah untuk shell script. Don't tahu apakah itu'll bekerja untuk anda, tapi saya kira itu mungkin.
Biarkan saya menyatakan bahwa saya menyarankan agar benar-benar melakukan ini, meskipun. I'm hanya menyebutkan hal itu untuk tujuan pendidikan ;-)
super [ -r reqpath] perintah [ argumen ]
Super memungkinkan ditentukan pengguna untuk menjalankan script (atau perintah-perintah) seolah-olah mereka adalah akar; atau dapat mengatur uid, gid, dan/atau pelengkap kelompok pada per-perintah dasar sebelum melaksanakan perintah. Hal ini dimaksudkan untuk menjadi alternatif yang aman untuk membuat script setuid root. Super juga memungkinkan pengguna biasa untuk menyediakan perintah untuk eksekusi oleh orang lain; ini mengeksekusi dengan uid, gid, dan kelompok pengguna dengan perintah.
Super berkonsultasi `super.tab'' file untuk melihat apakah pengguna diijinkan untuk mengeksekusi perintah yang diminta. Jika izin diberikan, super akan exec pgm [ argumen ], di mana pgm adalah program yang berhubungan dengan perintah ini. (Akar diperbolehkan eksekusi secara default, tetapi masih bisa membantah jika aturan tidak termasuk akar. Pengguna biasa yang dianulir eksekusi secara default.)
Jika perintah merupakan sebuah symbolic link (atau hard link, juga) super program kemudian mengetik % perintah args setara dengan mengetikkan % super perintah arg (perintah tidak harus super atau super tidak akan mengakui bahwa itu's yang dipanggil melalui sebuah link.)
http://www.ucolick.org/~akan/RUE/super/README
http://manpages.ubuntu.com/manpages/utopic/en/man1/super.1.html
Jika untuk beberapa alasan sudo
tidak tersedia, anda dapat menulis tipis wrapper script di C:
#include <unistd.h>
int main() {
setuid(0);
execle("/bin/bash","bash","/full/path/to/script",(char*) NULL,(char*) NULL);
}
Dan setelah anda compile mengaturnya sebagai setuid
dengan chmod 4511 wrapper_script
.
Ini adalah sama dengan yang lain diposting menjawab, tapi menjalankan script dengan lingkungan yang bersih dan secara eksplisit menggunakan /bin/bash
bukan shell yang disebut dengan sistem ()
, dan menutup beberapa potensi lubang keamanan.
Catatan bahwa ini membuang lingkungan sepenuhnya. Jika anda ingin menggunakan beberapa variabel lingkungan tanpa membuka kerentanan, anda benar-benar hanya perlu menggunakan sudo
.
Jelas, anda ingin memastikan naskah itu sendiri hanya dapat ditulis oleh root.
Pertama kali saya menemukan pertanyaan ini, yakin dengan semua jawaban, di sini adalah jauh lebih baik, yang juga memungkinkan anda untuk benar-benar obfuscate anda bash script, jika anda begitu ingin!
Itu harus jelas.
#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());
}
Kemudian anda menjalankan
g++ embedded.cpp -o embedded
sudo chown root embedded
sudo chmod u+s embedded