SignalR セキュリティ入門Introduction to SignalR Security

によってPatrick FletcherTom FitzMackenby Patrick Fletcher, Tom FitzMacken

Warning

このドキュメントは SignalR の最新バージョンはありません。This documentation isn't for the latest version of SignalR. 見てASP.NET Core SignalRします。Take a look at ASP.NET Core SignalR.

この記事では、SignalR アプリケーションを開発する際に考慮する必要があるセキュリティの問題について説明します。This article describes the security issues you must consider when developing a SignalR application.

このトピックで使用されるソフトウェアのバージョンSoftware versions used in this topic

このトピックの以前のバージョンPrevious versions of this topic

SignalR の以前のバージョンについては、次を参照してください。以前のバージョンの SignalRします。For information about earlier versions of SignalR, see SignalR Older Versions.

意見やご質問Questions and comments

このチュートリアルの良い点に関するフィードバックや、ページ下部にあるコメントで改善できる点をお知らせください。Please leave feedback on how you liked this tutorial and what we could improve in the comments at the bottom of the page. チュートリアルに直接関係のない質問がある場合は、ASP.NET SignalR フォーラムまたはStackOverflow.comにて投稿してください。If you have questions that are not directly related to the tutorial, you can post them to the ASP.NET SignalR forum or StackOverflow.com.

概要Overview

このドキュメントは、次のトピックに分かれています。This document contains the following sections:

SignalR セキュリティの概念SignalR Security Concepts

認証と承認Authentication and authorization

SignalR では、ユーザーを認証するための機能は提供されません。SignalR does not provide any features for authenticating users. 代わりに、アプリケーションの既存の認証の構造に SignalR の機能を統合します。Instead, you integrate the SignalR features into the existing authentication structure for an application. 通常、SignalR での認証の結果での作業、アプリケーションでのコードは、ユーザーを認証します。You authenticate users as you would normally in your application, and work with the results of the authentication in your SignalR code. たとえば、ASP.NET フォーム認証でユーザー認証を行うし、ハブ内にユーザーを適用する場合があります。 またはメソッドを呼び出す権限がロール。For example, you might authenticate your users with ASP.NET forms authentication, and then in your hub, enforce which users or roles are authorized to call a method. ハブでユーザー名またはユーザーがクライアントに、ロールに属しているかどうかなどの認証情報を渡すこともできます。In your hub, you can also pass authentication information, such as user name or whether a user belongs to a role, to the client.

SignalR の提供、 Authorizeハブまたはメソッドへのアクセスを持つユーザーを指定する属性。SignalR provides the Authorize attribute to specify which users have access to a hub or method. Authorize 属性を適用するには、ハブまたはハブのメソッドを特定します。You apply the Authorize attribute to either a hub or particular methods in a hub. Authorize 属性がない場合は、ハブのすべてのパブリック メソッドは、ハブに接続されているクライアント使用できます。Without the Authorize attribute, all public methods on the hub are available to a client that is connected to the hub. ハブの詳細については、次を参照してください。 SignalR ハブの認証と承認します。For more information about hubs, see Authentication and Authorization for SignalR Hubs.

適用する、Authorize属性をハブがいない永続的な接続します。You apply the Authorize attribute to hubs, but not persistent connections. 使用する場合は、承認規則を適用する、PersistentConnectionオーバーライドする必要があります、AuthorizeRequestメソッド。To enforce authorization rules when using a PersistentConnection you must override the AuthorizeRequest method. 永続的な接続の詳細については、次を参照してください。 SignalR 永続的な接続の認証と承認します。For more information about persistent connections, see Authentication and Authorization for SignalR Persistent Connections.

接続トークンConnection token

