Bagikan melalui


Pengantar SignalR Security (SignalR 1.x)

oleh Patrick Fletcher, Tom FitzMacken

Peringatan

Dokumentasi ini bukan untuk versi terbaru SignalR. Lihat ASP.NET Core SignalR.

Artikel ini menjelaskan masalah keamanan yang harus Anda pertimbangkan saat mengembangkan aplikasi SignalR.

Gambaran Umum

Dokumen ini berisi bagian berikut:

Konsep Keamanan SignalR

Autentikasi dan Otorisasi

SignalR dirancang untuk diintegrasikan ke dalam struktur autentikasi yang ada untuk aplikasi. Ini tidak menyediakan fitur apa pun untuk mengautentikasi pengguna. Sebagai gantinya, Anda mengautentikasi pengguna seperti biasa di aplikasi Anda, lalu bekerja dengan hasil autentikasi dalam kode SignalR Anda. Misalnya, Anda dapat mengautentikasi pengguna dengan autentikasi formulir ASP.NET, lalu di hub Anda, memberlakukan pengguna atau peran mana yang berwenang untuk memanggil metode. Di hub, Anda juga dapat meneruskan informasi autentikasi, seperti nama pengguna atau apakah pengguna termasuk dalam peran, ke klien.

SignalR menyediakan atribut Otorisasi untuk menentukan pengguna mana yang memiliki akses ke hub atau metode. Anda menerapkan atribut Otorisasi ke hub atau metode tertentu di hub. Tanpa atribut Otorisasi, semua metode publik di hub tersedia untuk klien yang terhubung ke hub. Untuk informasi selengkapnya tentang hub, lihat Autentikasi dan Otorisasi untuk SignalR Hubs.

Atribut Authorize hanya digunakan dengan hub. Untuk menerapkan aturan otorisasi saat menggunakan, PersistentConnection Anda harus mengambil alih AuthorizeRequest metode . Untuk informasi selengkapnya tentang koneksi persisten, lihat Autentikasi dan Otorisasi untuk Koneksi Persisten SignalR.

Token koneksi

SignalR mengurangi risiko menjalankan perintah berbahaya dengan memvalidasi identitas pengirim. Token koneksi, yang berisi id koneksi dan nama pengguna untuk pengguna yang diautentikasi, diteruskan antara klien dan server untuk setiap permintaan. Id koneksi adalah pengidentifikasi unik yang dihasilkan secara acak oleh server ketika koneksi baru dibuat, dan dipertahankan selama durasi koneksi. Nama pengguna disediakan oleh mekanisme autentikasi untuk aplikasi web. Token koneksi dilindungi dengan enkripsi dan tanda tangan digital.

Sistem Token Koneksi Diagram, memperlihatkan hubungan antara Klien, Server, Sistem Autentikasi, dan Token Koneksi.

Untuk setiap permintaan, server memvalidasi konten token untuk memastikan bahwa permintaan berasal dari pengguna yang ditentukan. Nama pengguna harus sesuai dengan id koneksi. Dengan memvalidasi id koneksi dan nama pengguna, SignalR mencegah pengguna jahat dengan mudah meniru pengguna lain. Jika server tidak dapat memvalidasi token koneksi, permintaan gagal.

Diagram sistem Token Koneksi, memperlihatkan hubungan antara Klien, Server, dan Token Tersimpan.

Karena id koneksi adalah bagian dari proses verifikasi, Anda tidak boleh mengungkapkan id koneksi satu pengguna kepada pengguna lain atau menyimpan nilai pada klien, seperti dalam cookie.

Bergabung kembali dengan grup saat menyambungkan kembali

Secara default, aplikasi SignalR akan secara otomatis menetapkan ulang pengguna ke grup yang sesuai saat menyambungkan kembali dari gangguan sementara, seperti ketika koneksi diputuskan dan dibuat ulang sebelum waktu koneksi habis. Saat menyambungkan kembali, klien meneruskan token grup yang menyertakan id koneksi dan grup yang ditetapkan. Token grup ditandatangani secara digital dan dienkripsi. Klien mempertahankan id koneksi yang sama setelah koneksi ulang; oleh karena itu, id koneksi yang diteruskan dari klien yang terhubung kembali harus cocok dengan id koneksi sebelumnya yang digunakan oleh klien. Verifikasi ini mencegah pengguna jahat melewati permintaan untuk bergabung dengan grup yang tidak sah saat menyambungkan kembali.

Namun, penting untuk dicatat, bahwa token grup tidak kedaluwarsa. Jika pengguna termasuk dalam grup di masa lalu, tetapi dilarang dari grup tersebut, pengguna tersebut mungkin dapat menimpulkan token grup yang menyertakan grup yang dilarang. Jika Anda perlu mengelola pengguna mana yang termasuk dalam grup mana dengan aman, Anda perlu menyimpan data tersebut di server, seperti dalam database. Kemudian, tambahkan logika ke aplikasi Anda yang memverifikasi di server apakah pengguna termasuk dalam grup. Untuk contoh memverifikasi keanggotaan grup, lihat Bekerja dengan grup.

