it-swarm-id.com

Apakah boleh untuk rahasia API disimpan dalam teks biasa atau yang dapat didekripsi?

Bukan API keys dianggap nama pengguna dan API secrets kata sandi yang dipertimbangkan? Mengapa server API seperti Amazon Web Services memungkinkan Anda untuk melihat rahasia API Anda dalam teks biasa? Itu membuat saya berpikir mereka menyimpannya dalam teks biasa atau setidaknya dalam format yang dapat mendekripsi.

Bukankah lebih baik jika rahasia API diperlakukan sebagai kata sandi yang harus Anda ketik untuk dibuat kemudian di-hash dalam database alih-alih diserahkan kepada Anda dalam teks biasa? Jika karena alasan tertentu basis data rahasia API mereka dikompromikan, ia akan dengan mudah membuka pintu banjir untuk banyak aplikasi yang menggunakan API mereka. Namun jika itu hash dengan cara non-dekripsi maka semua tidak mudah hilang.

36
IMB

Tidak. Kunci API harus disimpan dalam teks-jelas.

Itu bukan kata sandi: itu adalah kunci kriptografi. Kunci-kunci ini digunakan untuk hal-hal seperti permintaan otentikasi (menggunakan SHA1-HMAC). Server perlu mengetahui kunci kripto untuk menerapkan algoritma kriptografi.

Oleh karena itu, kunci API perlu disimpan dalam teks-jelas di server. Jika server hanya menyimpan hash kunci API, server tidak dapat memverifikasi keaslian pesan dari klien atau mengotentikasi pesan yang dikirim ke klien.

17
D.W.

Hashing bukan penyimpanan; itu tidak dapat dikembalikan lagi menghancurkan data. Kita bisa lolos dengan hashing kata sandi panggilan sebagai "penyimpanan kata sandi" karena ketika kita benar-benar membutuhkan kata sandi, kita memiliki operator manusia yang berguna untuk mengetiknya. Memang, ketika kita hash kata sandi kita tidak menyimpan kata sandi, tetapi hanya token cukup untuk memverifikasi kata sandi yang diketik.

Kunci API harus disimpan sedemikian rupa sehingga dapat digunakan kembali dengan cara tanpa pengawasan . Server harus benar-benar menyimpan itu, daripada hanya mengingat hantu itu, karena itu perlu kunci asli untuk mengakses API.

13
Tom Leek

Sementara itu akan lebih aman untuk hash token API, itu menyajikan masalah kegunaan: token itu panjang dan acak, dan harus diberitahu kepada pengguna hanya sekali sebelum hashing. Ini membuatnya sedikit sulit untuk mengamankan mereka dengan hash.

Saran saya untuk skenario aman adalah sebagai berikut:

  1. Hasilkan nilai _ salt acak dan simpan dalam database. Garam ini tidak boleh sama dengan garam kata sandi pengguna.
  2. Ambil kata sandi pengguna dan hitung KDF(password, salt), di mana KDF adalah fungsi derivasi kunci seperti bcrypt. Panggil nilai yang dihasilkan k.
  3. Hasilkan kunci API.
  4. Enkripsi nilai kunci API dengan AES, menggunakan k sebagai kunci, dan menyimpan ciphertext dalam database.
  5. Buang kunci API plaintext dan k.

Ketika pengguna masuk, webapp tahu kata sandi mereka dan menggunakannya untuk menghitung k, yang kemudian digunakan untuk mendekripsi kunci API dan menampilkannya kepada mereka.

Ketika pengguna ingin menggunakan API, mereka harus mengirim k serta kunci API plaintext, melalui SSL. Webapp kemudian dapat mendekripsi nilai kunci API yang disimpan menggunakan k dan membandingkannya dengan kunci API yang diberikan. Jika mereka cocok, itu valid. Ini memungkinkan penggunaan kunci API tanpa perlu menyimpan kata sandi pengguna.

