Php - 通过下载给最终用户访问文件的安全方式?

Posted

技术标签:

【中文标题】Php - 通过下载给最终用户访问文件的安全方式?【英文标题】:Php - Secure way to give access of a file via Downloading to the End User? 【发布时间】:2019-03-13 18:40:16 【问题描述】:

这更像是一个安全问题,我不确定这种方法是否足够安全可靠地下载文件并呈现给网络用户?

我们将客户发票文件存储在服务器位置(公共无法访问的位置),然后我们通过文件中的 php 代码读取它们(带有文件的公共位置),如下所示,

当然,我们在访问用户之前使用会话对用户进行身份验证,但是如果最终用户知道文件在哪里,他可以操纵他的请求以读取联合国授权的发票。

我只是想知道,如果这种方式

1.向最终用户展示文件是否足够安全?

2。最终用户根本不知道文件在服务器中的存储位置?

3.关于如何处理类似情况的任何其他建议?

$i = $invoice->get();
$filename = sprintf(INV_PDF_FILENAME,$i['customerid'],date('Ymd',$i['dateIssued']));
$x = sprintf('/tmp/invoices/%s',$filename);
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Pragma: cache');
header('Cache-Control: private');
readfile($x);

【问题讨论】:

$invoice 来自哪里,他们对此有任何控制权吗?例如,如果您使用订单 ID 创建发票并且该 ID 是 URL 的一部分,那么有人可以向其提供任何订单 ID(理论上)。在不知道发票对象是如何创建的情况下,谁能说出来,因为所有信息都来自那个......像$filename = sprintf(INV_PDF_FILENAME,$current_user_id,date('Ymd',$i['dateIssued'])); 这样的东西会更好。 @ArtisticPhoenix 我明白你在说什么,在我们针对用户会话进行验证时,用户无法操纵发票对象。我的问题更多的是最终用户是否会从外部知道文件的位置 【参考方案1】:
    是的,假设没有其他漏洞(即用户能够更改进入 $filename 的参数以执行目录遍历攻击)。 除非存在任何其他漏洞,否则所提供的代码不会将其本地文件路径泄露给最终用户。 Make sure uploaded files are stored outside the document root。验证 realpath($x) 是否以您希望它们所在的目录开头。

例如:

$x = sprintf('/tmp/invoices/%s',$filename);
$realpath = realpath($x);
if (strpos($realpath, '/tmp/invoices/') !== 0) 
    // Note: The strict comparison to 0 matters.
    // It means that the real file path must begin with "/tmp/invoices/"
    // or else this redirect/exit gets called.
    header("Location: /error");
    exit;

【讨论】:

以上是关于Php - 通过下载给最终用户访问文件的安全方式?的主要内容,如果未能解决你的问题,请参考以下文章

使用ajax下载文件

jsp下载文件的实现方法及注意事项 (转)

gpfdist通过外部表创建的文件权限问题

安全文件下载

通过 PHP 访问不在 web 文件夹中的 jpg

最终用户计算安全——特权访问控制