Ini adalah perintah yang saya gunakan untuk memeriksa bash shell saya untuk bug Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Adakah yang bisa menjelaskan perintah secara detail?
Ini adalah perintah yang saya gunakan untuk memeriksa bash shell saya untuk bug Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Adakah yang bisa menjelaskan perintah secara detail?
Jawaban:
Jawaban ini merupakan turunan dari artikel asli di Majalah Fedora oleh Matthew Miller, dilisensikan di bawah lisensi Creative Commons Attribution-Share Alike 4.0 .
Biarkan saya jelaskan:
env x='() { :;}; echo OOPS' bash -c :
Ini akan mencetak "OOPS" pada sistem yang rentan, tetapi keluar secara diam-diam jika bash telah ditambal.
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
Ini akan mencetak "OOPS" pada sistem yang rentan, tetapi mencetak “this is a test”
jika bash telah ditambal.
Dan Anda mungkin pernah mendengar bahwa itu ada hubungannya dengan variabel lingkungan. Tetapi, mengapa kode dalam variabel lingkungan dieksekusi? Yah, itu tidak seharusnya - tetapi, karena fitur yang saya tergoda untuk menelepon terlalu pintar untuk kebaikannya sendiri, ada beberapa ruang untuk kesalahan. Bash adalah apa yang Anda lihat sebagai terminal prompt, tetapi juga merupakan bahasa scripting, dan memiliki kemampuan untuk mendefinisikan fungsi. Anda melakukannya seperti ini:
$ Ubuntu() { echo "Ubuntu is awesome."; }
dan kemudian Anda memiliki perintah baru. Perlu diingat bahwa di echo
sini belum benar-benar berjalan; itu hanya disimpan sebagai apa yang akan terjadi ketika kita menjalankan perintah baru kita. Ini akan menjadi penting dalam satu menit!
$ Ubuntu
Ubuntu is awesome.
Berguna! Tetapi, katakanlah, untuk beberapa alasan, Kita perlu menjalankan instance baru dari bash, sebagai subproses, dan ingin menjalankan perintah baru yang mengagumkan di bawah itu. Pernyataan bash -c somecommand
tidak persis seperti ini: menjalankan perintah yang diberikan di shell baru:
$ bash -c Ubuntu
bash: Ubuntu: command not found
Ooh. Sedih. Anak itu tidak mewarisi definisi fungsi. Tapi, itu memang melekat pada lingkungan - kumpulan pasangan nilai kunci yang telah diekspor dari shell. (Ini adalah konsep 'nuther keseluruhan; jika Anda tidak terbiasa dengan ini, percayalah untuk saat ini.) Dan, ternyata, bash dapat mengekspor fungsi juga. Begitu:
$ export -f Ubuntu
$ bash -c Ubuntu
Ubuntu is awesome.
Yang semuanya baik dan baik - kecuali bahwa mekanisme yang digunakan untuk menyelesaikan ini agak cerdik . Pada dasarnya, karena tidak ada keajaiban Linux / Unix untuk melakukan fungsi dalam variabel lingkungan, fungsi ekspor sebenarnya hanya membuat variabel lingkungan biasa yang berisi definisi fungsi. Kemudian, ketika shell kedua membaca lingkungan "masuk" dan menemukan variabel dengan konten yang terlihat seperti fungsi, ia mengevaluasinya.
Secara teori, ini sangat aman , karena, ingat, mendefinisikan suatu fungsi tidak benar - benar menjalankannya . Kecuali - dan inilah mengapa kami di sini - ada bug dalam kode di mana evaluasi tidak berhenti ketika akhir definisi fungsi tercapai. Itu hanya kepts pergi.
Itu tidak akan pernah terjadi ketika fungsi yang disimpan dalam variabel lingkungan dibuat secara sah, dengan export -f
. Tapi, mengapa harus sah? Seorang penyerang bisa membuat variabel lingkungan lama apa saja, dan jika itu tampak seperti fungsi, shell bash baru akan berpikir itu!
Jadi, dalam contoh pertama kami:
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
The env
perintah menjalankan perintah dengan satu set variabel yang diberikan. Dalam hal ini, kami menetapkan x
sesuatu yang tampak seperti fungsi. Fungsi ini hanya satu :
, yang sebenarnya adalah perintah sederhana yang didefinisikan sebagai tidak melakukan apa-apa. Tapi kemudian, setelah semi-colon
yang menandakan akhir dari definisi fungsi, ada echo
perintah. Seharusnya tidak ada di sana, tetapi tidak ada yang menghentikan kita dari melakukannya.
Kemudian, perintah yang diberikan untuk menjalankan dengan lingkungan baru ini adalah bash shell baru, sekali lagi dengan perintah " echo this is a test
" atau "tidak melakukan apa-apa :
", setelah itu ia akan keluar, benar-benar tidak berbahaya.
Tapi - oops! Ketika shell baru itu mulai dan membaca lingkungan, ia sampai ke x
variabel, dan karena itu tampak seperti fungsi, ia mengevaluasinya. Definisi fungsi dimuat tanpa berbahaya - dan kemudian muatan berbahaya kami terpicu juga. Jadi, jika Anda menjalankan hal di atas pada sistem yang rentan, Anda akan “OOPS”
dicetak kembali pada Anda. Atau, seorang penyerang bisa melakukan jauh lebih buruk daripada hanya mencetak barang.
env
tidak perlu. Anda bisa mendapatkan hasil yang sama (lulus / gagal tergantung pada apakah Bash telah diperbarui) dengan menggunakan perintah tanpa itu: x='() { :;}; echo OOPS' bash -c "echo this is a test"
. Ini karena mendahului perintah dengan penugasan variabel melewati variabel itu dan nilainya ke lingkungan perintah ( bash -c "..."
dalam hal ini).
env
ditentukan oleh shell dari mana seseorang menjalankan tes, bukan shell yang diuji. (Ini mungkin sama. Bahkan kemudian, kami sedang menguji bagaimana bash memproses lingkungannya sendiri .) Kerang Bourne-style menerima NAME=value command
sintaksis; Kerang gaya-C (mis. csh
, tcsh
) Tidak. Jadi tes ini sedikit lebih portabel dengan env
(dengan biaya kadang-kadang membuat kebingungan tentang cara kerjanya).
Dalam versi yang tidak dititipbash
itu menyimpan definisi fungsi yang diekspor sebagai variabel lingkungan.
Simpan fungsi x
sebagai,
$ x() { bar; }
$ export -f x
Dan periksa definisinya sebagai,
$ env | grep -A1 x
x=() { bar
}
Jadi seseorang dapat memanfaatkan ini dengan mendefinisikan variabel lingkungannya sendiri, dan menafsirkannya sebagai definisi fungsi. Sebagai contoh env x='() { :;}'
akan diperlakukan sebagai
x() { :;
}
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Dari man env
,
env
- Jalankan program dalam lingkungan yang dimodifikasi.
:
tidak melakukan apa pun kecuali keluar dengan status keluar 0
. lihat lebih lanjut
Saat instance baru dari bash yang belum ditambak diluncurkan sebagai bash -c "echo this is a test"
, variabel lingkungan buatan diperlakukan sebagai fungsi dan dimuat. Dengan demikian seseorang mendapat output
rentan ini adalah sebuah ujian
Catatan: Gema di luar definisi fungsi telah secara tak terduga dieksekusi selama bash startup. Definisi fungsi hanyalah langkah untuk mendapatkan evaluasi dan mengeksploitasi terjadi, definisi fungsi itu sendiri dan variabel lingkungan yang digunakan sewenang-wenang. Shell melihat variabel lingkungan, melihat x, yang kelihatannya memenuhi batasan yang diketahuinya tentang seperti apa definisi fungsi, dan mengevaluasi baris, tanpa sengaja juga menjalankan gema (yang bisa berupa perintah apa pun, berbahaya atau tidak) . Lihat juga ini
env test='() { echo "anything"; }' bash -c "echo otherthing"
Anda akan melihat pada output otherthing
. Itu diperbaiki di patch. merasa bebas jika saya masih belum jelas.
unpatched bash
Anda dapat memanggil fungsi seperti yang didefinisikan, tetapi dalam tambalan bash
definisi itu sendiri tidak ada.
echo vulnerable
) tidak dieksekusi. Perhatikan bahwa di tambalan terbaru, fungsi yang diteruskan harus memiliki awalan spesifik ( env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test"
). Beberapa tambalan yang lebih baru mungkin digunakan %%
alih-alih yang pertama ()
.