SignalR では、送信者の id を検証することで悪意のあるコマンドを実行するリスクを軽減します。SignalR mitigates the risk of executing malicious commands by validating the identity of the sender. 要求ごとに、クライアントとサーバー接続の id と認証されたユーザーのユーザー名が含まれた接続トークンを渡します。For each request, the client and server pass a connection token which contains the connection id and username for authenticated users. 接続 id は、各接続のクライアントを一意に識別します。The connection id uniquely identifies each connected client. サーバーは、新しい接続が作成され、接続の間にその id が解決しない場合、接続 id をランダムに生成します。The server randomly generates the connection id when a new connection is created, and persists that id for the duration of the connection. Web アプリケーションの認証メカニズムは、ユーザー名を提供します。The authentication mechanism for the web application provides the username. SignalR は、接続トークンを保護するのに暗号化とデジタル署名を使用します。SignalR uses encryption and a digital signature to protect the connection token.

要求ごとに、サーバーは、要求が、指定されたユーザーから送信されたことを確認するトークンの内容を検証します。For each request, the server validates the contents of the token to ensure that the request is coming from the specified user. ユーザー名は、接続 id に対応する必要があります。接続の id とユーザー名の両方を検証するには、ことでは、SignalR は、簡単に別のユーザーを偽装する悪意のあるユーザーを回避します。The username must correspond to the connection id. By validating both the connection id and the username, SignalR prevents a malicious user from easily impersonating another user. サーバーは、接続トークンを検証できません、要求は失敗します。If the server cannot validate the connection token, the request fails.

接続 id が検証プロセスの一部であるため、他のユーザーに 1 つのユーザーの接続 id を表示または cookie などのクライアントでは、値を格納しない必要があります。Because the connection id is part of the verification process, you should not reveal one user's connection id to other users or store the value on the client, such as in a cookie.

その他のトークンの種類との接続トークンConnection tokens vs. other token types

セッション トークンや認証トークンは、公開されている場合の危険にするため、セキュリティ ツールで接続トークンはフラグが場合があります。Connection tokens are occasionally flagged by security tools because they appear to be session tokens or authentication tokens, which poses a risk if exposed.

SignalR の接続トークンは、認証トークンはありません。SignalR's connection token isn't an authentication token. この要求を行ったユーザーが接続を作成したものと同じであることを確認に使用されます。It is used to confirm that the user making this request is the same one that created the connection. 接続トークンは、ASP.NET SignalR のサーバー間で移動する接続を許可するために必要があります。The connection token is necessary because ASP.NET SignalR allows connections to move between servers. トークンは、接続が特定のユーザーに関連付けられますが、要求を行ったユーザーの id をアサートしません。The token associates the connection with a particular user but doesn't assert the identity of the user making the request. SignalR 要求の認証が正しくが、他の cookie など、ユーザーの id をアサートするトークンまたはベアラー トークンが必要です。For a SignalR request to be properly authenticated, it must have some other token that asserts the identity of the user, such as a cookie or bearer token. ただし、接続トークン自体はそのユーザーに関連付けられた接続 ID は、トークン内に含まれるそれだけで、そのユーザーが、要求が行われた要求はありません。However, the connection token itself makes no claim that the request was made by that user, only that the connection ID contained within the token is associated with that user.

接続トークンは、独自の認証要求を提供しないため、見なさなかった「セッション」または"authentication"トークンです。Since the connection token provides no authentication claim of its own, it isn't considered a "session" or "authentication" token. 指定したユーザーの接続のトークンを取得し、別のユーザーとして認証された要求 (または、要求を認証されていない) でそれを再生するため失敗します、要求のユーザー id とトークンに格納されている id が一致しません。Taking a given user's connection token and replaying it in a request authenticated as a different user (or an unauthenticated request) will fail, because the user identity of the request and the identity stored in the token won't match.

再接続時にグループの再参加Rejoining groups when reconnecting

既定では、SignalR アプリケーションは自動的に再ユーザー グループに割り当てる適切な接続が削除され、接続がタイムアウトする前に再確立するなどの一時中断から再接続時に。再接続時に、クライアントは接続の id と割り当てられたグループを含むグループ トークンを渡します。By default, the SignalR application will automatically re-assign a user to the appropriate groups when reconnecting from a temporary disruption, such as when a connection is dropped and re-established before the connection times out. When reconnecting, the client passes a group token that includes the connection id and the assigned groups. グループのトークンはデジタル署名および暗号化します。The group token is digitally signed and encrypted. クライアントが保持する; 再接続後も同じ接続 idそのため、再接続のクライアントから渡された接続 id は、クライアントで使用される前の接続 id と一致する必要があります。The client retains the same connection id after a reconnection; therefore, the connection id passed from the reconnected client must match the previous connection id used by the client. この検証では、悪意のあるユーザーが再接続時に承認されていないグループの参加要求を渡すことを防ぎます。This verification prevents a malicious user from passing requests to join unauthorized groups when reconnecting.

