Tırnaksız yankı çalıştırmak tehlikeli midir?


11

Birkaç benzer konu gördüm, ancak değişken sonuç vermemeye atıfta bulunuyorlar, ki bu da istenmeyen sonuçlara yol açabilir.

Bu kodu gördüm ve bu kod satırı çalıştırıldığında çalıştırılacak bir şey enjekte etmek mümkün olacağını merak ediyordum:

echo run after_bundle


Ben varken bunu karşılaştım: target = "*** LIVE SERVER ***"; yankı hedefi: $ hedef; ve *** bir klasör listesine genişletildi ... 😬
Matt

Yanıtlar:


17

Özel durum için

echo run after_bundle

alıntı yapmak gerekli değildir. Herhangi bir alıntıya gerek yoktur, çünkü argüman echodeğişken genişletme veya komut ikamesi vb. İçermeyen statik dizelerdir. Bunlar "sadece iki kelimedir" ( Stéphane'nin işaret ettiği gibi , ek olarak taşınabilir karakter kümesinden oluşturulmuştur) ).

"Tehlike", kabuğun genişleyebileceği veya yorumlayabileceği değişken verilerle uğraştığınızda ortaya çıkar. Bu gibi durumlarda, kabuğun doğru şeyi yapmasına ve sonucun amaçlanan şey olduğuna dikkat edilmelidir.

Aşağıdaki iki soru bununla ilgili bilgileri içerir:


echobazen bu sitedeki yanıtlarda potansiyel olarak zararlı komutları "korumak" için kullanılır. Örneğin, dosyaları nasıl kaldıracağımı veya dosyaları yeni bir hedefe nasıl taşıyacağımı gösterebilirim

echo rm "${name##*/}.txt"

veya

echo mv "$name" "/new_dir/$newname"

Bu, dosyaları gerçekten kaldırmak veya yeniden adlandırmak yerine terminalde komutlar çıkarır. Kullanıcı daha sonra komutları inceleyebilir, iyi görüneceğine karar verebilir, kaldırabilir echove tekrar çalışabilir.

Komutunuz echo run after_bundlekullanıcıya bir talimat olabilir veya sonuçları bilmeden çalıştırılması çok tehlikeli olan "yorumlanmış" bir kod parçası olabilir.

Kullanılması echoböyle bir modifiye komut yapar ve modifiye komut aslında bir zorunluluk garanti bilmek zorundadır olan (potansiyel olurdu güvenli değil o yönlendirmeleri içeriyorsa olabilir ve bir boru hattı üzerinde kullanmaktan vb çalışmıyor)


Tırnak ekleme değil yeterli sen söyleyemezsin tıpkı - bir kabuk ancak ne yapacağını bilmek echo rm "first file.txt" "second file.txt"gelen herhangi bir şekilde farklı olduğunu echo rm "first" "file.txt" "second" "file.txt"her ikisi de aynı olmaktan çıktı. Eğer çıkış olarak bir kabuk komutu oluşturmak istiyorsanız, bir gerekir kullanmak printf '%q ' rm "first file.txt" "second file.txt"; echoya da bir şey eşdeğer olduğunu değerlendirir alıntı sözdizimsel yeniden oluşturduğu argvgeçti.
Charles Duffy

@CharlesDuffy ben gerçekten kimse çıkışını ve kabukta çalışır o ayıklama copy-paste umut!
Kusalananda

1
Kabuk komutları oluşturmak ve daha sonra bunları oluşturmak shsıra dışı bir model değildir ve insanların " foobir komut satırında çalıştırdığımda neden çalıştığını, ancak satırın echoönünde tam olarak bu dizeyi yayan bu komut dosyasının sormadığını görmek. " olur her zaman burada. Daha da önemlisi, hata ayıklama çıktısı hatalarınızı gizlerse yararlı olmaz - ve hatalarınız alıntı ile ilgili ise, echobunları ortaya çıkarmaz.
Charles Duffy

27

@ Kusalananda'nın iyi cevabının üzerine fazladan bir not .

echo run after_bundle

iyidir çünkü bu 3 argümandaki karakterlerin hiçbiri echokabuğa özel karakterler içermez.

Ve (burada yapmak istediğim ekstra nokta), bu baytların kabuğa özel karakterlere çevirebileceği bir sistem yerel ayarı yok.

Tüm bu karakterler POSIX'in taşınabilir karakter setini çağırdığı karakterdedir . Bu karakterler bulunmalı ve POSIX sistemindeki tüm karakter kümelerinde aynı şekilde kodlanmalıdır²².

Böylece bu komut satırı, yerel ayardan bağımsız olarak aynı şekilde yorumlanacaktır.

Şimdi, bu taşınabilir karakter kümesinin dışındaki karakterleri kullanmaya başlarsak, kabuğa özel olmasalar bile bunları alıntılamak iyi bir fikirdir, çünkü başka bir yerde, onları oluşturan baytlar, farklı karakterler olarak yorumlanabilir kabuk için özel. İster echobaşka bir komut kullanıp kullanmadığınızı , sorunun echokabuğun kodunu nasıl ayrıştırdığı ile ilgili olduğunu unutmayın .

Örneğin bir UTF-8'de:

echo voilà | iconv -f UTF-8 -t //TRANSLIT

Bu à0xc3 0xa0 olarak kodlanır. Şimdi, bir kabuk komut dosyasında bu kod satırına sahipseniz ve kabuk komut dosyası, karakteri UTF-8 olmayan bir yerel ayar kullanan bir kullanıcı tarafından çağrılırsa, bu iki bayt çok farklı karakterler oluşturabilir.

Örneğin, bir fr_FR.ISO8859-15yerel ayarda, Fransızca dilini (İngilizce dahil çoğu batı Avrupa dili için kullanılanla aynı) kapsayan standart tek baytlık karakter kümesi kullanan tipik bir Fransız yerel ayarı, 0xc3 baytının Ãkarakter olarak ve 0xa0'ın boşluk karakteri.

Ve NetBSD³ gibi birkaç sistemde, bu kırılmayan boşluk boş bir karakter olarak kabul edilir ( isblank()üzerinde doğru döner, eşleştirilir [[:blank:]]) ve bashbu nedenle kabukları sözdiziminde bir token sınırlayıcı olarak ele alır.

Çalışan yerine aracı That echoile $'voil\xc3\xa0'argüman olarak, onlar ile çalıştırmak $'voil\xc3'o baskı anlamına gelir argüman olarak voilàdoğru.

Bu kodlama ile aynı kodlama içeren birçok karakter BIG5, bıg5-HKSCS, GB18030, GBK gibi Çinli karakter setleri ile çok daha kötü olur |, `, \Microsoft Kanji aka hariç (ayrıca o gülünç SJIS (en kötü isim) bunun ¥yerine, çoğu araç tarafından 0x5c olarak kodlandığı için \işlem görüyor \).

Örneğin, bir zh_CN.gb18030Çin yerel ayarındaysanız, aşağıdaki gibi bir komut dosyası yazarsınız:

echo  reboot

Bu komut dosyası 詜 rebootGB18030 veya GBK 唰 rebootkullanan bir yerel ayarda, BIG5 veya BIG5-HKSCS kullanan bir yerel ayarda, ancak ASCII kullanan bir C yerel ayarında veya ISO8859-15 veya UTF-8 kullanan bir yerel ayarda reboot, GB18030 kodlaması nedeniyle çalıştırılmasına neden olur arasında 0xd4 0x7c ve 0x7c ait kodlama |koşuyoruz sonunda böylece ASCII:

 echo �| reboot

(bununla birlikte , 0xd4 baytının yerel ayarda oluşturulduğu anlamına gelir). unameBunun yerine daha az zararlı olanlara örnek reboot:

$ echo $'echo \u8a5c uname' | iconv -t gb18030 > myscript
$ LC_ALL=zh_CN.gb18030 bash ./myscript | sed -n l
\324| uname$
$ LC_ALL=C bash ./myscript | sed -n l
Linux$

( unameçalıştırıldı).

Bu yüzden tavsiyem, taşınabilir karakter kümesinin dışında karakter içeren tüm dizeleri alıntılamak olacaktır.

Ancak kodlaması beri unutmayın \ve `bu karakterlerin bazılarının kodlama bulunur, bu kullanımda daha iyi değil \ya "..."ya $'...'(iç `ve / veya \hala özeldir), ancak '...'bunun yerine taşınabilir karakter kümesi dışında karakterleri alıntı.

Charset 'kodlama kodlama içeren herhangi bir karakter ( tabii ki kendisi dışında) herhangi bir karakteri olan herhangi bir sistem farkında değilim ', bu yüzden bu '...'kesinlikle en güvenli olmalıdır.

Birkaç kabuğun $'\uXXXX', Unicode kod noktalarına göre karakterleri ifade etmek için bir gösterimi de desteklediğini unutmayın . Gibi kabukları içinde zshve bash(yani charset o karakteri yoksa beklenmedik davranışlar neden olabilir gerçi) karakteri yerelin charset kodlanmış eklenir. Bu, kabuk kodunuza ASCII olmayan karakterler eklemekten kaçınmanızı sağlar.

Yukarıda:

echo 'voilà' | iconv -f UTF-8 -t //TRANSLIT
echo '詜 reboot'

Veya:

echo $'voil\u00e0'
echo $'\u8a5c reboot'

(uyarıyla, bu karakterleri olmayan yerel bölgelerde çalıştırıldığında komut dosyasını kırabilir).

Ya da daha iyisi, \aynı zamanda echo(ya da en azından bazı echo uygulamalar, en azından Unix uyumlu olanları) özel olduğu için:

printf '%s\n' 'voilà' | iconv -f UTF-8 -t //TRANSLIT
printf '%s\n' '詜 reboot'

( \ilk argümanında da özel olduğunu unutmayın printf, bu nedenle ASCII olmayan karakterlerin kodlamasını içerebilmeleri durumunda da bundan daha iyi kaçınılmalıdır \).

Şunları da yapabileceğinizi unutmayın:

'echo' 'voilà' | 'iconv' '-f' 'UTF-8' '-t' '//TRANSLIT'

(aşırıya kaçabilir ama taşınabilir karakter setinde hangi karakterlerin olduğundan emin değilseniz size biraz huzur verebilir)

Ayrıca, eski `...`bir komut değiştirme şekli (başka bir ters eğik çizgi işleme düzeyi tanıtır) kullanmadığınızdan emin olun , $(...)bunun yerine kullanın.


¹ teknik olarak echoda argüman olarak geçirilen echofayda (o çağrılan nasıl anlatmamız), bu kadar argv[0]ve argcen kabuklarda günümüzde bile, 3'tür echoyerleşik olduğu böylece, exec()a /bin/echosimüle edilir 3 bağımsız değişkenler listesi ile dosyanın kabuk. Ayrıca, argümanların listesini ikinciden ( argv[1]to argv[argc - 1]) başlayarak düşünmek yaygındır, çünkü komutların esas olarak hareket ettiği budur.

² ja_JP.SJISKarakterleri \veya ~karakterleri olmayan FreeBSD sistemlerinin gülünç yeri olmasının dikkate değer bir istisnası !

Systems birçok sistem (FreeBSD, Solaris, GNU değil) UF + 8A0'ı [[:blank:]]UTF-8 yerel ayarlarında olarak görürken , bu tür sorunlardan kaçınmak için ISO8859-15 kullananlar gibi diğer yerel ortamlarda çok azının çalıştığını unutmayın .


İlk paragrafta olarak, "... geçirilen o 3 argüman karakterlerin bize echo, sadece 2 argümanlar komutuna geçirilen saymak ..." echo, ben olduğunu sayabilir argümanlar runve after_bundlebakım nasıl açıklamak sayıldı ve 3 argüman var mı?
Ferrybig

1
@ViktorFonic, bağımsız değişkenlerin sayısı hakkındaki düzenlemeye bakın (ve asıl sorunun bununla olmaması echo). Bkz (exec -a foo /bin/echo --help)bir GNU sisteminde ve rasgele bir ilk argüman geçirmek nasıl GNU kabuğu ile /bin/echoyarar.
Stéphane Chazelas

@Ferrybig Bkz. Stephane'nin düzenlemesi, dipnot 1. Her zamanki C stilinde komut verilecek argümanlar argv dizisidir ve argv [0] yürütülebilir adın kendisidir. $0Kabuklardaki benzer ve konumsal parametreler.
Sergiy Kolodyazhnyy

373 kodlama var iconvolan ESCdönüştürülür '. Deneyin (örnek olarak):printf '\x1b'|iconv -f utf8 -t IBM-937|xxd
Isaac

Bazı kod noktalarının (ESC dışında) a'ya dönüştürüldüğü 173 kodlama vardır '. Deneyin printf '\u2804' | iconv -f utf8 -t BRF | xxd. İçinde çok fazla kod noktasının bulunduğu kodlamalar vardır '. UCS-4'te yaklaşık 8695 kod noktası haline gelir '. Deneyin printf '\U627' | iconv -cf utf-8 -t UCS-4. Birkaç (37) kodlama 0x127 karakterini a dönüştürür '. Deneyinprintf '\U127' | iconv -cf utf8 -t UCS2 |xxd
Isaac
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.