SignalR Güvenliğine Giriş (SignalR 1.x)

, Patrick Fleti, Tom FitzMacken

Warning

Bu belge, SignalR 'nin en son sürümü için değildir. ASP.NET Core SignalR'ye göz atın.

Bu makalede, bir SignalR uygulaması geliştirirken göz önünde bulundurmanız gereken güvenlik sorunları açıklanmaktadır.

Genel bakış

Bu belgede aşağıdaki bölümler yer alır:

SignalR güvenlik kavramları

Kimlik doğrulaması ve yetkilendirme

SignalR, bir uygulamanın mevcut kimlik doğrulama yapısıyla tümleştirilecek şekilde tasarlanmıştır. Kullanıcıların kimliğini doğrulamak için herhangi bir özellik sağlamaz. Bunun yerine, uygulamanızda normalde yaptığınız gibi kullanıcıların kimliğini doğrular ve ardından SignalR kodunuzda kimlik doğrulamanın sonuçlarıyla çalışırsınız. Örneğin, ASP.NET Forms kimlik doğrulaması ile kullanıcılarınızın kimliğini doğrulayabilir ve sonra merkezinizdeki bir yöntemi çağırmak için hangi kullanıcıların veya rollerin yetkilendirileceğini zorlayabilirsiniz. Hub 'ınızda, Kullanıcı adı gibi kimlik doğrulama bilgilerini veya bir kullanıcının bir role ait olup olmadığını istemciye geçirebilirsiniz.

SignalR, hangi kullanıcıların bir hub veya metoda erişimi olduğunu belirtmek için Yetkilendir özniteliği sağlar. Yetkilendir özniteliğini bir hub 'da veya belirli yöntemlere uygularsınız. Yetkilendirme özniteliği olmadan, hub 'daki tüm ortak Yöntemler hub 'a bağlı bir istemci tarafından kullanılabilir. Hub 'lar hakkında daha fazla bilgi için bkz. SignalR hub 'ları Için kimlik doğrulaması ve yetkilendirme.

Authorize özniteliği yalnızca Hub 'larla kullanılır. PersistentConnection kullanırken yetkilendirme kurallarını zorlamak için AuthorizeRequest metodunu geçersiz kılmanız gerekir. Kalıcı bağlantılar hakkında daha fazla bilgi için bkz. SignalR kalıcı bağlantıları Için kimlik doğrulaması ve yetkilendirme.

Bağlantı belirteci

SignalR, gönderenin kimliğini doğrulayarak kötü amaçlı komutları yürütme riskini azaltır. Kimliği doğrulanmış kullanıcılar için bağlantı kimliği ve Kullanıcı adı içeren bir bağlantı belirteci, istemci ile sunucu arasında her istek için geçirilir. Bağlantı kimliği, yeni bir bağlantı oluşturulduğunda sunucu tarafından rastgele oluşturulan ve bağlantı süresince kalıcı olan benzersiz bir tanımlayıcıdır. Kullanıcı adı, Web uygulaması için kimlik doğrulama mekanizması tarafından sağlanır. Bağlantı belirteci, şifreleme ve dijital imza ile korunur.

Her istek için sunucu, isteğin belirtilen kullanıcıdan geldiğinden emin olmak için belirtecin içeriğini doğrular. Kullanıcı adı bağlantı kimliğine karşılık gelmelidir. SignalR hem bağlantı kimliğini hem de Kullanıcı adını doğrulayarak kötü niyetli bir kullanıcının başka bir kullanıcıyı kolayca taklit etmesini engeller. Sunucu bağlantı belirtecini doğrulayamazsa istek başarısız olur.

Bağlantı kimliği doğrulama işleminin bir parçası olduğundan, bir kullanıcının bağlantı kimliğini diğer kullanıcılara açığa çıkarmamalıdır veya bir tanımlama bilgisinde olduğu gibi istemci üzerindeki değeri depolamamalısınız.

Yeniden bağlanıldığında grupları yeniden birleştirme

