Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
处理$\u安全获取PHP_Php_Security_Get - Fatal编程技术网

处理$\u安全获取PHP

处理$\u安全获取PHP,php,security,get,Php,Security,Get,我有这样一个代码: $myvar=$_GET['var']; // a bunch of code without any connection to DB where $myvar is used like this: $local_directory=dirname(__FILE__).'/images/'.$myvar; if ($myvar && $handle = opendir($local_directory)) { $i=0; while (

我有这样一个代码:

$myvar=$_GET['var'];

// a bunch of code without any connection to DB where $myvar is used like this:

$local_directory=dirname(__FILE__).'/images/'.$myvar;
if ($myvar && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}
$myvar =  preg_replace("/[^a-zA-Z0-9-]/","",$_GET['var']);

我对许多剥离和转义函数有点困惑,所以问题是,我需要用$myvar做什么才能保证代码的安全?在我的情况下,我不进行任何数据库连接。

这样做非常非常危险:opendir$local\u directory,其中$local\u directory是一个可能来自外部的值

如果有人进来,比如../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../?您有可能会危及主机的安全

您可以在此处浏览一下,开始:

IMHO,如果你没有在运行中创建任何东西,你应该有如下内容:

$allowed_dirs = array('dir1','dir2', 'dir3');
if (!in_array($myvar, $allowed_dirs)) {
    // throw an error and log what has happened
}
$allowed_dirs = array();
if ($handle = opendir(dirname(__FILE__) . '/images')) {
    while (false !== ($entry = readdir($handle))) {
            $allowed_dirs[] = $entry;
    } 
    closedir($handle);
}
$myvar=$_GET['var'];

// you can deny access to dirs you want to protect like this
unset($allowed_dirs['private_stuff']);

// rest of code
$local_directory = dirname(__FILE__) . "/images/.$myvar";
if (in_array(".$myvar", $allowed_dirs) && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}
您可以在收到外部输入后立即执行此操作。如果这样做是不切实际的,因为图像dir的数量会随时间而变化,并且您担心会丢失与代码库的同步,那么您也可以先扫描图像文件夹中的子目录,然后填充有效值数组

因此,在最后,你可能会有这样的结果:

$allowed_dirs = array('dir1','dir2', 'dir3');
if (!in_array($myvar, $allowed_dirs)) {
    // throw an error and log what has happened
}
$allowed_dirs = array();
if ($handle = opendir(dirname(__FILE__) . '/images')) {
    while (false !== ($entry = readdir($handle))) {
            $allowed_dirs[] = $entry;
    } 
    closedir($handle);
}
$myvar=$_GET['var'];

// you can deny access to dirs you want to protect like this
unset($allowed_dirs['private_stuff']);

// rest of code
$local_directory = dirname(__FILE__) . "/images/.$myvar";
if (in_array(".$myvar", $allowed_dirs) && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}

上面的代码没有优化。但是,在这种情况下,让我们避免过早的优化来避免另一次漂亮的否决;这个代码片段只是为了让您明白显式允许值,而不是允许所有内容的替代方法,除非匹配某个模式。我认为前者更安全。

像这样做真的非常危险:opendir$local\u directory,其中$local\u directory是一个可能来自外部的值

如果有人进来,比如../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../?您有可能会危及主机的安全

您可以在此处浏览一下,开始:

IMHO,如果你没有在运行中创建任何东西,你应该有如下内容:

$allowed_dirs = array('dir1','dir2', 'dir3');
if (!in_array($myvar, $allowed_dirs)) {
    // throw an error and log what has happened
}
$allowed_dirs = array();
if ($handle = opendir(dirname(__FILE__) . '/images')) {
    while (false !== ($entry = readdir($handle))) {
            $allowed_dirs[] = $entry;
    } 
    closedir($handle);
}
$myvar=$_GET['var'];

// you can deny access to dirs you want to protect like this
unset($allowed_dirs['private_stuff']);

// rest of code
$local_directory = dirname(__FILE__) . "/images/.$myvar";
if (in_array(".$myvar", $allowed_dirs) && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}
您可以在收到外部输入后立即执行此操作。如果这样做是不切实际的,因为图像dir的数量会随时间而变化,并且您担心会丢失与代码库的同步,那么您也可以先扫描图像文件夹中的子目录,然后填充有效值数组

因此,在最后,你可能会有这样的结果:

