3

As part of a bigger project that I am working on, I need to write a PHP script to convert a Base64 string into an image. The way I would like to go about passing the Base64 string into the script via a GET query, so...

example.com/base64ToPng.php?base64=thisIsTheBase64ForTheImage

I would then like to convert the Base64 that is passed in to a PNG image and display it as if the PHP file itself were an image. While this is not an issue from a development standpoint, I am concerned about the safety of doing this. Would I put myself in any danger since the Base64 is going to be created by the user? (Or more accurately, the Base64 is going to be created by a program based on the image the user provided it.) I am particularly worried about the user crafting a malicious image that could execute arbitrary code, but I do not know if this is a valid concern given that the image is only going to be recreated by the PHP script but not stored on the server.

<?php       
    if(!isset($_GET['x'])) {
        die();
    }

    $image = base64_decode($_GET['x']);
    header ('Content-type: image/png');
    imagepng($image, NULL, 0);
?>
  • 1
    It all depends on the implementation. If you did something like <img src="data:image/png;base64, <?php echo base64decode($userinput) ?>" /> you're gonna have problems with escaping the decoded output. One could give you the base64 of ">/ <script> alert("xss");</script> and it would trigger an XSS. The implementation could also choose to do the PNG decoding by piping the user input into a root-shell with like exec("base64 -d $userinput > image.png"); read_echo_and_delete_file("image.png");, with an obvious code exec vuln. Further questions can't be answered without the implementation. – Maximilian Gerhardt Mar 17 '17 at 18:37
  • 1
    One could say that you should better check that the provided base64 string actually encodes a png image. But the moment you decode an attacker controlled bitstring and try to analyze it, even more bad things can happen (think: imagetragick which allows for arbitrary code execution with an attacker controlled image). If the checks are too rudimentary, e.g. only checking the first 4 magic bytes of the string to be \x89PNG, the filter could be bypassed easily with a fake header and then some other string. – Maximilian Gerhardt Mar 17 '17 at 18:39
  • @MaximilianGerhardt I have not written the implementation that I intend to use yet, but as soon as I do, I will post it here so that it can be looked out. – DavidB Mar 17 '17 at 19:08
  • @MaximilianGerhardt I have added the code. It is actually not working properly, but at least it should get the idea across of what I want to do. – DavidB Mar 17 '17 at 19:29
2

It isn't safe to use URLs longer than about 2000 characters. While the URL RFC doesn't specify any particular limit, most browsers limits the number of characters in a URL to less than 2000 characters.

Another problem is that using base64 is very space inefficient, as you'll be encoding three bytes with four bytes. This means that the maximum size of image you can practically attach reliably o most browsers is less than 1.5 KB.

You also have to consider that running this service will make your webserver log files fill up really quickly, as it'll be logging the entire URLs. It may be possible to truncate/hash the logged URL, but that'll make troubleshooting issues more difficult.

Appendix:

Unless you want to actually edit the image data, your implementation can just echo the image data, no need for imagepng():

<?php
if(!isset($_GET['x'])) {
    die();
}
$image = base64_decode($_GET['x']);
header ('Content-type: image/png');
echo $image;
?>
  • Okay, thanks for the information. Since I am intending for this to be used as part of a server, I was thinking about instead including an embedded web server in the program. It would make matters more complicated for the users, but I would rather make the program slightly more complicated than introduce a feature that is likely to fail given the right circumstances. That said, do I still need to worry about code execution vulnerabilities if I use the method you suggested here? – DavidB Mar 19 '17 at 16:59
  • @DavidB: my code above would not be vulnerable to server side code execution vulnerabilities. It could still be vulnerable to a client side code execution vulnerability. If you want to validate that the image must be some valid PNG to prevent client side vulnerability, you can call imagecreatefromstring() function on it, and then use imagepng() to output the image. However, this opens up the possibility of server side code execution vulnerability if your PHP version had vulnerabilities in its imagecreatefromstring(). – Lie Ryan Mar 20 '17 at 1:42
0

That said, do I still need to worry about code execution vulnerabilities if I use the method you suggested here?

No, you don't. base64_decode still returns a string, which cannot get executed at the point of decoding. This way, that you just echo the string, it will not execute any PHP.

On the client side: Injecting JavaScript could be triggered however, but as you set the image/png header, this is already prevented.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.