Aracılığıyla paylaş


SignalR Güvenliğine Giriş

Patrick Fletcher, Tom FitzMacken

Uyarı

Bu belgeler SignalR'nin en son sürümüne yönelik değildir. SignalR ASP.NET Core göz atın.

Bu makalede SignalR uygulaması geliştirirken dikkate almanız gereken güvenlik sorunları açıklanmaktadır.

Bu konuda kullanılan yazılım sürümleri

Bu konunun önceki sürümleri

SignalR'nin önceki sürümleri hakkında bilgi için bkz. SignalR Eski Sürümleri.

Sorular ve yorumlar

Lütfen bu öğreticiyi nasıl beğendiğiniz ve sayfanın altındaki yorumlarda neleri geliştirebileceğimiz hakkında geri bildirim bırakın. Öğreticiyle doğrudan ilgili olmayan sorularınız varsa bunları ASP.NET SignalR forumunu veya StackOverflow.com gönderebilirsiniz.

Genel Bakış

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

SignalR Güvenlik Kavramları

Kimlik doğrulaması ve yetkilendirme

SignalR, kullanıcıların kimliğini doğrulamak için herhangi bir özellik sağlamaz. Bunun yerine SignalR özelliklerini bir uygulamanın mevcut kimlik doğrulama yapısıyla tümleştirirsiniz. Kullanıcıların kimliğini uygulamanızda normalde yaptığınız gibi doğrularsınız ve SignalR kodunuzda kimlik doğrulamasının sonuçlarıyla çalışırsınız. Örneğin, ASP.NET form kimlik doğrulaması ile kullanıcılarınızın kimliğini doğrulayabilir ve ardından hub'ınızda hangi kullanıcıların veya rollerin yöntem çağırma yetkisine sahip olduğunu zorunlu kabilirsiniz. Hub'ınızda, kullanıcı adı veya kullanıcının bir role ait olup olmadığı gibi kimlik doğrulama bilgilerini de istemciye geçirebilirsiniz.

SignalR, hub'a veya yönteme erişimi olan kullanıcıları belirtmek için Authorize özniteliğini sağlar. Authorize özniteliğini bir hub'a veya hub'daki belirli yöntemlere uygularsınız. Authorize özniteliği olmadan, hub'daki tüm genel yöntemler hub'a bağlı bir istemci tarafından kullanılabilir. Hub'lar hakkında daha fazla bilgi için bkz. SignalR Hubs için Kimlik Doğrulaması ve Yetkilendirme.

özniteliğini Authorize hub'lara uygularsınız ancak kalıcı bağlantılara uygulamazsınız. kullanırken PersistentConnection yetkilendirme kurallarını zorunlu kılmak için yöntemini geçersiz kılmanız AuthorizeRequest 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. her istek için istemci ve sunucu, kimliği doğrulanmış kullanıcıların bağlantı kimliğini ve kullanıcı adını içeren bir bağlantı belirteci geçirir. Bağlantı kimliği, bağlı her istemciyi benzersiz olarak tanımlar. Sunucu, yeni bir bağlantı oluşturulduğunda bağlantı kimliğini rastgele oluşturur ve bağlantı süresi boyunca bu kimliği kalıcı hale gelir. Web uygulamasının kimlik doğrulama mekanizması kullanıcı adını sağlar. SignalR, bağlantı belirtecini korumak için şifreleme ve dijital imza kullanır.

İstemci Yeni Bağlantı İsteğinden Alınan Sunucuya Bağlantı İsteğinden İstemci Alınan Yanıta Sunucu Yanıtı'na bir oku gösteren diyagram. Kimlik Doğrulama Sistemi, Yanıt ve Alınan Yanıt kutularında bir Bağlantı Belirteci oluşturur.

Her istek için, sunucu belirtecin içeriğini doğrular ve isteğin belirtilen kullanıcıdan gelmesini sağlar. Kullanıcı adı bağlantı kimliğine karşılık gelir. SignalR, hem bağlantı kimliğini hem de kullanıcı adını doğrulayarak kötü amaçlı bir kullanıcının başka bir kullanıcının kimliğine kolayca bürünmesini engeller. Sunucu bağlantı belirtecini doğrulayamazsa istek başarısız olur.

İstemci İsteği'nden Sunucu Tarafından Alınan İstekten Kaydedilen Belirteç'e bir oku gösteren diyagram. Bağlantı Belirteci ve İleti hem İstemci kutusunda hem de Sunucu kutusunda bulunur.

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 göstermemeli veya değeri bir tanımlama bilgisinde olduğu gibi istemcide depolamamalısınız.