ただしに注意してください、グループのトークンが失効しないことができます。However, it's important to note, that the group token does not expire. ユーザーが以前は、グループに属しているかが、そのグループから禁止されていますが、そのユーザーは禁止されているグループを含むグループ トークンを模倣することがあります。If a user belonged to a group in the past, but was banned from that group, that user may be able to mimic a group token that includes the prohibited group. どのグループに属するユーザーを安全に管理する必要がある場合は、データベースのようにサーバーで、そのデータを格納する必要があります。If you need to securely manage which users belong to which groups, you need to store that data on the server, such as in a database. 次に、サーバーで、ユーザーがグループに属しているかどうかを検証するアプリケーション ロジックを追加します。Then, add logic to your application that verifies on the server whether a user belongs to a group. グループ メンバーシップの確認の例は、次を参照してください。グループの操作します。For an example of verifying group membership, see Working with groups.

グループを自動的に再参加と、一時中断の後の接続が再接続されたときにのみ適用します。Automatically rejoining groups only applies when a connection is reconnected after a temporary disruption. によって、ユーザーが切断した場合、アプリケーションまたはアプリケーションが、アプリケーションが再起動を離れると、正しいグループにそのユーザーを追加する方法が処理する必要があります。If a user disconnects by navigating away from the application or the application restarts, your application must handle how to add that user to the correct groups. 詳細については、次を参照してください。グループの操作します。For more information, see Working with groups.

SignalR がクロスサイト リクエスト フォージェリを防止する方法How SignalR prevents Cross-Site Request Forgery

クロスサイト リクエスト フォージェリ (CSRF) は、悪意のあるサイトがで、ユーザーが現在ログインしている脆弱性のあるサイトに要求を送信する攻撃です。Cross-Site Request Forgery (CSRF) is an attack where a malicious site sends a request to a vulnerable site where the user is currently logged in. SignalR では、非常に SignalR アプリケーションの有効な要求を作成する悪意のあるサイトの可能性は低いので、CSRF ができないようにします。SignalR prevents CSRF by making it extremely unlikely for a malicious site to create a valid request for your SignalR application.

CSRF 攻撃の説明Description of CSRF attack

CSRF 攻撃の例を次に示します。Here is an example of a CSRF attack:

  1. www.example.com にユーザーが、フォーム認証の使用します。A user logs into www.example.com, using forms authentication.

  2. サーバーは、ユーザーを認証します。The server authenticates the user. サーバーからの応答には、認証 cookie が含まれています。The response from the server includes an authentication cookie.

  3. ログアウトすると、しなくてもユーザー悪意のある web サイトにアクセスします。Without logging out, the user visits a malicious web site. この悪意のあるサイトには、次の HTML フォームが含まれています。This malicious site contains the following HTML form:

    <h1>You Are a Winner!</h1>
    <form action="http://example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
        <input type="submit" value="Click Me"/>
    </form>
    

    フォームのアクションが悪意のあるサイトではない、脆弱性のあるサイトに投稿することに注意してください。Notice that the form action posts to the vulnerable site, not to the malicious site. これは、CSRF の"cross-site"の一部です。This is the "cross-site" part of CSRF.

  4. ユーザーは、[送信] ボタンをクリックします。The user clicks the submit button. ブラウザーには、要求の認証クッキーが含まれています。The browser includes the authentication cookie with the request.

  5. 要求では、ユーザーの認証コンテキストを持つ example.com サーバーで実行され、認証されたユーザーの実行が許可されたものを何でも実行できます。The request runs on the example.com server with the user's authentication context, and can do anything that an authenticated user is allowed to do.