Bergabung kembali grup secara otomatis hanya berlaku saat koneksi disambungkan kembali setelah gangguan sementara. Jika pengguna terputus dengan menavigasi jauh dari aplikasi atau aplikasi dimulai ulang, aplikasi Anda harus menangani cara menambahkan pengguna tersebut ke grup yang benar. Untuk informasi selengkapnya, lihat Bekerja dengan grup.

Bagaimana SignalR mencegah Pemalsuan Permintaan Lintas Situs

Pemalsuan Permintaan Lintas Situs (CSRF) adalah serangan di mana situs berbahaya mengirim permintaan ke situs yang rentan tempat pengguna saat ini masuk. SignalR mencegah CSRF dengan membuatnya sangat tidak mungkin bagi situs berbahaya untuk membuat permintaan yang valid untuk aplikasi SignalR Anda.

Deskripsi serangan CSRF

Berikut adalah contoh serangan CSRF:

  1. Pengguna masuk ke www.example.com, menggunakan autentikasi formulir.

  2. Server mengautentikasi pengguna. Respons dari server mencakup cookie autentikasi.

  3. Tanpa keluar, pengguna mengunjungi situs web berbahaya. Situs berbahaya ini berisi formulir HTML berikut:

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

    Perhatikan bahwa tindakan formulir memposting ke situs yang rentan, bukan ke situs berbahaya. Ini adalah bagian "lintas situs" dari CSRF.

  4. Pengguna mengklik tombol kirim. Browser menyertakan cookie autentikasi dengan permintaan.

  5. Permintaan berjalan di server example.com dengan konteks autentikasi pengguna, dan dapat melakukan apa pun yang diizinkan untuk dilakukan oleh pengguna terautentikasi.

Meskipun contoh ini mengharuskan pengguna untuk mengklik tombol formulir, halaman berbahaya bisa dengan mudah menjalankan skrip yang mengirim permintaan AJAX ke aplikasi SignalR Anda. Selain itu, menggunakan SSL tidak mencegah serangan CSRF, karena situs berbahaya dapat mengirim permintaan "https://".

Biasanya, serangan CSRF dimungkinkan terhadap situs web yang menggunakan cookie untuk autentikasi, karena browser mengirim semua cookie yang relevan ke situs web tujuan. Namun, serangan CSRF tidak terbatas pada mengeksploitasi cookie. Misalnya, autentikasi Dasar dan Hash juga rentan. Setelah pengguna masuk dengan autentikasi Dasar atau Hash, browser secara otomatis mengirim kredensial hingga sesi berakhir.

Mitigasi CSRF yang diambil oleh SignalR

SignalR mengambil langkah-langkah berikut untuk mencegah situs berbahaya membuat permintaan yang valid ke aplikasi SignalR Anda. Langkah-langkah ini diambil secara default dan tidak memerlukan tindakan apa pun dalam kode Anda.

  • Menonaktifkan permintaan lintas domain
    Secara default, permintaan lintas domain dinonaktifkan dalam aplikasi SignalR untuk mencegah pengguna memanggil titik akhir SignalR dari domain eksternal. Setiap permintaan yang berasal dari domain eksternal secara otomatis dianggap tidak valid dan diblokir. Disarankan agar Anda menjaga perilaku default ini; jika tidak, situs berbahaya dapat mengelabui pengguna untuk mengirim perintah ke situs Anda. Jika Anda perlu menggunakan permintaan lintas domain, lihat Cara membuat koneksi lintas domain .
  • Meneruskan token koneksi dalam string kueri, bukan cookie
    SignalR meneruskan token koneksi sebagai nilai string kueri, bukan sebagai cookie. Dengan tidak menyimpan token koneksi sebagai cookie, token koneksi tidak diteruskan secara tidak sengaja oleh browser ketika kode berbahaya ditemui. Selain itu, token koneksi tidak bertahan di luar koneksi saat ini. Oleh karena itu, pengguna berbahaya tidak dapat membuat permintaan berdasarkan kredensial autentikasi pengguna lain.
  • Memverifikasi token koneksi
    Seperti yang dijelaskan di bagian Token koneksi , server mengetahui id koneksi mana yang terkait dengan setiap pengguna yang diautentikasi. Server tidak memproses permintaan apa pun dari id koneksi yang tidak cocok dengan nama pengguna. Tidak mungkin pengguna berbahaya dapat menebak permintaan yang valid karena pengguna jahat harus mengetahui nama pengguna dan id koneksi yang dihasilkan secara acak saat ini. Id koneksi tersebut menjadi tidak valid segera setelah koneksi berakhir. Pengguna anonim tidak boleh memiliki akses ke informasi sensitif apa pun.

