Cadangan yang andal, aman, dan serbaguna untuk U2F

Saya sangat suka tingkat keamanan yang disediakan oleh U2F, tetapi seiring dengan keamanan, Anda perlu mempertimbangkan rencana pemulihan. Kehilangan akses ke akun terpenting Anda, jika terjadi sesuatu dengan token U2F utama, adalah masalah serius. Pada saat yang sama, saya ingin menghindari menggunakan cadangan yang membahayakan keamanan yang disediakan oleh U2F.

yubikey

Metode pencadangan populer


Sampai saat ini, sudah merupakan praktik yang baik untuk memegang token U2F independen kedua untuk cadangan; token ini harus ditambahkan secara manual ke setiap layanan dan disimpan di tempat "aman". Praktik umum lainnya adalah menggunakan metode non-U2F sebagai cadangan (OTP, kode pemulihan). Sejujurnya, kedua metode ini meninggalkan banyak yang harus diinginkan.

Token U2F Independen


Ini berarti bahwa setiap kali saya mendaftar pada beberapa layanan baru, saya perlu menambahkan kedua token saya. Fakta ini menimbulkan sejumlah masalah:

  • Token cadangan harus cukup mudah diakses. Terlepas dari kenyataan bahwa saya tidak akan membawanya dengan saya di gantungan kunci, saya harus dapat dengan cepat mendapatkannya, jadi saya hampir tidak dapat menghasilkan sesuatu yang lebih baik daripada menyimpannya di rumah. Betapa nyata itu aman, bahkan jika brankas digunakan, Anda dapat berbicara untuk waktu yang lama;
  • Ketika saya harus mendaftar untuk layanan saat jauh dari rumah, saya tidak dapat menambahkan token cadangan. Jadi, Anda perlu mencoba mengingat bahwa Anda perlu menambahkannya nanti, dan sampai ini terjadi, tidak ada cadangan. Dalam kasus terburuk, saya benar-benar bisa melupakannya;
  • Ketika saya di rumah, kedua token saya berada di tempat yang sama. Metode cadangan ini jauh dari ideal: kedua token mungkin tidak tersedia karena satu insiden (dihancurkan atau dicuri);
  • Fakta bahwa token cadangan disimpan di rumah benar-benar jelas. Jika seseorang benar-benar ingin mendapatkan token saya, dia sudah tahu di mana mencarinya;
  • Metode non-universal: tidak semua layanan memungkinkan Anda untuk menambahkan lebih dari satu kunci ke akun Anda.

Menurut pendapat saya, "praktik teladan" ini tidak terlalu bisa diandalkan, dan agak memberatkan. Mari kita lihat praktik umum lainnya.

Metode Non-U2F sebagai cadangan


OTP:

  • Menggunakan OTP sebagai cadangan lebih baik daripada menggunakannya sebagai metode 2FA utama, tetapi fakta memiliki OTP entah bagaimana membuka vektor serangan tambahan;
  • Ponsel rusak, hilang dan dicuri, dan jika setelah kehilangan ada kemungkinan ponsel itu akan berada di tangan orang asing, maka Anda perlu mengingat cadangan ini secara manual di semua akun;
  • Saya selalu membawa telepon dan token U2F, jadi sekali lagi, metode cadangan seperti itu jauh dari ideal: probabilitas kehilangan keduanya segera jauh lebih tinggi daripada jika cadangan disimpan secara terpisah. Tetapi item ini dapat sedikit dikompensasi dengan menggunakan, misalnya, Authy, yang menyimpan cadangan terenkripsi di servernya;
  • Metode non-universal: sayangnya, ada sejumlah layanan yang menawarkan hanya aplikasi khusus dan tidak mendukung TOTP standar.

Kode Pemulihan:

  • Kode pemulihan harus disimpan di tempat yang aman. Sekali lagi, "tempat aman" ini kemungkinan besar akan menjadi rumah saya, dengan masalah yang hampir sama dengan token U2F yang terpisah;
  • Sekali lagi, metode non-universal: setiap layanan memiliki pendekatan sendiri untuk cadangan

