将任意变量括在单引号中是否会阻止 eval() 执行代码?
Does enclosing an arbitrary variable in single quotes prevent eval() from executing code?
我正在尝试向我的同事展示在 PHP 中使用 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++;
}
}
更重要的是,他们应该为此使用关联数组。
但是,我无法真正演示为什么 eval 的这种用法容易导致任意代码执行。好像用单引号把变量括起来并没有执行代码。
我试着给他们看类似的东西:
http://localhost/eval.php?arg=var_dump($_ENV);&arg2=phpinfo():
而且似乎参数被清理了而不是被执行了,所以数组中填充了无害的字符串。
因此,即使每个人都认为 eval 是邪恶的,假设用单引号括起任意输入会阻止它退出是否正确?
所以在 PHP single quotes are different from double quotes 中,变量不会自动替换为字符串文字。在您的示例中,这使得 eval() (相对)安全,因为您引用的是 $value,它是由您的 foreach 提供的字符串变量。你在每一种情况下都在执行:
$data0 = $value;
这应该是相当安全的,因为攻击者无法指定正在评估的内容。如果您使用双引号,字符串将在 eval() 之前被替换,这将导致恶意代码 运行。这不会使 eval() 安全,但它确实适用于此示例。
这是用单引号重写的示例,会导致恶意代码 运行:
<?php
$i = 0;
foreach ($_GET as $key => $value) {
if (strpos($key, 'arg') !== false) {
(eval('$data' . $i . '=' . $value . ';'));
$i++;
}
}
?>
我正在尝试向我的同事展示在 PHP 中使用 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++;
}
}
更重要的是,他们应该为此使用关联数组。
但是,我无法真正演示为什么 eval 的这种用法容易导致任意代码执行。好像用单引号把变量括起来并没有执行代码。
我试着给他们看类似的东西:
http://localhost/eval.php?arg=var_dump($_ENV);&arg2=phpinfo():
而且似乎参数被清理了而不是被执行了,所以数组中填充了无害的字符串。
因此,即使每个人都认为 eval 是邪恶的,假设用单引号括起任意输入会阻止它退出是否正确?
所以在 PHP single quotes are different from double quotes 中,变量不会自动替换为字符串文字。在您的示例中,这使得 eval() (相对)安全,因为您引用的是 $value,它是由您的 foreach 提供的字符串变量。你在每一种情况下都在执行:
$data0 = $value;
这应该是相当安全的,因为攻击者无法指定正在评估的内容。如果您使用双引号,字符串将在 eval() 之前被替换,这将导致恶意代码 运行。这不会使 eval() 安全,但它确实适用于此示例。
这是用单引号重写的示例,会导致恶意代码 运行:
<?php
$i = 0;
foreach ($_GET as $key => $value) {
if (strpos($key, 'arg') !== false) {
(eval('$data' . $i . '=' . $value . ';'));
$i++;
}
}
?>