Pertanyaan ini ditanyakan dengan cara berbeda di forum lain. Tetapi belum ada penjelasan yang layak mengapa Anda tidak dapat melakukan hal di bawah ini di bash.
#!/bin/bash
command1
SWITCH_USER_TO rag
command2
command3
Biasanya, cara yang disarankan adalah
#!/bin/bash
command1
sudo -u rag command2
sudo -u rag command3
tetapi mengapa tidak mungkin bash
untuk mengubah ke pengguna yang berbeda di beberapa titik selama eksekusi skrip bash dan menjalankan sisa perintah sebagai pengguna yang berbeda?
Jawaban:
Informasi ini sudah ada di jawaban saya yang lain , tetapi agak terkubur di sana. Jadi saya pikir, saya akan menambahkannya di sini.
bash
tidak memiliki ketentuan untuk mengubah pengguna, tetapizsh
tidak.Di
zsh
, Anda mengubah pengguna dengan menetapkan nilai ke variabel-variabel itu:$EUID
: ubah id pengguna yang efektif (dan tidak ada yang lain). Biasanya, Anda dapat mengubah euid Anda antara userid asli Anda dan set id pengguna yang disimpan (jika dipanggil dari setuid yang dapat dieksekusi) atau mengubah apa pun jika euid Anda adalah 0.$UID
: mengubah id pengguna yang efektif, id pengguna nyata dan id pengguna set yang disimpan ke nilai baru. Kecuali jika nilai baru adalah 0, tidak akan kembali, karena ketiga ketiganya telah disetel ke nilai yang sama, tidak ada cara untuk mengubahnya ke hal lain.$EGID
dan$GID
: hal yang sama tetapi untuk id grup.$USERNAME
. Itu seperti menggunakansudo
atausu
. Ini mengatur cairan Anda, ruid, ssuid ke uid pengguna itu. Ini juga menetapkan kelompok egid, rgid dan ssgid dan tambahan berdasarkan keanggotaan grup sebagaimana didefinisikan dalam database pengguna. Seperti untuk$UID
, kecuali jika Anda mengatur$USERNAME
keroot
, tidak ada kembali, tetapi seperti untuk$UID
, Anda dapat mengubah pengguna hanya untuk subkulit.Jika Anda menjalankan skrip ini sebagai "root":
Sekarang, untuk mengubah pengguna seperti pada
sudo
atausu
, kita hanya bisa melakukannya dengan menggunakan subshell, kalau tidak kita hanya bisa melakukannya sekali:sumber
Penawaran kernel
man 2 setuid
dan teman-teman.Sekarang, ini berfungsi pada proses panggilan. Lebih penting lagi, Anda tidak dapat meningkatkan hak istimewa Anda. Itu sebabnya
su
dansudo
tetapkan SETUID agar mereka selalu berjalan dengan hak istimewa tertinggi (root
) dan turunkan ke pengguna yang diinginkan.Kombinasi itu berarti bahwa Anda tidak dapat mengubah UID shell dengan menjalankan beberapa program lain untuk melakukan itu (itu sebabnya Anda tidak dapat mengharapkan
sudo
atau program lain untuk melakukannya) dan Anda tidak dapat (sebagai shell) melakukannya sendiri kecuali Anda bersedia dijalankan sebagai root atau pengguna yang sama yang ingin Anda alihkan yang tidak masuk akal. Terlebih lagi begitu Anda melepaskan hak istimewa, tidak ada jalan kembali.sumber
Nah, Anda selalu bisa melakukan:
(ʘ‿ʘ)
Itu pertama kali dimulai sebagai lelucon karena mengimplementasikan apa yang diminta meskipun mungkin tidak persis seperti yang diharapkan, dan secara praktis tidak berguna. Tapi ketika berevolusi menjadi sesuatu yang bekerja sampai batas tertentu dan melibatkan beberapa peretasan yang bagus, berikut adalah sedikit penjelasan:
Seperti yang dikatakan Miroslav , jika kita mengesampingkan kemampuan gaya Linux (yang toh tidak akan membantu di sini juga), satu-satunya cara untuk proses tidak berubah untuk mengubah uid adalah dengan mengeksekusi setuid executable.
Setelah Anda mendapatkan hak istimewa pengguna super (dengan mengeksekusi setuid executable yang pemiliknya root misalnya), Anda dapat mengganti id pengguna yang efektif bolak-balik antara id pengguna asli Anda, 0 dan id lainnya kecuali jika Anda melepaskan id pengguna set yang disimpan ( suka hal-hal seperti
sudo
atausu
biasanya dilakukan).Contohnya:
Sekarang saya punya
env
perintah yang memungkinkan saya untuk menjalankan perintah dengan id pengguna yang efektif dan set id pengguna yang disimpan 0 ( id pengguna asli saya masih 1000):perl
memiliki pembungkus kesetuid
/seteuid
(yang$>
dan$<
variabel).Begitu juga zsh:
Meskipun di atas
id
perintah - perintah itu disebut dengan id pengguna nyata dan set userid disimpan dari 0 (meskipun jika saya telah menggunakan saya./env
bukansudo
itu akan hanya set userid yang disimpan, sedangkan id pengguna sebenarnya akan tetap 1000), yang berarti bahwa jika itu adalah perintah yang tidak dipercaya, mereka masih bisa melakukan kerusakan, jadi Anda ingin menulisnya seperti:(Yaitu mengatur semua uids (set efektif, nyata dan disimpan) hanya untuk pelaksanaan perintah-perintah itu.
bash
tidak memiliki cara untuk mengubah id pengguna. Jadi, bahkan jika Anda memiliki setuid yang dapat dieksekusi untuk memanggilbash
skrip Anda , itu tidak akan membantu.Dengan
bash
, Anda harus menjalankan setuid yang dapat dieksekusi setiap kali Anda ingin mengubah uid.Gagasan dalam skrip di atas adalah panggilan ke SWITCH_TO_USER, untuk mengeksekusi contoh bash baru untuk mengeksekusi sisa skrip.
SWITCH_TO_USER someuser
lebih atau kurang fungsi yang mengeksekusi skrip lagi sebagai pengguna yang berbeda (menggunakansudo
) tetapi melewatkan awal skrip sampaiSWITCH_TO_USER someuser
.Yang menjadi rumit adalah kami ingin menjaga status bash saat ini setelah memulai bash baru sebagai pengguna yang berbeda.
Mari kita jabarkan:
Kami membutuhkan alias. Salah satu trik dalam skrip ini adalah untuk melewatkan bagian skrip hingga
SWITCH_TO_USER someuser
, dengan sesuatu seperti:Bentuk itu mirip dengan yang
#if 0
digunakan dalam C, yaitu cara untuk melengkapi komentar beberapa kode.:
adalah no-op yang mengembalikan true. Jadi: || :
, yang kedua:
tidak pernah dieksekusi. Namun, ini diuraikan. Dan itu<< 'xxx'
adalah bentuk di sini-dokumen di mana (karenaxxx
dikutip), tidak ada perluasan atau interpretasi dilakukan.Kita bisa melakukan:
Tetapi itu berarti bahwa dokumen di sini harus ditulis dan diteruskan sebagai standar
:
.:||:
hindari itu.Sekarang, di mana peretasannya adalah kita menggunakan fakta yang
bash
memperluas alias lebih awal dalam proses penguraiannya. Menjadiskip
alias ke:||: << 'SWITCH_TO_USER someuther'
bagian konstruksi komentar .Mari kita lanjutkan:
Inilah definisi fungsi SWITCH_TO_USER . Kita akan melihat di bawah bahwa SWITCH_TO_USER pada akhirnya akan menjadi alias yang membungkus fungsi itu.
Fungsi itu melakukan sebagian besar mengeksekusi kembali skrip. Pada akhirnya kita melihat bahwa itu dieksekusi kembali (dalam proses yang sama karena
exec
)bash
dengan_x
variabel di lingkungan itu (kita gunakan dienv
sini karenasudo
biasanya membersihkan lingkungannya dan tidak memungkinkan melewati sewenang-wenang dan melalui). Itubash
mengevaluasi konten$_x
variabel itu sebagai kode bash dan sumber skrip itu sendiri._x
didefinisikan sebelumnya sebagai:Semua
declare
,alias
,shopt -p
set +o
keluaran membuat dump dari keadaan internal shell. Artinya, mereka membuang definisi semua variabel, fungsi, alias dan opsi sebagai kode shell yang siap dievaluasi. Selain itu, kami menambahkan pengaturan parameter posisi ($1
,$2
...) berdasarkan nilai$_a
array (lihat di bawah), dan beberapa membersihkan sehingga$_x
variabel besar tidak tinggal di lingkungan selama sisa naskah.Anda akan melihat bahwa bagian pertama hingga
set +x
dibungkus dalam grup perintah yang stderrnya diarahkan ke/dev/null
({...} 2> /dev/null
). Itu karena, jika pada beberapa titik dalam skripset -x
(atauset -o xtrace
) dijalankan, kami tidak ingin pembukaan itu menghasilkan jejak karena kami ingin membuatnya sesedikit mungkin mengganggu. Jadi kami menjalankanset +x
(setelah memastikan untuk membuang opsi (termasukxtrace
) pengaturan sebelumnya) di mana jejak dikirim ke / dev / null.The
eval "$_X"
stderr juga diarahkan ke / dev / null untuk alasan yang sama tetapi juga untuk menghindari kesalahan tentang menulis upaya untuk variabel read-only khusus.Mari kita lanjutkan dengan skrip:
Itu trik kami yang dijelaskan di atas. Pada permintaan skrip awal, itu akan dibatalkan (lihat di bawah).
Sekarang pembungkus alias di sekitar SWITCH_TO_USER. Alasan utamanya adalah untuk dapat meneruskan parameter posisi (
$1
,$2
...) ke yang barubash
yang akan menafsirkan sisa skrip. Kami tidak dapat melakukannya dalamSWITCH_TO_USER
fungsi karena di dalam fungsi,"$@"
ada argumen untuk fungsi, bukan dari skrip. Pengalihan stderr ke / dev / null lagi untuk menyembunyikan xtraces, daneval
untuk mengatasi bug dibash
. Lalu kita memanggilSWITCH_TO_USER
fungsi .Bagian itu membatalkan
skip
alias (menggantinya dengan perintah:
no-op) kecuali$_u
variabelnya disetel.Itu
skip
alias kami . Pada doa pertama, itu hanya akan menjadi:
(no-op). Pada subsequence re-doa, itu akan menjadi sesuatu seperti::||: << 'SWITCH_TO_USER root'
.Jadi di sini, sebagai contoh, pada saat itu, kami menginstal kembali skrip sebagai
root
pengguna, dan skrip akan memulihkan keadaan yang disimpan, dan melompat keSWITCH_TO_USER root
baris itu dan melanjutkan.Artinya adalah harus ditulis persis seperti stat, dengan
SWITCH_TO_USER
di awal baris dan dengan tepat satu spasi di antara argumen.Sebagian besar status, stdin, stdout, dan stderr akan dipertahankan, tetapi bukan deskriptor file lainnya karena
sudo
biasanya ditutup kecuali dikonfigurasikan secara eksplisit untuk tidak melakukannya. Jadi misalnya:biasanya tidak akan berfungsi.
Perhatikan juga bahwa jika Anda melakukannya:
Yang hanya bekerja jika Anda memiliki hak untuk
sudo
sebagaialice
danalice
memiliki hak untuksudo
sebagaibob
, danbob
sebagairoot
.Jadi, dalam praktiknya, itu tidak terlalu berguna. Menggunakan
su
alih-alihsudo
(atausudo
konfigurasi tempatsudo
mengotentikasi pengguna target alih-alih penelepon) mungkin lebih masuk akal, tetapi itu tetap berarti Anda harus mengetahui kata sandi semua orang itu.sumber
ioshcc
? Anda seharusnya memasukkan hanya satu baris.Perintah "sudo -u ram sh" dapat digunakan untuk mengubah ke pengguna "ram", dengan menjalankan perintah "sh" atau shell. Perintah "keluar" akan membawa Anda kembali ke pengguna asli.
sumber