Jadi, untuk meringkas, semua metode ini tidak universal, memberatkan dan tidak terlalu aman.

Metode cadangan terbaik


Sekarang, setelah saya cukup mengkritik keadaan saat ini, saya akhirnya akan mengatakan apa yang sebenarnya saya inginkan. Saya benar-benar ingin memiliki dua token U2F: primer dan cadangan, tetapi mereka harus dikonfigurasi dengan cara tertentu:

  • Ketika saya mendaftarkan token utama pada perangkat apa pun, token cadangan secara otomatis menjadi operasional untuk layanan ini;
  • Segera setelah saya menggunakan token cadangan pada layanan apa pun, token utama tidak valid untuk layanan ini.

Sebelum kita membahas kelayakan teknis ini dalam U2F, saya akan menjelaskan mengapa ini bagus dan bagaimana saya menggunakannya.

Kenapa ini bagus?


Jika kita melihat kritik terhadap token cadangan independen yang dijelaskan di atas, kita dapat melihat bahwa semua kekurangan dari metode ini dihilangkan:

  • Token cadangan seharusnya tidak lagi mudah diakses. Contoh ekstrem dapat berupa: memasang token di dalam dinding bata, atau mengubur satu setengah meter di taman atau di tempat lain. Tidak bercanda, saya cukup siap untuk melakukannya;
  • Di mana pun saya berada, jika saya mendaftar untuk layanan apa pun, saya tidak perlu melakukan apa pun untuk menambahkan token cadangan ke layanan ini. Saya hanya menggunakan token utama saya, dan saya merasa tenang, mengetahui bahwa saya memiliki cadangan;
  • Untuk orang luar, sama sekali tidak jelas di mana token cadangan saya berada. Bahkan mengetahui bahwa itu ada, berusaha menemukannya sendiri hampir tidak masuk akal;
  • Cukup aman. Bahkan jika sesuatu yang buruk terjadi pada token utama saya, sangat tidak mungkin bahwa kejadian yang sama akan mempengaruhi token cadangan;
  • Itu universal. Metode cadangan ini akan berfungsi pada layanan apa pun yang mendukung U2F, apa pun yang didukung layanan ini.

Dan jika sesuatu yang buruk benar-benar terjadi dengan token utama, maka saya melakukan hal berikut:

  • Saya menggali / tidak jelas token cadangan;
  • Otentikasi pada semua layanan saya dengan U2F, dengan demikian membatalkan token utama;
  • Saya memesan sepasang token baru, dan setelah diterima, menambahkan token utama baru di semua layanan, dan mencabut yang lama.

Setidaknya bagi saya pribadi, strategi ini adalah kompromi yang bagus untuk tingkat keamanan yang tinggi dan beban cadangan yang mudah. Ini lebih aman dan lebih dapat diandalkan daripada metode lainnya.

Implementasi


Ikhtisar Protokol U2F


Sebelum kita dapat berbicara tentang implementasi, kita perlu memahami pada tingkat tertentu bagaimana U2F bekerja. Sebagian besar pabrikan mengimplementasikannya sebagai berikut (tidak semua yang berikut ada dalam standar; beberapa hal adalah detail implementasi, tetapi sebagian besar implementasi yang ada, sejauh yang saya tahu, bekerja seperti itu):

device_secret diprogram dalam token U2F, bersama dengan counter 32-bit, yang hanya dapat ditingkatkan. Ketika kami mendaftarkan token U2F pada layanan, berikut ini terjadi:

  • Browser mengirim AppID (sebenarnya, nama domain) ke perangkat U2F;
  • Perangkat menghasilkan angka acak ( nonce ), menggabungkannya dengan itu dengan AppID , melewati semuanya melalui HMAC-SHA256 menggunakan device_secret sebagai kunci, dan hash yang dihasilkan menjadi kunci pribadi untuk layanan khusus ini: service_private_key ;
  • Dari service_private_key , kunci publik service_public_key dihasilkan;
  • Perangkat mengambil AppID lagi, menggabungkannya dengan service_private_key , dan meneruskannya melalui HMAC-SHA256 lagi menggunakan kunci device_secret . Hasilnya ( MAC ), bersama dengan nonce yang dihasilkan sebelumnya, menjadi key_handle ;
  • Perangkat mengirim key_handle dan service_public_key kembali ke browser, dan browser beralih ke layanan, yang menyimpan data ini untuk otentikasi berikutnya.

