Jump to content


Photo

php file upload directory permissions


  • Please log in to reply
16 replies to this topic

#1 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 25 April 2006 - 07:10 PM

Hi,

We have PHP running as nobody on the server and have scripts that let users upload pictures to a directory. The directory is located inside the DOC ROOT, is owned by nobody and has permissions of 777 so the upload will work without complaining about permissions.

In the past (this has happened twice) we have lost all of the images in the directory, they seem to have "vanished". What I am wondering is, could someone have gotten in their and deleted them maliciously because of the permissions, or is there possibly a bug in the code somewhere?

Are there other ways to let php run as nobody and allow the folders to have other permissions?
Eric

#2 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 25 April 2006 - 07:23 PM

[!--quoteo(post=368587:date=Apr 25 2006, 07:18 PM:name=Brandi)--][div class=\'quotetop\']QUOTE(Brandi @ Apr 25 2006, 07:18 PM) View Post[/div][div class=\'quotemain\'][!--quotec--]
absolutly! with permissions 777 that means anyone can get in the folder. i've seen scripts on here that allow you to run a hosting site, maybe check that out?
[/quote]

How do they get in?

Eric

#3 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 26 April 2006 - 05:11 PM

[!--quoteo(post=368588:date=Apr 25 2006, 07:23 PM:name=embsupafly)--][div class=\'quotetop\']QUOTE(embsupafly @ Apr 25 2006, 07:23 PM) View Post[/div][div class=\'quotemain\'][!--quotec--]
How do they get in?
[/quote]
Anyone with a real answer?
Eric

#4 Yesideez

Yesideez
  • Members
  • PipPipPip
  • Advanced Member
  • 2,334 posts
  • LocationDevon, UK

Posted 26 April 2006 - 05:25 PM

[a href=\"http://webmasterworkshop.com/guides/chmod_guide.shtml\" target=\"_blank\"]http://webmasterworkshop.com/guides/chmod_guide.shtml[/a]

Hope this link explains it better than I can.
Not a pro just an enthusiast :)

if (empty($coffee)) {$coffee=new coffee();}

Please surround any code using the CODE tags - I rarely look at anything without them

#5 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 26 April 2006 - 05:36 PM

I know how chmod works, but I am asking about php upload directories as far as what permissions are best... Do you have to have 777 on the directory to allow php scripts running as nobody be able to upload an image/file? Are there more secure permissions that can be set that won't break the upload process?
Eric

#6 Yesideez

Yesideez
  • Members
  • PipPipPip
  • Advanced Member
  • 2,334 posts
  • LocationDevon, UK

Posted 26 April 2006 - 05:39 PM

I'm not too hot on these myself but I do know that you can have chmod permissions set on a folder or a file.

I suggest having the folder set to 755 at all times. When a user uploads set the folder to 777 and once uploaded, set the folder to 755 again and set the file to 755.

There might be an easier way of doing it but as I said, I'm not too hot on this myself and this is how I'd give it a go...
Not a pro just an enthusiast :)

if (empty($coffee)) {$coffee=new coffee();}

Please surround any code using the CODE tags - I rarely look at anything without them

#7 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 26 April 2006 - 05:44 PM

Chmod'ing the directory after the upload from 777 to 755 is a good idea, but it is not very feasable because the users don't have access to chmod the files and would have to call us all of the time to chmod them. Is there a way to do it with a script to where when they login, the directory gets chmod'd to 777 and when they logout, it gets chmod'd back to 755? I am sure there is a better way. Also if nobody owns the directory and it is 755, nobody will still have write permissions...isn't that a problem? Can't someone easily exploit nobody and get their permission levels?
Eric

#8 Yesideez

Yesideez
  • Members
  • PipPipPip
  • Advanced Member
  • 2,334 posts
  • LocationDevon, UK

Posted 26 April 2006 - 05:51 PM

Its about having a secure script - there is a function within PHP called chmod() to do it within a script - try that and let us know how you get on.
Not a pro just an enthusiast :)

if (empty($coffee)) {$coffee=new coffee();}

Please surround any code using the CODE tags - I rarely look at anything without them