Varsayılan olarak, SignalR uygulaması, bağlantı zaman aşımına uğramadan önce bir bağlantının düşürülme ve yeniden oluşturulması gibi geçici bir kesintiden yeniden bağlanıldığında bir kullanıcıyı uygun gruplara otomatik olarak yeniden atar. Yeniden bağlanıldığında, istemci bağlantı kimliği ve atanan grupları içeren bir grup belirteci geçirir. Grup belirteci dijital olarak imzalanır ve şifrelenir. İstemci, bir yeniden bağlantıdan sonra aynı bağlantı kimliğini korur; Bu nedenle, yeniden bağlanan istemciden geçirilen bağlantı kimliğinin, istemci tarafından kullanılan bir önceki bağlantı kimliğiyle eşleşmesi gerekir. Bu doğrulama, kötü niyetli bir kullanıcının yeniden bağlanıldığında yetkisiz gruplara katılması için istekleri geçmesini engeller.

Ancak, Grup belirtecinin süre sonu olmadığı unutulmamalıdır. Bir Kullanıcı geçmişte bir gruba aitdi, ancak bu gruptan yasaklanmış ise, bu kullanıcı yasaklanmış grubu içeren bir grup belirtecini taklit edebilir. Hangi kullanıcıların hangi gruplara ait olduğunu güvenli bir şekilde yönetmeniz gerekiyorsa, bu verileri sunucuda (örneğin,) bir veritabanında depolamanız gerekir. Ardından, uygulamanıza bir kullanıcının bir gruba ait olup olmadığını doğrulayan bir mantığı ekleyin. Grup üyeliğini doğrulama örneği için bkz. gruplarla çalışma.

Grupları otomatik olarak yeniden birleştirme işlemi yalnızca geçici bir kesinti sonrasında bağlantı yeniden bağlandığında geçerlidir. Kullanıcının bağlantısı kesilirse veya uygulama yeniden başlatıldıktan sonra, uygulamanız bu kullanıcının doğru gruplara nasıl ekleneceğini ele almalıdır. Daha fazla bilgi için bkz. gruplarla çalışma.

SignalR, siteler arası Istek sahteciliği nasıl engeller

Siteler arası Istek forgery (CSRF), kötü niyetli bir sitenin kullanıcının şu anda oturum açtığı bir güvenlik açığı olan siteye istek gönderdiği bir saldırıya neden olur. SignalR, kötü amaçlı bir sitenin SignalR uygulamanız için geçerli bir istek oluşturması için son derece olası bir durum oluşturarak CSRF 'yi önler.

CSRF saldırısı açıklaması

CSRF saldırılarına bir örnek aşağıda verilmiştir:

  1. Kullanıcı, Forms kimlik doğrulaması kullanarak www.example.comoturum açar.

  2. Sunucu, kullanıcının kimliğini doğrular. Sunucudan gelen yanıt bir kimlik doğrulama tanımlama bilgisi içerir.

  3. Oturum açmadan, Kullanıcı kötü amaçlı bir Web sitesi ziyaret ettiğinde. Bu kötü amaçlı site aşağıdaki HTML biçimini içerir:

    <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>
    

    Form eyleminin kötü amaçlı siteye değil, güvenlik açığı bulunan siteye gönderdiğine dikkat edin. Bu, CSRF 'nin "siteler arası" parçasıdır.

  4. Kullanıcı Gönder düğmesine tıklar. Tarayıcı, istekle kimlik doğrulama tanımlama bilgisini içerir.

  5. İstek, example.com sunucusunda kullanıcının kimlik doğrulama içeriğiyle çalışır ve kimliği doğrulanmış bir kullanıcının yapmasına izin verilen her şeyi yapabilir.

Bu örnek, kullanıcının form düğmesine tıklayabilmesine rağmen, kötü amaçlı sayfa yalnızca SignalR uygulamanıza yönelik bir AJAX isteği gönderen bir betiği kolayca çalıştırabilir. Üstelik, SSL kullanmak CSRF saldırılarına engel değildir çünkü kötü amaçlı site "https://" isteği gönderebilir.

Genellikle, tarayıcılar tüm ilgili tanımlama bilgilerini hedef Web sitesine gönderdikleri için kimlik bilgilerini kullanan Web sitelerine karşı CSRF saldırıları mümkündür. Ancak, CSRF saldırıları, tanımlama bilgilerini kötüye ile sınırlı değildir. Örneğin, temel ve Özet kimlik doğrulaması da savunmasız olacaktır. Kullanıcı temel veya Özet kimlik doğrulamasıyla oturum açtıktan sonra, oturum sona erene kadar tarayıcı kimlik bilgilerini otomatik olarak gönderir.

