Are there differences when I use that functions? Why should I use one instead of the other one...
copy() copies the file - you now have 2 files, and for large files, this can take very long
rename() changes the file's name, which can mean moving it between directories.
move_uploaded_file() is basically the same as rename(), but it will only work on files that have been uploaded via PHP's upload mechanism. This is a security feature that prevents users from tricking your script into showing them security-relevant data.
In the future, I suggest looking up such information in the PHP Manual yourself.
I found this in the manual of move_uploaded_file():
Florian S. in H. an der E. [.de] at 17-Aug-2008 09:02
move_uploaded_file (on my setup) always makes files 0600 (rw- --- ---) and owned by the user running the webserver (owner AND group).
Even though the directory has a sticky bit set to the group permissions!
I couldn't find any settings to change this via php.ini or even using umask().
I want my regular user on the server to be able to tar cjf the directory .. which would fail on files totally owned by the webserver-process-user;
the copy(from, to) function obeys the sticky-bit though!
so it seems like copy and rename do a slightly different work.
Related
I have setup a demo "admin" website with all file permissions set to 555 for directories and 444 for files so that any "save" functionality is disabled. So far so good.
However, I noticed that the PHP touch() function is unaffected by file permissions? I am successfully running PHP touch() on directories that have no-WRITE permissions (555). Seems a bit odd. Is this intended behavior (PHP 7.2)?
I am trying to prevent touch() from being able to execute (via file permissions), but can't currently see how this is possible.
Thanks.
From the utimes(3) documentation:
The effective user ID of the process shall match the owner of the file, or has write access to the file or appropriate privileges to use this call in this manner.
So the owner can update the timestamps even without write access. You need to change the ownership of the files so they're not the same as the user running the PHP script.
If this is a problem, maybe you should use some other method to keep track of changes that the file modification times.
I am creating a website creation service where users can upload files in an FTP browser interface. I also want them to be able to create real directories, but I was worried that if they uploaded scripts, that hey could reek havoc on the server.
I am using PHP, and the mkdir() function. Would it be a good idea to use mode 0664 when making directories, to prevent:
Malicious files from being executed.
Prevent just anyone from writing or executing those files.
Is this a good idea?
No, it does not make sense to use 0664 on directories.
You very likely need the X flag on them because you want to be able to get a directory listing. "Executing" a directory has nothing in common with executing a program. Disabling the X-flag on a directory will not affect execution of programs stored inside.
You have identify yourself which account is actually involved with file access. This account might be the owner of some files, and the owner of the directories of these files. Anything PHP does will be done as this user. So it does not matter if you restrict access to the file for the group or the world (aka 0700). On the other hand, your FTP access might not be the same user, but only sharing a group. In this case it is an annoying idea to restrict this group to not having access to the files, because you cannot read, write or delete them.
If you allow users to use an upload facility to your server, and you cannot guarantee that these files will never be executed, you probably shouldn't offer this service. Using access flags will not improve the situation, because PHP does not need the X flag, it only needs the file to be readable. So if the FTP site should be of any use, being able to read the files is a must, otherwise why uploading them?
Note that the usual FTP upload/download service separates uploads from downloads. An upload is a one-way operation that places the file on the server but without being accessible. An administrator has to check the upload and move it into the download area where it is read-only. Nobody can trigger the execution of any file because the server will ignore any executable flags and simply send the bytes of such a file back.
You cannot even open files in a directory without an executable permission. But you can access files in a directory without a read permission. A read permission is needed to list directory contents.
0644 directories are inaccessible except by root.
Examples
Inaccessible:
dir/ = drw-rw-r-- (0644) -- effectively the same as d--------- (0000)
So file_get_contents ('dir/file.txt') will always fail.
Accessible, but no listing possible:
dir/ = d-wx-wx--x (0331)
So file_get_contents ('dir/file.txt') will work if dir/file.txt exists. But opendir ('dir') will not.
Fully accessible:
dir/ = drwxrwxr-x (0775)
file_get_contents ('dir/file.txt') will work if dir/file.txt exists. And opendir ('dir') will return the contents of the directory.
Scratching my head on this one, seems so basic.
I've got a PHP based content management system for our website written by a contractor. One feature is the ability to upload images to be displayed in various places on the website (like a product gallery). All such uploaded images are stored in a particular directory called "attachments".
drwxrwsr-x 4 www ftpusers 4096 Oct 10 14:47 attachments
As you can see I've got the setgid bit set on that dir so that any files written will have the group that users (like FTP user) who need access to those files will able to modify/overwrite them. I've set the umask for Apache so that it will write files as group writable.
When I try this with ANY user in the system by creating a new file in that directory, it correctly inherits the group of the parent. When a new file is created through PHP running in Apache, it always has the apache.apache ownership. Apache seems to be ignoring the setgid bit, which I didn't think it could do as this was done by the file system. Here is one file I uploaded:
-rw-rw-r-- 1 apache apache 30536 Oct 10 14:43 209
I can't test as the apache user directly as it doesn't have a login shell specified (for obvious security reasons).
I can get the same permissions capability by adding the ftpusers group to the apache group, but this doesn't seem wise from a security perspective.
I did find one thing that seemed like it might be related - php safe mode, which I've verified is off in /etc/php.ini, although I'm not positive I found the php.ini file that mod_php in apache is using. The php script is using move_uploaded_file(); as far as I can tell, nothing fancy with permissions is being done in the php code.
My best guess would be that this is an intentional limitations for security, but I can't find anything that seems to indicate that is the case.
Running CentOS 5.6 with Apache 2.2.17 and php 5.2.16.
Anyone have a clue?
When you upload a file it is created in the dir specified by the PHP's "upload_tmp_dir" setting. Then move_uploaded_file() moves it to your target dir. It maintains the permissions given to it upon creation and not those of the target directory you move the file to.
So you want the tmp dir to have the permissions you want, basically those you've given to your target dir. Then it will be created with the setgid having effect and the move will keep them.
IIRC "upload_tmp_dir" is not available in .htaccess so if you cannot change this setting or the permissions given to the dir then you will need to do it another way.
I can't use fopen because PHP is in safemode and admin wont change this. How can I write a static html file using php?
With difficulty, unfortuantely. If your sysadmin has not set up user permissions that allow you to do this, then there's no general workaround. Other answers (e.g. FTP-ing) may work in certain circumstances (again, if user permissions allow it).
The only foolproof solution is to talk to the sysadmin.
You can only open (and thus write) to files in directories, that are permitted by the safemode settings.
You can use FTP.
You can still do with safe mode enabled
Beware: Safe mode will not permit you
to create new files in directories
which have different owner than the
owner of the script. This typically
applies to /tmp, so contrary to Unix
intuition, you will not be able to
create new files there (even if the
/tmp rights are set correctly).
If you need to write into files in
/tmp (for example to put logfiles of
your PHP application there) create
them first on the command line by
doing a
touch /tmp/whatever.log
as the same user who owns the PHP
script. Then, provided the rest is
configured correctly, the PHP script
will be able to write into that file.
http://php.net/manual/en/features.safe-mode.php
I've got a "globabVars.php" doc in my own little framework that contains database connection vars etc... I'm thinking would be neat to store outside of the web facing directories to keep it a little more secure. But, then I was thinking, is it really THAT much more secure? I mean, if someone were able to look at my .php files as a whole (without the server processing them) they would be INSIDE my server looking at all my files anyway...
Thoughts?
Moving a config file outside of the web root can prevent this file from getting leaked if you accidentally mis-configure apache. For instance if you remove Apache's mod_php then all .php files will be treated as text files. I have seen config files moved outside of the web root on production systems for this reason, and it did stop the file from getting leaked! (An admin iced the config during an update, doah!). Although this doesn't happen very often.
If an attacker can control the path of one of these functions: file_get_contents(), fopen(), readfile() or fgets() then he can read any file on your system. You also have to worry about sql injection. For instance this query under MySQL can be used to read files: select load_file("/etc/passwd").
To mitigate this issue, remove FILE privileges from your MySQL user account that PHP uses. Also do a chmod 500 -R /path/to/web/root, The last 2 zeros keeps any other account from accessing the files. You should also follow it up with a chown www-data -R /path/to/web/root where www-data is the user account that php is executed as, you can figure this out by doing a <?php system('whoami');?>.
It means noone can access it via a URL by default.
You can hide with .htaccess if it is in your docroot, but storing it above the docroot is just that bit safer.
You can have it read via PHP if your application is prone to directory traversal attacks.
Yeah, you are right. There is a very small difference.