Jika penyerang melanggar basis data, mereka harus memecahkan kata sandi pengguna untuk menghitung k.

9
Polynomial

Tampaknya ada sedikit kebingungan di sini dan tempat lain , jadi saya menambahkan jawaban ini dengan harapan akan menjelaskan situasi bagi pengguna lain.

Ada dua jenis rahasia API yang mungkin digunakan.

Kasus penggunaan yang sebagian besar jawaban pada halaman ini diskusikan adalah kunci rahasia yang digunakan untuk menandatangani dan memverifikasi pesan menggunakan algoritma seperti HMAC. Dalam hal ini, baik klien dan API membutuhkan nilai kunci yang sebenarnya untuk membuat tanda tangan pesan. Server kemudian membandingkan tanda tangan yang dihasilkannya dengan tanda tangan yang dikirim klien dan dapat memverifikasi pesan. Seperti disebutkan di atas, jika kunci asli tidak dapat direproduksi di server ini tidak dapat berfungsi. Setelah awalnya berbagi kunci dengan klien (melalui saluran terenkripsi) kunci tidak perlu ditransmisikan antara klien dan server lagi.

Rahasia klien API umum lainnya hanyalah kredensial rahasia (seperti yang mungkin Anda lihat dalam permintaan token akses OAuth2 yang khas). Kredensial ini ditransmisikan pada setiap permintaan, dan karenanya hanya boleh dikirimkan melalui saluran terenkripsi (seperti HTTPS). Dalam hal ini server hanya perlu menyimpan informasi yang cukup untuk memverifikasi bahwa nilai rahasia yang diberikan oleh klien sudah benar, sehingga rahasia dapat dan harus di-hash. Dalam hal ini, rahasia tersebut secara efektif bertindak sebagai kata sandi, sehingga tindakan pencegahan yang sama harus diambil.

Penafian: Saya bukan peneliti keamanan, dan Anda harus benar-benar melakukan lebih banyak penelitian tentang ini dan subjek apa pun sebelum secara membabi buta mengikuti saran apa pun di StackExchange ini!

tl; dr Yang paling penting adalah bahwa API yang berbeda dapat menggunakan rahasia dengan cara yang berbeda. Penting untuk memahami bagaimana API Anda menggunakan rahasia klien untuk mengevaluasi praktik terbaik untuk menyimpannya.

8
Nick Sloan

Menempatkan dalam dua sen saya sendiri karena satu masalah yang belum disebutkan. Secara khusus, saya setuju dengan apa yang dikatakan @NickSloan, tetapi dengan satu peringatan lagi.

Ada satu lagi perbedaan penting antara kunci API dan kata sandi. Kunci API unik untuk situs Anda. Bagian yang membuat keamanan kata sandi sangat penting adalah berbagi kata sandi. Jika seseorang mendapatkan kata sandi yang disimpan pengguna di situs Anda, itu bukan hanya situs Anda yang dikompromikan: itu adalah setiap situs lain yang pengguna gunakan untuk kata sandi (dan email/nama pengguna) itu. Banyak orang menggunakan kembali kata sandi di situs-situs penting: bank, media sosial, email, dll, yang berarti bahwa keamanan kata sandi yang baik tidak begitu banyak tentang melindungi akses ke situs Anda, tetapi juga tentang melindungi pengguna Anda di situs lain. Kami tidak dapat memaksa pengguna untuk melakukan keamanan yang lebih baik, jadi kami harus menganggap yang terburuk dan mengambil langkah ekstra bagi mereka untuk melindungi privasi mereka sendiri.

Kunci API adalah skenario yang sama sekali berbeda karena ini unik untuk situs Anda. Akibatnya, jika dicuri, penyerang mendapatkan akses ke situs Anda, tetapi tidak memperoleh apa pun yang dapat mereka manfaatkan terhadap bank/email/orang lain tersebut. Ini berarti bahwa tingkat risiko untuk kunci API sebenarnya lebih rendah daripada kata sandi. Mereka tidak cukup di ball park yang sama: Kunci API lebih mirip dengan pengidentifikasi sesi daripada kata sandi.