Bağlantı belirteçleri ile diğer belirteç türleri karşılaştırması

Bağlantı belirteçleri zaman zaman güvenlik araçları tarafından işaretlenir çünkü bunlar oturum belirteçleri veya kimlik doğrulama belirteçleri gibi görünür ve bu da kullanıma sunulduğunda bir risk oluşturur.

SignalR'nin bağlantı belirteci bir kimlik doğrulama belirteci değildir. Bu isteği yapan kullanıcının bağlantıyı oluşturan kullanıcıyla aynı olduğunu onaylamak için kullanılır. ASP.NET SignalR bağlantıların sunucular arasında hareket etmesine izin verdiğinden bağlantı belirteci gereklidir. Belirteç bağlantıyı belirli bir kullanıcıyla ilişkilendirir ancak isteği yapan kullanıcının kimliğini onaylamaz. SignalR isteğinin doğru şekilde doğrulanması için kullanıcının kimliğini onaylayan tanımlama bilgisi veya taşıyıcı belirteç gibi başka bir belirtece sahip olması gerekir. Ancak, bağlantı belirtecinin kendisi isteğin o kullanıcı tarafından yapıldığına dair bir iddiada bulunmaz, yalnızca belirtecin içinde yer alan bağlantı kimliğinin bu kullanıcıyla ilişkili olduğunu iddia eder.

Bağlantı belirteci kendi kimlik doğrulama talebi sağlamadığından, "oturum" veya "kimlik doğrulaması" belirteci olarak kabul edilmez. Belirli bir kullanıcının bağlantı belirtecini alma ve farklı bir kullanıcı (veya kimliği doğrulanmamış istek) olarak doğrulanmış bir istekte yeniden yürütme başarısız olur çünkü isteğin kullanıcı kimliği ve belirteçte depolanan kimlik eşleşmez.

Yeniden bağlanırken gruplara yeniden katılma

Varsayılan olarak SignalR uygulaması, bağlantı zaman aşımına uğramadan önce bir bağlantının bırakılması ve yeniden kurulması gibi geçici bir kesintiden yeniden bağlanırken kullanıcıyı otomatik olarak uygun gruplara yeniden atar. Yeniden bağlanırken, istemci bağlantı kimliğini ve atanan grupları içeren bir grup belirteci geçirir. Grup belirteci dijital olarak imzalanır ve şifrelenir. İstemci, yeniden bağlantıdan sonra aynı bağlantı kimliğini korur; Bu nedenle, yeniden bağlanan istemciden geçirilen bağlantı kimliği, istemci tarafından kullanılan önceki bağlantı kimliğiyle eşleşmelidir. Bu doğrulama, kötü amaçlı bir kullanıcının yeniden bağlanırken yetkisiz gruplara katılmak için istek geçirmesini engeller.

Ancak, grup belirtecinin süresinin dolmadığını unutmayın. Bir kullanıcı geçmişte bir gruba aitse ancak bu gruptan yasaklanmışsa, 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 bir veritabanında olduğu gibi sunucuda depolamanız gerekir. Ardından, uygulamanıza bir kullanıcının bir gruba üye olup olmadığını doğrulayan bir mantık ekleyin. Grup üyeliğini doğrulama örneği için bkz. Gruplarla çalışma.

Gruplara otomatik olarak yeniden katılma yalnızca geçici bir kesintiden sonra bağlantı yeniden bağlandığında uygulanır. Bir kullanıcı uygulamadan uzaklaşarak bağlantıyı keserse veya uygulama yeniden başlatılırsa, uygulamanızın bu kullanıcıyı doğru gruplara nasıl ekleyeceğini işlemesi gerekir. Daha fazla bilgi için bkz . Gruplarla çalışma.

SignalR Siteler Arası İstek Sahteciliğini nasıl önler?

Siteler Arası İstek Sahteciliği (CSRF), kötü amaçlı bir sitenin kullanıcının şu anda oturum açtığı savunmasız bir siteye istek gönderdiği bir saldırıdır. SignalR, kötü amaçlı bir sitenin SignalR uygulamanız için geçerli bir istek oluşturmasını çok düşük bir olasılık haline getirerek CSRF'yi engeller.

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

