Jump to content

Recommended Posts

I was hacked by a spammer and I found that they got in using a form that did not have any security. I did not restrict file extensions. I know, I probably deserve it. Anyway I have read a bit the past few days about security and Mag posted some links that I am using to help me with security.

First is to check the Referrer. I will have to get to that one. (But I will research for sure)

Second is Restricting file types. This is where I am starting. What I have done is started by only accepting 5 file extensions with this bit of code.

		//This should process uploaded files
	$accept_ext = array('doc', 'docx', 'wps', 'pub','pdf');
	$ext = pathinfo($_FILES['uploadedfile']['name'], PATHINFO_EXTENSION);
	if(!inarray($ext, $accept_ext){
		//Explain security risk a little more so a non techi will understand
		//Maybe create a link with form data will still be in form
		//Will need to research this possibly using $_GET. Instead of echoing Sorry
		//maybe use header function to a page that will process variables in a new form.
		//Then Giving a warning about "Wrong File Extension."
		echo "Sorry Wrong File Extension. Try Again.
		<input type=button value=\"Back\" onClick=\"history.go(-1)\">";
	}
	else
	{
	$target = "/home/crowleys/public_html/admin/uploads/"$date."-".$event_link.".".$ext
    @copy($_FILES[file][tmp_name],$target);
  	}

My first question is, "Is file extension the same as file type"?

If not what should I start doing first with my form. The form is a bit long and I was going to rewrite bit by bit.

Can anyone give me a starting?

Thanks for any assistance.

It is a matter of policy in the microsoft world to associate a type of file with a particular extension, and to a lesser extent, this policy is also used on unix like systems.

 

But the one thing in your favour, is the fact that the webserver will only attempt to execute files with particular extensions, such as .php, so these are the main ones to ensure cannot be uploaded.

 

There is no guarantee that a file with an extension .jpg will, in fact be a jpeg image, but you can further check the mime type which for jpeg should be 'image/jpeg'.

 

So your code would need to look something like this

 

 $allowed_image_types = array('jpg'=>'image/jpeg','jpeg'=>'image/jpeg','jpe'=>'image/jpeg','gif'=>'image/gif','png'=>'image/png');
                $extension = strtolower(substr(strrchr($_FILES['image']['name'], '.'), 1));
                if(in_array($extension, array_keys($allowed_image_types)))
                {
                        switch($extension)
                        {
                                case 'jpeg':
                                case 'jpg':
                                case 'jpe':
                                        if(!imagecreatefromjpeg($_FILES['image']['tmp_name']))
                                                $error .= 'Invalid image.';
                                        break;
                                case 'gif':
                                        if(!imagecreatefromgif($_FILES['image']['tmp_name']))
                                                $error .= 'Invalid image.';
                                        break;
                                case 'png':
                                        if(!imagecreatefrompng($_FILES['image']['tmp_name']))
                                                $error .= 'Invalid image.';
                                        break;
                        }
                        if(empty($error))
                        {
                                if(file_exists($upload_path . $_FILES['image']['name']))
                                        $image = substr($_FILES['image']['name'], 0, -strlen($extension)) . uniqid('') . '.' . $extension;
                                else
                                        $image = $_FILES['image']['name'];
                                if(!move_uploaded_file($_FILES['image']['tmp_name'], $upload_path . $image))
                                        $error .= 'Failed to move image. Check permissions<br />';
                                else
                                        $extra = mysql_real_escape_string($image);
                                chmod($upload_path . $image,0644);
                        }
                }

I know this may be irrelevant as I am working on a test script that will tell me about file types using $_FILES[test_file][type] with a say word document or a pdf.

 

I did add to the bit above:

chmod($target, 0644);

 

I am really not dealing with images yet.

Yes, you can easily add pdf which has mime type application/pdf to the list

 

the chmod call simply sets the permissions on the file.

 

644 means owner has read/write, group has read only, and rest of world has read only.

 

644 translates to rw_r__r__

 

 

OK so if:

$acceptable_ext = array('pdf' => 'application/pdf',  'doc' => 'application/doc',  'docx' => application/docx'); 
$ext = pathinfo($_FILES['uploadedfile']['name'], PATHINFO_EXTENSION);
if(in_array($ext, array_keys($acceptable_ext))){
//process form 
}

Or would it be:

$acceptable_ext = array('pdf' => 'application/pdf',  'doc' => 'application/doc',  'docx' => application/docx'); 
$type = $_FILES['uploadedfile']['type'];
if(in_array($type, array_keys($acceptable_ext))){
//process form
}

Been testing and I wanted to know which is more reliable. Checking for just extension or type?

This is what I have so far:

if(isset($_FILES['test_file']['tmp_name'])){
	$acceptable_ext = array('pdf' => 'application/pdf',  'doc' => 'application/msword',  'docx' => 'application/msword',
													'pub' => 'application/vnd.mspublisher', 'pub' => 'application/x-mspublisher');
//$ext = pathinfo($_FILES['test_file']['name'], PATHINFO_EXTENSION);
$type = $_FILES['test_file']['type'];
if(in_array($type, array_values($acceptable_ext))){
//process form

  echo "Upload: " . $_FILES["test_file"]["name"] . "<br />";
  echo "Type: " . $_FILES["test_file"]["type"] . "<br />";
  echo "Size: " . ($_FILES["test_file"]["size"] / 1024) . " Kb<br />";
  echo "Stored in: " . $_FILES["test_file"]["tmp_name"];
}
else
{
	echo "Wrong Extension";
}
}

or

if(isset($_FILES['test_file']['tmp_name'])){
	$acceptable_ext = array('pdf' => 'application/pdf',  'doc' => 'application/msword',  'docx' => 'application/msword',
													'pub' => 'application/vnd.mspublisher', 'pub' => 'application/x-mspublisher');
$ext = pathinfo($_FILES['test_file']['name'], PATHINFO_EXTENSION);
//$type = $_FILES['test_file']['type'];
if(in_array($ext, array_values($acceptable_ext))){
//process form

  echo "Upload: " . $_FILES["test_file"]["name"] . "<br />";
  echo "Type: " . $_FILES["test_file"]["type"] . "<br />";
  echo "Size: " . ($_FILES["test_file"]["size"] / 1024) . " Kb<br />";
  echo "Stored in: " . $_FILES["test_file"]["tmp_name"];
}
else
{
	echo "Wrong Extension";
}
}

Both ways work. Is one more reliable than the other?

OK I tried to combine and I am having trouble with the pub ext:

<?php
ini_set ("display_errors", "1");
error_reporting(E_ALL);
session_start();
if(isset($_POST['submit'])){
	$acceptable_ext = array('pdf' => 'application/pdf',  'doc' => 'application/msword',  'docx' => 'application/msword',
													'pub' => 'application/x-mspublisher', 'pub' => 'application/vnd.mspublisher');
	if(isset($_FILES['test_file']['tmp_name'])){
$type = $_FILES['test_file']['type'];
$ext = pathinfo($_FILES['test_file']['name'], PATHINFO_EXTENSION);

if(in_array($type, array_values($acceptable_ext))){
//process form
if(in_array($ext, array_keys($acceptable_ext))){
//process form

  echo "Upload: " . $_FILES["test_file"]["name"] . "<br />";
  echo "Type: " . $_FILES["test_file"]["type"] . "<br />";
  echo "Size: " . ($_FILES["test_file"]["size"] / 1024) . " Kb<br />";
  echo "Stored in: " . $_FILES["test_file"]["tmp_name"];
}
}
else
{
	echo "Wrong Extension";

}
}
}
else
{
?>
<html>
<form method="post" action="text_upload.php"
enctype="multipart/form-data">
	<input type="file" name="test_file">
	<input type="submit" name="submit" value="SUBMIT">
</form></html>
<?php
}
?>

This works for doc and pdf but not for pub, Why?

OK I have the form working now and reading through my notes I see where the article mentioned double-barreled extensions. As I am checking for extension and mime-type of file. The process renames the file. Should this take care of the double-barrel extension?

There is one gotcha to be aware of when uploading images, and that is ie using the unregistered mime type of image/pjpeg for jpeg images instead of image/jpeg. There are various ways of dealing with this, but I check the type and change image/pjpeg to image/jpeg before the other checks are done. This only happens when uploading with IE

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.