この例には、ユーザーがフォームのボタンをクリックする必要がありますが、悪意のあるページは、SignalR アプリケーションに AJAX 要求を送信するスクリプトを簡単に実行する場合と同様でした。Although this example requires the user to click the form button, the malicious page could just as easily run a script that sends an AJAX request to your SignalR application. さらに、SSL を使用しても、CSRF 攻撃、悪意のあるサイトは、"https://"要求を送信できるので。Moreover, using SSL does not prevent a CSRF attack, because the malicious site can send an "https://" request.

通常、CSRF 攻撃は、認証 cookie を使用する web サイトに対して可能なブラウザーすべての関連クッキーを模擬 web サイトに送信するためです。Typically, CSRF attacks are possible against web sites that use cookies for authentication, because browsers send all relevant cookies to the destination web site. ただし、CSRF 攻撃では、cookie の利用に制限はありません。However, CSRF attacks are not limited to exploiting cookies. たとえば、基本認証とダイジェスト認証では、また脆弱です。For example, Basic and Digest authentication are also vulnerable. 基本認証またはダイジェスト認証を使用してユーザーのログオン、ブラウザーは、セッションが終了するまで自動的に資格情報を送信します。After a user logs in with Basic or Digest authentication, the browser automatically sends the credentials until the session ends.

SignalR 要した CSRF 対策CSRF mitigations taken by SignalR

SignalR は、悪意のあるサイトが、アプリケーションに有効な要求を作成するを防ぐために、次の手順を受け取ります。SignalR takes the following steps to prevent a malicious site from creating valid requests to your application. SignalR は、次の手順を既定では、コードで何もする必要はありません。SignalR takes these steps by default, you do not need to take any action in your code.

  • クロス ドメイン要求を無効にするSignalR は、ユーザーが、外部ドメインから SignalR エンドポイントを呼び出すことを防止するクロス ドメイン要求を無効にします。Disable cross domain requests SignalR disables cross domain requests to prevent users from calling a SignalR endpoint from an external domain. SignalR では、無効である、外部ドメインのすべての要求を考慮し、要求をブロックします。SignalR considers any request from an external domain to be invalid and blocks the request. この既定の動作を維持することをお勧めします。それ以外の場合、悪意のあるサイトでは、サイトにコマンドを送信するのにユーザーをだましてでした。We recommend that you keep this default behavior; otherwise, a malicious site could trick users into sending commands to your site. クロス ドメイン要求を使用する必要がある場合は、次を参照してください。ドメイン間の接続を確立する方法します。If you need to use cross domain requests, see How to establish a cross-domain connection .
  • クエリ文字列、cookie ではない接続トークンを渡すSignalR は、の代わりにクエリ文字列の値として接続トークンを cookie として渡します。Pass connection token in query string, not cookie SignalR passes the connection token as a query string value, instead of as a cookie. 悪意のあるコードが発生した場合に、ブラウザーは接続トークンを転送誤ってできるため、接続トークンを cookie に格納するセーフはありません。Storing the connection token in a cookie is unsafe because the browser can inadvertently forward the connection token when malicious code is encountered. また、クエリ文字列で接続トークンを渡すの現在の接続を超える永続化接続トークンが防止します。Also, passing the connection token in the query string prevents the connection token from persisting beyond the current connection. そのため、悪意のあるユーザーは、別のユーザーの認証の資格情報で要求を作成することはできません。Therefore, a malicious user cannot make a request under another user's authentication credentials.
  • 接続トークンを確認します。 」の説明に従って、接続トークン セクションで、サーバーでは、どの接続 id が各認証済みユーザーに関連付けられたがわかっています。Verify connection token As described in the Connection token section, the server knows which connection id is associated with each authenticated user. サーバーは、ユーザー名と一致しない接続 id からの要求を処理しません。The server does not process any request from a connection id that does not match the user name. 悪意のあるユーザーは、ユーザー名と、現在の接続をランダムに生成された id を知っている必要があるために、悪意のあるユーザーは有効な要求を推測でした可能性が高いことはできません。接続が終了するとすぐに、その接続 id が無効になります。It is unlikely a malicious user could guess a valid request because the malicious user would have to know the user name and the current randomly-generated connection id. That connection id becomes invalid as soon as the connection is ended. 匿名ユーザーには、機密情報へのアクセスはありません。Anonymous users should not have access to any sensitive information.

