Shellshock hatası için bash kabuğumu kontrol etmek için kullandığım komut:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Birisi lütfen komutu ayrıntılı olarak açıklayabilir mi?
Shellshock hatası için bash kabuğumu kontrol etmek için kullandığım komut:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Birisi lütfen komutu ayrıntılı olarak açıklayabilir mi?
Yanıtlar:
Bu cevap, Creative Commons Attribution-Share Alike 4.0 lisansı altında lisanslı Matthew Miller tarafından Fedora Dergisi'nde yayınlanan bir makalenin bir türevidir .
Açıklamama izin ver:
env x='() { :;}; echo OOPS' bash -c :
Bu, savunmasız bir sistemde “OOPS” yazacaktır ancak bash eklenmişse sessizce çıkacaktır.
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
Bu, savunmasız bir sistemde “OOPS” yazacaktır ancak “this is a test”
bash eklenmişse yazdırır .
Muhtemelen çevre değişkenleriyle ilgisi olduğunu duymuşsunuzdur. Ancak, neden çevre değişkenlerindeki kod yürütülüyor? Olması gerekmiyor - ama, kendi iyiliği için çok akıllıca çağırmak istediğim bir özellik yüzünden, bir kusur için yer var. Bash, bir terminal istemi olarak gördüğünüz şeydir, ancak aynı zamanda bir betik dilidir ve işlevleri tanımlayabilme yeteneğine sahiptir. Bunu böyle yaparsın:
$ Ubuntu() { echo "Ubuntu is awesome."; }
ve sonra yeni bir komutunuz var. Unutmayın echo
burada aslında henüz çalıştırmak değildir; Yeni komutumuzu çalıştırdığımızda ne olacağı gibi kaydedildi. Bu bir dakika içinde önemli olacak!
$ Ubuntu
Ubuntu is awesome.
İşe yarar! Ancak, diyelim ki, bir nedenden dolayı, alt süreç olarak yeni bir bash örneği yürütmeliyiz ve bunun altındaki harika yeni komutumu çalıştırmak istiyoruz. İfadesi bash -c somecommand
aynen yapar: Yeni bir kabuk verilen komutu çalıştırır:
$ bash -c Ubuntu
bash: Ubuntu: command not found
Ooh. Üzgün. Çocuk işlev tanımını devralmadı. Ancak, çevreye özgüdür - kabuğundan ihraç edilen bir anahtar-değer çiftleri koleksiyonu. (Bu tam bir 'somut kavramdır; buna aşina değilseniz, şimdilik bana güvenin.) Görünüşe göre bash, fonksiyonları da verebiliyor. Yani:
$ export -f Ubuntu
$ bash -c Ubuntu
Ubuntu is awesome.
Hangisi iyi ve iyi - bunun başarıldığı mekanizma sorta tehlikeli . Temel olarak, ortam değişkenlerinde işlev yapmak için Linux / Unix sihri olmadığından, verme işlevi aslında işlev tanımını içeren normal bir ortam değişkeni yaratır. Daha sonra, ikinci kabuk “gelen” ortamı okuduğunda ve bir fonksiyona benzeyen içerikleri olan bir değişkenle karşılaştığında, onu değerlendirir.
Teoride, bu tamamen güvenlidir , çünkü bir işlevi tanımlamanın aslında onu yerine getirmediğini unutmayın . Dışında - ve bu yüzden buradayız - kodda işlev tanımının sonuna gelindiğinde değerlendirmenin durmadığı bir hata vardı. Sadece devam ediyor.
Bir ortam değişkeninde saklanan fonksiyon meşru bir şekilde, ile yapıldığında bu asla olmazdı export -f
. Fakat niye okunaklı olun ki? Bir saldırgan eski herhangi bir ortam değişkenini oluşturabilir ve eğer bir işleve benzerse, yeni bash kabukları öyle olduğunu düşünür!
Yani, ilk örneğimizde:
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
env
Komut verilen bir değişken seti ile bir komut çalıştırır. Bu durumda, x
fonksiyona benzeyen bir şeye bakıyoruz . İşlev, sadece bir tek :
, aslında hiçbir şey yapmamak olarak tanımlanan basit bir komuttur. Ama sonra, semi-colon
hangi fonksiyon tanımının sona erdiğini bildirdikten sonra, bir echo
komut var. Bunun orada olmaması gerekiyordu, ama bizi yapmamızı engelleyen hiçbir şey yok.
Daha sonra, bu yeni ortamla çalışmak için verilen komut, tekrar “ echo this is a test
” veya “hiçbir şey yapmama :
” komutuyla yeni bir bash kabuğudur , bundan sonra tamamen zararsız bir şekilde çıkacaktır.
Ama - ayy! Bu yeni kabuk başladığında ve çevreyi okuduğunda, x
değişkene geçer ve bir işleve benzemesi nedeniyle onu değerlendirir. İşlev tanımı zararsız bir şekilde yüklenir - ve ardından kötü niyetli yükümüz de tetiklenir. Eğer yukarıdakileri savunmasız bir sistemde çalıştırırsan, sana “OOPS”
geri basılırsın. Veya bir saldırgan, yalnızca bir şeyleri yazdırmaktan çok daha kötü bir şey yapabilir.
env
gerekli değildir. Sen aynı sonucu onsuz komutunu kullanarak (geçişli / Bash güncellendi olmasına göre başarısız) alabilirsiniz: x='() { :;}; echo OOPS' bash -c "echo this is a test"
. Bunun nedeni, değişken ataması olan bir komutun önüne gelmek, o değişkeni ve değerini komutun ( bash -c "..."
bu durumda) ortamına iletir.
env
, test edilen kabuğu değil, testi yaptığı kabuk tarafından belirlenir. (Bunlar aynı olabilir. O zaman bile, bash'ın kendi ortamını nasıl işlediğini test ediyoruz .) Bourne tarzı mermiler NAME=value command
sözdizimini kabul ediyor ; C tarzı kabukları (örneğin csh
, tcsh
) yapmaz. Bu nedenle test biraz daha taşınabilir env
(bazen nasıl çalıştığı konusunda kafa karışıklığı yaratma pahasına).
Gelen bir yama uygulanmamış sürümübash
kendisine saklar ortam değişkenleri olarak işlev tanımlarını ihraç etti.
Bir fonksiyonu Mağaza x
olarak,
$ x() { bar; }
$ export -f x
Ve tanımını şu şekilde kontrol edin:
$ env | grep -A1 x
x=() { bar
}
Böylece, kendi çevre değişkenlerini tanımlayarak bundan faydalanabilir ve onları işlev tanımları olarak yorumlayabilir. Örneğin env x='() { :;}'
;
x() { :;
}
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Gönderen man env
,
env
- değiştirilmiş bir ortamda bir program çalıştırmak.
:
hiçbir şey yapmayın ama çıkış durumundan çıkın 0
. bkz fazla
Yeni bir yamalı bash örneği olduğu gibi başlatıldığında bash -c "echo this is a test"
, hazırlanmış çevre değişkeni bir işlev olarak değerlendirilir ve yüklenir. Buna göre bir çıktı alır
savunmasız bu bir test
Not: İşlev tanımı dışındaki eko, bash başlatma sırasında beklenmedik şekilde yürütüldü. İşlev tanımı, değerlendirme ve istismarın gerçekleşmesi için yalnızca bir adımdır, işlev tanımının kendisi ve kullanılan ortam değişkeni keyfidir. Kabuk, ortam değişkenlerine bakar, bir işlev tanımının nasıl göründüğü ile ilgili bildiği kısıtlamaları karşıladığı gibi görünen x'i görür ve çizgiyi değerlendirir, istemeden de olsa yankıyı uygular (herhangi bir komut olabilir, kötü amaçlı olabilir) . Ayrıca Bkz bu
env test='() { echo "anything"; }' bash -c "echo otherthing"
çıktıda göreceksin otherthing
. Bu düzeltme ekinde düzeltildi. Hala net değilsem çekinmeyin.
unpatched bash
tanımlandığı gibi fonksiyonu çağırabilirsiniz, ancak bir yamada bash
tanımın kendisi yoktur.
echo vulnerable
) izleyen kodun yürütülmemesidir. Son yamalarda, iletilen işlevin belirli bir öneki ( env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test"
) olması gerektiğini unutmayın . %%
İlk yerine bazı daha yeni yamalar kullanabilir ()
.