CsRF saldırısı örneği aşağıda verilmiştir:

  1. Kullanıcı form kimlik doğrulaması kullanarak www.example.com oturum 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. Kullanıcı oturumu kapatmadan kötü amaçlı bir web sitesini ziyaret etti. Bu kötü amaçlı site aşağıdaki HTML formunu 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önderiler göndermesine dikkat edin. Bu, CSRF'nin "siteler arası" bölümüdür.

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

  5. İstek, kullanıcının kimlik doğrulama bağlamıyla example.com sunucusunda çalışır ve kimliği doğrulanmış bir kullanıcının gerçekleştirmesine izin verilen her şeyi yapabilir.

Bu örnek kullanıcının form düğmesine tıklamasını gerektirse de kötü amaçlı sayfa SignalR uygulamanıza AJAX isteği gönderen bir betiği aynı şekilde kolayca çalıştırabilir. Ayrıca, kötü amaçlı site bir "https://" isteği gönderebileceğinden SSL kullanılması CSRF saldırısını engellemez.

Genellikle, tarayıcılar tüm ilgili tanımlama bilgilerini hedef web sitesine gönderdiğinden kimlik doğrulaması için tanımlama bilgileri kullanan web sitelerine CSRF saldırıları yapılabilir. Ancak CSRF saldırıları, tanımlama bilgilerini kötüye kullanmakla sınırlı değildir. Örneğin, Temel ve Özet kimlik doğrulaması da savunmasızdır. Kullanıcı Temel veya Özet kimlik doğrulamasıyla oturum açtığında, oturum bitene kadar tarayıcı kimlik bilgilerini otomatik olarak gönderir.

SignalR tarafından alınan CSRF azaltmaları

SignalR, kötü amaçlı bir sitenin uygulamanıza geçerli istekler oluşturmasını önlemek için aşağıdaki adımları uygular. SignalR bu adımları varsayılan olarak uygular, kodunuzda herhangi bir işlem yapmanız gerekmez.

  • Etki alanları arası istekleri devre dışı bırakma SignalR, kullanıcıların dış etki alanından SignalR uç noktasını çağırmasını önlemek için etki alanları arası istekleri devre dışı bırakır. SignalR, dış etki alanından gelen tüm istekleri geçersiz olarak kabul eder ve isteği engeller. Bu varsayılan davranışı korumanızı öneririz; aksi takdirde, kötü amaçlı bir site kullanıcıları sitenize komut göndermeleri için kandırabilir. Etki alanları arası istekleri kullanmanız gerekiyorsa, bkz. Etki alanları arası bağlantı kurma .
  • Bağlantı belirtecini tanımlama bilgisinde değil sorgu dizesinde geçirme SignalR, bağlantı belirtecini tanımlama bilgisi yerine sorgu dizesi değeri olarak geçirir. Kötü amaçlı kodla karşılaşıldığında tarayıcı yanlışlıkla bağlantı belirtecini iletebileceğinden bağlantı belirtecinin bir tanımlama bilgisinde depolanması güvenli değildir. Ayrıca, bağlantı belirtecinin sorgu dizesine geçirilmesi, bağlantı belirtecinin geçerli bağlantının ötesinde kalıcı olmasını önler. Bu nedenle, kötü amaçlı bir kullanıcı başka bir kullanıcının kimlik doğrulaması kimlik bilgileri altında istekte bulunamaz.
  • Bağlantı belirtecini doğrulamaBağlantı belirteci bölümünde açıklandığı gibi, sunucu kimliği doğrulanmış her kullanıcıyla hangi bağlantı kimliğinin ilişkili olduğunu bilir. Sunucu, kullanıcı adıyla eşleşmeyen bir bağlantı kimliğinden gelen istekleri işlemez. Kötü amaçlı kullanıcının kullanıcı adını ve rastgele oluşturulan geçerli bağlantı kimliğini bilmesi gerekeceğinden, kötü amaçlı bir kullanıcının geçerli bir isteği tahmin etme olasılığı düşüktür. Bağlantı sona erer bitmez bu bağlantı kimliği geçersiz hale gelir. Anonim kullanıcıların hassas bilgilere erişimi olmamalıdır.

SignalR Güvenlik Önerileri

Güvenli Yuva Katmanları (SSL) protokolü

SSL protokolü, bir istemci ile sunucu arasında veri aktarımının güvenliğini sağlamak için şifreleme kullanır. SignalR uygulamanız istemci ve sunucu arasında hassas bilgiler aktarıyorsa, aktarım için SSL kullanın. SSL'yi ayarlama hakkında daha fazla bilgi için bkz. IIS 7'de SSL'yi ayarlama.

Grupları güvenlik mekanizması olarak kullanmayın

