Pergunta

Is this code explotable in any way?

<?
$arg=$_REQUEST['arg'];
preg_replace("/([0-9]+)(.+)/e",'list($var,$var2)=array("$1","$2")',$arg);
echo "$var - $var2";
?>

Is it possible to use special characters or some other method to inject code?

I'm using similar code in some projects and I just want to make sure that it is safe.

Foi útil?

Solução 2

Using

(.+)

with /e parameter is always exploitable because it allows any language constructions there.

Example exploit code:

$test = new test();
$test->setSuperSecret();
$test->exploitableExpression();

class test
{
    private $mySuperSecretVariable;
    public function exploitableExpression()
    {
        $arg= '1234$this->mySuperSecretVariable';
        preg_replace("/([0-9]+)(.+)/e",'list($var,$var2)=array("$1","$2")',$arg);
        var_dump($var,$var2);
    }
    public function setSuperSecret()
    {
        $this->mySuperSecretVariable = 'SECRET!';
    }
}

Outras dicas

The /e modifier is very hard to make safe, and it will be removed in a future version of PHP. The reason is that it performs its substitution first and then evaluates the code (as though with eval()).

It is therefore possible to craft input such that the substituted code runs arbitrary PHP functions or exposes private variables.

Some escaping is performed automatically, but it is insufficient protection, as shown by this example which executes an arbitrary function using your code and the examples in the PHP manual:

function dangerous()
{
    echo 'Dangerous code executed';
}

$arg = '42{${dangerous()}}';
preg_replace("/([0-9]+)(.+)/e",'list($var, $var2) = array("$1", "$2")', $arg);
var_dump($var, $var2);

In contrast, preg_replace_callback() sends the value of the substitution as a parameter to a callback function, so there is no way for the contents of the initial string to be evaluated directly as code.

Note that in your example, the executed code is just assigning variables anyway, so doesn't need any kind of callback, only to capture the matches with preg_match():

preg_match("/([0-9]+)(.+)/", $arg, $matches);
$var = $matches[1];
$var2 = $matches[2];
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top