这个preg_replace示例是否可以以任何方式利用?

时间:2014-03-28 14:33:42

标签: php regex preg-replace exploit

此代码是否可以任何方式进行曝光?

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

是否可以使用特殊字符或其他方法来注入代码?

我在某些项目中使用类似的代码,我只是想确保它是安全的。

2 个答案:

答案 0 :(得分:3)

/e修饰符非常难以安全,并且将在未来的PHP版本中删除。原因是它首先执行替换然后评估代码(就像使用eval())。

因此可以设置输入,使替换代码运行任意PHP函数或公开私有变量。

某些转义会自动执行,但保护不足,如this example which executes an arbitrary function using your codeexamples 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);

相反,preg_replace_callback()将替换值作为参数发送给回调函数,因此初始字符串的内容无法直接作为代码进行评估。

请注意,在您的示例中,执行的代码只是分配变量,所以不需要任何类型的回调,只能用preg_match()捕获匹配项:

preg_match("/([0-9]+)(.+)/", $arg, $matches);
$var = $matches[1];
$var2 = $matches[2];

答案 1 :(得分:2)

使用

(.+)

/ e 参数始终可以被利用,因为它允许任何语言构造。

示例漏洞利用代码:

$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!';
    }
}