JavaScriptには、ディスクへの読み書きを禁止し、他のブラウザーウィンドウまたはドメインへのアクセスを許可しないなどの特定の制限があります。しかし、悪意のあるコードの実行を防ぐために必要なことはそれだけですか?
JavaScriptはかなり強力であり、ブラウザが提供されたすべてのJavaScriptコードを疑いなく実行するのは奇妙に思えます。それはどのように安全ですか?
(標準は安全に設計されています。実装ないかもしれません。
ブラウザは、ブラウザプロセス自体の中で実行されるため、JavaScriptを分離します。ブラウザのJavaScriptインタープリタやJITコンパイラで許可されていないことはできません。ただし、その複雑さのために、JavaScriptがブラウザーを危険にさらしたり、ブラウザープロセスの権限を使用して任意のコードを実行したりできる脆弱性が見つかることも珍しくありません。
これらのタイプのセキュリティバグは非常に一般的であるため、多くのブラウザはサンドボックスを実装します。これは、侵害されたブラウザプロセスを分離し、それがさらに害を及ぼすのを防ぐための保護メカニズムです。サンドボックスの動作は、ブラウザによって異なります。 ChromeとEdgeにはサンドボックス化がかなりありますが、Firefoxのサンドボックス化は非常に制限されています。ただし、この多層防御にもかかわらず、ブラウザの脆弱性はサンドボックスエスケープの脆弱性と組み合わせることがよくあります。
どのように安全ですか?
そうではない。より正確には、ブラウザの実装と同じくらい安全です。ブラウザ(JavaScriptエンジンを含む)は複雑なソフトウェアであり、ユーザーが望んでいるため、新しい機能が定期的に追加されています。
つまり、既知の脆弱性が既知の脆弱性に対してコードをテストするための品質の手順を確実に備えている場合でも、機能を実装する際に検出されない欠陥のリスクが常に存在するということです。
現在、受け入れられている方法は、違反が検出されるとすぐに、修正を含む新しいバージョンがリリースされることです。しかし、違反の発見から修正のインストールまでの間に、ブラウザは脆弱です。そのため、 zero-day の脆弱性。
JavaScriptレベルでは、ブラウザーは実行中のコードをサンドボックス化するように設計されています(主に危険なAPIを公開しないことにより)が、JavaScriptは非常に複雑な解析および実行。
ECMAScriptはJavaScriptの背後にある標準です。今日私たちが経験している初心者に優しいプログラミング言語の周りの巨大なマーケティングインフレのため、ECMAScriptは高速に更新され、ランタイムに実装するためのますます複雑な機能を導入しています。
これにより、攻撃の範囲が広がり、バグが侵入することを可能にします。
wonderful の例は、Patrick Biernat、Markusの最近の作品ですGawndelen、pwn2own 2018のAmy Burnett。
http://blog.ret2.io/2018/06/05/pwn2own-2018-exploit-development/
ブログでは、WebKitで任意のコード実行を許可する0dayの発見と、それを使用してmacOSウィンドウマネージャーで別の0dayを悪用し、Sanbox Safariが実行されているエスケープする(それはSafariのものではなくmacOSサンドボックス。「ルート」にエスカレートしてシステムを所有します。
要するに、JavaScriptを有効にした状態でリンクにアクセスするだけで、macOSシステムが完全に危険にさらされ、ユーザーにグリッチが1つ表示されることはありません。
それがJavaScriptの安全性です。WebKitのJSCoreと同じくらい複雑なソフトウェアと同じくらい安全です。
そのため、高度なセキュリティを必要とするユーザーは、JavaScriptを無効にすることをお勧めします(これは、DarkWebなどではかなり一般的な要件です)。
上記の著者によって発見されたWebKitの脆弱性は、新しく導入されたガベージコレクターとarray.reverse
関数の間の競合状態です。逆になっているときにGCが配列のマーキングを開始すると、UAF(Use After Free)につながる可能性があります)エクスプロイト。マークは配列で順番に行われます。逆にすると、GCが配列の真ん中にあり、後半がマークされないため、収集のために選出され、結果としてUAFになります(配列オブジェクト自体は収集されません。その要素のみ)。
UAFを使用して任意のコード実行につながる可能性のあるより強力なエクスプロイトプリミティブを作成する方法は、ほぼ同じ手法のバリエーションです。最初に興味深いオブジェクトが新しく解放されたスペース(たとえば配列)に割り当てられ、次にRWプリミティブが割り当てられます。 (例えば、配列の境界を変更することにより)作成され、最後に任意のオペコードがメモリ(例えばJITされたページ)に書き込まれます。
この特定の0dayの詳細は、リンクされたブログにあります。
興味深いのは、この0dayが見つかった方法です。WebKitは非常に大きいため、膨大な労力をかけずに詳細なコードレビューを行うことは不可能であり、自動ジッターが設定されています。
これにより、数十万または数百万のコード行がある場合、各行を他のすべての行に対して適切に動作させることは非常に難しいという事実を反映させる必要があります。
他の回答で述べたように、各ブラウザーにはJavaScript実行をサンドボックス化するように設計された独自のスクリプトエンジンがあり、各エンジンは悪意のある動作につながる可能性があるJavaScript機能を制限しようとします。
しかし、原則として、JavaScriptはブラウザー内で安全ではありませんでした。悪意のあるコードの開発者は、悪意のある目標を達成するために、各エンジンの機能や利用可能なJavaScript機能を活用する方法を常に模索しています。
最初の数年間、JavaScriptはブラウザー内ではかなり危険でした。今では、悪意のあるコードの開発者とブラウザ/エンジンの開発者の間の絶え間ない競争であり、最終的には悪意のある開発者は、たとえ短時間であっても常に勝ちます。したがって、JavaScriptは安全とは言えません。 「現時点では安全である必要があります」は、より正確な方法です。
JavaScriptはかなり強力です
これが、多くのユーザーが安全ではないと考え、ブラウザ拡張機能を使用してブロックする理由です。 JavaScriptを使用すると、Webサイトは、ブラウザーをフィンガープリントしてCookieを削除した後にユーザーを特定することを含め、それなしでは不可能な方法でユーザーを追跡できます。 WebUSBのような新しいWeb APIの多くは、安全ではないものを許可しますが、ブラウザーはUSBやカメラなどの安全でないAPIにアクセスするときにユーザーの許可を要求します。
JavaScriptには本質的に安全なものはなく、多くの点で他の言語よりも安全性が低くなります。
安全性を提供するのは、ブラウザがJavaScriptを実行するサンドボックスです。 Chrome sandbox here )のドキュメントを参照してください。JavaScriptまたはECMAスクリプトへの参照がないことに注意してください。
現在、ブラウザーで実行されるコードの大部分はJavaScriptで記述されています。 WebAssembly の台頭により、ブラウザープラットフォームが今日の主に単一言語のロックイン(過去のメインフレームのような)から、WebAssembly準拠の言語を使用できるオープンプラットフォームに切り替わることが見られます。 。ある時点で、これはJavaScriptが特に安全/特別ではないことを証明します。その時点で、多くの言語がブラウザーで実行されるようになるからです。これらの言語はすべて、ブラウザが提供する sandbox を使用して実行します。
JavaScriptは「比較的安全」ですが、「完全に安全」ではありません。システムで実行するコードには、害を及ぼす可能性があります。使用したことがないシステムを除いて、完全に安全なシステムはありません。 JavaScriptは、未知のUSBデバイスをコンピューターに置くよりも安全で、怪しいウェブサイトからダウンロードしたり、疑わしいメールの添付ファイルを取得したりするよりも安全であり、ウェブサイトで見つけられるいくつかのスクリプトよりもはるかに安全です。それらをシェルにコピーして貼り付けます。
これには安全機能があります。プロセスを分離するのに役立つサンドボックス、任意のコンピューター命令の実行を回避するのに役立つセキュリティ制約がある比較的限定されたAPI、および指紋やクロスドメインデータ共有などの機密データの公開を制限するためのセキュリティコントロールです。これらは、悪意のある動作を制限するためにブラウザーバイナリに適用されるオペレーティングシステムのコントロールと、そのような攻撃を阻止するのに役立つアンチウイルスアプリケーションの上にあります。
ただし、絶対に安全というわけではありません。ブラウザのランタイムエンジン、ブラウザ自体、ウイルス対策、またはプロセッサ自体のバグはすべて、JavaScriptのセキュリティを危険にさらす可能性があります。システムは、最も弱いセキュリティと同じくらい安全です。 JavaScriptのセキュリティは、ほとんどの場合、「偶然の」エクスプロイト(初めて8歳のJavaScriptを学習し、誤ってエクスプロイトを作成するなど)を防ぐことを目的としていますが、熱心な攻撃者には対抗できません。 JavaScriptは非常に複雑で、おそらく奇妙で予期しない方法でバグが発生する可能性があります。
ハッキング、ペンのテスト、セキュリティに精通している人なら、ソースコードを閲覧したり、実行ファイルをデバッグしたり、他にできることは何でもできます。 JavaScript実装の弱点。また、JavaScriptは、これらのバグを見つける可能性のあるすべての可能なテストを自動化することさえ事実上不可能であるため、最初はそのような細かい部分が存在するほど十分に大きいです。
一般的に言えば、典型的なWebサイトで実行される可能性のある典型的なスクリプトはおそらく "安全"です。特に、主要な検索エンジンによってリンクされているものは特にそうです。しかし、いったん弱体化したパスを使い始めると、弱点が1つでもあれば、ある時点でシステムが危険にさらされる可能性が非常に高くなります。システムを完全に乗っ取るには、本当に優れたエクスプロイトが1つ、場合によっては2つまたは3つが必要です。
確かに、信頼できるサイト(私はこの目的のためにNoScriptを個人的に使用しています)に対してのみJavaScriptを有効にし、すべてのソフトウェアを常に最新の状態に保ち、無効な証明書などのブラウザーの警告に常に注意してください。それでも、100%安全ではありませんが、独自の緩和戦略に積極的に参加します。
ActiveXが使用するようなマシンレベルの実行可能コードと比較して安全です。
マシンコードプログラムは、オペレーティングシステムとライブラリがそのユーザーアカウントで実行されているプログラムに提供する任意のインターフェイスに疑いなくアクセスでき、ハードウェアとオペレーティングシステムが制限することによって、実行できることだけが実際に制限されます。それを実行しているユーザーと同じくらい強力です。提供されたインターフェースの一部をインターセプトすることによってそれを試みて制限するツールがあるかもしれませんが、それらを回避するためのそのような手段を認識しているプログラムを停止するのは困難です。
JavaScriptインタープリターはブラウザーの一部であり、インターフェースを実行しているプログラムとインターフェースに提供したいパワーのみを提供するように記述されています。
この回答は、質問で提起された2つのポイントと、質問で提起されていない1つのブラウザーの「機能」に対処します。
JavaScriptには、ディスクへの読み書きを防止するなどの特定の制限があります。
このような制限は、requestFileSystem
が定義されているChromium/Chromeブラウザでは技術的に存在せず、ディスクに直接書き込みます。つまり、File System
ユーザーのファイルシステムにあるChromium/Chrome構成ディレクトリのフォルダ。
参照 JavaScriptを使用してファイル(ユーザーディレクトリ)に書き込む方法
他のブラウザウィンドウやドメインへのアクセスを許可しない。
window
がすでに開かれているwindow
から開かれている場合、window
s間の通信は、postMessage
、MessageChannel
、SharedWorker
、または単にクエリ文字列パラメーター。
参照 共有Webワーカーにユーザースクリプトをロードするにはどうすればよいですか?
ここでChromium/Chromeに限定して提起する必要があるOPで言及されていないもう1つの点は、それらのブラウザーでのWeb Speech APIのSpeechRecognition
実装がユーザーの声(生体認証識別子)を記録し、その記録を送信するという事実です。発生していることをユーザーに直接助言することなく、リモートサービスに。記録が非公開の「Webサービス」または「削除」された時点で(永久に)保持されているかどうかは、すぐにはわかりません。
参照 デフォルトでは、webkitSpeechRecognitionは記録された音声をリモートWebサービスに送信しますか?