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?
bash
shellshock
heemayl
sumber
sumber
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:
Ini akan mencetak "OOPS" pada sistem yang rentan, tetapi keluar secara diam-diam jika bash telah ditambal.
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:
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!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: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:
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:
The
env
perintah menjalankan perintah dengan satu set variabel yang diberikan. Dalam hal ini, kami menetapkanx
sesuatu yang tampak seperti fungsi. Fungsi ini hanya satu:
, yang sebenarnya adalah perintah sederhana yang didefinisikan sebagai tidak melakukan apa-apa. Tapi kemudian, setelahsemi-colon
yang menandakan akhir dari definisi fungsi, adaecho
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.sumber
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 menerimaNAME=value command
sintaksis; Kerang gaya-C (mis.csh
,tcsh
) Tidak. Jadi tes ini sedikit lebih portabel denganenv
(dengan biaya kadang-kadang membuat kebingungan tentang cara kerjanya).Dalam versi yang tidak dititip
bash
itu menyimpan definisi fungsi yang diekspor sebagai variabel lingkungan.Simpan fungsi
x
sebagai,Dan periksa definisinya sebagai,
Jadi seseorang dapat memanfaatkan ini dengan mendefinisikan variabel lingkungannya sendiri, dan menafsirkannya sebagai definisi fungsi. Sebagai contoh
env x='() { :;}'
akan diperlakukan sebagaiApa yang dilakukan perintah untuk memeriksa shellshock,
Dari
man env
,env
- Jalankan program dalam lingkungan yang dimodifikasi.:
tidak melakukan apa pun kecuali keluar dengan status keluar0
. lihat lebih lanjutSaat 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 outputsumber
env test='() { echo "anything"; }' bash -c "echo otherthing"
Anda akan melihat pada outputotherthing
. Itu diperbaiki di patch. merasa bebas jika saya masih belum jelas.unpatched bash
Anda dapat memanggil fungsi seperti yang didefinisikan, tetapi dalam tambalanbash
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()
.