安全地将base64字符串保存到php中的文件中


Securely save a base64 string to a file in php

我将转换后的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. 是否将Base64字符串转换为图像文件
  2. 文件的PHP数据URI

写入文件后,将文件名馈送到imagecreatefrompng()或任何其他文件格式。如果它返回false,则它实际上不是图像。

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

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

从理论上讲,这种方式应该不可能破解你的服务器,因为你的服务器不应该在PNG文件中运行任何代码。不幸的是,这样做很容易误解nginx。正确的解决方案当然是正确配置nginx了。您可以尝试进行一些过滤(例如检测<?php,但这有误报的风险,即合法图像被拒绝)。我可能会在文档中注明,在nginx上安装软件的人应该真正按照服务器提供的说明进行操作,并检查是否存在此问题,而不必进一步担心。请注意,可以创建一个包含PHP代码的完全有效的PNG文件,因此简单地检查该文件是否为有效的图像在这里没有帮助。

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

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

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

当您以一种不安全且有时很简单的方式处理数据时,问题就来了,可能是使用eval()echo,它直接到web浏览器,而不需要转义或标记删除等。

所以,如果你的问题是安全,那你就找错地方了。

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);