$allowed_dirs = array('dir1','dir2', 'dir3');
if (!in_array($myvar, $allowed_dirs)) {
    // throw an error and log what has happened
}
$allowed_dirs = array();
if ($handle = opendir(dirname(__FILE__) . '/images')) {
    while (false !== ($entry = readdir($handle))) {
            $allowed_dirs[] = $entry;
    } 
    closedir($handle);
}
$myvar=$_GET['var'];

// you can deny access to dirs you want to protect like this
unset($allowed_dirs['private_stuff']);

// rest of code
$local_directory = dirname(__FILE__) . "/images/.$myvar";
if (in_array(".$myvar", $allowed_dirs) && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}

上面的代码没有优化。但是,在这种情况下,让我们避免过早的优化来避免另一次漂亮的否决;这个代码片段只是为了让您明白显式允许值,而不是允许所有内容的替代方法,除非匹配某个模式。我认为前者更安全。

您正试图防止目录遍历攻击,因此您不希望此人输入。/../../../../../../../或其他内容,希望读取文件或文件名,这取决于您正在做什么

我经常使用这样的方法:

$myvar=$_GET['var'];

// a bunch of code without any connection to DB where $myvar is used like this:

$local_directory=dirname(__FILE__).'/images/'.$myvar;
if ($myvar && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}
$myvar =  preg_replace("/[^a-zA-Z0-9-]/","",$_GET['var']);
这将用一个空格替换任何不是a-zA-Z0-9的内容,因此如果变量包含*,则此代码将删除该内容


然后,我更改a-zA-Z0-9-以匹配字符串中允许的字符。然后,我可以将其锁定为仅包含数字或我需要的任何内容。

您正在尝试防止目录遍历攻击,因此您不希望此人输入。/../../../../../../或其他内容,希望读取文件或文件名,具体取决于您正在执行的操作

我经常使用这样的方法:

$myvar=$_GET['var'];

// a bunch of code without any connection to DB where $myvar is used like this:

$local_directory=dirname(__FILE__).'/images/'.$myvar;
if ($myvar && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}
$myvar =  preg_replace("/[^a-zA-Z0-9-]/","",$_GET['var']);
这将用一个空格替换任何不是a-zA-Z0-9的内容,因此如果变量包含*,则此代码将删除该内容


然后,我更改a-zA-Z0-9-以匹配字符串中允许的字符。然后,我可以将其锁定为只包含数字或我需要的任何内容。

与来自不受信任来源的所有数据一样:在使用前对其进行验证,并在将其传递到其他上下文时对其进行正确编码

对于前者,首先需要指定数据必须被视为有效的属性。这主要取决于其使用目的


在您的情况下,$myvar的值可能至少应该是一个有效的目录名,但也可以是由目录名组成的有效相对路径,具体取决于您的需求。此时,您应该指定这些要求。

与来自不受信任来源的所有数据一样:在使用前对其进行验证,并在将其传递到其他上下文时对其进行正确编码

对于前者,首先需要指定数据必须被视为有效的属性。这主要取决于其使用目的


在您的情况下,$myvar的值可能至少应该是一个有效的目录名,但也可以是由目录名组成的有效相对路径,具体取决于您的需求。此时,您应该指定这些要求。

为了完整起见,请允许我注意,如果您可以确保您的代码只在Unixish系统(如Linux)上运行,那么您只需要确保:

$myvar不包含任何斜杠/、U+002F或null \0,U+0000个字符,以及

$myvar不为空或不等于。或者,等价地,.$myvar不等于。或者

这是因为,在Unix文件系统上,唯一的目录分隔符和文件名中不允许的两个字符中的一个,另一个是空字符\0是斜杠,目录树中唯一指向上的特殊目录项是斜杠。而且


但是,如果有一天您的代码可能会在Windows上运行,那么您需要禁止使用更多的字符,至少是反斜杠、\\,可能还有其他字符。我对Windows文件系统约定不太熟悉,无法确切说明哪些字符需要禁止,但安全的方法是这样做,并且只允许您知道是安全的字符。

为了完整起见,请注意,如果您可以确保您的代码只在Unixish系统(如Linux)上运行,您需要确保的唯一事项是:

$myvar不包含任何斜杠/、U+002F或null\0、U+0000字符,以及

$myvar不为空或不等于。或者,等价地,.$myvar不等于。或者

这是因为,在Unix文件系统上,唯一的目录分隔符和文件名中不允许的两个字符中的一个,另一个是空字符\0是斜杠,目录树中唯一指向上的特殊目录项是斜杠。而且



