JavaScriptを(ブラウザで)ハッキングするのはどれくらい簡単ですか?


37

私の質問はJavaScriptのセキュリティに関するものです。

BackboneAngularJSのようなJavaScriptフレームワークを使用し、安全なエンドポイントが必要な認証システムを想像してください。サーバーは常に最後の単語を持ち、あなたが望むことをする権限があるかどうかをチェックするので、それは問題ではありません。

しかし、サーバーを使用せずに少しのセキュリティが必要な場合はどうでしょうか?それは可能ですか?

たとえば、クライアント側のルーティングシステムがあり、ログインしたユーザーに対して具体的なルートを保護したいとします。したがって、保護されたルートへのアクセスを許可されているかどうかを確認するためにサーバーにpingを実行します。問題は、サーバーにpingを送信すると、応答を変数に保存するため、次回プライベートルートにアクセスしたときに、既にログインしている(サーバーにpingを送信していない)かどうか、および応答でそれが行くかどうか。

ユーザーがその変数を変更してアクセスするのは簡単ですか?

私のセキュリティ(およびJavaScript)の知識はあまり良くありません。しかし、変数がグローバルスコープ内になく、ゲッターのみを持ちセッターを持たないモジュールパターンのプライベート部分にある場合、その場合でも、ハッキングできますか?


29
これらすべての長い答え。要するに、ヘッダーに答えるには、「非常にハッキング可能」です。最初の2つの質問を互いにインラインで答えるには、「サーバーなしでセキュリティが失われました」と「いいえ」です。3番目の「非常に簡単」に答え、最後に「はい、簡単に」に答えます。行くぞ すべての質問に答えました。:P
SpYk3HH

主な例は、jQueryを任意のWebページに追加することに関する私のブログ投稿を参照してください。spyk3lc.blogspot.com/2013/05/…さあ、若いパダワン、出かけましょう。jQueryがまだないサイトにjQueryを追加するのがどれほど簡単かを確認してから、jqueryを使用して、JavaScriptの長い行なしでサイトの任意の部分を非常に簡単に操作します。ブーム!
SpYk3HH

7
かつて、ドメイン名を登録するとき、電話番号は必須フィールドでしたが、サーバー側ではなく、javascriptでのみ強制されていました。そのため、関数を再定義して(Firebugを使用)、それを無効にして無効にしました!彼らは私の電話番号を持っていません。
イズカタ

8
manipulate any part of the sight without long lines サイト対サイト
mplungjan

8
プロのWebプログラマーはそのようなことを正しくする必要があります。お願いします。これは、文法ナチの事:)よりも恥ずかしされplus.google.com/u/0/+MonaNomura/posts/h9ywDhfEYxT
mplungjan

回答:


26

これを読む前にヨアヒムの答えを読んでください。彼は、クライアント側の脆弱性の背後にある一般的な理由をカバーしています。さて、この問題を回避する方法を提案するために...

リクエストごとにサーバーで手動で認証する必要のないクライアント/サーバー通信の安全なスキーム:

あなたはしている今でも、サーバーが最後の発言権を持っせ、およびサーバは、まだクライアントが言うすべてを検証するために持っているが、それは透過的に行われます。

HTTPSプロトコルを想定して、中間者攻撃(MITMA)を防ぎます。

  • クライアントは初めてサーバーとハンドシェイクし、サーバーはクライアントの公開鍵生成し、非対称暗号化スキームを使用して秘密鍵保持します。クライアントは、サーバーの「公開」キーをローカルストレージに保存し、どこにも保存しない安全なパスワードで暗号化します。

  • これで、クライアントはオフラインになりました。クライアントは信頼できるアクションを実行したいと考えています。クライアントはパスワードを入力し、サーバーの公開キーを取得します。

  • クライアントはそのデータの知識に基づいてアクションを実行し、クライアントは実行するすべてのアクションをそのクライアントのサーバーの公開キー暗号化します

  • クライアントがオンラインの場合、クライアントはクライアントIDを送信し、クライアントが実行したすべてのアクションは、サーバーの公開キーで暗号化されたサーバーに送信されます。

  • サーバーはアクションを解読し、それらが正しい形式である場合、クライアントで発生したことを信頼します。

