Perlにはeval構文が2つあります:
エラーハンドリングの特徴:
$@にエラーメッセージが格納されます(エラーがあった場合)、そうでなければ$@は空です。eval BLOCKは速く、安全で、動的コードを実行する必要がない場合に好ましいです。eval STRINGは動的コード生成に便利ですが、文字列を追加でコンパイルするため遅く、潜在的に危険です。# eval BLOCKの使用例 my $result = eval { die "Error!" unless 1 + 1 == 2; return "OK"; }; if ($@) { warn "Error caught: $@"; } # eval STRINGの使用例 my $code = '$x = 1 + 2; $x;'; my $res = eval $code; if ($@) { warn "Eval string error: $@"; }
eval STRING内に動的に挿入される変数を適切にエスケープせずに配置した場合、追加のリスクが発生する可能性はありますか?
はい、挿入される文字列が特に外部から取得された変数(たとえばユーザー入力から)から生成される場合、セキュリティ/インジェクションの脅威があります。常にエスケープを使用するか、他のデータに対してeval STRINGを使用しないようにする必要があります。
my $user_code = 'system("rm -rf /");'; eval $user_code; # 非常に危険です!
物語
仮想マシンのパラメータをチェックするための監査スクリプトでeval STRINGを使用しており、データが外部設定ファイルから"誤って"読み取られていました。ある日、ファイルが置き換えられ、攻撃者のコードが実行され、サーバーが危険にさらされました。
物語
開発者は、潜在的なクラッシュ部分をeval BLOCKで囲むことで、実行時エラーだけでなくコンパイルエラー(たとえば、構文エラー)を"キャッチ"することを期待していました。しかし、構文エラー(たとえば、変数名のタイプミス)はeval BLOCKではキャッチされず、プロセスがクラッシュしました。
物語
Dumperダンプを介してeval STRINGで複雑なデータ構造をデシリアライズする際、文字列が有効なPerlコードのみを含むことを確認するのを忘れ、ユーザーがinput injectionを使用して実行可能なコードを追加し、サーバーで悪意のあるコマンドが実行されました。