Pengamanan Akses Login dalam Visual Studio
Sudah
bukan merupakan rahasia lagi bahwa suatu aplikasi memerlukan pengamanan
untuk User dan Password yang digunakan. Rahasia yang mungkin belum
diketahui adalah, bagaimana password tersebut bisa dijaga dan disimpan
dengan aman.
Password sebaiknya tidak disimpan dalam
database sebagai string, sebaiknya, diubah ke suatu nilai yang tidak
mudah dikenali dan unik. Nilai seperti ini disebut hash. Algoritma hashing diberikan agar setiap string yang di hash ke dalam nilai yang unik akan selalu berbentuk hash.
Ketika user memberikan suatu password, password tersebut sebaiknya di hash
ke nilai yang unik, dan nilai unik tersebut yang sebaiknya disimpan
dalam database. Ketika user login dengan menggunakan password, password
tersebut bisa di hash kembali menggunakan algoritma yang sama, Nilai hasilnya bisa dibandingkan dengan nilai hash yang tersimpan dalam database untuk validasi login.
Nilai yang telah di hash tidak bisa di un-hash, jadi tidak ada cara untuk memperoleh password asli dari nilai yang sudah di hash. Cara ini memberikan level keamanan tambahan, karena, jika seseorang mengambil password yang telah di hash
dari database, password tersebut tidak bisa diubah kembali ke format
aslinya. Resikonya adalah, jika user lupa dengan passwordnya, password
baru akan diberikan.
Library System.Security.Cryptography dalam Framework .NET menyediakan beberapa class yang menyediakan hash. Dua buah skema hashing yang disediakan dalam library ini adalah:
1. MD5 : Message Digest 5 (MD5). Menggunakan algoritma MD5 untuk meng-hash suatu nilai, seperti password. Algoritma ini memberikan performa yang baik dibandingkan dengan SHA1.
2. SHA1: Secure Hash Algorithm-1 (SHA1). Menggunakan algoritma SHA1 untuk meng-hash suatu nilai, seperti password. Algoritma ini memberikan keamanan data yang lebih baik dibandingkan dengan MD5.
Suatu password, contoh : “password” akan memiliki hash yang akan terlihat seperti: W6ph5Mm5Pz8GgiULbPgzG37mj9g=.
Kode berikut menggunakan algoritma SHA1 untuk meng-hash suatu password:
Dalam VB:
- Imports System.Security.Cryptography
- Public Function ComputeHash(ByVal textToHash As String) As String
- Dim SHA1 As SHA1CryptoServiceProvider = New SHA1CryptoServiceProvider
- Dim byteValue As Byte() = System.Text.Encoding.UTF8.GetBytes(textToHash)
- Dim byteHash As Byte() = SHA1.ComputeHash(byteValue)
- SHA1.Clear()
- Return Convert.ToBase64String(byteHash)
- End Function
Dalam C#:
- using System.Security.Cryptography;
- public static String ComputeHash(string textToHash)
- {
- SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();
- byte[] byteValue = System.Text.Encoding.UTF8.GetBytes(textToHash);
- byte[] byteHash = SHA1.ComputeHash(byteValue);
- SHA1.Clear();
- return Convert.ToBase64String(byteHash);
- }
Kita bisa menggunakan kode di atas pada setiap aplikasi untuk menyimpan suatu password atau informasi penting lainnya.
Tetapi meng-hash password tidak bisa melindungi aplikasi dari suatu Dictionary Attack. Untuk menambah keamanan, salt password tersebut,
Salting password
Password yang telah di-hash memberikan keamanan yang lebih baik daripada menyimpan password dalam database sebagai text. Hash – masih memiliki kelemahan bila diserang menggunakan Dictionary Attack. Dengan menggunakan Dictionary Attack, cracker berusaha menebak password dengan menggunakan software untuk mencari pola hash yang sama dari semua kata dalam kamus kata yang disiapkan dan membandingkan nilai hash yang didapat dengan nilai hash yang terdapat dalam database.
Untuk mempersulit kerja para cracker
tersebut, kita bisa menambahkan beberapa byte acak pada awal dan/atau
akhir dari password sebelum melakukan proses hashing dan penyimpanan. Byte acak tersebut disebut salt. Kemudian kita bisa menyimpan nilai salt ini ke dalam tabel bersamaan dengan password.
Dalam VB:
- Public Function ComputeSalt() As String
- Dim GuidValue As System.Guid = System.Guid.NewGuid()
- Return GuidValue.ToString()
- End Function
Dalam C#:
- public static String ComputeSalt()
- {
- System.Guid GuidValue = System.Guid.NewGuid();
- return GuidValue.ToString();
- }
Dengan menggunakan 2 teknik hash dan salt, kita bisa meminimalisir kemungkinan akses ilegal ke dalam aplikasi kita.
Validasi Login
Kode-kode pada bagian berikut akan
mencoba menyatukan semua konsep di atas untuk mendemonstrasikan suatu
method ValidasiLogin. Method ini menggunakan teknik salt dan hash seperti yang telah dijelaskan sebelumnya.
Dalam VB:
- Public Function ValidasiLogin(ByVal sUserName As String, _
- ByVal sPassword As String) As Boolean
- Dim dsUser As New DataSet
- If sUserName.Length = 0 OrElse sPassword.Length = 0 Then
- Throw New ArgumentOutOfRangeException("Username dan Password diperlukan.")
- End If
- dsUser = Me.Retrieve(sUserName)
- ' Jika User tidak ditemukan, tampilkan pesan error
- If dsUser Is Nothing _
- OrElse dsUser.Tables(TN_USER) Is Nothing _
- OrElse dsUser.Tables(TN_USER).Rows.Count = 0 Then
- Throw New UsernameNotFoundException("Invalid Username")
- End If
- ' Jika User ditemukan, lanjutkan dengan validasi password
- ' Suatu nilai hash dari gabungan salt dan password yang dimasukkan.
- With dsUser.Tables(TN_USER).Rows(0)
- Dim sPasswordEncoded As String = CType(.Item(FN_PASSWORD_ENCODED), String)
- Dim sPasswordSalt As String = CType(.Item(FN_PASSWORD_SALT), String)
- Dim sPasswordHash As String = SecurityUtility.ComputeHash(sPasswordSalt & _
- sPassword)
- ' apakah nilai hash yang didapat sesuai dengan nilai hash dalam database?
- If String.Compare(sPasswordEncoded, sPasswordHash) <> 0 Then
- Throw New PasswordInvalidException("Invalid Password")
- End If
- Return True
- End Function
Dalam C#:
- public bool ValidasiLogin(string sUserName, string sPassword)
- {
- DataSet dsUser;
- if (sUserName.Length == 0 || sPassword.Length == 0)
- {
- throw new ArgumentOutOfRangeException("Username dan Password diperlukan.");
- }
- dsUser = this.Retrieve(sUserName);
- // Jika User tidak ditemukan, tampilkan pesan error
- if (dsUser == null || dsUser.Tables[TN_USER] == null
- || dsUser.Tables[TN_USER].Rows.Count == 0)
- {
- throw new UsernameNotFoundException("Invalid Username");
- }
- DataRow dr = dsUser.Tables[TN_USER].Rows[0];
- string sPasswordEncoded = dr[FN_PASSWORD_ENCODED].ToString();
- string sPasswordSalt = dr[FN_PASSWORD_SALT].ToString();
- string sPasswordHash = SecurityUtility.ComputeHash(sPasswordSalt +
- sPassword);
- if (String.Compare(sPasswordEncoded, sPasswordHash) != 0)
- {
- throw new PasswordInvalidException("Invalid Password");
- }
- return true;
- }
NB: PasswordInvalidException dan UsernameNotFoundException merupakan developer-defined Exception.
Method ini mengambil nilai password dan
username yang dimasukkan sebagai parameter, Jika parameter kosong, kode
akan menampilkan pesan kesalahan. Username kemudian akan diteruskan ke
method Retrieve, yang akan menerima dataset dari database yang
memiliki data mengenai user yang sedang login. Kode akan memberi pesan
kesalahan jika dataset kosong.
Salt diterima dari dataset dan ditambahkan ke password yang dimasukkan oleh user. Hasilnya diteruskan ke method ComputeHash untuk menghitung nilai hash. Dari hasil tersebut kemudian akan dibandingkan dengan nilai hash yang diterima dari dalam dataset. Kode akan memberi pesan kesalahan jika kedua nilai hash tidak sesuai.
Finally, Anda bisa menggunakan cara ini
sebagai pattern dalam validasi login aplikasi Anda untuk menjaga dan
membatasi akses-akses ilegal ke dalam aplikasi Anda.
Ada tambahan?
0 komentar: