7

当我执行从 Java 到 PHP 的流上传时,有时会收到一个 PHP 错误,提示输入变量超出max_input_vars.

起初,我不明白为什么。我先解释一下:

正在使用类似于以下的方法上传文件:

// get file data from input stream
$putdata = fopen("php://input", "r");
$tmp = tmpfile();
filesize = stream_copy_to_stream ($putdata, $tmp);
fclose ($putdata);

// copy temp stream into destination stream
$target = fopen('myfile.dwg', "w");        
fseek($tmp, 0, SEEK_SET);
stream_copy_to_stream($tmp, $target);
fclose($target);
fclose ($tmp);

为了了解为什么 PHP 会给我这样的警告,我转储了正在发送的数据:

file_put_contents ('input_vars.log', print_r ($_REQUEST, true));
file_put_contents ('php_input.log', file_get_contents ('php://input'));

这是有趣的部分:正在上传的文件是 1.8 兆字节。生成的日志是:

  • input_vars.log=> 5 兆字节,90,000 行
  • php_input.log => 20 兆字节,283,000 行

现在错误消息突然看起来是合法的。仅包含字节码,php_input.loginput_vars.log格式如下:

Array
(
    [filename] => 0018-101-001_67.dwg
    [versionId] => 11253
    [filetype] => dwg
    [‘á‹Úê-8øFj–sÙ/ghÔ÷JJÐWhvPV] => ...
    ....
)

前三个密钥是通过 GET 发送的,其余的都是文件数据。如果我搜索并计算 的匹配项=>,我会得到 25,954 个匹配项。然后我假设它REQUEST拥有 26,000 个密钥。

现在,回到我的问题:我已经max_input_vars多次提高了价值,现在它的价值为30000. 我是否应该忽略此安全设置,并将其设置为尽可能高?我担心的是 PHP 会从 REQUEST 数组中删除大于 的部分30000,从而导致文件损坏。

将此值设置得太高是否存在任何安全问题?是否有更好的方法将文件上传到 PHP?

4

6 回答 6

2

也许尝试将enable_post_data_reading指令设置为“false”(或“Off”)以防止 PHP 解析文件正文?

顺便说一句,如果您使用的是 PHP 5.3.9,您应该修补 max_input_vars漏洞

于 2012-10-26T14:45:27.157 回答
2

您想要做的是PUT upload,您不应该将其作为 POST 处理;或 - 至少 - 将Content-TypeHTTP 标头设置为application/octet-stream

于 2012-10-27T15:12:01.757 回答
1

就其本身“php.net”(PHP.NET - max_input_vars)而言,他们报告说您增加此设置的值没有问题,但是,这是“使用此指令减轻拒绝服务的可能性的一种形式使用哈希冲突的攻击。”。

为了解决这个僵局,你可以尝试在运行时设置变量值,使用下面的函数:

ini_set("max_input_vars", 30000);

我最近遇到了这个问题,以及调用是如何远程的,而不是配置运行时,所以不幸的是我们不得不增加这个值。

到目前为止,我们没有问题,但想法是未来,修改代码以按部分发送数据,从而使代码保持在语言的标准当前配置内。

于 2012-10-26T14:30:18.920 回答
0

您没有展示如何用 Java 上传文件。PHP 将普通的 POST 请求视为来自表单并尝试从中解析字段 - 如果数据是二进制数据,这是个坏主意。您最好模拟 HTML 文件上传表单的功能并发送“多部分帖子”(示例)。然后使用PHP 的标准文件上传处理功能,就像从表单接收一样。

于 2012-10-26T14:25:50.300 回答
0

接受的答案是有效的,但您必须意识到关闭也enable_post_data_reading意味着关闭自动填充$_POST和数组。由于我广泛使用这些数组,我决定限制为专用于文件上传的特定文件:$_GET$_REQUESTenable_post_data_reading

<Files "UploadFile.php">
    php_value enable_post_data_reading Off
</Files>

因为我使用 ajax 请求上传,所以可以这样设置用户定义的标头:

oXhr.setRequestHeader("X-File-Name", I_sFileName);
oXhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

通过这样做,您绕过了使用$_REQUESTor的需要$_POST,因为您在 php 中获取信息:

$fileName = $_SERVER['HTTP_X_FILE_NAME'];

于 2016-04-08T03:21:53.967 回答
-1

尝试通过增加大小 post_max_size , upload_max_filesize 和 max_file_uploads 在 php.ini

于 2012-10-31T10:01:43.020 回答