代码之家  ›  专栏  ›  技术社区  ›  ffflabs

单引号中是否包含一个任意变量阻止EVAL()执行代码?

  •  1
  • ffflabs  · 技术社区  · 7 年前

    我试图证明使用 eval() 给我的同事。

    在一段代码中,我发现了如下内容(这非常简单):

    <?php
    
    $i        = 0;
    foreach ($_GET as $key => $value) {
        if (strpos($key, 'arg') !== false) {
            eval('$data' . $i . '=$value;');
            $i++;
        }
    }
    

    当然我告诉过他们应该重写为

    <?php
    $i=0;
    foreach ($_GET as $key => $value) {
        if (strpos($key, 'arg') !== false) {
            $varname  = 'data' . $i;
            $$varname = $value;
            $i++;
        }
    }
    

    更重要的是,他们应该为此使用一个关联数组。

    然而,我还不能真正演示为什么EVE的使用倾向于任意代码执行。似乎用单引号括住变量不会执行代码。

    我试着给他们看一些东西,比如:

    http://localhost/eval.php?arg=var_dump($_ENV);&arg2=phpinfo():
    

    而且似乎参数被消毒而不是被执行,所以数组中填充了无害字符串。

    所以,即使每个人都同意EVE是邪恶的, 假设将任意输入括在单引号中会阻止它执行equecuting,这是正确的吗? ?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Michael Powers    7 年前

    所以在PHP中 single quotes are different from double quotes 在这些变量中不会自动替换字符串文字。在您的示例中,这使得EVAL()相对安全,因为您引用的是$FULL值,这是您的前程提供的字符串变量。在任何情况下,你都在执行:

    $data0 = $value;
    

    这应该是相当安全的,因为攻击者无法指定要评估的内容。如果使用双引号,字符串将在eval()之前被替换,这将导致恶意代码运行。这并不能保证eval()的安全性,但对于本例来说确实有效。

    下面是用单引号重新编写的示例,它会导致恶意代码运行:

    <?php
    $i = 0;
    foreach ($_GET as $key => $value) {
        if (strpos($key, 'arg') !== false) {
            (eval('$data' . $i . '=' . $value . ';'));
            $i++;
        }
    }
    ?>