web-dev-qa-db-ja.com

JavaScriptの「eval()」のセキュリティ問題は何ですか?

誰かがeval()について言及するたびに、誰もがそれについて「セキュリティの問題」があると言いますが、誰がそれが何であるかについて詳細に行くことはありません。最新のブラウザのほとんどは、通常のコードと同様にeval()をデバッグできるようであり、パフォーマンスの低下に関する人々の主張は疑わしい/ブラウザに依存しています。

それで、もしあれば、eval()に関連する問題は何ですか? JavaScriptのeval()で悪用される可能性のあるものを思いつくことができませんでした。 (サーバー上のeval()のコードに問題があるようですが、クライアント側のeval()は安全なようです。)

23
Stack Tracer

eval()は、文字列をコードとして実行します。 eval()を使用するのは、文字列の内容が事前にわかっていないため、またはサーバー側で生成されることさえないためです。基本的に、JavaScript自体がクライアントで動的にのみ利用可能なデータから文字列を生成するため、eval()が必要です。

したがって、JavaScriptコードがコードを生成する状況では、eval()は意味があります。これは本質的にevilではありませんが、安全に行うことは困難です。プログラミング言語は、人間がコンピュータが理解できる命令を書くことができるように設計されています。そのため、どの言語も人間のプログラマーを助けるはずの小さな癖と特別な振る舞いでいっぱいです(例えば、JavaScriptのいくつかのステートメントの最後に「;」が自動的に追加されます)。これはすべて、「通常の」プログラミングにとっては素晴らしいものです。しかし、他のプログラムからコードを生成して、潜在的に敵対的である可能性のあるデータ(他のサイトユーザーからの文字列の抜粋など)に基づいている場合は、コードジェネレーターの開発者として、これらの癖allを理解し、敵意のあるデータが有害な方法でそれらを悪用するのを防ぎます。

その意味で、コードジェネレーター(およびeval())は、生のSQLと同じ概念的な問題とその結果 SQLインジェクション攻撃 を引き起こします。実行時に外部から提供されたパラメーターからのSQL要求を安全にアセンブルできますが、これには非常に多くの詳細に留意する必要があるため、通常のアドバイスはそうすることではありません。これは、通常の難解なセキュリティに関連しています。つまり、テストできません。コードの一部が正しいデータで正しく動作するかどうかをテストできますが、誤ったデータでは正しく動作しないことはありません。同様に、eval()を安全に使用することは可能ですが、実際には非常に難しいためお勧めしません。

これはすべて一般的に言われています。特定のコンテキストでは、eval()が安全な場合があります。ただし、実際にeval()を必要とするeval()を使用するためにコンテキストセーフにするためには、多少の労力が必要です。

30
Thomas Pornin

eval()はクロスサイトスクリプティングの可能なベクトルです。
通常の状況では、XSSを試みる攻撃者はスクリプトを取得したい場合があります<script></script>タグが配置されている可能性のあるエンコード、フィルター、またはファイアウォールを通過した。 eval()がユーザー入力で動作している場合は、スクリプトタグが不要になります。

Evalは、コードを難読化したり、禁止された文字をフィルターを通過させたりするのに役立つため、多くの悪意のあるスクリプトに存在します。このため、ユーザー入力でeval()がチェックされることがよくあります。したがって、eval()を使用すると、攻撃者に必要なツールの1つを提供する可能性があります。私は銀行を強奪しており、建物内の傘立てに束があるので、金属探知機のそばに銃をこっそり入れる必要がないことを知っています。

14
mcgyver5

他の人が説明したように、evalを使用して動的にコードを作成すると、プログラムの制御フローを理解することが難しくなります。ただし、document.write(...)object.innerHTML(...)など、実行時にコードを生成する他のすべての方法よりもevalの方が悪であるとは考えていません。これらは主にプログラムのDOMを変更するために使用されますが、新しいコードを挿入するためにも使用されます(つまり、コードにスクリプトステートメントを追加するか、onXXXXハンドラーを持つ新しい要素を追加します)。

また、evalは攻撃(XSS、不正広告など)でよく使用されますが、フィルターを回避したり、コードの実際の目的を隠したりするために、難読化された形式(z='ev'; z+='al'; v=window; v[z]("alert(1)")などのコード)で使用されることがよくあります。これは、呼び出しが難読化されているか、innerHTMLのような「良い」関数が不適切な目的で使用されているため、evalの明示的な呼び出しでコードをフィルターしようとするだけでは安全ではないことを意味します。

4
Steffen Ullrich

ここで述べた優れた点に加えて、明確にしたいと思います。eval()を使用するときに基本的に処理するのは、次の質問に答える必要があることです。

  • 確保する価値はありますか?
  • どの程度徹底的にセキュリティを確保できますか?そのレベルは許容範囲ですか?
  • コードベースと開発チームの今後の進化に対して安全性を維持できるという確信はどのくらいありますか?
  • 上記で必要なリスクと労力の量は、動的に生成された、場合によっては不明なコードの実行が不要になるようにコードを構築する労力とどのように比較されますか?

これらの質問を攻撃者がよりも完全に熟考し、それでもeval()の使用を検討している場合は、それを試してください。あなたは、あなたの開発キャリアの過程を通して、その原則の使用を単純に回避し始めると考えることにうんざりすることに気付くかもしれません。

2
S.C.