- Daftar
- 18 Apr 2014
- Post
- 1̶3̶3̶7̶
- Like diterima
- 7.182
Halaman Log In yang kita buat setidaknya harus mampu menangani serangan-serangan umum seperti berikut ini :
Algoritma proses loginnya secara umum adalah :
Sampai disini apa sudah bisa berjalan? Jelas..
Jelas belum bisa.. Class Loginnya kan masih kosong begitu.. Sekarang kita akan mengisi seluruh method yang sudah disebutkan di login-proses.php tadi sesuai alur logika yang diinginkan.
Penyesuaian Class Login
Salin method-method dibawah ini, letakkan sesuai di class Login yang sudah ada tadi. Penjelasan singkatnya bisa dilihat di komentar-komentarnya
Dan terakhir ....
SELESAI GAMPANG KAN PHP
- Brute Force Attack : serangan paling primitif (hehe) dimana hacker berusaha menebak segala kemungkinan username dan password secara terus menerus sampai ketemu.
- SQL Injection : serangan dimana hacker menginputkan injeksi skrip SQL di inputan, dengan harapan skrip tersebut dapat terinjeksi dan berjalan di server untuk mengambil / merusak data tertentu.
- Session Hijacking : teknik pencurian session di perangkat tertentu. Apabila di script pengecekan log in kita hanya menggunakan fungsi isset() atau sejenisnya, hacker yang mencuri session di perangkat yang sudah log in pun jadi memiliki hak akses yang sama.
Algoritma proses loginnya secara umum adalah :
- Cek_Salah_Login() apakah sudah melebihi batas? Jika iya, hentikan eksekusi dan tampilkan pesan error.
- Cek di database, apakah ada username yang sama seperti yang diinputkan di $_POST[username] ?
- Jika tidak ada, catat kesalahan login, dan tampilkan pesan error
- Jika ada, cek password apakah valid atau tidak?
- Jika valid, lakukan proses pembuatan token, lalu redirect ke halaman index
- Jika tidak valid, catat kesalahan login, dan tampilkan pesan error
Code:
<?php
//login-proses.php
include "conf/conn.php";
if(!$login->cek_salah_login()){
//kalau user salah login melebihi batas yang ditentukan, maka proses langsung berhenti
create_alert("error","Mohon maaf Anda tidak dapat login lagi karena kesalahan login Anda terlalu banyak. Hubungi Administrator untuk informasi lebih lanjut","index.php");
}
//tombol $_POST['btn'] harus ditekan. kalau tidak ditekan artinya nggak ada proses apapun yang dijalankan
if(isset($_POST['btn'])){
$username = $_POST['username'];
$password = $_POST['password'];
//step 1 : cek apakah username ada di tabel
$cek = $db->query("SELECT * FROM tb_admin WHERE user = ".$db->quote($username));
if($cek->rowCount() > 0){
//username ada, tangkap password yg ada di database
$row = $cek->fetch();
$password_db = $row['pass'];
#password_verify adalah fungsi PHP 5.5> yang otomatis mengecek kesamaan inputan dengan hash
if(password_verify($password, $password_db)){
//password sudah cocok
$expired = 0;
if(isset($_POST['remember'])){
if($_POST['remember'] = 1){
$expired = '+1 year'; // 1 tahun
}
}
#kalau remember me dicentang, login akan expired dalam waktu 1 tahun, selain itu ya akan seperti session biasa yang hilang ketika diclose
$login->true_login($username, $expired); //pencatatan token akan dilakukan disini
create_alert("success","Log In Berhasil","index.php");
}
else{
//password tidak cocok
$login->salah_login_action($username); //pencatatan kesalahan login
create_alert("error","Username atau password tersebut salah","index.php");
}
}
else{
$login->salah_login_action($username); //pencatatan kesalahan login
create_alert("error","Username atau password tersebut tidak terdaftar","index.php");
}
}
Sampai disini apa sudah bisa berjalan? Jelas..
Jelas belum bisa.. Class Loginnya kan masih kosong begitu.. Sekarang kita akan mengisi seluruh method yang sudah disebutkan di login-proses.php tadi sesuai alur logika yang diinginkan.
Penyesuaian Class Login
Salin method-method dibawah ini, letakkan sesuai di class Login yang sudah ada tadi. Penjelasan singkatnya bisa dilihat di komentar-komentarnya
Code:
...
public function salah_login_action($username){
//logic : dipanggil saat user salah memasukkan username/password.
//username, tgl, ip, dan user agent dicatat dengan FLAG=0.
$tgl = date("Y-m-d H:i:s");
$ip = $_SERVER['REMOTE_ADDR'];
$useragent = $_SERVER['HTTP_USER_AGENT'];
//memasukkan data ke tb_admin_log dengan flag STAT = 0.
$save = $this->db->prepare("INSERT INTO tb_admin_log VALUES (NULL, ?, '', '', ?, ?, ?, 0)");
$save->execute(array(
$tgl, $username, $ip, $useragent
));
return true;
}
...
Code:
...
public function cek_salah_login($limit=5){
#method ini dipanggil sekali di login-proses paling atas.
#$limit bisa disesuaikan sesuai kebutuhan kita.
//cek apakah di tabel tb_admin_log ada 5 IP yang sama dalam keadaan salah login (STAT = 0)
$ip = $_SERVER['REMOTE_ADDR'];
$cek = $this->db->prepare("SELECT * FROM tb_admin_log WHERE stat = 0 AND ip = ?");
$cek->execute(array($ip));
if($cek->rowCount() >= $limit)
return false;
return true;
}
...
Code:
...
public function true_login($username, $expired){
#method yang dipanggil ketika username dan password sudah tepat dimasukkan
$tgl = date("Y-m-d H:i:s");
if($expired <> 0){
#kalau remember me dicentang, tanggal expirenya adalah 1 tahun dari sekarang.
$expireddb = date("Y-m-d H:i:s",strtotime($expired));
}
else{
#kalau remember me tidak dicentang, secara default user dapat login selama 6 jam saja.
$expireddb = date("Y-m-d H:i:s",strtotime("+6 hours"));
}
$ip = $_SERVER['REMOTE_ADDR'];
$useragent = $_SERVER['HTTP_USER_AGENT'];
$token = sha1($ip.$expireddb."string_random_apasaja".microtime()); //intinya membuat karakter acak saja
//$token ini penting,, nantinya akan disimpan sebagai COOKIE
//apabila ada kesalahan login sebelumnya dengan IP & user agent yang sama sebelumnya harus ditandai dulu
//penandaan dilakukan dengan mengubah FLAG dari 0 menjadi 9, sehingga di pengecekan selanjutnya data ini tidak akan dianggap
$upd = $this->db->query("UPDATE tb_admin_log SET stat = 9 WHERE token = '' AND ip = ".$this->db->quote($ip)." AND useragent = ".$this->db->quote($useragent));
//memasukkan data lengkap ke tb_admin_log dengan flag STAT = 1.
$save = $this->db->prepare("INSERT INTO tb_admin_log VALUES (NULL, ?, ?, ?, ?, ?, ?, 1)");
$save->execute(array(
$tgl, $expireddb, $token, $username, $ip, $useragent
));
//simpan token ke cookie
$expr = 0;
if($expired <> 0){
$expr = intval(strtotime($expired));
}
setcookie("adv_token", $token, $expr, "/");
#kalau remember me tidak dicentang, cookie akan otomatis bertindak sebagai session
#kalau dicentang, cookie akan terus disimpan
return true;
}
...
Code:
...
public function cek_login(){
/*kondisi user dinyatakan login adalah :
1. Memiliki $_COOKIE['adv_token']; (yang dibuat di method true_login() tadi)
2. $_COOKIE['adv_token'] terdaftar di tabel tb_admin_log, dan dalam keadaan masih belum expired
3. IP dan User Agent sesuai dengan token yang terdaftar
*/
if(isset($_COOKIE['adv_token'])){
$token = $_COOKIE['adv_token'];
$now = date("Y-m-d H:i:s");
$cek = $this->db->query("SELECT * FROM tb_admin_log WHERE token = ".$this->db->quote($token)." AND expired > ".$this->db->quote($now));
if($cek){
#kalau token di cookie tersebut ada, lakukan pengecekan IP dan User Agent
$row = $cek->fetch();
if($row['ip'] == $_SERVER['REMOTE_ADDR'] || $row['useragent'] == $_SERVER['HTTP_USER_AGENT']){
//kondisi bisa disesuaikan utk kebutuhan dengan ATAU / DAN
//kondisi DAN boleh dipakai, tapi terlalu strict.. Lebih baik pakai ATAU saja.
$username = $row['username'];
//kembalikan data user yg sedang login,, siapa tahu nanti ingin diolah
$get_admin = $this->db->query("SELECT * FROM tb_admin WHERE user = ".$this->db->quote($username));
$rget = $get_admin->fetch();
return array(
"username" => $rget['user'],
"name" => $rget['name'],
"email" => $rget['email'],
"priviledge" => $rget['priviledge']
);
}
}
}
return false;
}
...
Code:
...
public function logout(){
#dipanggil saat user logout dari sistem.
if(isset($_COOKIE['adv_token'])){
$token = $_COOKIE['adv_token'];
//cara menghapus cookie adalah dengan mengubah tanggal expirednya menjadi sekarang
$now = date("Y-m-d H:i:s");
unset($_COOKIE['adv_token']);
setcookie("adv_token",null,$now,"/");
#jangan lupa tanggal expired di database diupdate juga, supaya session token yang sudah logout tidak dihijack
$this->db->query("UPDATE tb_admin_log SET expired = ".$this->db->quote($now)." WHERE token = ".$this->db->quote($token));
}
return true;
}
...
SELESAI GAMPANG KAN PHP