但是,如果有一天您的代码可能会在Windows上运行,那么您需要禁止使用更多的字符,至少是反斜杠、\\,可能还有其他字符。我对Windows文件系统约定不太熟悉,无法确切说明哪些字符需要禁止,但安全的方法是这样做,并且只允许您知道是安全的字符。

是否已经存在。$myvar目录,或者你是在运行中创建的?@Pekka:这段代码不会在运行中创建任何东西。如果使用php过滤器清理所有输入,那么它应该足以满足你的代码@Niklas根据OP,上面的代码只是一个摘录。Smartass回答:没有,因为您使用的是,所以您尝试访问的目录实际上是images/$myvar、dollar sign和所有。是否已经存在“$myvar”目录,或者你是在运行中创建的?@Pekka:这段代码不会在运行中创建任何东西。如果使用php过滤器清理所有输入,那么它应该足以满足你的代码@Niklas根据OP,上面的代码只是一个摘录。Smartass回答:没有,因为您使用的是,所以您尝试访问的目录实际上是images/$myvar,美元符号等等。有什么例子可以过滤吗?语法突出显示的好处是某些错误会立即被发现。我会寻找我想要友好处理的有效子文件夹。然后我只允许在这些文件夹中指定外部参数。我不允许传递任何其他内容。因为您似乎允许图像的任何子目录作为有效输入,所以您完全可以不使用目录白名单,而只使用更简单的基于正则表达式的解决方案。记住,如果一个目录不存在,opendir已经失败了。你说得对,Niklas B。我不想对上面的代码进行全面介绍。但是,通过阵列解决方案,您可以轻松地取消设置不希望用户在扫描源目录或更高版本时访问的目录,同时还可以容纳动态值。顺便说一句,你今天对我似乎很严厉。我一定对你做了什么。我道歉,不是我的本意-有没有关于如何过滤的例子?语法突出显示的好处是某些错误会立即被发现。我会寻找我想要友好处理的有效子文件夹。然后我只允许在这些文件夹中指定外部参数。我不允许传递任何其他内容。因为您似乎允许图像的任何子目录作为有效输入,所以您完全可以不使用目录白名单,而只使用更简单的基于正则表达式的解决方案。记住,如果一个目录不存在,opendir已经失败了。你说得对,Niklas B。我不想对上面的代码进行全面介绍。但是,通过阵列解决方案,您可以轻松地取消设置不希望用户在扫描源目录或更高版本时访问的目录,同时还可以容纳动态值。顺便说一句,你今天对我似乎很严厉。我一定对你做了什么。我道歉,不是我的本意-在大多数情况下效果很好。当您在同级文件夹中有需要保护的数据时,应予以注意。这就是为什么我倾向于明确说明什么是允许的,而不是试图阻止我应该避免的。是的,当然。在非常清楚的情况下,您可以将正则表达式改为类似于/^option1 | option2 | option3/的内容。总是尽可能地限制输入。所有好的建议都是真的。我倾向于在更复杂的情况下依赖数组或其他东西,因为它可以灵活地保持w/FS同步,避免重复的代码/逻辑。
但是,无论如何,这是好的观点。是的,这真的取决于上下文-使用像这样的正则表达式是一个很好的快速简单的解决方案,可以在没有太多思考的情况下抛出,虽然是的,通常你会想与数据库中的已知值进行比较。这完全取决于你在做什么。再加上正则表达式让我觉得自己像个编码大师啊啊。绝对是好的观点。我知道这是什么感觉-在大多数情况下效果很好。当您在同级文件夹中有需要保护的数据时,应予以注意。这就是为什么我倾向于明确说明什么是允许的,而不是试图阻止我应该避免的。是的,当然。在非常清楚的情况下,您可以将正则表达式改为类似于/^option1 | option2 | option3/的内容。总是尽可能地限制输入。所有好的建议都是真的。我倾向于在更复杂的情况下依赖数组或其他东西,因为它可以灵活地保持w/FS同步,避免重复的代码/逻辑。但是,无论如何,这是好的观点。是的,这真的取决于上下文-使用像这样的正则表达式是一个很好的快速简单的解决方案,可以在没有太多思考的情况下抛出,虽然是的,通常你会想与数据库中的已知值进行比较。这完全取决于你在做什么。再加上正则表达式让我觉得自己像个编码大师啊啊。绝对是好的观点。我知道这是什么感觉-