我有一个需要输出python脚本的PHP应用程序,更具体地说是一堆变量赋值语句,例如。
subject_prefix = 'This String From User Input'
msg_footer = """This one too."""
需要编写subject_prefix等的内容以获取用户输入;因此,我需要逃避字符串的内容。写下面的内容不会削减它;一旦有人使用引用或换行或其他任何我不知道可能有危险的东西,我们就会被塞满:
echo "subject_prefix = '".$subject_prefix."'\n";
因此。有什么想法吗?
(由于时间限制,无法用Python重写应用程序。:P)
编辑,多年后:
这是用于web应用程序(用PHP编写)和Mailman(用Python编写)之间的集成。我无法修改后者的安装,所以我需要想出一种方法来用它的语言来管理它的配置。
这也是真的坏主意。
答案 0 :(得分:2)
不要尝试在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源代码作为数据交换格式的另一个例子。
答案 1 :(得分:0)
我首先标准化我在python中使用的字符串类型,使用三引号字符串(“”“)。这应该减少输入中杂散引号引起的问题。你仍然需要当然要逃避它,但它应该减少一些问题的数量。
我为逃避弦乐而做的事情在某种程度上取决于我担心的内容,以及他们再次打印出来的背景。如果你只是担心引起问题的引用,你可以简单地检查和发生“”“并逃避它们。另一方面,如果我担心输入本身是恶意的(并且它是用户输入,所以你可能应该),然后我会看看像strip_tags()或其他类似函数的选项。
答案 2 :(得分:0)
另一种选择可能是将数据作为数组或对象导出为JSON字符串,并稍微修改python代码以处理新输入。虽然通过JSON逃避不是100%防弹,但它仍然比自己的逃避例程更好。
如果JSON字符串格式错误,您将能够处理错误。
Python有一个用于编码和解码JSON的包:python-json 3.4
答案 3 :(得分:0)
我需要对此进行编码以转义“ntriples”格式的字符串,该格式使用python escaping。
以下函数接受一个utf-8字符串并返回它为python(或ntriples格式)转义。 如果给出非法的utf-8数据,它可能会做奇怪的事情。它不了解超过xFFFF的Unicode字符。它(当前)没有用双引号包装字符串。
uniord函数来自对php.net的评论。
function python_string_escape( $string ) {
$string = preg_replace( "/\\\\/", "\\\\", $string ); # \\ (first to avoid string re-escaping)
$string = preg_replace( "/\n/", "\\n", $string ); # \n
$string = preg_replace( "/\r/", "\\r", $string ); # \r
$string = preg_replace( "/\t/", "\\t", $string ); # \t
$string = preg_replace( "/\"/", "\\\"", $string ); # \"
$string = preg_replace( "/([\x{00}-\x{1F}]|[\x{7F}-\x{FFFF}])/ue",
"sprintf(\"\\u%04X\",uniord(\"$1\"))",
$string );
return $string;
}
function uniord($c) {
$h = ord($c{0});
if ($h <= 0x7F) {
return $h;
} else if ($h < 0xC2) {
return false;
} else if ($h <= 0xDF) {
return ($h & 0x1F) << 6 | (ord($c{1}) & 0x3F);
} else if ($h <= 0xEF) {
return ($h & 0x0F) << 12 | (ord($c{1}) & 0x3F) << 6 | (ord($c{2}) & 0x3F);
} else if ($h <= 0xF4) {
return ($h & 0x0F) << 18 | (ord($c{1}) & 0x3F) << 12 | (ord($c{2}) & 0x3F) << 6 | (ord($c{3}) & 0x3F);
} else {
return false;
}
}
答案 4 :(得分:-2)
我建议编写一个函数,它将采用两个参数:要转义的文本和字符串所在的引号类型。然后,例如,如果引号的类型是单引号,则函数将转义单引号在字符串和任何其他需要转义的字符(反斜杠?)。
function escape_string($text, $type) {
// Escape backslashes for all types of strings?
$text = str_replace('\\', '\\\\', $text);
switch($type) {
case 'single':
$text = str_replace("'", "\\'", $text);
break;
case 'double':
$text = str_replace('"', '\\"', $text);
break;
// etc...
}
return $text;
}
我假设对于单引号字符串,你想要转义单引号,并且使用双引号字符串,你想要转义双引号......