Memahami bahwa ini lebih mirip dengan pengidentifikasi sesi daripada kata sandi memberikan beberapa wawasan praktis tentang cara melindungi kunci tersebut dengan benar. Perhatikan bahwa diskusi berikut ini berlaku untuk Kunci API untuk hal-hal seperti OAuth kredensial, dan bukan kredensial enkripsi (seperti yang dibahas oleh @NickSloan dalam jawabannya).

Ancaman terbesar terhadap kata sandi adalah serangan phising dan basis data yang diretas, itulah sebabnya kami menyimpannya di dalam basis data kami. Ancaman terbesar terhadap kunci API sama dengan kunci sesi: kelemahan pada aplikasi front-end seperti kerentanan XSS, MIM, dan sejenisnya. Penting untuk dicatat bahwa aplikasi front-end membutuhkan kata sandi dalam bentuk yang tidak terenkripsi, jadi hashing kunci API tidak benar-benar memberi Anda apa-apa ketika orang yang paling mungkin memilikinya dicuri membutuhkannya dalam teks biasa.

Sebaliknya, Anda melindungi pengidentifikasi sesi (atau OAuth token, atau kunci API khusus klien) terutama dengan melacak klien. Jika pengidentifikasi sesi dicuri melalui XSS atau cara lain dari klien , hasil tipikal adalah untuk pengidentifikasi yang akan digunakan oleh penyerang pada perangkat baru. Itu berarti bahwa tiba-tiba Anda akan melihat kunci lama datang dengan agen pengguna baru. Perubahan seperti itu mudah untuk dideteksi dan diperbaiki: segera membatalkan semua kunci API. Terutama dalam kasus OAuth permintaan, ini sangat tidak menyakitkan bagi pengguna: mereka hanya masuk kembali dan segera mendapatkan yang baru, sementara seseorang yang hanya mencuri kunci tersebut (dan tidak memiliki kata sandi) kembali ke papan gambar.

Ini adalah ukuran pertahanan yang cukup umum sehingga peretas yang pintar juga akan mencoba untuk merekam agen pengguna yang terkait dengan kunci curian dan menggunakannya dalam semua permintaan di masa depan, tetapi Anda masih dapat dengan mudah melihat sesuatu yang mencurigakan terjadi ketika pengguna yang sama memiliki permintaan yang muncul. dari beberapa Alamat IP. Seperti semua hal lain di dunia, ini bisa menjadi permainan kucing-dan-tikus, tetapi ada beberapa kesimpulan penting:

  1. Kunci API/OAuth Token/Session ID benar-benar hanya cara mengingat pengguna pada perangkat tertentu, sehingga mereka tidak harus memasukkan kata sandi mereka di setiap halaman. Akibatnya, ketika ragu, Anda bisa saja membunuh semua kunci yang diotorisasi dan memaksa pengguna untuk masuk kembali.
  2. Dalam ketiga kasus, karena kehilangan Kunci/Token/ID menyebabkan akun dikompromikan, penting untuk memiliki keamanan aktif di sekitar hal-hal ini dan mendeteksi/merespons jika terjadi sesuatu yang mencurigakan. Jika Anda pernah mendapat pemberitahuan dari facebook/google/etc tentang seseorang yang mencoba masuk ke akun Anda dari Meksiko, itu karena petugas keamanan di suatu tempat melakukan pekerjaannya dengan benar.
  3. Vektor serangan utama untuk Kunci/Token/Id berbeda dari yang ada pada kata sandi. Anda mungkin masih ingin mem-hash mereka di basis data Anda (sekali lagi, kita tidak berbicara tentang kredensial enkripsi yang perlu dalam teks biasa), tetapi Anda tidak bisa hanya hash mereka dalam database Anda dan menyebut diri Anda aman. Anda perlu memastikan dan mengamankan mereka terhadap berbagai vektor serangan baru. Jika Anda menganggapnya sebagai kata sandi saja, Anda akan kehilangan beberapa bagian penting dari gambaran besarnya.