SignalR セキュリティに関する推奨事項SignalR Security Recommendations

セキュリティで保護されたソケット レイヤー (SSL) プロトコルSecure Socket Layers (SSL) protocol

SSL プロトコルは、クライアントとサーバー間のデータの転送をセキュリティで保護するのに暗号化を使用します。The SSL protocol uses encryption to secure the transport of data between a client and server. SignalR アプリケーションがクライアントとサーバー間で機密情報を送信する場合は、トランスポートの SSL を使用します。If your SignalR application transmits sensitive information between the client and server, use SSL for the transport. SSL の設定の詳細については、次を参照してください。 IIS 7 で SSL を設定する方法します。For more information about setting up SSL, see How to set up SSL on IIS 7.

セキュリティ メカニズムとしてグループを使用しませんDo not use groups as a security mechanism

グループは、関連するユーザーを収集する場合の便利な方法が、機密情報へのアクセスを制限するためのセキュリティで保護されたメカニズムではありません。Groups are a convenient way of collecting related users, but they are not a secure mechanism for limiting access to sensitive information. これは、ユーザーことができます、再接続中にグループを自動的に再参加するときに特に当てはまります。This is especially true when users can automatically rejoin groups during a reconnect. 代わりに、特権のあるユーザーをロールに追加して、そのロールのメンバーのみにハブ メソッドへのアクセスを制限することを検討してください。Instead, consider adding privileged users to a role and limiting access to a hub method to only members of that role. 役割に基づくアクセス制限の例は、次を参照してください。 SignalR ハブの認証と承認します。For an example of restricting access based on a role, see Authentication and Authorization for SignalR Hubs. 再接続時にユーザー グループへのアクセスのチェックの例は、次を参照してください。グループの操作します。For an example of checking user access to groups when reconnecting, see Working with groups.

安全にクライアントからの入力の処理Safely handling input from clients

悪意のあるユーザーが他のユーザーにスクリプトを送信しないことを確認するには、他のクライアントへのブロードキャストが想定されているクライアントからのすべての入力をエンコードする必要があります。To ensure that a malicious user does not send script to other users, you must encode all input from clients that is intended for broadcast to other clients. SignalR アプリケーションのさまざまな種類のクライアントの可能性があるため、サーバーではなく、受信側のクライアントにメッセージをエンコードする必要があります。You should encode messages on the receiving clients rather than the server, because your SignalR application may have many different types of clients. そのため、HTML エンコードと、web クライアントの場合、その他の種類のクライアントではなくは機能します。Therefore, HTML-encoding works for a web client, but not for other types of clients. たとえば、チャット メッセージを表示する web クライアントのメソッドは安全に処理、ユーザー名とメッセージ呼び出すことによって、html()関数。For example, a web client method to display a chat message would safely handle the user name and message by calling the html() function.

chat.client.addMessageToPage = function (name, message) {
    // Html encode display name and message. 
    var encodedName = $('<div />').text(name).html();
    var encodedMsg = $('<div />').text(message).html();
    // Add the message to the page. 
    $('#discussion').append('<li><strong>' + encodedName
        + '</strong>:  ' + encodedMsg + '</li>');
};

アクティブな接続のユーザーの状態の変更の調整Reconciling a change in user status with an active connection

アクティブな接続が存在する場合、ユーザーの認証の状態が変更された場合、ユーザーを示すエラーが表示されます、「ユーザー id をアクティブな SignalR 接続中に変更できません」If a user's authentication status changes while an active connection exists, the user will receive an error that states, "The user identity cannot change during an active SignalR connection." その場合は、アプリケーションでは、接続 id とユーザー名が調整されたことを確認するサーバーに接続する必要がありますし直します。In that case, your application should re-connect to the server to make sure the connection id and username are coordinated. たとえば、アプリケーションでは、アクティブな接続が存在する場合、ログアウトするユーザーを許可している場合、最後に次の要求で渡される名前が、接続のユーザー名と一致しなくなります。For example, if your application allows the user to log out while an active connection exists, the username for the connection will no longer match the name that is passed in for the next request. ユーザーがログアウトすると、前に、接続を停止してから再起動されます。You will want to stop the connection before the user logs out, and then restart it.

