perl -ne '...'実行のセキュリティリスク*

perl -ne '...'実行のセキュリティリスク*

明らかに、以下を実行します。

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 scriptperl

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;' -- *

しかし、それにもかかわらず、(モード)、(モード)、/(モード)のいずれかを使用するたびに、<>どの演算子を使用するかに応じて依然として危険です。-nsed -n-psed-a-Fawk-i

問題はperldoc perlopマニュアルで説明されています。

この特殊演算子は、シーケンスに渡された各引数から入力の1行(デフォルトではレコードは行です)を読み取るために使用されます@ARGV

存在する:

perl -pe '' a b

-pwhile (<>)コードの周りにループがあることを意味します(ここでは空です)。

<>まず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いいえユーザーのロケールでファイル名を解釈してください。

修正/解決方法

perlAFAIK、システム全体の安全でないデフォルト動作を完全に変更することはできません。

まず、ファイル名の先頭と末尾にある文字でのみ問題が発生します。では、いつperl -ne '' *またはperl -ne '' *.txt質問がありますか?

perl -ne 'some code' ./*.txt

これは、すべてのパラメータが、、、、空白ではないこと./から始めて終了するためではありません。より一般的には、プレフィックスを追加することをお勧めします。.txt-<>|そして./。これは、最初に他の多くのユーティリティ呼び出しやファイルに関連する-問題も回避します-(ここではオプションを閉じる(--)タグが必要なくなることを意味します)。

-Tオープンモードを使用すると役に立ちtaintます。これらの悪意のあるファイルが見つかると、コマンドは中断されます(>and|ケースにのみ適用され、<orスペースには適用されません)。

これは危険なことが進行中であることを警告するので、これらのコマンドを対話的に使用するときに非常に便利です。ただし、一部の自動処理を実行する場合は理想的ではないかもしれません。誰かがこれを行うことができるという意味だからです。処理ファイルを生成するだけでは失敗します。

名前に関係なくすべてのファイルを処理するには、次のものを使用できます。ARGV::readonly perlCPANのモジュール(残念ながら、通常はデフォルトではインストールされません。)これは非常に短いモジュールであり、実行される作業は次のとおりです。

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です。$ARGVyour code here

更新 2015-06-03

perlv5.21.5以降では、<<>>同様に動作する新しい演算子が<>ありますが、いいえ特別待遇を受けます。パラメータはファイル名としてのみ処理されます。したがって、これらのバージョンでは、次のように書くことができます。

perl -e 'while(<<>>){ ...;}' -- *

--(忘れたり使用しないでください./*)ファイルを上書きしたり、予期しないコマンドを実行したりすることを心配しないでください。

-n/しかし-pまだ危険な<>形式を使用してください。そしてシンボリックリンクはまだ追跡されているので、信頼できないディレクトリで使用しても安全であるという意味ではありません。

おすすめ記事