Shellshock'u kontrol etme komutunun açıklaması


32

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?


4
Ayrıca bakınız: unix.stackexchange.com/q/157329/70524 - Fixee'nin cevabı yardımcı olabilir.
muru

Yanıtlar:


45

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 echoburada 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 somecommandaynen 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"

envKomut verilen bir değişken seti ile bir komut çalıştırır. Bu durumda, xfonksiyona benzeyen bir şeye bakıyoruz . İşlev, sadece bir tek :, aslında hiçbir şey yapmamak olarak tanımlanan basit bir komuttur. Ama sonra, semi-colonhangi fonksiyon tanımının sona erdiğini bildirdikten sonra, bir echokomut 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, xdeğ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.


1
Bunun neden işe yaradığına dair mükemmel bir açıklama için Muchas gracias.
Doug R.

2
Not envgerekli 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.
sonraki duyuruya kadar duraklatıldı.

1
... ancak daha yeni yamaların bazılarında gerekli olabilir. İşler akıcı.
sonraki duyuruya kadar duraklatıldı.

4
@DennisWilliamson Gerekli olup olmadığının 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 commandsö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).
Eliah Kagan,

2

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 xolarak,

$ 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() { :;
}

Deniz kabuğunu kontrol etme komutu ne işe yarıyor?

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

Gönderen man env,

  1. env - değiştirilmiş bir ortamda bir program çalıştırmak.

  2. :hiçbir şey yapmayın ama çıkış durumundan çıkın 0. bkz fazla

  3. 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


Herhangi bir tanımlanmış bash işlevinin, bash'ın yamalı sürümünde alt kabukta değerlendirilmekte olan dışa aktarılması durumunda buldum. Şuna bakın: chayan @ chayan: ~ / testr $ test () {echo "anything"; }; ihracat -f testi; bash -c testi Ouput: bir şey Yani cevabınız biraz doğru şekilde yönlendirilmemiştir. kasiyA'nın hata tanımını, değişkeni tanımının ötesine genişlettiği şeklinde açıklaması doğru.
heemayl

@heemayl bu davranış doğaldır. Ama eğer denersen env test='() { echo "anything"; }' bash -c "echo otherthing"çıktıda göreceksin otherthing. Bu düzeltme ekinde düzeltildi. Hala net değilsem çekinmeyin.
souravc

Lütfen beni bir kez daha açıklığa kavuşturun. Son yorumunuzda temel olarak fonksiyonu tanımlıyoruz ve sonra bash'a echo komutunu çalıştırmasını söylüyoruz. Bu örnekte bash işlevini çağırmadık. Bunun hem yamalanmış hem de yamalanmamış bash'te aynı çıktısı olmaz mıydı? Hata, temel olarak, işlev tanımından sonra yerleştirilen komutları çalıştırırken, bash'ın komut olarak çalıştığı fikrindeyim, ancak fonksiyon daha sonra hiçbir yerde çağrılmadı; }; yankı "foo" 'bash-c "yankı başka bir şey". Lütfen beni bu bağlamda netleştirin.
heemayl

@heemayl Cevabımı düzenledim, umarım şimdi açıktır. Örnekte haklısın son yorumumda fonksiyon denmiyoruz. Fakat fark şudur ki, bir tanımda unpatched bashtanımlandığı gibi fonksiyonu çağırabilirsiniz, ancak bir yamada bashtanımın kendisi yoktur.
souravc

@heemayl: Hayır, bu yanlış. Yamalanmış bir Bash, fonksiyon tanımını hala çocuğun çevresine aktaracaktır. Düzeltme ekinin yaptığı fark, işlev tanımını ( 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 ().
sonraki duyuruya kadar duraklatıldı.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.