SignalR tarafından alınan CSRF azaltmaları

SignalR, kötü amaçlı bir sitenin SignalR uygulamanıza geçerli istekler oluşturmasını engellemek için aşağıdaki adımları alır. Bu adımlar varsayılan olarak alınır ve kodunuzda herhangi bir işlem gerektirmez.

  • Etki alanları arası istekleri devre dışı bırak
    Varsayılan olarak, kullanıcıların bir SignalR uygulamasında dış etki alanından bir SignalR uç noktası aramasını engellemek için, çapraz etki alanı istekleri bir SignalR uygulamasında devre dışıdır. Dış etki alanından gelen her türlü istek otomatik olarak geçersiz kabul edilir ve engellenir. Bu varsayılan davranışı tutmanız önerilir; Aksi takdirde, kötü amaçlı bir site kullanıcıların sitenize komut göndermesini sağlayabilir. Çapraz etki alanı istekleri kullanmanız gerekiyorsa bkz. etki alanları arası bağlantı oluşturma .
  • Bağlantı belirtecini tanımlama bilgisine değil sorgu dizesinde geçir
    SignalR bağlantı belirtecini tanımlama bilgisi olarak değil sorgu dizesi değeri olarak geçirir. Bağlantı belirtecini bir tanımlama bilgisi olarak depolamadığınızda, kötü amaçlı kod ile karşılaşıldığında bağlantı belirteci yanlışlıkla tarayıcı tarafından iletilmez. Ayrıca, bağlantı belirteci geçerli bağlantının ötesinde kalıcı değildir. Bu nedenle, kötü niyetli bir Kullanıcı başka bir kullanıcının kimlik doğrulama kimlik bilgileri altında istek yapamaz.
  • Bağlantı belirtecini doğrula
    Bağlantı belirteci bölümünde açıklandığı gibi, sunucu, kimliği doğrulanmış her kullanıcıyla ilişkili bağlantı kimliğini bilir. Sunucu, Kullanıcı adıyla eşleşmeyen bir bağlantı kimliğinden gelen isteği işlemez. Kötü amaçlı Kullanıcı Kullanıcı adını ve geçerli rastgele oluşturulan bağlantı kimliğini bilmemiz gerektiğinden, kötü niyetli bir kullanıcının geçerli bir isteği tahmin etmesi olası değildir. Bağlantı sona erdikten hemen sonra bu bağlantı kimliği geçersiz hale gelir. Anonim kullanıcıların herhangi bir hassas bilgilere erişimi olmamalıdır.

SignalR güvenlik önerileri

Güvenli Yuva katmanları (SSL) protokolü

SSL protokolü, istemci ve sunucu arasında veri aktarımını güvenli hale getirmek için şifrelemeyi kullanır. SignalR uygulamanız, istemci ve sunucu arasında hassas bilgiler gönderiyorsa, aktarım için SSL kullanın. SSL ayarlama hakkında daha fazla bilgi için bkz. IIS 7 ' de SSL ayarlama.

Grupları bir güvenlik mekanizması olarak kullanmayın

Gruplar ilgili kullanıcıları toplamanın kolay bir yoludur, ancak gizli bilgilere erişimin sınırlandırılmasının güvenli bir mekanizması değildir. Bu özellikle, kullanıcılar yeniden bağlanma sırasında gruplara otomatik olarak katılabileceği durumlarda geçerlidir. Bunun yerine, ayrıcalıklı kullanıcıları bir role eklemeyi ve bir hub yöntemine erişimi yalnızca o rolün üyelerine sınırlamayı göz önünde bulundurun. Bir role göre erişimi kısıtlama örneği için bkz. SignalR hub 'ları Için kimlik doğrulaması ve yetkilendirme. Yeniden bağlanıldığında, gruplara kullanıcı erişimini denetleme örneği için bkz. gruplarla çalışma.

İstemcilerden gelen girişi güvenle işleme

