0

我正在尝试设置一个 PHP 页面,该页面将安全地接受文件上传(简历),将其存储为 mysql blob,并稍后提供下载。但是当我稍后下载 PDF 进行查看时,它们似乎总是损坏并且无法正常打开。

感谢 Jgoettsch 提出的问题(php: reversing mysql_real_escape_string's effects on binary),我意识到通过 mysql_real_escape_string 提供文件数据(以防止注入)可能会损坏文件内容,并想到通过 base64_encode() 传递二进制文件,并在下载前使用 base64_decode() 。

这是一些样机代码,演示了我目前正在做什么(不起作用):

上传:

<? 
// Get file contents
$cv_pointer = fopen($_FILES['cv']['tmp_name'], 'r');
$cv_content = fread($cv_pointer, filesize($_FILES['cv']['tmp_name']));
fclose($cv_pointer);

// Insert SQL
$sql = sprintf("INSERT INTO documents (name, file, size, date_uploaded)
  VALUES ('%s', '%s', '%s', NOW())",
    mysql_real_escape_string($_FILES['cv']['name']),
    mysql_real_escape_string($cv_content),
    mysql_real_escape_string($_FILES['cv']['size']));
$result = mysql_query($sql);
?>

和下载:

<? 
if (isset($_GET['view_cv'])) {
  $cv = mysql_fetch_assoc($rsApplicationCv);

  header("Content-length: ".$cv['size']); 
  header("Content-type: application/pdf"); 
  header("Content-disposition: attachment; filename=".$cv['name']);
  echo $cv['file'];
  exit();
}
?>

以下是我的问题:

  1. 如果您有文件上传字段,该字段是否容易受到 sql 注入?还是我不必要地担心?显然,如果我可以将二进制文件传递到 blob 字段而不进行任何翻译,那么这个文件上传任务会简单得多。
  2. 如果我通过 base64_encode() 提供上传的文件内容,那是否等同于清理?还是我应该对其进行编码,然后另外通过 mysql_real_escape_string 传递编码的字符串?
  3. 这一切似乎只是为了存储和获取 PDF 付出了很多努力。对于这种常见需求,是否有更简单的解决方案,我还没有偶然发现?

提前致谢!

4

2 回答 2

1

既然你在谈论消毒,我假设这是一个公共网站,陌生人将上传文件。存储用户提交的 PDF 文件是一个非常糟糕的主意。首先,您如何确定您收到的文件甚至是 PDF?用户 100% 有可能将恶意文件卷曲到您的数据库中,并让用户在不知不觉中下载病毒。PDF 本身(如果我没记错的话)实际上可以在某些 Windows 操作系统中执行病毒,就像 WMV 和 WMA 文件一样。

如果您绝对需要 PDF,那么最好的选择是使用用户提交的经过清理的数据创建您自己的 PDF 文件。您可能可以在网上找到有关如何执行此操作的教程。我个人不建议首先使用 PDF,因为您可以使用 HTML 和 CSS 来构建简历并完美地打印出来。

于 2013-07-31T18:33:06.610 回答
1

Q如果你有一个文件上传字段,该字段是否容易受到 sql 注入?

是的(有点。易受 SQL 注入攻击的不是表单上的字段;该漏洞实际上存在于处理请求中提交的值的代码中。)

Q还是我不必要地担心?

A不。您应该始终意识到发生坏事的可能性,并以防止漏洞暴露(和利用)的方式编写代码。

Q如果我通过 base64_encode() 提供上传的文件内容,那是否等于净化?

A差不多了,只要您的 base64_encode 保证返回的值将仅包含 [A-Za-z0-9+./=]。最佳实践是使用绑定参数

Q还是我应该对其进行编码,然后另外通过 mysql_real_escape_string 传递编码的字符串?

禁止使用带有绑定参数的准备好的语句,然后最佳实践规定所有值(包括 base64_encoded 值)如果它们包含在要提交到数据库的 SQL 文本中,则通过 mysql_real_escape_string 运行。

于 2013-07-31T19:38:27.343 回答