SignalR セキュリティ入門 (SignalR 1.x)Introduction to SignalR Security (SignalR 1.x)

によって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.

概要Overview

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

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

認証と承認Authentication and authorization

アプリケーションの既存の認証の構造に統合するのには、SignalR は設計されています。SignalR is designed to be integrated into the existing authentication structure for an application. ユーザーを認証するための機能は行いません。It does not provide any features for authenticating users. 代わりに、アプリケーションでは、通常どおり、SignalR のコードで、認証の結果を使用すると、ユーザーを認証します。Instead, you authenticate users as you would normally in your application, and then 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属性は、ハブでのみ使用されます。The Authorize attribute is used only with hubs. 使用する場合は、承認規則を適用する、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 と認証されたユーザーのユーザー名を含む、接続トークンは、要求ごとに、クライアントとサーバー間で渡されます。A connection token, containing the connection id and username for authenticated users, is passed between the client and server for each request. 接続 id は、新しい接続が作成され、接続の期間が永続化されるときに、サーバーによってランダムに生成される一意の識別子です。The connection id is a unique identifier that is randomly generated by the server when a new connection is created, and is persisted for the duration of the connection. ユーザー名は、web アプリケーションの認証メカニズムによって提供されます。The username is provided by the authentication mechanism for the web application. 接続トークンは、暗号化とデジタル署名で保護されます。The connection token is protected with encryption and a digital signature.

要求ごとに、サーバーは、要求が、指定されたユーザーから送信されたことを確認するトークンの内容を検証します。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.

再接続時にグループの再参加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 is 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 アプリケーションに有効な要求を作成するを防ぐために、次の手順を受け取ります。SignalR takes the following steps to prevent a malicious site from creating valid requests to your SignalR application. これらの手順では、既定によって実行され、コード内のアクションを必要としません。These steps are taken by default and do not require any action in your code.

  • クロス ドメイン要求を無効にします。Disable cross domain requests
    既定では、クロス ドメイン要求が無効になっているで SignalR アプリケーションをユーザーが、外部ドメインから SignalR エンドポイントを呼び出すことを防ぐためにします。By default, cross domain requests are disabled in a SignalR application to prevent users from calling a SignalR endpoint from an external domain. 外部ドメインに由来するすべての要求が自動的に無効とみなされはブロックされます。Any request that comes from an external domain is automatically considered invalid and is blocked. この既定の動作を維持することをお勧めそれ以外の場合、悪意のあるサイトでは、サイトにコマンドを送信するのにユーザーをだましてでした。It is recommended 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 ではない接続トークンを渡すPass connection token in query string, not cookie
    SignalR は、代わりにクエリ文字列の値として接続トークンを cookie として渡します。SignalR passes the connection token as a query string value, instead of as a cookie. 接続トークンを cookie として保存しないで、接続トークンが誤っては転送されません、ブラウザーによって悪意のあるコードが検出されたとき。By not storing the connection token as a cookie, the connection token is not inadvertently forwarded by the browser when malicious code is encountered. また、接続トークンは、現在の接続以外は保持されません。Also, the connection token is not persisted beyond the current connection. そのため、悪意のあるユーザーは、別のユーザーの認証の資格情報で要求を作成することはできません。Therefore, a malicious user cannot make a request under another user's authentication credentials.
  • 接続トークンを確認します。Verify connection token
    」の説明に従って、接続トークン セクションで、サーバーでは、どの接続 id が各認証済みユーザーに関連付けられたがわかっています。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

悪意のあるユーザーが他のユーザーにスクリプトを送信しないことを確認する他のクライアントへのブロードキャストが想定されているクライアントからのすべての入力をエンコードする必要があります。All input from clients that is intended for broadcast to other clients must be encoded to ensure that a malicious user does not send script to other users. お勧め、サーバーではなく、受信側のクライアントにメッセージをエンコードする SignalR アプリケーションのさまざまな種類のクライアントの可能性があるためです。It is best to 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;
RouteTable.Routes.MapHubs("/signalr", 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.");
    }
}