ただしは、ほとんどのアプリケーションが、手動で停止し、接続を開始する必要がないことに注意してください。However, it is important to note that most applications will not need to manually stop and start the connection. アクティブな接続が自動的に切断していないアプリケーション、Web フォーム アプリケーションまたは MVC アプリケーションの既定の動作など、ログインした後、別のページにユーザーをリダイレクトまたはログアウトした後は、現在のページを更新、追加アクションが必要です。If your application redirects users to a separate page after logging out, such as the default behavior in a Web Forms application or MVC application, or refreshes the current page after logging out, the active connection is automatically disconnected and does not require any additional action.

次の例では、停止し、ユーザーの状態が変更されたときに、接続を開始する方法を示します。The following example shows how to stop and start a connection when the user status has changed.

<script type="text/javascript">
    $(function () {
        var chat = $.connection.sampleHub;
        $.connection.hub.start().done(function () {
            $('#logoutbutton').click(function () {
                chat.connection.stop();
                $.ajax({
                    url: "Services/SampleWebService.svc/LogOut",
                    type: "POST"
                }).done(function () {
                    chat.connection.start();
                });
            });
        });
    });
</script>

または、サイトでは、スライド式有効期限を使用して、フォーム認証で有効な認証クッキーを保持するアクティビティがない場合、ユーザーの認証の状態を変更することがあります。Or, the user's authentication status may change if your site uses sliding expiration with Forms Authentication, and there is no activity to keep the authentication cookie valid. その場合は、ユーザーがログアウトして、ユーザー名は、接続トークン内のユーザー名と一致しなくなります。In that case, the user will be logged out and the user name will no longer match the user name in the connection token. この問題を修正するには、定期的に有効な認証クッキーを保持する web サーバー上のリソースを要求するいくつかのスクリプトを追加します。You can fix this problem by adding some script that periodically requests a resource on the web server to keep the authentication cookie valid. 次の例では、30 分ごとにリソースを要求する方法を示します。The following example shows how to request a resource every 30 minutes.

$(function () {
    setInterval(function() {
        $.ajax({
            url: "Ping.aspx",
            cache: false
        });
    }, 1800000);
});

自動的に生成された JavaScript プロキシ ファイルAutomatically generated JavaScript proxy files

ユーザーごとの JavaScript プロキシ ファイルにすべてのハブおよびメソッドを含めるしたくない場合は、ファイルの自動生成を無効にできます。If you do not want to include all of the hubs and methods in the JavaScript proxy file for each user, you can disable the automatic generation of the file. 複数のハブおよびメソッドがあるすべてのメソッドの対応するすべてのユーザーを作成したくない場合は、このオプションを選択する可能性があります。You might choose this option if you have multiple hubs and methods, but do not want every user to be aware of all of the methods. 自動生成を無効に設定してEnableJavaScriptProxiesfalseします。You disable automatic generation by setting EnableJavaScriptProxies to false.

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableJavaScriptProxies = false;
app.MapSignalR(hubConfiguration);

JavaScript プロキシ ファイルの詳細については、次を参照してください。 、生成されたプロキシとは何がします。For more information about the JavaScript proxy files, see The generated proxy and what it does for you.

例外Exceptions

オブジェクトは機密情報をクライアントに公開される可能性があるために、クライアントに例外オブジェクトを渡すことは避ける必要があります。You should avoid passing exception objects to clients because the objects may expose sensitive information to the clients. 代わりに、関連するエラー メッセージを表示するクライアントでメソッドを呼び出します。Instead, call a method on the client that displays the relevant error message.

public Task SampleMethod()
{
    try
    { 
        // code that can throw an exception
    }
    catch(Exception e)
    {
        // add code to log exception and take remedial steps

        return Clients.Caller.DisplayError("Sorry, the request could not be processed.");
    }
}