Gruplar, ilgili kullanıcıları toplamanın kolay bir yoludur, ancak hassas bilgilere erişimi sınırlamak için güvenli bir mekanizma değildir. Bu durum özellikle kullanıcılar yeniden bağlanma sırasında gruplara otomatik olarak yeniden bağlanabiliyorsa geçerlidir. Bunun yerine, bir role ayrıcalıklı kullanıcılar eklemeyi ve hub yöntemine erişimi yalnızca bu rolün üyeleriyle sınırlamayı göz önünde bulundurun. Rolü temel alarak erişimi kısıtlama örneği için bkz. SignalR Hubs için Kimlik Doğrulaması ve Yetkilendirme. Yeniden bağlanırken gruplara kullanıcı erişimini denetleme örneği için bkz. Gruplarla çalışma.

İstemcilerden gelen girişleri güvenli bir şekilde işleme

Kötü amaçlı bir kullanıcının diğer kullanıcılara betik göndermediğinden emin olmak için, diğer istemcilere yayın için tasarlanan istemcilerden gelen tüm girişleri kodlamanız gerekir. SignalR uygulamanızın birçok farklı istemci türü olabileceğinden iletileri sunucu yerine alıcı istemcilerde kodlamanız gerekir. Bu nedenle, HTML kodlaması bir web istemcisi için çalışır, ancak diğer istemci türleri için çalışmaz. Örneğin, bir sohbet iletisini görüntülemek için kullanılan bir web istemcisi yöntemi, işlevi çağırarak html() kullanıcı adını ve iletiyi güvenli bir şekilde 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ı durumundaki bir değişikliği mutabıklaştırma

Etkin bir bağlantı varken kullanıcının kimlik doğrulama durumu değişirse, kullanıcı "Etkin signalR bağlantısı sırasında kullanıcı kimliği değiştirilemez" hatasını alır. Bu durumda, bağlantı kimliğinin ve kullanıcı adının eşgüdümlü 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 oturumunu kapatmasına izin veriyorsa, bağlantının kullanıcı adı artık bir sonraki istek için geçirilen adla eşleşmez. Kullanıcı oturumu kapatmadan önce bağlantıyı durdurmak ve sonra yeniden başlatmak isteyeceksiniz.

Ancak, çoğu uygulamanın bağlantıyı el ile durdurması ve başlatması gerekmeyeceğini unutmayın. Uygulamanız, bir Web Forms uygulamasında veya MVC uygulamasında varsayılan davranış gibi oturumu kapattıktan sonra kullanıcıları ayrı bir sayfaya yönlendirirse veya oturumu kapattıktan sonra geçerli sayfayı yenilerse, etkin bağlantı otomatik olarak kesilir ve ek bir eylem gerektirmez.

Aşağıdaki örnek, kullanıcı durumu değiştiğinde bağlantının nasıl durdurulacağını ve başlatıldığı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>

Öte yandan, siteniz Forms Kimlik Doğrulaması ile kayan süre sonu kullanıyorsa ve kimlik doğrulama tanımlama bilgisini geçerli tutacak bir etkinlik yoksa kullanıcının kimlik doğrulama durumu değişebilir. Bu durumda, kullanıcı oturumu kapatılır ve kullanıcı adı artık bağlantı belirtecindeki kullanıcı adıyla eşleşmez. Kimlik doğrulama tanımlama bilgisinin geçerli kalmasını sağlamak için web sunucusundaki bir kaynağı düzenli aralıklarla isteyen bazı betikler ekleyerek bu sorunu çözebilirsiniz. Aşağıdaki örnekte her 30 dakikada bir kaynak isteme gösterilmektedir.

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

Otomatik olarak oluşturulan JavaScript proxy dosyaları

Her kullanıcı için tüm hub'ları ve yöntemleri JavaScript proxy dosyasına eklemek istemiyorsanız, dosyanın otomatik olarak oluşturulmasını devre dışı bırakabilirsiniz. Birden çok hub've yönteminiz varsa ancak her kullanıcının tüm yöntemlerin farkında olmasını istemiyorsanız bu seçeneği belirleyebilirsiniz. EnableJavaScriptProxies ayarını false olarak ayarlayarak otomatik oluşturmayı devre dışı bırakırsınız.

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

JavaScript proxy dosyaları hakkında daha fazla bilgi için bkz. Oluşturulan ara sunucu ve sizin için yaptıkları.

Özel durumlar

Özel durum nesnelerini istemcilere geçirmekten kaçınmanız gerekir çünkü nesneler hassas bilgileri istemcilere gösterebilir. Bunun yerine, istemcide ilgili hata iletisini görüntüleyen bir yöntem ç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.");
    }
}