【发布时间】:2020-02-12 04:38:45
【问题描述】:
我假设 $_GET 变量被解释为单引号字符串(而不是双引号字符串)。
我相信这是真的,因为以下测试(我自己试图进行目录遍历攻击):
$file = "../test.php";
/**
* same as file1 but using hexadecimal encoding, which is a feature
* only available to double quoted strings
* https://www.php.net/manual/en/language.types.string.php
*/
$file2 = "\x2e\x2e\x2ftest.php";
include $file1; // will succeed in my environment
include $file2; // will succeed in my environment
但是,如果我通过 $_GET 传递十六进制符号,它会失败,包括 文件:
$file3 = $_GET["path"]; // (string) \x2e\x2e\x2ftest.php
include $file3; // will fail in my environment
所以我的问题是:$_GET 变量是否真的被解释为单引号字符串? (因为如果是这样,那么从用户输入中简单地删除两个连续的点可能会阻止任何目录遍历攻击)
如果是这样,它是否写在 php 手册的任何地方?
【问题讨论】:
-
为什么要包含基于 $_GET 变量值的文件?
-
它们不会以任何方式被“解释”为字符串,它们只是是字符串值。您在这里将 data 与 code 混淆了。单引号和双引号仅在后者中相关。
-
我猜你的问题的答案只是“否”,因为字符串值没有“引号”,只是数据。在代码中定义字符串 literals 时使用引号。如果您在 GET 中收到的值是
\x2e\x2e\x2ftest.php,那么这就是您拥有的值。 -
“我假设
$_GET变量被解释为单引号字符串”——你搞错了。单引号和双引号是一种可以将源代码片段标记为原始文本(即数据)而不是代码的方式。$_GET是一个包含字符串的变量,即从 URL 中提取的原始文本;不涉及源代码。 -
“也许从用户输入中简单地删除两个连续的点就可以防止任何目录遍历攻击)”——这是一个幼稚的假设。永远不要使用用户输入作为文件路径。曾经。无论您多么小心,恶意用户(实际上是脚本)总会找到一种方法来欺骗您的代码,使其包含一个完全不同的文件。