注意:

  • クライアントのパスワードをどこにも保存することはできません。そうしないと、攻撃者はキーを取得し、独自のアクションに署名することができます。このスキームのセキュリティは、サーバーがクライアント用に生成するキーの整合性のみに依存します。そのキーを要求するとき、クライアントはまだサーバーで認証される必要があります。

  • 実際に、クライアントではなくセキュリティをサーバーに依存しています。クライアントが実行するすべてのアクションは、サーバーで検証する必要があります。

  • Web Workerで外部スクリプトを実行することが可能です。あなたが持っているすべての JSONPリクエストは、今やはるかに大きなセキュリティ問題になっていることに留意しください。すべてのコストでキーを保護する必要があります。紛失すると、攻撃者はユーザーになりすますことができます。

  • これは、「サーバーへのpingを実行しない」という要求を満たします。攻撃者は、鍵を知らない場合、偽造データでHTTPリクエストを単純に模倣することはできません。

  • ヨアヒムの答えはまだ正しい。実際には、サーバーですべての認証実行しています。ここで保存した唯一のものは、毎回サーバーでのパスワード検証の必要性です。これで、コミットするとき、または更新されたデータをプルするときにのみサーバーに関与する必要があります。ここで行ったのは、クライアント側で信頼できるキーを保存し、クライアントにそれを再検証させることだけです。

  • これは、単一ページアプリケーション(AngularJSなど)の非常に一般的なスキームです。

  • サーバーの公開鍵をRSAのようなスキームで何を意味するのかを「公開」と呼びますが、実際にはスキーム内の機密情報であり、保護する必要があります。

  • パスワードをメモリ内のどこにも保管しません。ユーザーがオフラインコードの実行を開始するたびに、「オフライン」パスワードを送信するようにします。

  • 独自の暗号を転がさないでください -認証にはスタンフォード大学のような既知のライブラリを使用してください

  • このアドバイスをそのままお使いください。実際のビジネスに不可欠なアプリケーションでこの種の認証を行う前に、セキュリティの専門家に相談してください。これは深刻な問題であり、苦痛であり、間違いを起こしやすいものです。

他のスクリプトがページにアクセスできないことが重要です。つまり、Webワーカーで外部スクリプトのみを許可します。ユーザーがパスワードを入力したときにパスワードを傍受する可能性のある他の外部スクリプトを信頼することはできません。

使用promptしていない、あなたが完全にわからないと(それはイベントがそれへのアクセス権を持っていますが、唯一の同期コード内のポイントへのライブべきではない)その実行延期しない場合は、インラインパスワードフィールドを。また、実際にはパスワードを変数に保存しないでください。これも、ユーザーのコンピューターが危険にさらされていないことを信頼する場合にのみ機能します(ただし、サーバーに対する検証についても同様です)。

クライアントをまだ信用していないこと付け加えたいと思います。クライアントだけを信頼することはできません。Joachimの答えはそれを否定すると思います。作業を開始する前にサーバーをpingする必要がないという利便性のみを得ました。

関連資料:


3
「あなた自身の暗号を転がさないでください」というのは、プリミティブではなくプロトコルに当てはまります。人々は通常、自分のプリミティブを作るほど愚かではないが、彼らは素晴らしいプロトコルを作成できると考えているからです。また、ここでRSAが必要な理由もわかりません。HTTPSを使用しているので、なぜ16-32バイトの共有シークレットを生成し、将来のリクエストで送信する必要があるのですか?もちろん、これを行う場合は、文字列で時不変の等値チェックを必ず使用してください。
Reid

2
+1 @Reidええ、私は最近、これについて幾分かの専門家と議論しました。ここでプリミティブスキームは、(Rabin IIRCによって)学んだプロトコルに基づいていますが、少なくとも詳細が見つかるまで(そして、この場合に非対称暗号化が必要な理由を正当化するなど)少なくとも。最初にセキュリティ専門家に相談しないで、この答えで提案された計画を使用しないでください。私はこのアプローチがいくつかの場所で使用されているのを見てきましたが、実際にはそれはほとんどないことを意味します。また、答えを編集してそれを強化しました。
ベンジャミングリュンバウム

プロンプトを使用しても、セキュリティはほとんど追加されません。攻撃者はwindow.prompt、パスフレーズを傍受するためにメソッドをオーバーライドしたり、独自のプロンプトを(おそらくiframe内で!)起動したりできます。パスワードフィールドにはもう1つの利点があります。文字は表示されません。
ロブW

@RobWもちろん、ページが侵害された場合、このスキーム全体は価値がありません。攻撃者がページでJavaScriptを実行するためのアクセス権を持っている場合、私たちは台無しにされています。プロンプトの背後にある考え方は、それがブロックされているということでしたが、あなたは正しい、それが提供するセキュリティ上の利点は疑わしいです。リストの最後のリンクを参照してください。
ベンジャミングリュンバウム

1
まず第一に。素晴らしい答え、私は他に何も要求できないと思います。一方で、私は(そしてもちろんそれを使いたい人のために)ペットプロジェクトをやりたいと思っていましたが、これは多すぎるかもしれません(多分そうではないかもしれません)。つまり、深刻なことは何もしたくありません。あなたが説明したこの種の認証、知識の不足は、私にはできないと思います。単純な401チェックを実行するか、リクエストがない場合は、そのようなルートにアクセスするたびにサーバーにpingするだけだと思います。認証トークンもオプションです(おそらく、ここで説明した内容に関連する最も近いもの)。ありがとう:)
イエスロドリゲス

89

簡単です。攻撃者がクライアントを制御している場合、クライアントが指示どおりの操作のみを行うことに依存しているセキュリティメカニズムは危険にさらされる可能性があります。

クライアントでセキュリティチェックを行うことができます、「キャッシュ」として効果的に機能するためにのみです(クライアントが回答が「いいえ」であることを既に知っている場合にサーバーへの高価な往復を回避するため)。