Otentikasi selanjutnya dilanjutkan sebagai berikut:

  • Layanan menghasilkan challenge (data yang dihasilkan secara acak) dan mengirimkannya ke browser bersama dengan key_handle (yang terdiri dari nonce dan MAC ). Browser meneruskan semua ini ke perangkat, bersama dengan AppID (yaitu nama domain);
  • Perangkat, yang memiliki nonce dan AppID , menghasilkan service_private_key dengan cara yang sama seperti yang dihasilkan saat pendaftaran;
  • Perangkat menghasilkan MAC dengan cara yang sama seperti saat registrasi, dan membandingkannya dengan MAC diterima dari browser, memastikan bahwa nonce tidak diganti, dan oleh karena itu, service_private_key diandalkan;
  • counter kenaikan perangkat;
  • Perangkat menandatangani challenge , AppID dan counter menggunakan service_private_key , dan mengirimkan tanda tangan yang dihasilkan ( signature ) dan counter browser, yang mentransfer data ini lebih jauh ke layanan;
  • Layanan memeriksa signature menggunakan service_public_key yang dimilikinya setelah pendaftaran. Juga, sebagian besar layanan memverifikasi bahwa counter lebih besar dari nilai sebelumnya (jika ini bukan otentikasi pertama). Tujuan dari tes ini adalah untuk membuat kloning perangkat U2F tidak dapat diakses. Akibatnya, jika pencocokan signature dan counter lebih besar dari nilai sebelumnya, otentikasi dianggap berhasil diselesaikan, dan layanan menyimpan nilai counter baru.

Sekarang mari kita uraikan detail yang berhubungan langsung dengan diskusi.

Rincian bunga


Yang pertama adalah bahwa perangkat tidak menyimpan service_private_key untuk setiap layanan: sebagai gantinya, itu menampilkan service_private_key setiap kali menggunakan HMAC-SHA256. Ini sangat penting bagi kami: jelas bahwa jika setiap perangkat akan menyimpan kunci unik secara terpisah untuk setiap layanan, maka hanya perangkat ini yang dapat mengautentikasi selanjutnya.

Omong-omong, ini bukan persyaratan U2F: U2F tidak menunjukkan bagaimana kunci harus disimpan, dan beberapa implementasi awal U2F memang, pada kenyataannya, menyimpan kunci untuk setiap layanan secara terpisah. Pendekatan ini memiliki kelemahan bahwa jumlah layanan yang dapat digunakan perangkat terbatas. Derivasi dari service_private_key menghilangkan kelemahan ini.

Dan kedua, perangkat memiliki counter untuk mencegah kloning.

Pada pandangan pertama, tampaknya counter ini tidak memungkinkan kami untuk menerapkan strategi cadangan yang dibahas (setidaknya bagi saya ketika saya mencoba menemukan solusi), tetapi kenyataannya, itu hanya membantu kami! Saya akan jelaskan sekarang.

Ide utama


Idenya adalah ini: pada tahap produksi, program dua token sedemikian rupa sehingga mereka berdua memiliki device_secret sama, tetapi token cadangan perlu beberapa koreksi: daripada menggunakan counter dalam bentuk murni (seperti token biasa), itu harus menambahkan beberapa konstanta besar untuk counter . Misalnya, setengah dari kisaran 32-bit, mis. kira-kira 2 000 000 000 , kelihatannya masuk akal: Saya tidak mungkin menghabiskan begitu banyak autentikasi sepanjang hidup saya.