Rekomendasi Keamanan SignalR

Protokol Secure Socket Layers (SSL)

Protokol SSL menggunakan enkripsi untuk mengamankan transportasi data antara klien dan server. Jika aplikasi SignalR Anda mengirimkan informasi sensitif antara klien dan server, gunakan SSL untuk transportasi. Untuk informasi selengkapnya tentang menyiapkan SSL, lihat Cara menyiapkan SSL di IIS 7.

Jangan gunakan grup sebagai mekanisme keamanan

Grup adalah cara mudah untuk mengumpulkan pengguna terkait, tetapi mereka bukan mekanisme yang aman untuk membatasi akses ke informasi sensitif. Ini terutama berlaku ketika pengguna dapat secara otomatis bergabung kembali dengan grup selama koneksi ulang. Sebagai gantinya, pertimbangkan untuk menambahkan pengguna istimewa ke peran dan membatasi akses ke metode hub hanya untuk anggota peran tersebut. Untuk contoh pembatasan akses berdasarkan peran, lihat Autentikasi dan Otorisasi untuk SignalR Hubs. Untuk contoh memeriksa akses pengguna ke grup saat menyambungkan kembali, lihat Bekerja dengan grup.

Menangani input dengan aman dari klien

Semua input dari klien yang ditujukan untuk disiarkan ke klien lain harus dikodekan untuk memastikan bahwa pengguna jahat tidak mengirim skrip ke pengguna lain. Yang terbaik adalah mengodekan pesan pada klien penerima daripada server, karena aplikasi SignalR Anda mungkin memiliki banyak jenis klien yang berbeda. Oleh karena itu, pengodean HTML berfungsi untuk klien web, tetapi tidak untuk jenis klien lain. Misalnya, metode klien web untuk menampilkan pesan obrolan akan menangani nama pengguna dan pesan dengan aman dengan memanggil html() fungsi .

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

Merekonsiliasi perubahan status pengguna dengan koneksi aktif

Jika status autentikasi pengguna berubah saat koneksi aktif ada, pengguna akan menerima kesalahan yang menyatakan, "Identitas pengguna tidak dapat berubah selama koneksi SignalR aktif." Dalam hal ini, aplikasi Anda harus terhubung kembali ke server untuk memastikan id koneksi dan nama pengguna dikoordinasikan. Misalnya, jika aplikasi Anda memungkinkan pengguna untuk keluar saat koneksi aktif ada, nama pengguna untuk koneksi tidak akan lagi cocok dengan nama yang diteruskan untuk permintaan berikutnya. Anda akan ingin menghentikan koneksi sebelum pengguna keluar, lalu memulai ulang.

Namun, penting untuk dicatat bahwa sebagian besar aplikasi tidak perlu menghentikan dan memulai koneksi secara manual. Jika aplikasi Anda mengalihkan pengguna ke halaman terpisah setelah keluar, seperti perilaku default dalam aplikasi Formulir Web atau aplikasi MVC, atau merefresh halaman saat ini setelah keluar, koneksi aktif secara otomatis terputus dan tidak memerlukan tindakan tambahan.

Contoh berikut menunjukkan cara menghentikan dan memulai koneksi saat status pengguna telah berubah.

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

Atau, status autentikasi pengguna dapat berubah jika situs Anda menggunakan kedaluwarsa geser dengan Autentikasi Formulir, dan tidak ada aktivitas untuk menjaga cookie autentikasi tetap valid. Dalam hal ini, pengguna akan keluar dan nama pengguna tidak akan lagi cocok dengan nama pengguna dalam token koneksi. Anda dapat memperbaiki masalah ini dengan menambahkan beberapa skrip yang secara berkala meminta sumber daya di server web agar cookie autentikasi tetap valid. Contoh berikut menunjukkan cara meminta sumber daya setiap 30 menit.

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

File proksi JavaScript yang dihasilkan secara otomatis

Jika Anda tidak ingin menyertakan semua hub dan metode dalam file proksi JavaScript untuk setiap pengguna, Anda dapat menonaktifkan pembuatan otomatis file. Anda dapat memilih opsi ini jika Anda memiliki beberapa hub dan metode, tetapi tidak ingin setiap pengguna menyadari semua metode. Anda menonaktifkan pembuatan otomatis dengan mengatur EnableJavaScriptProxies ke false.

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

Untuk informasi selengkapnya tentang file proksi JavaScript, lihat Proksi yang dihasilkan dan apa fungsinya untuk Anda.

Pengecualian

Anda harus menghindari meneruskan objek pengecualian ke klien karena objek dapat mengekspos informasi sensitif kepada klien. Sebagai gantinya, panggil metode pada klien yang menampilkan pesan kesalahan yang relevan.

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