command line - php prevent '`rm -rf ~/`;'

231

Good day guys. The issue I am having is specifically with handling this specific input case.

A part of my project I need to do is to take argument though command line into a PHP script. for eg ./do_op_2.php "`rm -rf ~/`;" .

I have tried using escapeshellarg($argv[1]), escapesellcmd($argv[1]); but to no avail it still executes the command. I have tried iterating through the string looking for ` and ; before anything happens, it is still executed.

If there are any more specific questions please do ask, I am willing to give more information.

Code for those who are curious.

#!/usr/bin/php
<?php
unset($argv[0]);
$argv[1] = escapeshellarg($argv[1]);
$argv[1] = escapeshellcmd($argv[1]);
function    add($a, $b)
{
    if (is_numeric($a) && is_numeric($b))
        return ($a + $b);
    else    
        return (0);
}

function    minus($a, $b)
{
    if (is_numeric($a) && is_numeric($b))
        return ($a - $b);
    else    
        return (0);
}

function    mult($a, $b)
{
    if (is_numeric($a) && is_numeric($b))
        return ($a * $b);
    else    
        return (0);
}

function    divide($a, $b)
{
    if (is_numeric($a) && is_numeric($b))
        return ($a / $b);
    else    
        return (0);
}

function    mod($a, $b)
{
    if (is_numeric($a) && is_numeric($b))
        return ($a % $b);
    else    
        return (0);
}

function ft_split($str)
{
    $ret = array_filter(preg_split('/\s+/', $str));
    return ($ret);
}

if ($argc == 2)
{
    $split = ft_split(trim($argv[1], " \t"));
    if (is_numeric($split[0]) && is_numeric($split[2]))
    {
        if ($split[1] == "+")
            echo add(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
        else if ($split[1] == "-")
            echo minus(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
        else if ($split[1] == "*")
            echo mult(trim($argv[0], " \t"), trim($split[2], " \t")) . "\n";
        else if ($split[1] == "/")
            echo divide(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
        else if ($split[1] == "%")
            echo mod(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
        else
            echo "Syntax Error\n";
    }
    else
        echo "Syntax Error\n";
}else
    echo "Incorrect Parameters\n";
?>
995

Answer

Solution:

The only thing I can think of is command substitution (see also parameter substitution) - something which happens in bash and other shells. If this is what's going on, then your reporting of the situation is a little misleading (read on).

It's very unlikely that PHP will be doing this, it'll be done by the shell, and there is no way to modify your code to prevent this... It's a feature of the shell.


For example a variable, using${...}:

$ FOO="test"
$ echo ${FOO}
test

It's also possible to run a command and use the output (stdout) as the value with$(...):

$ echo $(date)
Tue 2 Oct 12:02:59 BST 2018

Another variant of this is using backticks:

$ echo `date`
Tue 2 Oct 12:04:03 BST 2018

You've listed the following in your question:

./do_op_2.php '`rm -rf ~/`;'

The use of single quotes (') should prevent the shell from substituting the backticks:

$ echo '${FOO}'
${FOO}
$ echo '`date`'
`date`

But using double quotes (") will not prevent this:

$ echo "${FOO}"
test
$ echo "`date`"
Tue  2 Oct 12:05:17 BST 2018

I can only presume that you've reported single quotes, but actually used double quotes when you observed this behaviour. Your comment supports this theory.

For eg../do_op_2.php "`rm -rf test.doc`;" will delete test.doc instead of ignoring the command.

People are also looking for solutions to the problem: php - WooCommerce: How can I get orders with a custom ID in order meta data object?

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.