#9 koencalliauw

koencalliauw
  • Members
  • PipPipPip
  • Advanced Member
  • 36 posts

Posted 26 April 2006 - 09:34 PM

the user 'nobody' by default has no shell permissions at all, as it has no login shell specified in /etc/passwd, check this out.
If you webserver is running with 'nobody' and all file stuff is done using your webserver (php), then you can rest assured that 755 or even 775 would be secure enough, that is ofcourse, relying on the fact that your script itsself is secure, which is the most common security breach.

#10 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 26 April 2006 - 09:52 PM

So ... since all of the files in the upload directory have disappeared twice, would it be because the directory was set to 777 or because there is a problem with the script?
Eric

#11 koencalliauw

koencalliauw
  • Members
  • PipPipPip
  • Advanced Member
  • 36 posts

Posted 26 April 2006 - 09:54 PM

[!--quoteo(post=369023:date=Apr 26 2006, 11:52 PM:name=embsupafly)--][div class=\'quotetop\']QUOTE(embsupafly @ Apr 26 2006, 11:52 PM) View Post[/div][div class=\'quotemain\'][!--quotec--]
So ... since all of the files in the upload directory have disappeared twice, would it be because the directory was set to 777 or because there is a problem with the script?
[/quote]
My guess would be the script.
Does your script have in-built functionality to move or delete files that exist?

#12 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 26 April 2006 - 10:08 PM

[!--quoteo(post=369025:date=Apr 26 2006, 09:54 PM:name=Koen Calliauw)--][div class=\'quotetop\']QUOTE(Koen Calliauw @ Apr 26 2006, 09:54 PM) View Post[/div][div class=\'quotemain\'][!--quotec--]
My guess would be the script.
Does your script have in-built functionality to move or delete files that exist?
[/quote]

Yes there are functions to delete the files....

What it is is a car for sale (database holds the data) and pictures stored in the filesystem.

The users can delete a car, which removes it from the database and also removes the directory.

Deleting cars works flawlessly, but I am wondering if there is a glitch if they do something wrong, like click the "submit" or "delete" button twice, or if there are two people logged in at the same time, both trying to delete the same car???

Eric

#13 koencalliauw

koencalliauw
  • Members
  • PipPipPip
  • Advanced Member
  • 36 posts

Posted 26 April 2006 - 10:10 PM

I think in your case it would be best if we could see the whole script, can you upload it somewhere?

#14 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 26 April 2006 - 10:18 PM

Here is the delete script: I think I already see some problems if the delete script is not called from an intended url:

<?
$db_name = "***";
$table_name = "cars";
$connection = @mysql_connect("localhost", "***", "***")
or die(mysql_error());
$db = @mysql_select_db($db_name, $connection) or die(mysql_error());
$sql = "SELECT * FROM $table_name WHERE vehicle_id = '$_POST[vehicle_id]'";

$result = @mysql_query($sql,$connection) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
$vehicle_id = $row['vehicle_id'];
$vehicle_make = $row['vehicle_make'];
$vehicle_model = $row['vehicle_model'];
$vehicle_style = $row['vehicle_style'];
$vehicle_description = $row['vehicle_description'];
$vehicle_price = $row['vehicle_price'];
$vehicle_image_a = $row['vehicle_image_a'];
$vehicle_image_b = $row['vehicle_image_b'];
$vehicle_image_c = $row['vehicle_image_c'];
$vehicle_image_d = $row['vehicle_image_d'];
$vehicle_image_e = $row['vehicle_image_e'];
$vehicle_image_f = $row['vehicle_image_f'];
$popup_vehicle_a = $row['popup_vehicle_a'];
$popup_vehicle_b = $row['popup_vehicle_b'];
$popup_vehicle_c = $row['popup_vehicle_c'];
$popup_vehicle_d = $row['popup_vehicle_d'];
$popup_vehicle_e = $row['popup_vehicle_e'];
$popup_vehicle_f = $row['popup_vehicle_f'];

$vehicle_year = $row['vehicle_year'];
}

$dbfield = $popup_vehicle_a;

//new stuff to delete directory of images

$the_url = $dbfield;
$pieces = explode("%20", $the_url);
$state = $pieces[0];
$piece = explode("/", $state);
$uniquedir = $piece[4];
$dirname = "/home/***/www/phpcars/$uniquedir";
$files = "/home/***/www/phpcars/$uniquedir/";

// define function that will recursively enter directory and remove files in order for rmdir() function to 
// work. rmdir() can not remove a directory unless it is empty, that is what this purge() function does
 function purge($dir)

  {

  $handle = opendir($dir);

  while (false !== ($file = readdir($handle)))

  {

  if ($file != "." && $file != "..")

  {

  if (is_dir($dir.$file))

  {

  purge ($dir.$file."/");

  rmdir($dir.$file);

  }

  else

  {

  unlink($dir.$file);

  }

  }

  }

  closedir($handle); 

  }
 // end of define purge()

//call purge() function and then rmdir()
purge($files);  
rmdir($dirname);

//remove database entry
$sql = "DELETE FROM $table_name WHERE vehicle_id = '$_POST[vehicle_id]'";
$result = @mysql_query($sql,$connection) or die(mysql_error());


?>

<html>
<head>
<title>Vehicle has Been Deleted</title>
</head>

<body>
<h2>Vehicle Deleted</h2>

<p> <? echo " The <strong><u><font color=\"blue\">$_POST[vehicle_year] $_POST[vehicle_make] $_POST[vehicle_model] $_POST[vehicle_style]</font></u></strong> being offered at $$_POST[vehicle_price]"; ?> has been deleted from the Database and Website.</p>
<p>The directory: <strong><font color="red">/home/***/www/phpcars/<? echo "$uniquedir" ?> </font></strong> and it's contents have been removed from the server.</p>
<table width="84%"  border="0" cellspacing="1" cellpadding="1">
  <tr>
    <th scope="col"><a href="pick_to_delete.php">Delete Another Vehicle</a> </th>
    <th scope="col"><a href="insert_form.php">Add A New Vehicle</a></th>
    <th scope="col"><a href="show_records.php">Show All Vehicles</a> </th>
    <th scope="col"><a href="index.php">Go back to Main Menu </a></th>
  </tr>
</table>
</body>
</html>

Eric

#15 koencalliauw

koencalliauw
  • Members
  • PipPipPip
  • Advanced Member
  • 36 posts

Posted 26 April 2006 - 10:45 PM

Exactly, I think that will be the problem, suppose googlebot hits your site, It'll not know what url to enter, just call the file without params, if that happens, no vars get set, so no $uniquedir gets set, ... boom.

Check the dirs you want to delete, check that they are at least 1 or 2 chars long (use strlen or something), check if the directory exists and make sure you put in an extra check that it does not delete some unintended dir for some weird reason.
Like this, this script was bound to have this kind of behaviour at some point.

Koen

#16 embsupafly

embsupafly
  • Members
  • PipPip
  • Member
  • 29 posts

Posted 26 April 2006 - 10:51 PM

[!--quoteo(post=369055:date=Apr 26 2006, 10:45 PM:name=Koen Calliauw)--][div class=\'quotetop\']QUOTE(Koen Calliauw @ Apr 26 2006, 10:45 PM) View Post[/div][div class=\'quotemain\'][!--quotec--]
Exactly, I think that will be the problem, suppose googlebot hits your site, It'll not know what url to enter, just call the file without params, if that happens, no vars get set, so no $uniquedir gets set, ... boom.

Check the dirs you want to delete, check that they are at least 1 or 2 chars long (use strlen or something), check if the directory exists and make sure you put in an extra check that it does not delete some unintended dir for some weird reason.
Like this, this script was bound to have this kind of behaviour at some point.

Koen
[/quote]

Well, the entire directory is password protected, so it must be done by someone logging in right?

Eric

#17 koencalliauw

koencalliauw
  • Members
  • PipPipPip
  • Advanced Member
  • 36 posts

Posted 27 April 2006 - 06:40 AM

the functions you execute are run in the shell by the user nobody, not through HTTP, which means your .htaccess files (password protection) are rendered useless for these kind of actions.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users