Вопрос

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.

Это было полезно?

Решение 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!';
    }
}

Другие советы

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];
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top