不要尝试在 PHP 中编写此函数。您将不可避免地出错,您的应用程序将不可避免地具有任意远程执行漏洞。
首先,考虑您实际解决的是什么问题。我想你只是想从 PHP 到 Python 获取数据。您可能会尝试编写 .ini 文件而不是 .py 文件。Python 有一个出色的 ini 语法解析器ConfigParser。您可以在 PHP 中编写明显且可能不正确的引用函数,如果(阅读:何时)您弄错了,不会发生任何严重的事情。
您还可以编写一个 XML 文件。PHP 和 Python 的 XML 解析器和发射器太多了,我什至无法在此处列出。
如果我真的不能让你相信这是一个糟糕的、糟糕的想法,那么你至少可以使用 Python 已有的功能来做这样的事情:repr()
.
这是一个方便的 PHP 函数,它将运行 Python 脚本为您执行此操作:
<?php
function py_escape($input) {
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$process = proc_open(
"python -c 'import sys; sys.stdout.write(repr(sys.stdin.read()))'",
$descriptorspec, $pipes);
fwrite($pipes[0], $input);
fclose($pipes[0]);
$chunk_size = 8192;
$escaped = fread($pipes[1], $chunk_size);
if (strlen($escaped) == $chunk_size) {
// This is important for security.
die("That string's too big.\n");
}
proc_close($process);
return $escaped;
}
// Example usage:
$x = "string \rfull \nof\t crappy stuff";
print py_escape($x);
该chunk_size
检查旨在防止攻击导致您的输入最终成为两个非常长的字符串,它们分别看起来像("hello " + ("." * chunk_size))
和'; os.system("do bad stuff")
。现在,这种天真的攻击不会完全起作用,因为 Python 不会让单引号字符串在行的中间结束,并且system()
调用中的那些引号本身也会被引用,但是如果攻击者设法得到一行延续(“\”)到正确的位置并使用类似的东西,os.system(map(chr, ...))
然后他们可以注入一些将运行的代码。
我选择简单地读取一个块,如果有更多的输出就放弃,而不是继续读取和累积,因为 Python 源文件行长度也有限制;据我所知,这可能是另一个攻击媒介。Python 并非旨在防止任意人在您的系统上编写任意源代码,因此该领域不太可能被审计。
我不得不为这个简单的例子考虑所有这些,这只是另一个例子,说明为什么不应该使用 python 源代码作为数据交换格式。