how safe the following code is, in case everybody could make use of it:
$file = $_FILES["file"]['tmp_name'];
$contents = file_get_contents($file);
$base64 = base64_encode($contents);
<img src="data:image/png;base64,'.$base64.'">
in case this is not safe agains hackers, etc. how should i secure it?
Char set of a base64 encoded string is ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/ and an = sign as a last byte filter.
So no matter what the file contents is, you are putting its base64 encoded value and even without escaping, browser will show the given string in the img tag.
You will however need to make sure that the string actually encodes to an image.
And by the way, you are wasting a lot of your server memory for this task by assigning a new variable in every step.
Related
I have a base64 encoded string which my frontend team has provided me with.The string is a video which was encoded using base64. I want to convert that back into a video file using Php.
I am currently just using the following to decode the string but I don't know how to proceed further.
$decoded = base64_decode ($encoded_string);
There seems to be a way to convert images from string using imagecreatefromstring() function, but I could not find a way to convert it into a video.
Thank you
you should know the video file type. you can decode to original format
$fp=file_put_contents('sample.mp4',base64_decode($encoded_string,true));
Video streams tend to be very large so is isn't a good idea to convert them to plain text in the first place. We'd also need to know the exact mechanism (protocol, format...) used to deliver the base64 string. In any case, once there you can do something like this (error checking omitted for brevity):
$chunk_size = 8192; // Bytes (must be multiple of 4)
$input = fopen('php://input', 'rb');
$output = fopen('/tmp/foo.avi', 'wb');
while ($chunk = fread($input, $chunk_size)) {
fwrite($output, base64_decode($chunk));
}
fclose($output);
fclose($input);
Smaller chunks reduce RAM usage and larger chunks improve I/O performance. You'll need to find a balance that works best for you.
When I take content of a picture I try to dump it like that:
$filename = '(900).jpg';
$im = file_get_contents($filename);
var_dump(serialize($im));
When the picture is under 1mb everything works, but if it is more than 1mb browser crash can you tell me why is that a browser issue or some limitation of file_get_contents() function?
The only limitation of file_get_contents might be the memory which is allowed for PHP to use. And the default is about 128 MB.
It is a browser "issue" if you want to call it that. Outputting so much debug information to the browser is not a good idea as you can see. Additionally there is no benefit in viewing a binary file as text.
If you want to find out if the variable is set, you can use functions to check the size of the (binary) string e.g. mb_strlen().
A better way would be this
$filename = '(900).jpg';
$im = file_get_contents($filename);
// check if the file could be loaded
if ($im !== false) {
// start your processing
}
But this does not check what kind of file you have loaded into the string. If you must store the file into the database - which is considered very evil - you can either store the binary string into a BLOB type row or encode the binary string with base64_encode() and store it into a text type. Both of this solutions are also not recommended!
If you need to store image information into the database, you should think about using references to the files - e.g. the file path. Your primary objective is to secure that the database information and the filesystem information is always synchronized.
I'm trying to send an image (any size) over to an API I'm creating, using base64 encoding. The encoded string hits my API as a parameter in the URL. The API built with PHP.
Once the request hits my API, I want to store the image onto my server, and save the file name in the database. This is working, however I'm getting some odd outputs with the actual image.
For reference, I also followed http://blog.justin.kelly.org.au/simple-base64-encodedecode-url-safe-functions/ but have the same results.
The image I am trying to store on my server:
$encode = base64_encode(file_get_contents($image));
echo $encode;
For testing, the ouput of this is the string I'm using to pass to my API.
In the API:
$image = base64_decode($_POST['image']));
$image_name = md5($image) . ".jpg";
file_put_contents(/public/image/ . $image_name, $image);
This works, my image is put onto the server in the correct directory with a random name which is saved to the database.
However, when navigating to the image directly, the image is warped:
If you have a sharp eye, the top part of the image is actually correct before it starts to fail, which makes me start to think whether the string is not getting encoded correctly to be sent as a parameter?
Any clues would be lovely, cheers.
EDIT: Changed it to POST, removed urlencode/decode & removed strtr.
Thanks to the comments:
base64_encode(file_get_contents($image_path));
No urlencode or strtr needed. Use POST request, and alter the post_max_size on the web server to allow for bigger images to be passed through.
$image = base64_decode($this->getParameters('avatar'));
$image_name = md5($image) . ".jpg";
Maybe I'm looking at it wrong, but first you encode it base64 -> urlencode and then you decode it base64 -> urldecode again, shouldn't the latter be in reverse order?
I have a built a script around class.upload from http://www.verot.net/php_class_upload.htm
Basically what it is that all my images are stored on the server in a directory called /images/
The script I built basically takes some parameters from my website such as /xyzDir/tomnjerry.jpg?w=100&h=100&fill=1&color=fff
Then I have mod_rewrite which reads the file from /xyzDir/ into a php script which then translates the width and height and returns the image.
Lately I have noticed some idiots from Turkey trying to input weird characters into the parameters w= and h=
On my script I do check to make sure only integer is allowed in width and heigh and fill can be either 1 or 2 and color can only be certain values which i check via array.
I just want to see if there is anything else I should be doing in order to avoid getting hacked.
Thanks
Always remember, Filter In, Escape Out for all user supplied (or untrusted) input.
When reading user supplied data, filter it to known values. DO NOT BLACKLIST! Always always always always whitelist what you are expecting to get. If you're expecting a hex number, validate it with a regex like: ^[a-f0-9]+$. Figure out what you expect, and filter towards that. Do none of your filenames have anything but alpha, numeric and .? Then filter to ^[a-z0-9.]+$. But don't start thinking blacklisting against things. It won't work.
When using user-data, escape it properly for the use at hand. If it's going in a database, either bind it as a parameterized query, or escape it with the database's escape function. If you're calling a shell command, escape it with escapeshellarg(). If you're using it in a regex pattern, escape it with preg_quote(). There are more than that, but you get the idea.
When outputting user data, escape it properly for the format you're outputting it as. If you're outputting it to HTML or XML, use htmlspecialchars(). If you're outputting to raw headers for some reason, escape any linebreaks (str_replace(array("\r", "\n"), array('\r', '\n'), $string)). Etc, etc, etc.
But always filter using a white-list, and always escape using the correct method for the context. Otherwise there's a significant chance you'll miss something...
create a validation class to validate your post params like so.
class MyValidation
{
public function is_interger($val)
{
return is_int($val);
}
public function within_range($val,$min,$max)
{
if($this->is_interger($val))
{
return ($val < $max && $val > $min);
}
return false;
}
public function is_hex($val)
{
return preg_match("/^([a-f0-9]{3}){1,2}$/",$val);
}
}
And use to validate your values.
Example:
$Validator = new MyValidation();
if($Validator->is_hex($_POST['color']))
{
//Sweet.
}
Make sure the image name does not contain string like "../". Depending on your script, that could be a way to step out images directory and make the script deliver other files.
You should use intval() for ensuring that the width and height are integers
$width = intval($_GET['w']);
$height = intval($_GET['h']);
You can do
$fill = $fill == 1 ? 1 : 2;
Which is a ternary operator, so if it's anything apart from 1 it's going to be set to 2.
As for validation of hex, the rules of hex dictate that it must be in range of 0-9/A-F.
$color = preg_replace('/[^0-9a-f]/i', "", $_GET['color']);
Hope that helps.
(It should be noted that my suggested code will perform the manipulation required to make it suitable for your page, rather than confirming that is is valid before hand)
No one's mentioned the filter extension here which provides great filtering natively implemented in the PHP engine. IMHO this is a great extension and should always be used before rolling your own filtering code. For example, checking for an integer is as simple as:
<?php
if (filter_var($value, FILTER_VALIDATE_INT)) {
//Valid Integer.
}
?>
Validating a hex number can be done with:
<?php
if (filter_var($value, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX)) {
//Valid Hex number
}
?>
Then I have mod_rewrite which reads the file from /xyzDir/ into a php script which then translates the width and height and returns the image.
If you include the file, image or other type, it will execute any PHP code buried within it. So if you didn't shake off any possible code appended to a user uploaded image by reformatting it through imagemagick or gd into a completely new file, that is one way your server can be compromised.
So for example if you serve the user uploaded image like this...
<?php
header('Content-type: image/jpeg');
header('Content-Disposition: attachment; filename="tomnjerry.jpg"');
include('xyzDir/tomnjerry.jpg');
?>
...and if the user opened the jpg in a raw text editor and appended <?php phpinfo(); ?> to the very end before uploading it to your server, then they can browse to and download it and extract all phpinfo details of your PHP installation from it.
But since you mentioned resizing the image first, you're probably not even serving the image this way. So you should be safe from this attack.
How can i restore or access MySQL blob field so I can preview it as HTML using PHP codes? Is there an available function in PHP so I can store as jpeg those blob field.
Storing is easy. Assuming you have a mysql table with BLOB field for pictures....
Once the image is uploaded you get the contents of the file into memory and then insert into the blob field.
<?php
$file = '/tmp/MyImg.jpg';
// you migh want to escape it just in case
$data = file_get_contents($file);
// Insert into database
$sql = "INSERT INTO my_picture_table (`picture_blob_field`) VALUES ('$data');"
?>
Retrieving is fairly simple as well. It is simpler to make a separate file to load images from blob.
<?php
// file = getPicture.php
$id = (int) $_GET['id'];
$sql = "SELECT `picture_blob_field` FROM `my_picture_table` WHERE `id` = $id"
// query the db
// store data into var $picData
// Set the content type and print the data.
header("Content-type: img/jpeg");
echo $picData;
?>
This is all you have to do... Now in HTML page just create an
<img scr="getPicture.php?id=PICTURE_ID alt="blah blah" />
Note that above example is for JPEG type, store the file type in the db and then use it to specify file type with header("Content-type: img/xxx")
Hope this solved your problem.
I found an example/tutorial on storing images in mysql. If above is not clear look through the code (its paginated, so look at the other pages)
The code presented above is vulnerable to SQL injection attacks and will in any case fail at the first byte of the JPEG that happens to match the ASCII code for a quote mark (which should happen quite quickly). I do see your comment that you "might" want to escape the data, but it should be emphasized that in a big binary file, there will almost certainly be a byte that matches the quote mark. It's not "just in case," it's practically every case.
Use mysql_real_escape_string() on the JPEG data and the id parameter (which comes from the user, who may be malicious). Better yet, use PDO and parameter substitution to avoid that mess.
Also, the content type must be image/jpeg, not img/jpeg.