明らかに、以下を実行します。
perl -n -e 'some perl code' *
または
find . ... -exec perl -n -e '...' {} +
(-p
代替と同じ-n
)
または
perl -e 'some code using <>' *
このサイトに掲載されているジョークによく表示され、セキュリティ上のリスクが発生します。どうなりますか?それを避ける方法?
ベストアンサー1
問題は何ですか
まず、多くのユーティリティと同様に-
。
sh -c 'inline sh script here' other args
に渡される他の引数は次のとおりですinline sh script
。perl
perl -e 'inline perl script here' other args
その他のオプションについては、他のパラメータをスキャンしてください。真珠まず、インラインスクリプトではありません。たとえば、-eBEGIN{do something evil}
現在のディレクトリに呼び出されたファイルがある場合
perl -ne 'inline perl script here;' *
(あるかどうか-n
)悪いことをします。
--
他のユーティリティと同様に、回避策は閉じるタグ()オプションを使用することです。
perl -ne 'inline perl script here;' -- *
しかし、それにもかかわらず、(モード)、(モード)、/(モード)のいずれかを使用するたびに、<>
どの演算子を使用するかに応じて依然として危険です。-n
sed -n
-p
sed
-a
-F
awk
-i
問題はperldoc perlop
マニュアルで説明されています。
この特殊演算子は、シーケンスに渡された各引数から入力の1行(デフォルトではレコードは行です)を読み取るために使用されます@ARGV
。
存在する:
perl -pe '' a b
-p
while (<>)
コードの周りにループがあることを意味します(ここでは空です)。
<>
まずa
、ファイルを開き、ファイルがすべて使い果たされるまで、一度に1行ずつレコードを読み取り、開きますb
。
問題は、ファイルを開くときに最初の安全でない形式を使用することですopen
。
open ARGV, "the file as provided"
引数が次の場合は、この形式を使用してください。
"> afile"
、afile
書き込みモードで開きます。"cmd|"
、実行され、cmd
出力を読み取ります。"|cmd"
、に書き込む入力ストリームを開きますcmd
。
たとえば、
perl -pe '' 'uname|'
というファイルの内容uname|
(完全に有効なファイル名)を出力せずにコマンドの出力を出力しますuname
。
実行中の場合:
perl -ne 'something' -- *
誰かが現在のディレクトリに(やはり完全に有効なファイル名)という名前のファイルを作成しましたrm -rf "$HOME"|
(たとえば、ディレクトリに他の人が一度書き込んだ場合、信頼できないアーカイブを抽出した場合、信頼できないコマンドを実行しました場合、または他の脆弱性がある場合)。他のソフトウェアが悪用されている場合)大きな問題が発生します。問題領域は、自動的にファイルを処理するツールであることを認識することが重要です。人々同様の領域/tmp
(またはこれらのツールが呼び出すことができるツール)。
> foo
名前のfoo|
ファイル|foo
に問題があります。ただし、ある程度は、< foo
前後foo
にASCIIスペース文字(スペース、タブ、改行、cr ...を含む)が含まれていると、これらのファイルが処理されないか、間違ったファイルが生成されることを意味します。
また、一部のマルチバイト文字セット(ǖ
BIG5-HKSCSなど)の一部の文字は、バイト0x7cで終わります|
。
$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000 88 7c
210 |
0000002
したがって、この文字セットを使用するロケールでは、
perl -pe '' ./nǖ
./n\x88
コマンドの実行を試みますperl
いいえユーザーのロケールでファイル名を解釈してください。
修正/解決方法
perl
AFAIK、システム全体の安全でないデフォルト動作を完全に変更することはできません。
まず、ファイル名の先頭と末尾にある文字でのみ問題が発生します。では、いつperl -ne '' *
またはperl -ne '' *.txt
質問がありますか?
perl -ne 'some code' ./*.txt
これは、すべてのパラメータが、、、、空白ではないこと./
から始めて終了するためではありません。より一般的には、プレフィックスを追加することをお勧めします。.txt
-
<
>
|
球そして./
。これは、最初に他の多くのユーティリティ呼び出しやファイルに関連する-
問題も回避します-
(ここではオプションを閉じる(--
)タグが必要なくなることを意味します)。
-T
オープンモードを使用すると役に立ちtaint
ます。これらの悪意のあるファイルが見つかると、コマンドは中断されます(>
and|
ケースにのみ適用され、<
orスペースには適用されません)。
これは危険なことが進行中であることを警告するので、これらのコマンドを対話的に使用するときに非常に便利です。ただし、一部の自動処理を実行する場合は理想的ではないかもしれません。誰かがこれを行うことができるという意味だからです。処理ファイルを生成するだけでは失敗します。
名前に関係なくすべてのファイルを処理するには、次のものを使用できます。ARGV::readonly
perl
CPANのモジュール(残念ながら、通常はデフォルトではインストールされません。)これは非常に短いモジュールであり、実行される作業は次のとおりです。
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 }; };
デフォルトでは、たとえば変換して" foo|"
@ARGVをクリーンアップします。"< ./ foo|\0"
BEGIN
ステートメントでも同じことができますperl -n/-p
。
perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*
ここでは、私たちが使用する前提に基づいてこれを単純化します./
。
しかし、これの副作用は末尾のNUL文字がに表示されることARGV::readonly
です。$ARGV
your code here
更新 2015-06-03
perl
v5.21.5以降では、<<>>
同様に動作する新しい演算子が<>
ありますが、いいえ特別待遇を受けます。パラメータはファイル名としてのみ処理されます。したがって、これらのバージョンでは、次のように書くことができます。
perl -e 'while(<<>>){ ...;}' -- *
--
(忘れたり使用しないでください./*
)ファイルを上書きしたり、予期しないコマンドを実行したりすることを心配しないでください。
-n
/しかし-p
まだ危険な<>
形式を使用してください。そしてシンボリックリンクはまだ追跡されているので、信頼できないディレクトリで使用しても安全であるという意味ではありません。