Faktanya, itu saja. Sederhana dan efektif.

Setelah dua token diprogram dengan cara ini, saya menyembunyikan token cadangan di tempat yang sangat sulit dijangkau, dan tidak pernah menyentuhnya. Jika sesuatu yang buruk terjadi dan saya kehilangan akses ke token utama, saya masih mendapatkan token cadangan, dan saya dapat segera menggunakannya pada semua layanan di mana saya mendaftarkan token utama, karena Cadangan memiliki device_secret sama, dan counter dimulai dengan jumlah yang sangat besar, yang tidak akan saya dapatkan selama sisa hidup saya.

Juga, saya menarik perhatian pada fakta bahwa saya tidak mengusulkan membuat token yang dikloning . Dua token, meskipun mereka memiliki device_secret sama, memiliki penghitung yang berbeda, dan setelah memprogram device_secret seharusnya tidak ada cara untuk mendapatkannya kembali dari perangkat atau membuat klon dengan cara lain.

Catatan Tentang Penghitung


Pembaca yang penuh perhatian mungkin memperhatikan bahwa ada masalah keamanan berikut: bagaimana jika seorang penyerang mendapatkan akses ke token utama dan entah bagaimana memulai 2.000.000.000 otentikasi? Kemudian dia mendapatkan akses ke layanan bahkan setelah token cadangan telah digunakan pada layanan ini.

Untungnya, masalah ini memiliki solusi sederhana. Bagaimanapun, penghitung harus diimplementasikan dalam perangkat keras (mungkin pada beberapa prosesor kripto), dan untuk implementasi yang aman, penghitung perangkat keras ini harus memiliki kisaran kurang dari 32 bit. Misalnya, pada ATECC508A, penghitung hanya dapat menghitung hingga 2097151, jadi dengan menetapkan konstanta yang ditambahkan ke penghitung ke nilai yang lebih besar dari nilai maksimum penghitung, kita dapat memastikan bahwa token utama tidak pernah dapat dihitung ke penghitung di token cadangan.

Untuk memperjelas: katakanlah token U2F kami menggunakan ATECC508A, dan menunjukkan penghitung di dalam ATECC508A sebagai hw_counter . Lalu:

  • Dalam token utama, kami menggunakan untuk perhitungan: hw_counter ;
  • Dalam token cadangan, kami menggunakan untuk perhitungan: hw_counter + 2000000000 .

Harap dicatat bahwa kami tidak mengubah hw_counter di dalam prosesor crypto; masih akan dihitung dari 0 hingga 2097151. Sebaliknya, setiap kali kita perlu mendapatkan nilai penghitung, kita membaca hw_counter dari ATECC508A, lalu kita tambahkan konstanta dan mengembalikannya (untuk perhitungan lebih lanjut untuk U2F).

Dengan demikian, kisaran nilai penghitung dalam token utama adalah [0, 2097151], sedangkan rentang nilai penghitung dalam token cadangan adalah [2000000000, 2002097151]. Fakta bahwa rentang ini tidak tumpang tindih memastikan pembatalan token utama saat menggunakan cadangan (jika layanan menggunakan counter ; layanan utama yang saya periksa menggunakannya).

Implementasi aktual


Tak satu pun dari produsen token U2F yang saya tahu tentang mendukung penyesuaian yang diperlukan hari ini. Tapi untungnya, ada implementasi open-source token U2F : SoloKeys .

Saya menulis artikel asli saya (dalam bahasa Inggris) setahun yang lalu, dan bagian ini sedikit ketinggalan jaman: kemudian SoloKeys berada pada tahap prototyping, dan saya menggunakan iterasi proyek sebelumnya: u2f-zero . Oleh karena itu, saya tidak akan menerjemahkan bagian ini sekarang, karena satu-satunya cara untuk mendapatkan perangkat u2f-zero adalah menyoldernya sendiri, dan hampir tidak disarankan untuk melakukan ini (walaupun ada instruksi pada github).