一連のユーザーからの情報を保持する場合は、それらのユーザーのクライアントがその情報にアクセスしないようにしてください。「秘密データ」と「表示しないでください」という指示を一緒に送信すると、そのリクエストをチェックするコードを無効にするのは簡単になります。

ご覧のとおり、この回答ではJavaScript / Browserの詳細については言及していません。これは、クライアントが何であっても、この概念が同じだからです。ファットクライアント(従来のクライアント/サーバーアプリ)、旧式のWebアプリケーション、または広範なクライアント側JavaScriptを備えた単一ページアプリであるかどうかは、実際には関係ありません。

データがサーバーを離れると、攻撃者がデータに完全にアクセスできると想定する必要があります。


ありがとうございました。あなたがもう少し説明できるなら素敵でしょう、私のセキュリティ知識はそれほど良くありません、そして私が理解している唯一の部分は私が間違っているということです:P。キャッシュについて話すとき、それはサーバーがノーと言ったときにのみキャッシュすることですか?サーバーが一度「はい」と言ったら、それをキャッシュできませんよね?
イエスロドリゲス

3
私と思いちょうどそれがいることを追加したいです :)特にデバッガで、(モジュールのパターンのように、あなたの言及)ブラウザでアクセスクロージャ変数への可能性
ベンジャミンGruenbaum

2
@BenjaminGruenbaum:それをJS側のことに焦点を当てた答えに自由に拡張してください。ここでは、技術にとらわれない高レベルの概要のみを説明しました。JS自体に焦点を当てた答えもいいでしょう!
ヨアヒムザウアー

1
つまり、javascript変数に応じて何らかの情報/ルート/アクセス可能なものがあれば、そのプライベートなものにアクセスするために必要なものを簡単に変更できるため、いずれにしても安全ではありません。
イエスロドリゲス

4
@JoachimSauerあなたがうまく釘付けにしたこの質問のポイントを見逃すと思います。クライアントがどのセキュリティ対策を講じているかに関係なく、通信を危険にさらす可能性があります。JavaScriptで非常に強固な認証システムを作成できますが、他のクライアントが真実のソースとして扱うサーバーへの通信を挿入した瞬間には、何の価値もありません。ソースコードはすべてクライアント側に送信され、賢明な攻撃者はそれを読み取って、サーバーへのHTTPリクエストを模倣することができます。サーバーで検証されない限り、クライアントから発信されたものはすべて信頼できないものとして扱う必要があります。
ベンジャミングリュンバウム

10

ゲームコミュニティにクライアントは敵の手の中にいる」という格言があります。「。サーバーなどのセキュリティ保護された領域の外で実行されているコードは脆弱です。最も基本的なシナリオでは、そもそも実行されないことに対して脆弱です。実際に「セキュリティコード」を実行するのはクライアントの決定であり、ユーザーはネイティブコードを使用すると、少なくともアセンブリへの自動難読化と、それを操作するために攻撃者が優れたプログラマーである必要があるという事実による追加の保護層がありますが、JSは通常、難読化されずプレーンテキストとして提供されます。攻撃を仕掛けるのに必要なのは、プロキシサーバーやテキストエディターなどの原始的なツールだけです。攻撃者はプログラミングに関するある程度の教育が必要になりますが、実行可能ファイルにコードを挿入するよりも、テキストエディターを使用してスクリプトを変更する方が簡単です。


アセンブリは難読化ではなく、それ以外の場合はウォーゲームをプレイしたことがないと考えている人
miniBill

@miniBill:中程度の経験を積んだ攻撃者は、アセンブルされたコードに問題はありませんが、非常に基本的なハイパスフィルターを提供します。(悲しいことに、これはアカデミックです。スクリプトキディを
取り除く

1

これはJavaScriptをハッキングする問題ではありません。アプリを攻撃したい場合、プライベートプロキシを使用して、トラフィックをキャプチャ、変更、およびリプレイできます。提案されたセキュリティスキームには、それに対する保護が設定されていないようです。


0

特にAngularについて話す:

ルートクライアント側の保護は存在しません。ユーザーがいつでも入力できるルートにボタンを「非表示」にしても、Angularは文句を言いますが、クライアントはそれをコーディングできます。

ある時点で、コントローラーはビューのレンダリングに必要なデータをサーバーに要求する必要があります。ユーザーがそのデータにアクセスすることを許可されていない場合、サーバー側でこのデータを保護しているため、ユーザーはデータを受信しません、Angularアプリは401を適切に処理する必要があります。

生データを保護しようとしている場合、特定のユーザーが特定の方法でのみ共通データを表示できるようにしたい場合は、送信するのではなく、サーバー上でデータ「ビュー」を作成します生データをクライアントに送信し、それを再編成する(とにかく、パフォーマンス上の理由からこれを既に行う必要があります)。

サイドノート:Angularが要求するビューテンプレートに組み込まれている機密情報は絶対に使用しないでください。何らかのクレイジーな理由がある場合は、サーバー側のレンダリングを行う場合と同様に、サーバー側でこれらのビューテンプレートを保護する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.