Diğer istemcilere yayın için tasarlanan istemcilerden gelen tüm girişler, kötü niyetli bir kullanıcının diğer kullanıcılara betik gönderemediğinden emin olmak için kodlanmalıdır. SignalR uygulamanızda birçok farklı türde istemci olabileceğinden, iletileri sunucu yerine alıcı istemcilere kodlamak en iyisidir. Bu nedenle, HTML kodlaması bir Web istemcisi için geçerlidir, ancak diğer istemci türlerine yönelik değildir. Örneğin, bir sohbet iletisini görüntüleyen Web istemcisi yöntemi, html() işlevini çağırarak kullanıcı adını ve iletisini güvenle işleyebilir.

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>');
};

Etkin bağlantıyla Kullanıcı durumunda değişiklik mutabık kılma

Etkin bağlantı varken kullanıcının kimlik doğrulama durumu değişirse, "Kullanıcı kimliği etkin bir SignalR bağlantısı sırasında değiştiremeyecektir." şeklinde bir hata alır. Bu durumda, bağlantı kimliği ve Kullanıcı adının koordine olduğundan emin olmak için uygulamanızın sunucuya yeniden bağlanması gerekir. Örneğin, uygulamanız etkin bir bağlantı varken kullanıcının oturumu açmasına izin veriyorsa, bağlantı için Kullanıcı adı artık sonraki istek için geçirilen adla eşleşmez. Kullanıcı oturumu kapatmadan önce bağlantıyı durdurup yeniden başlatmanız gerekir.

Ancak, çoğu uygulamanın bağlantıyı el ile durdurmanız ve yeniden başlatmanız gerektiğini unutmayın. Uygulamanız, bir Web Forms uygulaması veya MVC uygulamasındaki varsayılan davranış gibi, Kullanıcı oturum kapatıldıktan sonra ayrı bir sayfaya yeniden yönlendirirse veya oturum kapatıldıktan sonra geçerli sayfayı yenileirse, etkin bağlantının bağlantısı otomatik olarak kesilir ve ek eylem gerektirir.

Aşağıdaki örnek, Kullanıcı durumu değiştiğinde bir bağlantının nasıl durdurulacağını ve başlatılacağını gösterir.

<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>

Ya da sitenizin form kimlik doğrulaması ile kayan süre sonu kullanıyorsa ve kimlik doğrulama tanımlama bilgisinin geçerli tutulması için bir etkinlik yoksa kullanıcının kimlik doğrulaması durumu değişebilir. Bu durumda, Kullanıcı oturumu kapatılır ve Kullanıcı adı bağlantı belirtecindeki Kullanıcı adıyla eşleşmez. Kimlik doğrulama tanımlama bilgisinin geçerli tutulması için, Web sunucusunda düzenli aralıklarla bir kaynak isteyen bir betik ekleyerek bu sorunu çözebilirsiniz. Aşağıdaki örnek, her 30 dakikada bir kaynağın nasıl isteneceğini gösterir.

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

Otomatik olarak oluşturulan JavaScript proxy dosyaları

Her bir kullanıcı için JavaScript ara sunucu dosyasına tüm Hub 'ları ve yöntemleri dahil etmek istemiyorsanız, dosyanın otomatik olarak oluşturulmasını devre dışı bırakabilirsiniz. Birden çok hub ve yöntemlere sahipseniz ancak her kullanıcının tüm yöntemlerin farkında olmasını istemiyorsanız bu seçeneği belirleyebilirsiniz. Enablejavascriptproxy 'leri falseolarak ayarlayarak otomatik oluşturmayı devre dışı bırakabilirsiniz.

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableJavaScriptProxies = false;
RouteTable.Routes.MapHubs("/signalr", hubConfiguration);

JavaScript proxy dosyaları hakkında daha fazla bilgi için bkz. oluşturulan ara sunucu ve sizin için ne yapar.

Özel Durumlar

Nesneler, istemcilere hassas bilgiler sergilebileceğinden, istemcilere özel durum nesneleri geçirmekten kaçınmalısınız. Bunun yerine, ilgili hata iletisini görüntüleyen istemcisinde bir yöntemi çağırın.

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.");
    }
}