Namun demikian, semua detail modifikasi yang diperlukan u2f-nol diberikan dalam artikel asli .

Ketika tangan saya mencapai solokeys, saya akan menulis instruksi untuk modifikasi.

Dengan satu atau lain cara, ini adalah satu-satunya cara yang saya tahu hari ini untuk mendapatkan token U2F yang berfungsi dengan cadangan yang dapat diandalkan. Memeriksa beberapa layanan (setidaknya google dan github) menunjukkan bahwa ia berfungsi: dengan mendaftarkan token utama pada layanan, kami juga dapat menggunakan cadangan, dan setelah penggunaan pertama cadangan, token utama berhenti berfungsi. Awwwwwww. <3

Peringatan


Terlepas dari kenyataan bahwa strategi cadangan ini keren, saya tidak begitu yakin implementasi spesifiknya melalui u2f-zero atau solokey. Jalan ini adalah satu-satunya cara untuk mendapatkan apa yang Anda inginkan, jadi saya pergi ke sana; tetapi dengan asumsi bahwa penyerang mendapatkan akses fisik ke perangkat U2F, saya tidak yakin bahwa meretas perangkat (mis. mendapatkan device_secret darinya) akan sesulit seperti pada Yubikey atau produsen besar lainnya. Para penulis solokey mengklaim bahwa "tingkat keamanannya sama dengan kunci mobil modern," tetapi saya tidak melakukan pemeriksaan apa pun untuk mengonfirmasi hal ini.

Namun, jujur โ€‹โ€‹saja, saya tidak terlalu khawatir tentang ini. Jika seorang penyerang hanya mencuri token tanpa niat mengembalikannya, maka kompleksitas mematahkannya tidak masalah, karena seorang penyerang bisa menggunakan token ini untuk mengakses akun dan, misalnya, cukup mencabut token ini dan menambahkan yang lain. Namun, untuk ini saya harus memiliki masalah keamanan serius lainnya juga. Token U2F hanyalah faktor kedua.

Jadi, satu-satunya skenario di mana solokey mungkin kurang aman daripada sesuatu yang lain adalah ketika seorang penyerang mencoba mengakses perangkat untuk waktu yang singkat, dapatkan device_secret darinya, dan mengembalikan perangkat itu kembali, tanpa terlihat oleh saya. Untuk melakukan ini, ia perlu membaca isi mikrokontroler flash (atau RAM pada waktu yang tepat), dan ini tidak terlalu sepele.

Mempertimbangkan semua faktor, saya percaya bahwa bagi saya pribadi untuk memiliki cadangan yang andal jauh lebih penting daripada memiliki implementasi perangkat keras yang sangat aman dari perangkat U2F. Kemungkinan masalah dengan implementasi yang aman dan kurangnya cadangan yang baik lebih tinggi daripada kemungkinan masalah dengan u2f-zero (solokey) dan cadangan.

Kesimpulan


Strategi cadangan yang dipertimbangkan mengungguli alternatif di semua dimensi: itu universal, lebih aman dan lebih dapat diandalkan daripada metode lainnya.

Saya akan senang jika setidaknya salah satu produsen utama menerapkan ini dalam produk mereka, tetapi belum ada kepastian. Seorang pria dari dukungan Yubico, James A., bahkan mengatakan kepada saya bahwa untuk mengimplementasikan cadangan yang saya butuhkan, tidak mungkin dengan cara U2F dirancang, dan setelah saya menetapkan rincian implementasi, itu hanya berhenti merespons.

Untungnya, ini tidak mustahil seperti yang Yubico yakini.



Artikel asli saya dalam bahasa Inggris: Cadangan yang Andal, Aman, dan Universal untuk Token U2F . Karena penulis artikel asli adalah diri saya sendiri, maka, dengan izin Anda, saya tidak memasukkan artikel ini ke dalam kategori โ€œterjemahanโ€ .

Source: https://habr.com/ru/post/id474300/


All Articles