.class
File Java dapat didekompilasi dengan cukup mudah. Bagaimana cara melindungi database saya jika saya harus menggunakan data login dalam kode?
.class
File Java dapat didekompilasi dengan cukup mudah. Bagaimana cara melindungi database saya jika saya harus menggunakan data login dalam kode?
Jawaban:
Jangan pernah memasukkan kata sandi ke dalam kode Anda. Hal ini baru-baru ini diangkat dalam 25 Kesalahan Pemrograman Paling Berbahaya Teratas :
Melakukan hard-coding akun rahasia dan kata sandi ke dalam perangkat lunak Anda sangat nyaman - untuk insinyur yang terampil. Jika kata sandi sama di semua perangkat lunak Anda, maka setiap pelanggan menjadi rentan ketika kata sandi itu pasti diketahui. Dan karena ini memiliki kode keras, sangat sulit untuk memperbaikinya.
Anda harus menyimpan informasi konfigurasi, termasuk sandi, dalam file terpisah yang dibaca aplikasi saat dijalankan. Itu adalah satu-satunya cara nyata untuk mencegah kata sandi bocor akibat dekompilasi (jangan pernah mengkompilasinya ke dalam biner untuk memulai).
Untuk informasi selengkapnya tentang kesalahan umum ini, Anda dapat membaca artikel CWE-259 . Artikel tersebut berisi definisi yang lebih menyeluruh, contoh, dan banyak informasi lain tentang masalah tersebut.
Di Java, salah satu cara termudah untuk melakukannya adalah dengan menggunakan kelas Preferensi. Ini dirancang untuk menyimpan semua jenis pengaturan program, beberapa di antaranya dapat menyertakan nama pengguna dan kata sandi.
import java.util.prefs.Preferences;
public class DemoApplication {
Preferences preferences =
Preferences.userNodeForPackage(DemoApplication.class);
public void setCredentials(String username, String password) {
preferences.put("db_username", username);
preferences.put("db_password", password);
}
public String getUsername() {
return preferences.get("db_username", null);
}
public String getPassword() {
return preferences.get("db_password", null);
}
// your code here
}
Pada kode di atas, Anda dapat memanggil setCredentials
metode tersebut setelah menampilkan dialog askign untuk nama pengguna dan kata sandi. Saat Anda perlu menyambungkan ke database, Anda cukup menggunakan metode getUsername
dan getPassword
untuk mengambil nilai yang disimpan. Kredensial login tidak akan di-hardcode ke dalam biner Anda, jadi dekompilasi tidak akan menimbulkan risiko keamanan.
Catatan Penting: File preferensi hanyalah file XML teks biasa. Pastikan Anda mengambil langkah-langkah yang tepat untuk mencegah pengguna yang tidak sah melihat file mentah (izin UNIX, izin Windows, dan sebagainya). Di Linux, setidaknya, ini bukan masalah, karena pemanggilan Preferences.userNodeForPackage
akan membuat file XML di direktori home pengguna saat ini, yang toh tidak bisa dibaca oleh pengguna lain. Di Windows, situasinya mungkin berbeda.
Lebih Banyak Catatan Penting: Ada banyak diskusi di komentar jawaban ini dan lainnya tentang apa arsitektur yang benar untuk situasi ini. Pertanyaan asli tidak benar-benar menyebutkan konteks di mana aplikasi tersebut digunakan, jadi saya akan berbicara tentang dua situasi yang dapat saya pikirkan. Yang pertama adalah kasus di mana orang yang menggunakan program sudah mengetahui (dan diberi wewenang untuk mengetahui) kredensial database. Yang kedua adalah kasus di mana Anda, pengembang, mencoba merahasiakan kredensial database dari orang yang menggunakan program.
Kasus Pertama: Pengguna diberi wewenang untuk mengetahui kredensial login database
Dalam hal ini, solusi yang saya sebutkan di atas akan berfungsi. Kelas Java Preference
akan menyimpan nama pengguna dan kata sandi dalam teks biasa, tetapi file preferensi hanya akan dapat dibaca oleh pengguna yang berwenang. Pengguna cukup membuka file XML preferensi dan membaca kredensial login, tetapi itu bukan risiko keamanan karena pengguna tahu kredensial tersebut sejak awal.
Kasus Kedua: Mencoba menyembunyikan kredensial login dari pengguna
Ini adalah kasus yang lebih rumit: pengguna seharusnya tidak mengetahui kredensial login tetapi masih membutuhkan akses ke database. Dalam hal ini, pengguna yang menjalankan aplikasi memiliki akses langsung ke database, yang berarti program perlu mengetahui kredensial login sebelumnya. Solusi yang saya sebutkan di atas tidak sesuai untuk kasus ini. Anda dapat menyimpan kredensial login database dalam file preferensi, tetapi pengguna tersebut akan dapat membaca file itu, karena mereka akan menjadi pemiliknya. Faktanya, tidak ada cara yang baik untuk menggunakan kasing ini dengan cara yang aman.
Kasus yang Benar: Menggunakan arsitektur multi-tingkat
Cara yang benar untuk melakukannya adalah dengan memiliki lapisan tengah, di antara server database dan aplikasi klien Anda, yang mengautentikasi pengguna individu dan memungkinkan serangkaian operasi terbatas untuk dilakukan. Setiap pengguna akan memiliki kredensial login mereka sendiri, tetapi tidak untuk server database. Kredensial akan memungkinkan akses ke lapisan tengah (tingkat logika bisnis) dan akan berbeda untuk setiap pengguna.
Setiap pengguna akan memiliki nama pengguna dan kata sandi mereka sendiri, yang dapat disimpan secara lokal di file preferensi tanpa risiko keamanan. Ini disebut arsitektur tiga tingkat (tingkatannya adalah server database Anda, server logika bisnis, dan aplikasi klien). Ini lebih kompleks, tetapi ini adalah cara paling aman untuk melakukan hal semacam ini.
Urutan operasi dasar adalah:
getInventoryList
.Perhatikan bahwa di seluruh proses, aplikasi klien tidak pernah terhubung langsung ke database . Tingkat logika bisnis menerima permintaan dari pengguna yang diautentikasi, memproses permintaan klien untuk daftar inventaris, dan hanya kemudian menjalankan kueri SQL.
Masukkan kata sandi ke dalam file yang akan dibaca aplikasi. JANGAN PERNAH menyematkan kata sandi dalam file sumber. Titik.
Ruby memiliki modul yang kurang dikenal bernama DBI :: DBRC untuk penggunaan semacam itu. Saya tidak ragu bahwa Java memiliki padanan. Bagaimanapun, tidak sulit untuk menulisnya.
Apakah Anda sedang menulis aplikasi web? Jika demikian, gunakan JNDI untuk mengkonfigurasinya secara eksternal ke aplikasi. Ringkasan tersedia di sini :
JNDI menyediakan cara yang seragam bagi aplikasi untuk menemukan dan mengakses layanan jarak jauh melalui jaringan. Layanan jarak jauh dapat berupa layanan perusahaan apa pun, termasuk layanan pesan atau layanan khusus aplikasi, tetapi, tentu saja, aplikasi JDBC tertarik terutama pada layanan database. Setelah objek DataSource dibuat dan didaftarkan dengan layanan penamaan JNDI, aplikasi dapat menggunakan JNDI API untuk mengakses objek DataSource tersebut, yang kemudian dapat digunakan untuk menyambungkan ke sumber data yang diwakilinya.
Apa pun yang Anda lakukan, informasi sensitif akan disimpan di beberapa file di suatu tempat. Tujuan Anda adalah membuatnya sesulit mungkin. Berapa banyak dari ini yang dapat Anda capai tergantung pada proyek Anda, kebutuhan dan ketebalan dompet perusahaan Anda.
Cara terbaik adalah dengan tidak menyimpan sandi apa pun di mana pun. Ini dicapai dengan menggunakan fungsi hash untuk menghasilkan dan menyimpan hash kata sandi:
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
Algoritma hash adalah fungsi satu arah. Mereka mengubah sejumlah data menjadi "sidik jari" dengan panjang tetap yang tidak dapat dibalik. Mereka juga memiliki properti bahwa jika input berubah bahkan sedikit, hash yang dihasilkan sangat berbeda (lihat contoh di atas). Ini bagus untuk melindungi kata sandi, karena kami ingin menyimpan kata sandi dalam bentuk yang melindungi mereka bahkan jika file kata sandi itu sendiri disusupi, tetapi pada saat yang sama, kami harus dapat memverifikasi bahwa kata sandi pengguna benar.
Catatan tidak terkait: Di masa lalu internet, ketika Anda mengklik tautan 'lupa kata sandi saya', situs web akan mengirimi Anda kata sandi teks biasa Anda melalui email. Mereka mungkin menyimpannya dalam database di suatu tempat. Ketika peretas mendapatkan akses ke database mereka, mereka akan mendapatkan akses ke semua kata sandi. Karena banyak pengguna akan menggunakan kata sandi yang sama di banyak situs web, ini adalah masalah keamanan yang sangat besar. Untungnya, sekarang ini bukan praktik yang umum.
Sekarang muncul pertanyaan: apa cara terbaik untuk menyimpan kata sandi? Saya akan menganggap solusi (otentikasi dan layanan manajemen pengguna stormpath) ini sangat ideal:
Jelas Anda bukan google atau bank, jadi ini adalah solusi yang berlebihan untuk Anda. Tetapi kemudian muncul pertanyaan: Berapa banyak keamanan yang dibutuhkan proyek Anda, berapa banyak waktu dan uang yang Anda miliki?
Untuk banyak aplikasi, meskipun tidak disarankan, menyimpan sandi dengan kode keras dalam kode mungkin merupakan solusi yang cukup baik. Namun, dengan menambahkan beberapa langkah keamanan ekstra dengan mudah dari daftar di atas, Anda dapat membuat aplikasi Anda jauh lebih aman.
Misalnya, anggap saja langkah 1 bukanlah solusi yang dapat diterima untuk proyek Anda. Anda tidak ingin pengguna memasukkan kata sandi setiap saat, atau Anda bahkan tidak ingin / perlu pengguna mengetahui kata sandinya. Anda masih memiliki informasi sensitif di suatu tempat dan Anda ingin melindungi ini. Anda memiliki aplikasi sederhana, tidak ada server untuk menyimpan file Anda atau ini terlalu merepotkan proyek Anda. Aplikasi Anda berjalan di lingkungan yang tidak memungkinkan untuk menyimpan file dengan aman. Ini adalah salah satu kasus terburuk, tetapi masih dengan beberapa tindakan keamanan tambahan, Anda dapat memiliki solusi yang jauh lebih aman. Misalnya, Anda dapat menyimpan informasi sensitif dalam sebuah file, dan Anda dapat mengenkripsi file tersebut. Anda dapat memiliki kunci pribadi enkripsi yang di-hardcode dalam kode. Anda dapat mengaburkan kode tersebut, sehingga Anda mempersulit seseorang untuk memecahkannya.tautan ini . (Saya ingin memperingatkan Anda sekali lagi bahwa ini tidak 100% aman. Seorang peretas cerdas dengan pengetahuan dan alat yang tepat dapat meretas ini. Tetapi berdasarkan kebutuhan dan kebutuhan Anda, ini mungkin solusi yang cukup baik untuk Anda).
Pertanyaan ini menunjukkan cara menyimpan kata sandi dan data lain dalam file terenkripsi: Java 256-bit AES Password-Based Encryption
MD5 adalah algoritma hash, bukan algoritma enkripsi, singkatnya u cant mendapatkan kembali wat u hash, u hanya dapat membandingkan. Ini idealnya digunakan saat menyimpan informasi otentikasi pengguna dan bukan nama pengguna dan kata sandi db. db username dan pwd harus dienkripsi dan disimpan dalam file konfigurasi, untuk melakukan paling sedikit.