【问题标题】:Is it safe to use fopen to perform a cURL with file upload?使用 fopen 通过文件上传执行 cURL 是否安全?
【发布时间】:2019-09-14 06:54:12
【问题描述】:

我目前有一个上传表单,它通过其 API 将文件发送到 Dropbox。执行cURL后接收文件的.php如下:

$localFile = $_FILES["file_key"]['tmp_name'];
$fp = fopen($localFile, 'r');

$ch = curl_init();

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_URL, 'https://content.dropboxapi.com/2/files/upload');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    "authorization: Bearer MY-TOKEN",
    "content-type: application/octet-stream",
    "dropbox-api-arg: {\"path\": \"/tmp/a.txt\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}"
));
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
curl_exec ($ch);

这很好用,但我对第二行中的fopen 感到困扰。使用这个是不好的做法吗?即使是“只读”模式,我是否可以收到恶意文件并破坏我的系统?

【问题讨论】:

    标签: php curl file-upload dropbox-api


    【解决方案1】:

    绝对安全。 PHP 将其作为纯数据读取,它不会尝试执行它。 curl 将简单地将其传递给 DropBox API。这时就是 DropBox 的问题了(如果他们执行用户上传的代码,那将是相当令人惊讶的,除非他们有严重的安全漏洞)。

    【讨论】:

      【解决方案2】:

      是的,如果您使用只读模式,这是安全的,因为文件没有被执行,内容只是被读取。

      【讨论】:

        【解决方案3】:

        如果您使用的是 linux 或 MacOS* 或 *BSD 并且不关心 windows 兼容性,这是正确的方法,但我仍然想对您的代码进行 nicpick:

        如果您曾经编写过任何可以在 Windows 上运行的代码,请养成使用 fopen 模式 rb 而不是 r 的习惯,因为 Windows 上的 fopen r 模式可能会损坏二进制数据(并且通过您的 @987654324 @header,是二进制数据)和linux/macos/*BSD对rrb模式的处理方式都是一样的,所以就做吧

        $fp = fopen($localFile, 'rb');
        

        还有这一行

        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "authorization: Bearer MY-TOKEN",
            "content-type: application/octet-stream",
            "dropbox-api-arg: {\"path\": \"/tmp/a.txt\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}"
        ));
        

        应该实际阅读

        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "authorization: Bearer MY-TOKEN",
            "content-type: application/octet-stream",
            "dropbox-api-arg: " . json_encode(array(
                'path' => '/tmp/a.txt',
                'mode' => 'add',
                'autorename' => true,
                'mute' => false,
                'strict_conflict' => false,
            ))
        ));
        

        这种方式更具可读性、可维护性和更易于修改。尽管我必须说将这些数据作为 HTTP HEADER 对 Dropbox 而言是一个糟糕的设计决定,但 HTTP 标头中的非法字符在大多数文件系统标准的文件名中是完全合法的,这意味着我怀疑可以制作一个有效的 json 包含一个不能被 http-header-encoded 的有效文件名.. 他们应该使用 multipart/form-data 代替,并将文件和 json 作为 2 个单独的表单变量,imo。

        【讨论】:

          猜你喜欢
          • 2013-04-04
          • 2020-06-13
          • 2017-02-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-24
          • 1970-01-01
          相关资源
          最近更新 更多