【问题标题】:Securely save a base64 string to a file in php安全地将base64字符串保存到php中的文件
【发布时间】:2013-12-13 18:38:27
【问题描述】:

我将转换后的 base64 编码字符串存储为图像文件。我必须将文件作为字符串获取。

目前我通过 POST 获取字符串,我担心有人发布了一些他们可能会用来破坏服务器的内容。我的问题是如何确保它尽可能安全。

这就是它目前的工作方式(总结):

$encodedString = $_POST['image'];
// Strip the crud from the front of the string [1]
$encodedString = substr($encodedString,strpos($encodedString,",")+1);
// Cleanup File [2]
$encodedString = str_replace(' ','+',$encodedString);
// Decode string
$decoded = base64_decode($encodedString);
// Save File
file_put_contents(uniqid().'.png',$decoded);

接下来我应该怎么做才能确保有人没有/没有将一些恶意代码注入到 post 变量中?

或者有比 POST 更好的方法吗?

参考资料:

  1. Convert Base64 string to an image file?
  2. PHP Data-URI to file

【问题讨论】:

标签: php security


【解决方案1】:

写入文件后,将文件名提供给imagecreatefrompng() 或任何其他可能的文件格式。如果它返回false,那么它实际上不是图像。

除此之外,弄清楚如何在发送应用程序中将您的POST 请求格式化为多部分,PHP 将完成工作将其连同文件名和mime 类型等相关信息一起放入$_FILES 超全局中。不过,这无助于防止任何形式的代码注入。

【讨论】:

  • 结合其他答案和 cmets 我将接受这一点,因为我可以使用这种技术来测试有效图像并删除任何非图像残渣。
【解决方案2】:

通过给文件一个用户无法影响的自动生成的名称,您已经避免了最糟糕的问题。

理论上,用这种方式破解你的服务器是不可能的,因为你的服务器不应该在 PNG 文件中运行任何代码。不幸的是,misconfigure nginx to do so 真的很容易。当然,正确的解决方案是正确配置 nginx。您可以尝试进行一些过滤(例如检测<?php,但这可能会导致误报,即合法图像被拒绝)。我可能会在文档中注明,在 nginx 上安装您的软件的人应该真正遵循服务器提供的说明并检查此问题,并且不会再担心它。请注意,可以创建包含 PHP 代码的完全有效的 PNG 文件,因此仅检查该文件是否为有效图像在这里没有帮助。

现在,针对客户端的攻击。您的服务器将(希望)以正确的 MIME 类型提供文件。这应该可以防止浏览器将其作为代码运行。不幸的是,某些浏览器(也称为“Internet Explorer”)是愚蠢的,并且无论如何都试图猜测文件类型。这不会直接损害您的服务器,但可能会导致使用这些浏览器的用户的用户帐户受到威胁。因此,您可能需要检查文件类型。如果可以的话,提供所有带有 nosniff 标头的文件(例如,通过设置相应的 htaccess 或在设置标头后通过 fpassthru 提供它们)。

通过加载和重新保存图像,您可以(或多或少)确保图像中的任何“讨厌”的东西都消失了。另一方面,如果有人在您的图片库中发现了可利用的错误,他们可以入侵您的服务器,因此并非没有风险。

【讨论】:

    【解决方案3】:

    $_POST'ed 数据(或任何数据,实际上)没有安全问题。它只是数据,您可以安全地将其保存在服务器中的文件中。

    当您以不安全且有时简单的方式处理该数据时,问题就来了等等等等等等。

    因此,如果您的问题是安全性,那么您就找错地方了。

    【讨论】:

    • 可能还会提到将文件保存在 webroot 之外。想象一下上传一个 php 文件,然后用浏览器访问它。
    • 我明白你的意思,我想这就是问题的真正意义所在,我不能真正将它存储在 root 之外,因为它是通过常规的 <img> 标签访问而不是被提供的通过脚本。
    【解决方案4】:
    function get_base64_file_ext($base64ImageString)
    {
        if(stristr($base64ImageString, 'image/png'))
            return 'png';
        if(stristr($base64ImageString, 'image/gif'))
            return 'gif';
        else
            return 'jpg';
    }
    function base64_to_file($base64ImageString)
    {
        $data = explode(',', $base64ImageString);
        return base64_decode($data[1]); 
    }
    function save_base64_to_file($path, $filename, $base64ImageString)
    {
        if(!stristr($base64ImageString, 'image/'))
            return 'No image found';
        $file_contents = base64_to_file($base64ImageString);
        //$file_contents = strip_tags($file_contents);
    
        $save_file = $path.$filename.'.'.get_base64_file_ext($base64ImageString);
        if(file_put_contents($save_file,$file_contents))
            return 'image saved successfully to '.$save_file;
        else
            return 'error while writing a file';
    }
    

    用法:

    echo save_base64_to_file('/home/username/public_html/images/', 'my_image_file', $base64ImageString);
    

    【讨论】:

      猜你喜欢
      • 2016-12-03
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      • 2013-06-04
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 2016-08-24
      相关资源
      最近更新 更多