Uploading of image

good day, please am trying to upload an image with this php codes but it not working as expected.here is the code
$passport_path=$mysqli->real_escape_string(‘images/’.$_FILES[‘passport’][‘name’]);

				//make sure file type is image 
			if(preg_match("!images!",$_FILES['passport']['type'])){
				//COPY image to images/ folder

					if(copy($_FILES['passport']['tmp_name'],$passport_path)){
						$_SESSION['name'] = $name;
						$_SESSION['passport'] = $passport;

What does it do that you do not want, or what does it not do that you do want? Wouldn’t you normally use move_uploaded_files() for this?

1 Like

here is the complete code but what am having instead of that image to upload is the sesssion message set for else statement. that only jpg,png or gif is allowed.thanks
$passport_path=$mysqli->real_escape_string(‘images/’.$_FILES[‘passport’][‘name’]);

				//make sure file type is image 
			if(preg_match("!images!",$_FILES['passport']['type'])){
				//COPY image to images/ folder

					if(copy($_FILES['passport']['tmp_name'],$passport_path)){
						$_SESSION['name'] = $name;
						$_SESSION['passport'] = $passport;

						$mysql = "INSERT INTO users (name , studentid , department ,role ,institute ,pwd , passport )" .
							"VALUES ('$name','$studentid','$department','$role','$institute','$pwd','$passport_path')";
							//if the query successive redirect to index.php
							if($mysqli->query($sql)=== true) {
								$_SESSION['message']="registration successive!";
									header("location: index.php");
								# code...
							}

							else{$_SESSION['message']="user cannot be added to the database";}
							
					}
					else{$_SESSION['message']="file upload failed";}

				
			}
			else{$_SESSION['message']="please only upload the type jpg, png,gif";}

	}

	else{$_SESSION['message']="two password do not match";}
}

I know very little about regular expressions, other than how difficult they can be, but this doesn’t look correct:

if(preg_match("!images!",$_FILES['passport']['type'])){

specifically, the !images! pattern. The fact that you’re getting your upload rejected because of an invalid type suggests that this is where the problem lies, presuming that you are trying to upload a valid type.

(ETR some irrelevant stuff)

please can you put me through a little bit

i do not know any mime-type that contains “images”, most of the ones i think you want start with “image/…”, so that’s what you have to look for with e.g. strpos().

When you check the mime type of the array type, you’re really checking the mime type of the file extension as it relates to it. You should be checking the mime type of the tmp file as it should hold the correct original mime type.

$_FILES[‘passport’][‘type’]

Is not safe, it can be forged. You should use FileInfo functions or class.

To check image type you can do it like this:

$tmp_file = $_FILES['passport']['tmp_name'];
$allowed_types = ['image/jpg', 'image/png', 'image/gif'];
$file_type = check_file($tmp_file);

if (in_array($file_type, $allowed_types)
{
    // allow user to upload file
} 
else
{
    echo 'Only JPG, PNG and GIF allowed!';
}

Function check_file:

function check_file($file)
{
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $type = finfo_file($finfo, $file);
    finfo_close($finfo);
    return $type;
}

I hode this helps.

Best regards!

function check_file($file)

Is not safe, it can be forged. Test the file extension, not contents. You don’t want to allow a php file disguised as an image.

That can be forged too (or at least mis-represented).

1 Like

That can be forged too

Well, your code should deny that forged image with .php as one of its extensions - exactly what I said.

Is it? You said Test the file extension.

What happens if you have a PHP script with a JPG extension?

1 Like

What happens if you have a PHP script with a JPG extension?

You tell us?

You don’t know then? I don’t which is why I asked the question.

2 Likes

I have tested my function from my previous post.

I saved php file as jpg
1:


2:

And then I tried to upload image and got an error (only png, jpg allowed).

Am I doing something wrong?

1 Like

Nope. You are doing it right. It would be pointless to upload an image that wouldn’t render. That means checking the file extension would be pointless if the image doesn’t render. Might as well just allow the user to upload a malicious PHP file with this kind of legacy logic. You can test this method on Facebook, the social media giant that has thought of every possible scenario and every possible way of doing things. See for yourself if they check mime type of the content or allowing a whitelist of file extensions. I can tell you that they check mime type contents because anyone who says “checking file extensions” is safe is pretty delusional.

2 Likes

Nothing special security wise. The same as if you take an .xls file for example.

However, I suppose I was too focused on security matters and didn’t consider simple usability. So, speaking of images you may want to test whether an uploaded file could be interpreted as a valid image. However, reading first few bytes from the file contents won’t guarantee you a valid image of course.

So, speaking of the usability, a bullet-proof solution would be attempt to create an image from the file uploaded. But that’s outside of this question’s scope, I believe.

Am I doing something wrong?

Yes, of course.
You should take a jpeg file and add PHP code somewhere inside. I thought we were talking of forging, aren’t we?

I just forged image and it’s normaly uploaded so the addition to file check is to recreate image (as you said) with GD library or any other library used for image processing.

Thanks!

1 Like

The term “file check” is too vague and could be interpreted in many ways, so it is not clear whether you finally understood that testing the file extension is most important. Thus, to be sure: it is.

Whereas “to recreate an image” could help you with usability (disallowing malformed images) but won’t help with security, so you couldn’t rely on it solely.

the simplest way to validate a filename, making sure it is harmless, would be something like this

$parts = pathinfo($_FILES['passport']['name']);
$ext = $parts['extension'];
if (!in_array(strtolower($ext), ['jpg','png','gif']))
{
    throw new \Exception("Invalid file type");
}
$name = str_replace(".","_",$parts['basename']).".".$ext;
1 Like