PHP: Does base64_encode protect from mysql injections?
我正在尝试设置一个PHP页面,它可以安全地接受文件上传(履历),将其存储为mysql blob,并稍后提供下载。但当我稍后下载PDF以供查看时,它们似乎总是损坏,无法正确打开。
由于jgoettsch提出的一个问题(php:reversing mysql_real_escape_string对二进制文件的影响),我意识到通过mysql_real_escape_string(防止注入)输入文件数据可能会损坏文件内容,于是我想到通过base64_encode()传递二进制文件,并在下载之前使用base64_decode()。
下面是一些演示我当前正在做什么(不起作用)的模拟代码:
上传:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?
// 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);
?> |
下载内容:
1 2 3 4 5 6 7 8 9 10 11
| <?
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();
}
?> |
以下是我的问题:
如果您有文件上载字段,那么该字段是否容易受到SQL注入的攻击?还是我不必要地担心?显然,如果我可以将二进制文件传递到blob字段而不进行任何转换,那么这个文件上传任务就简单多了。
如果我通过base64_encode()输入上传的文件内容,这是否等同于卫生处理?或者我应该对它进行编码,然后再通过mysql_real_escape_string传递编码的字符串吗?
这一切似乎只是为了存储和获取一个PDF文件而付出了很大的努力。有没有一个更简单的解决办法来满足这个我还没有偶然发现的共同需求?
事先谢谢!
- 答:没有
- 将mysqli或pdo与准备好的查询和占位符一起使用,这样可以解决编码和注入问题。
- 注射是安全的,就像不把叉子塞进电源插座一样,可以保护你不触电。注入漏洞的规则:如果您在查询中使用"外部"数据,那么您就容易受到攻击。不管数据从哪里来,即使是你自己的。您仍然可以轻松地插入自己的查询。
- @艾琳先生:你想更具体地谈谈你所说的话吗?
- 在数据库中存储任意二进制数据通常被认为是一个坏主意。您应该存储的是对磁盘上文件的引用,或者像AmazonS3这样的批量对象存储服务。另外,请不要在新代码中使用mysql_query,它已被弃用,并已从将来的PHP版本中删除。如果操作正确,转义二进制数据不会损坏它。
- @马卡:谢谢你的比喻,我会坚持住的。我以为1是个愚蠢的问题,但无论如何还是值得问。
- @塔德曼:谢谢你提醒我:MySQL查询。关于:转义二进制数据,我的理解是mysql_real_escape_string,通常被认为是转义进入的二进制数据的最佳方法,可能会损坏pdf和其他文件类型。这不正确吗?请参见:stackoverflow.com/questions/885239/&hellip;
- @topherhunt这不是最好的数据转义方法,但如果您仍在使用吱吱作响的mysql_query接口,它是可靠转义的唯一方法。转义只是为了让MySQL正确地解释您的数据,并且在检索时应该是好的。但是,如果您意外地双重逃避您的数据,它可能会使事情一团糟。我强烈建议不要在数据库中放置任意的二进制文件。他们不属于那里。
- @塔德曼:所有这些都是实话。谢谢你的意见。mysql_real_escape_字符串似乎会破坏我的pdf(我很确定我不是双重转义),但与base64_编码结合起来可以很好地工作。把你的建议牢记在心。
问:如果您有文件上载字段,那么该字段是否容易受到SQL注入的攻击?
A是的(有点。表单上易受SQL注入攻击的字段并非如此;该漏洞实际上存在于处理请求中提交的值的代码中。)
问:还是我不必要地担心?
答:不。您应该始终意识到可能发生的坏事情,并以防止漏洞被暴露(和利用)的方式编写代码。
问:如果我通过base64_encode()输入上传的文件内容,这是否等同于卫生处理?
a它就在那里,只要您的base64_编码保证返回值只包含[a-za-z0-9+./=]。最佳实践是使用绑定参数
或者我应该对它进行编码,然后再通过mysql_real_escape_string传递编码的字符串?
禁止使用带有绑定参数的准备好的语句,那么最佳实践要求所有值(包括base64_编码的值)都通过mysql_real_escape_字符串运行,如果这些值包含在要提交到数据库的SQL文本中。
既然你说的是卫生处理,我假设这是一个公共网站,陌生人会上传文件。存储用户提交的PDF文件是一个非常糟糕的主意。首先,你怎么能确定你收到的文件是一个PDF文件呢?用户有100%的可能将恶意文件卷入数据库,并让用户自动下载病毒。pdf本身(如果我记得正确的话)实际上可以像wmv和wma文件一样,在某些Windows操作系统中执行病毒。
如果你绝对需要一个PDF,那么最好的选择是用用户提交的净化数据创建你自己的PDF文件。你可能会在网上找到一个关于如何做到这一点的教程。我个人不建议首先使用PDF,因为您可以使用HTML&css构建简历并完美打印出来。
- 谢谢安得烈。PDF文件将由公众提交,短期内我看不到解决这一问题的方法。我们需要让未来的实习生更容易申请职位,并接受他们最标准的简历形式,他们可能会用它方便(.docx,.doc,.pdf)。它不会与人力资源一起要求申请人复制和粘贴他们的简历到cKeditor或类似的东西。
- 是的,我知道你想建立一个对用户友好的网络应用程序,但是当处理文件时,它变得相当困难。除了让自己受到安全漏洞的影响,我没有看到短期的解决方案。一般来说,您不必担心mysqli或pdo中的注入,但真正的问题是下载文件的用户。
- PDF文件通常不易受攻击。我不知道最新Adobe Reader更新未修复的任何漏洞。确实值得检查的是,该文件实际上是一个真正的PDF文件,但不需要完全放弃PDF上载。
- 谢谢伙计们。我要把这一切牢记在心。听起来mysqli是我需要进入的方向,我正朝着那个方向前进。