5
Conor Mancone

Salah satu alasan utama kata sandi di-hash sebelum disimpan, adalah untuk melindungi terhadap penyerang yang mendapatkan akses hanya-baca ke basis data . Dengan cara ini, jika seorang penyerang mendapatkan daftar kredensial login, mereka masih tidak akan dapat menggunakannya secara langsung karena kata sandi di-hash/diasinkan.

Dan ini bukan hanya masalah teoritis yang kami coba selesaikan di sini, jenis serangan ini benar-benar terjadi ( termasuk untuk pemain utama di industri ), dan hashing yang tepat membantu mengurangi dampak serangan.

Jika Anda pengguna yang mengotentikasi menggunakan API rahasia maka rahasia API telah secara efektif menjadi kata sandi karena itu, dari sudut pandang keamanan, mereka harus memiliki yang sama mekanisme perlindungan seperti kata sandi biasa.

Amazon sendiri sekarang tidak memungkinkan mengambil rahasia API . Jika Anda lupa, Anda harus meminta yang baru.

2
Pedro Rodrigues

Tidak, tidak apa-apa untuk beberapa jenis layanan.

Implementasi

1. Setelah koneksi pengguna dengan kata sandi login, buat kunci yang berasal dari kata sandinya untuk mengenkripsi data untuk pengguna ini dan menyimpannya dalam sesi di server.

Dengan begitu, setiap pengguna akan memiliki kunci yang unik. Kunci turunan ini harus tidak dapat dibalik, ini adalah poin utama. Menggunakan hash_mac atau metode hashing lainnya dengan garam dan/atau kunci master akan memungkinkan ini.

2. Gunakan kunci ini untuk mengenkripsi API API yang dihasilkan menggunakan AES 256 dengan iv acak untuk setiap pengguna.

Atau

2.bis Gunakan kunci ini untuk menghasilkan kunci enkripsi nyata pada saat-saat terakhir dan mengenkripsi metode API menggunakan cara yang sama seperti pada 2. untuk menghindari kata sandi mengambang dalam memori.

. Simpan iv di basis data bersama dengan id pengguna dan id aplikasi dalam tabel khusus

4. Simpan Rahasia API terenkripsi dalam database pada tabel yang sesuai.

Penggunaan

Sekarang ketika pengguna terhubung ke panel kontrolnya, Anda dapat membuat ulang kunci, mengambil iv, menguraikan Rahasia API untuk pengguna ini dan menampilkannya dalam teks yang jelas. Anda juga menampilkan kunci dan meminta keduanya saat membuat Panggilan API sehingga Anda dapat memverifikasi App Secret.

Jika Anda ingin menghindari menampilkan kunci dan tidak harus memintanya pada panggilan API Anda juga dapat untuk otentikasi menggunakan metode yang sama seperti untuk login. Berarti Anda dapat membuat tabel lain untuk menyimpan kunci/garam acak untuk setiap aplikasi klien dan menyimpan versi hash_mac dari Rahasia API. Dengan demikian hanya ID API dan Rahasia API yang diperlukan untuk mengotentikasi Permintaan API. tapi ini lebih banyak pekerjaan.

Catatan

Ini praktis sama dengan jawaban @Polynomial.

Dengan cara ini, sangat sulit bagi seseorang untuk meretas server dan basis data Anda untuk mencuri kredensial pengguna Anda dan melakukan panggilan api atas nama mereka. Anda sekarang dapat menilai bahwa jika permintaan telah diterima dari klien API, itu adalah klien yang tepat atau kebocorannya.

Jika pengguna kehilangan kata sandinya, maka Anda membuat ulang API Secret dan Key baru dari kata sandi barunya.

0
Nicolas Manzini