Sorun ne
İlk olarak, birçok yardımcı programda olduğu gibi, ile başlayan dosya adlarıyla ilgili bir sorun yaşarsınız -
. İçinde iken:
sh -c 'inline sh script here' other args
Diğer argümanlar inline sh script
; ile perl
eşdeğer
perl -e 'inline perl script here' other args
Diğer argümanlar , satır içi komut dosyasında değil, önce perl işleminde daha fazla seçenek için taranır . Örneğin, -eBEGIN{do something evil}
geçerli dizinde adı verilen bir dosya varsa ,
perl -ne 'inline perl script here;' *
(olan veya olmayan -n
) kötülük yapacak.
Diğer araçlarda olduğu gibi, bunun için çalışılması da seçenekler sonu işaretleyicisini ( --
) kullanmaktır:
perl -ne 'inline perl script here;' -- *
Fakat o zaman bile, hala tehlikelidir ve bu <>
, -n
/ tarafından kullanılan operatöre bağlıdır -p
.
Sorun perldoc perlop
belgelerde açıklanmıştır .
Bu özel operatör girişin bir satırını (bir kayıt, varsayılan olarak satırları kaydeder) okumak için kullanılır, burada o giriş her bir argümandan sırayla gelir @ARGV
.
İçinde:
perl -pe '' a b
-p
while (<>)
kodun etrafında bir döngü anlamına gelir (burada boş).
<>
açılacak a
, dosya tükenene kadar her seferinde bir satır kayıtları okuyacak ve sonra açacaktır b
...
Sorun şu ki, dosyayı açmak için ilk, güvensiz şeklini kullanıyor open
:
open ARGV, "the file as provided"
Argüman ise, bu formla
"> afile"
, afile
yazma modunda açılır ,
"cmd|"
, çalışır cmd
ve çıktılarını okur.
"|cmd"
, girişine yazmak için açık bir akışınız var cmd
.
Mesela:
perl -pe '' 'uname|'
uname|
Adı verilen dosyanın içeriğini ( btw olarak tamamen geçerli bir dosya adı) çıkarmaz, ancak uname
komutun çıktısını alır .
Eğer koşuyorsanız:
perl -ne 'something' -- *
Ve birisi rm -rf "$HOME"|
geçerli dizinde (yine de geçerli bir dosya adı) adlı bir dosya yarattı (örneğin, bu dizin bir zamanlar başkaları tarafından yazılabilirdi ya da çok tehlikeli bir arşiv çıkarttınız ya da çok tehlikeli bir komut çalıştırdınız ya da başka bir yazılımdaki başka bir güvenlik açığından yararlanıldı), o zaman başınız büyük belada. Bu sorunun farkında olmanın önemli olduğu alanlar , kamuya açık alanlarda /tmp
(veya bu araçlar tarafından çağrılabilecek araçlar) dosyaları otomatik olarak işleyen araçlardır.
Denilen Dosyalar > foo
, foo|
, |foo
bir sorun vardır. Ancak, daha az ölçüde < foo
ve foo
önde gelen veya sondaki ASCII boşluk karakterleri (boşluk, sekme, yeni satır, cr ... dahil) ile birlikte, bu dosyaların işlenmeyeceği veya yanlış olanın olacağı anlamına gelir.
Ayrıca bazı çok baytlık karakter kümelerindeki bazı karakterlerin ( ǖ
BIG5-HKSCS'de olduğu gibi) kodlaması olan bayt 0x7c ile bittiğine dikkat edin |
.
$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000 88 7c
210 |
0000002
Yani bu karakter dizisini kullanan yerel ayarlarda,
perl -pe '' ./nǖ
Çalıştırmayı denediğinizde misiniz ./n\x88
olarak komutunu perl
olur değil kullanıcının yerel ayar o dosya adını yorumlamaya çalışın!
Nasıl düzeltilir / çalışır
AFAIK, bir perl
kez ve tüm sistem genelinde güvenli olmayan varsayılan davranışını değiştirmek için yapabileceğiniz hiçbir şey yoktur .
İlk olarak, sorun yalnızca dosya adının başındaki ve sonundaki karakterlerle oluşur. Yani, ne zaman perl -ne '' *
ya perl -ne '' *.txt
da bir sorun
perl -ne 'some code' ./*.txt
Tüm bağımsız değişkenler şimdi ile başlamaz, çünkü ./
ve bitiş içinde .txt
(yani değil -
, <
, >
, |
..., uzay). Daha genel olarak, bu iyi bir fikir için önek var Neználkovo ile ./
. Bu, çağrılan -
veya -
başka birçok yardımcı programla başlayan dosyalardaki sorunları da önler (ve burada, seçeneklerin sonunu ( --
) artık işaretlemeye gerek duymazsınız).
Kullanımı -T
açmak için taint
mod bir ölçüde yardımcı olur. Böyle kötü amaçlı bir dosyayla karşılaşılırsa komutu iptal eder (ancak >
ve |
durumlar için değil, <
boşluklar için).
Bu tür komutları etkileşimli olarak kullanmanız yararlıdır, çünkü sizi tehlikeli bir şey olduğuna dair uyarır. Bazı otomatik işlemler yaparken bu arzu edilmeyebilir, çünkü bu işlem birisinin sadece bir dosya oluşturarak işlemi başarısız hale getirebileceği anlamına gelir .
Her dosyayı işlemek istiyorsanız, adından bağımsız olarak , ARGV::readonly
perl
modülü CPAN'da kullanabilirsiniz (ne yazık ki genellikle varsayılan olarak kurulmaz). Bu çok kısa bir modül yapar:
sub import{
# Tom Christiansen in Message-ID: <24692.1217339882@chthon>
# reccomends essentially the following:
for (@ARGV){
s/^(\s+)/.\/$1/; # leading whitespace preserved
s/^/< /; # force open for input
$_.=qq/\0/; # trailing whitespace preserved & pipes forbidden
};
};
Temel olarak, @ARGV'yi " foo|"
, örneğin içine çevirerek temizler "< ./ foo|\0"
.
Aynısını komutunuzdaki bir BEGIN
ifadede yapabilirsiniz perl -n/-p
:
perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*
Burada ./
kullanılmakta olan varsayımı basitleştiriyoruz .
(Ve bir yan etkisi ARGV::readonly
) rağmen olmasıdır $ARGV
olarak your code here
gösterir NULL karakteri arka olduğu.
Güncelleme 2015-06-03
perl
v5.21.5 ve üzeri , özel işlem yapmaması haricinde <<>>
davranan yeni bir operatöre sahiptir . Bağımsız değişkenler yalnızca dosya adları olarak kabul edilir. Yani bu sürümlerle, şimdi yazabilirsiniz:<>
perl -e 'while(<<>>){ ...;}' -- *
(unutma --
ya da kullanma ./*
), dosyaların üzerine yazma veya beklenmeyen komutları çalıştırmadan korkmadan.
-n
/ -p
yine de tehlikeli <>
formu kullanın . Ve dikkatin devam eden sembolik bağları takip etmeye devam edin, bu yüzden mutlaka güvenilmez dizinlerde kullanmanın güvenli olduğu anlamına gelmez.