Categories
Tutorial, Manual, Tips dan Trik

Memperkuat General Purpose Hashing

General Purpose Hashing kurang lebih adalah algoritma hash yang didesain untuk dapat memberikan hash pada berkas yang besar dan prosesnya terjadi dengan cepat, sehingga tidak cocok digunakan untuk password karena lebih cepat dibobol dengan dictionary and brute force attack (serangan kamus dan paksa). Algoritma general purpose hashing antara lain md5, sha256, dan sebagainya.

Daftar Isi

Memperkuat General Purpose Hashing

Menggunakan General Purpose Hashing sangat-sangat tidak disarankan. Akan tetapi, apabila dalam kondisi tertentu hanya memungkinkan menggunakan General Purpose Hashing, maka untuk memperkuat perlu ditambah pelambatan dan salt+pepper agar tidak dapat (lama) dibobol dengan brute force dan dictionary attack.

— Memperkuat General Purpose Hashing
https://bptsi.unisayogya.ac.id/memperkuat-general-purpose-hashing/ 2022-10-07 15:36:43

Serangan brutal dilakukan dengan cara mengirimkan kombinasi password secara acak/berututan hingga menemukan password yang sesuai. Serangan kamus dilakukan dengan cara menyimpan input dan hasil hash agar dapat digunakan untuk hash lain, seperti layaknya kamus.

Skenario 1: Serangan paksa langsung ke server web

Penyerang mengirimkan kombinasi password secara terus menerus ke server hingga ditemukan password yang cocok. Teknik ini dapat ditangani dengan pelambatan (slow down)

Skenario 2: Password dalam bentuk hash dan salt sudah didapatkan

Penyerang mendapatkan password dalam bentuk hash, misalnya melalui SQL Injection. Penyerang akan mencoba kombinasi password secara terus menerus di komputer milik penyerang, sehingga tidak mungkin dilambatkan.

Disinilah salt berperan. Salt akan memaksa penyerang membuat satu kamus untuk satu username dan tidak dapat digunakan untuk username lain. Sayangnya, salt ada disamping password sehingga penyerang tinggal menggabungkan password dengan salt.

Disinilah pepper berperan. Penyerang terpaksa menebak pepper yang digunakan karena tidak ada informasi pepper di database.

Serangan Kamus / Dictionary Attack

Hash bukanlah enkripsi sehingga tidak dapat dibalik menjadi kata asli. Apabila ditemukan istilah hash decrypt, maka istilah itu tidak benar. Hal yang sebenarnya adalah dibuat kamus untuk sekian banyak kata, kemudian dilakukan pencarian hasil hash di kamus tersebut.

Sangat tidak dianjurkan menggunakan general purpose hash untuk menyimpan password. Menggunakan general purpose hash dengan salt masih bisa ditoleransi. Best practice-nya menggunakan password hash, baik dengan atau tanpa salt.

Baca juga: General Purpose Hashing vs Password Hashing

Implementasi

<?php
//pepper, informasi ini tidak ada di database
$_pepper = base64_encode(md5("abcdefg12345678!@#$%^&*"));

//semakin tinggi cost, maka waktu akan semakin lama
function slowdown()
{
  $options   = ['cost' => 12];
  $randpass_ = uniqid();
  $crypt_    = password_hash($randpass_, PASSWORD_BCRYPT, $options);
  password_verify($randpass_, $crypt_);
  return true;
}

function slowdown_sleep()
{
  sleep(1);
}

function isvalid()
{
  global $_pepper;
  //get upass
  $_pass = filter_input(INPUT_POST, "password", FILTER_SANITIZE_STRING);
  $_user = filter_input(INPUT_POST, "username", FILTER_SANITIZE_STRING);
  
  //get pass di database dan salt
  $_salt = "";  
  $conn = new mysqli($dbservername, $dbusername, $dbpassword, $dbname);
  if (!$conn->connect_error)
  {
    $stmt = $conn->prepare("select pass, salt from tblUser where username=?");
    $stmt->bind_param("s", $_user);
    $stmt->execute();
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc())
    {
      $_salt      = $row["salt"];
      $_challenge = $row["pass"];
    }
  }
  
  //upass valid?
  return $_challenge == md5($_pass . $_salt . $_pepper));
}

//query insertnya:
//$_salt = base64_encode(md5(uniqid()));
//$stmt = $conn->prepare("insert into tblUser (username, pass, salt) values (?, ?, ?)");
//$stmt->bind_param("sss", $_user, md5($_pass . $_salt . $_pepper), $_salt);

//cek login menggunakan slowdown
if (slowdown() && isvalid())
{
  //....
}

//cek login menggunakan slowdown_sleep
if (slowdown_sleep() && isvalid())
{
  //....
}

Uji Cepat

<?php
//semakin tinggi cost, maka waktu akan semakin lama
function slowdown()
{
  $options   = ['cost' => 12];
  $randpass_ = uniqid();
  $crypt_    = password_hash($randpass_, PASSWORD_BCRYPT, $options);
  password_verify($randpass_, $crypt_);
  return true;
}

function slowdown_sleep()
{
  sleep(1);
}

function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}

$time_start = microtime_float();
slowdown();
$time_end = microtime_float();
$time = $time_end - $time_start;

echo "Waktu slowdown(): $time<br/>";

$time_start = microtime_float();
slowdown_sleep();
$time_end = microtime_float();
$time = $time_end - $time_start;

echo "Waktu slowdown_sleep(): $time<br/>";

Tabrakan

Hash memungkinkan terjadinya tabrakan, dalam arti input yang berbeda mendapatkan hasil hash yang sama. Salt+Pepper membuat tabrakan menjadi tidak ada fungsinya.

<?php
function hexToStr($hex)
{
  $string='';
  for ($i=0; $i < strlen($hex)-1; $i+=2){
    $string .= chr(hexdec($hex[$i].$hex[$i+1]));
  }
  return $string;
}

//perbedaan ada di 200a dengan 202a dan 1555 dengan 1d55
$pass1 = hexToStr("4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2");
$pass2 = hexToStr("4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2");

echo "<br />No Salt & Pepper: ". ((md5($pass1) == md5($pass2)) ? "same" : "diff");

//ada di database
$salt   = base64_encode(md5("1234"));
//tidak ada di database
$pepper = base64_encode(md5("*&^sxp134"));


echo "<br />With Salt & Pepper: ". ((md5($salt . $pepper . $pass1) == md5($salt . $pepper . $pass2)) ? "same" : "diff");
echo "<br />With Salt & Pepper: ". ((md5(utf8_encode($pass1) . $salt . $pepper) == md5(utf8_encode($pass2) . $salt . $pepper)) ? "same" : "diff");
echo "<br />With Salt & Pepper: ". ((md5($pass1 . $salt . $pepper) == md5($pass2 . $salt . $pepper)) ? "same" : "diff") . " --> bugs";
echo "<br />With Salt & Pepper: ". ((md5($salt . $pepper . $pass1) == md5($salt . $pepper . $pass2)) ? "same" : "diff");

//hasil
//No Salt: same
//With Salt: diff
//With Salt: diff
//With Salt: same --> bugs 
//With Salt: diff

Demikian, semoga bermanfaat. [bst]

By basit

Biro Pengembangan Teknologi Dan Sistem Informasi

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.