php $_GET是被解释为单引号还是双引号字符串?

3

我做出的假设是,$_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手册中是否有写明?

2
你为什么要根据 $_GET 变量的值来包含文件呢? - ascsoftw
4
这里的字符串值并不以任何方式被“解释”为字符串,它们只是字符串值。你在混淆数据和代码。单引号与双引号仅在后者中相关。 - 04FS
1
我猜你问题的答案很简单,就是“不行”,因为字符串值没有“引号”,它们只是数据。当在代码中定义字符串字面量时,才会使用引号。如果你在GET请求中收到的值是\x2e\x2e\x2ftest.php,那么这就是你拥有的值。 - David
2
我做出了一个假设,即$_GET变量被解释为单引号字符串。你犯了一个混乱的错误。单引号和双引号是标记源代码片段为纯文本(即数据)而不是代码的一种方式。$_GET是一个包含字符串的变量,即从URL中获取的纯文本,没有涉及到任何源代码。 - axiac
2
"也许简单地从用户输入中删除连续的两个点就可以防止任何目录遍历攻击" - 那是一个天真的假设。永远不要将用户输入用作文件路径。无论你多么小心,恶意用户(事实上是脚本)总会找到一种方法来欺骗你的代码,并包含完全不同的文件。" - axiac
显示剩余4条评论
1个回答

1

简短回答: $_GET['path'] 是一个变量。PHP 只有在双引号中才会解释转义序列,而不是在变量中。-> 字符串手册

$get = "\x2e";
var_dump($get);  
//string(1) "."

$get = "\\"."x2e";
var_dump($get);
//string(4) "\x2e"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接