PHP from root user, mkdir permission denied - php

Today I have encountered a strange behaviour which I do not understand.
I am trying to create a directory on the local disk using a PHP 7.0 script using mkdir() function but it produces a "permission denied" error.
In my experience (although very little) this always meant that the user which is executing the PHP script is not authorized to write to the directory. This makes sense to me and is usually not a problem when developing web applications. The default PHP user when using Apache is www-data and I don't encounter problems with it.
In this case though I am using Zend Framework 2 and in particular I am using it's console routes so I am not going through Apache (correct me if I am wrong). I am calling my script as:
php index.php route name [--options]
with my user (which is not root but is a sudoer). The problems start if I output the result of PHP's get_current_user() function because I get 'root' instead of my expected user name. Not only this, but I get 'permission denied' when using mkdir() in the following directory:
drwxr-xr-x 2 www-data www-data 4096 Aug 19 21:21 logs
What I understand from this is that I probably am not the root user as PHP seems to suggest. If I then run the script with 'sudo' in front I am able to create the desired folders but the permissions do not match the ones I specify in my mkdir() function. If I write mkdir('path', 0777) I then get:
drwxr-xr-x 3 root root
This I do not understand. So, if someone could help me figure out what I am doing wrong I would be very thankful. Keep in mind that the fact that I am going through Zend Framework 2 might influence this behaviour (although I am not keen on thinking so).
Thank you in advance for your time.
Edit.
I just realized I didn't tell you what my final goal is so I will now put things in context, sorry.
What I am trying to do is to use this script (run either from root or from my user, preferably from my user) to create these folders inside
/var/www
and to then be able to read and write files (and possibly other folders) to those directories whith the standard PHP user which in my case is www-data

your php runned as apache extension, and using apache permissions.
If you need to create folder as root, you can create cron script for it, which will monitor change in some file, and create directory as root.
Another way to do it, using suid extension, but it a bit complicated.

Related

XAMPP SQLite DB using PHP, Can't get to insert [duplicate]

I have a SQLite database that I am using for a website. The problem is that when I try to INSERT INTO it, I get a PDOException
SQLSTATE[HY000]: General error: 8 attempt to write a readonly database
I SSH'd into the server and checked permissions, and the database has the permissions
-rw-rw-r--
I'm not that familiar with *nix permissions, but I'm pretty sure this means
Not a directory
Owner has read/write permissions (that's me, according to ls -l)
Group has read/write permissions
Everyone else only has read permissions
I also looked everywhere I knew to using the sqlite3 program, and found nothing relevant.
Because I didn't know with what permissions PDO is trying to open the database, I did
chmod o+w supplies.db
Now, I get another PDOException:
SQLSTATE[HY000]: General error: 14 unable to open database file
But it ONLY occurs when I try to execute an INSERT query after the database is open.
Any ideas on what is going on?
The problem, as it turns out, is that the PDO SQLite driver requires that if you are going to do a write operation (INSERT,UPDATE,DELETE,DROP, etc), then the folder the database resides in must have write permissions, as well as the actual database file.
I found this information in a comment at the very bottom of the PDO SQLite driver manual page.
This can happen when the owner of the SQLite file itself is not the same as the user running the script. Similar errors can occur if the entire directory path (meaning each directory along the way) can't be written to.
Who owns the SQLite file? You?
Who is the script running as? Apache or Nobody?
For me the issue was SELinux enforcement rather than permissions. The "read only database" error went away once I disabled enforcement, following the suggestion made by Steve V. in a comment on the accepted answer.
echo 0 >/selinux/enforce
Upon running this command, everything worked as intended (CentOS 6.3).
The specific issue I had encountered was during setup of Graphite. I had triple-checked that the apache user owned and could write to both my graphite.db and its parent directory. But until I "fixed" SELinux, all I got was a stack trace to the effect of: DatabaseError: attempt to write a readonly database
This can be caused by SELinux. If you don't want to disable SELinux completely, you need to set the db directory fcontext to httpd_sys_rw_content_t.
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/railsapp/db(/.*)?"
restorecon -v /var/www/railsapp/db
I got this error when I tried to write to a database on an Android system.
Apparently sqlite3 not only needs write permissions to the database file and the containing directory (as #austin-hyde already said in his answer) but also the environment variable TMPDIR has to point to a (possibly writable) directory.
On my Android system I set it to TMPDIR="/data/local/tmp" and now my script runs as expected :)
Edit:
If you can't set environment variables you can use one of the other methods listed here: https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations
like PRAGMA temp_store_directory = 'directory-name';
In summary, I've fixed the problem by putting the database file (* .db) in a subfolder.
The subfolder and the database file within it must be a member of the
www-data group.
In the www-data group, you must have the right to write to the
subfolder and the database file.
####### Additional Notes For Similar Problem #####
I gave write permissions to my sqlite database file to other users and groups but it still didn't work.
File is in my web root directory for my .NET Core WebApi.
It looked like this:
-rw-rw-rw- 1 root root 24576 Jan 28 16:03 librestore.db
Even if I ran the service as root, I kept getting the error :
Error: SQLite Error 8: 'attempt to write a readonly database'.
I also did a chown to www-data on the librestore.db and I still received the same error.
Finally I moved up above my webroot directory and gave others write access to that directory (LibreStore - the root of my WebApi) also and then it worked.
I'm not sure why I had to give the directory write access if the specific file already had write access, but this is the only thing that worked.
But once I made that change www-data user could access the .db file and inserts succeeded.
I got the same error from IIS under windows 7. To fix this error i had to add full control permissions to IUSR account for sqlite database file. You don't need to change permissions if you use sqlite under webmatrix instead of IIS.
I used:
echo exec('whoami');
to find out who is running the script (say username), and then gave the user permissions to the entire application directory, like:
sudo chown -R :username /var/www/html/myapp
(For followers looking for an answer to a similar question)
I'm building a C# .Net Core 6.0 WPF app. I put the Sqlite.db3 on the c:\ drive for convenience while developing. To write to the database I must open Visual Studio 2019 as Administrator.
#Charles in a comment pointed out the solution to this (or at least, a botch solution). This is merely me spelling it out more clearly. Put file_put_contents('./nameofyourdb.sqlite', null); (or .db, whichever you fancy) in a .php file in the root directory of your app (or wherever you want the db to be created), then load that page which renders the php code. Now you have an sqlite db created by whichever user runs your php code, meaning your php code can write to it. Just don't forget to use sudo when interacting with this db in the console.
A good clean solution to this is to allow the file of your main user account to be written to by (in my case) the http user but this worked for me and its simple.
None of these solutions worked for me and I suppose I had a very rare case that can still happen. Had a power shortage so even with 777 permissions on folder and db file, without SELinux, I would get this error.
Turns out there was a jellyfin.pid file (not sure if it's named after the service or user as they have the same name) locking it after the power shortage. Deleted it, restarted the service and everything worked.
I got this in my browser when I changed from using http://localhost to http://145.900.50.20 (where 145.900.50.20 is my local IP address) and then changed back to localhost -- it was necessary to stay with the IP address once I had changed to that once

Folder permissions when telling PHP to save a file to that folder?

I'm trying to use this Dagon Design PHP form to help a local non-profit publication enable their readers to submit photos. I've got the "mailer" part working -- the notifications work fine -- but the "saving a file to a folder" part isn't functioning.
On the form page, the author says "the directory must have write permissions," but I'm not sure "who" is writing to that folder -- is this PHP script considered "Owner" when it saves something on my site? Or do I need to allow save permissions for Owner, Group and Others?
I'm not sure why the script isn't saving the photos, but this seems like a good place to start. I've tried looking around on Stack for answers, but most questions seem to have to do with folder creation/permissions.
The page I'm clumsily trying to build is here, if that helps.
As Jon has said already, you don't want to allow write access to everyone.
It's also possible (depending on the hosting) that something like suEXEC is being employed - which will cause your PHP script to run as a user other than the webserver's (as reported by Dunhamzzz).
Probably your best approach, in my opinion, is a script calling whoami:
passthru('whoami');
Or alternatively you could try:
var_dump(posix_getpwuid(posix_geteuid()));
Bear in mind, this does give system information away to the world - so delete the script once you've used it!
Then, as you've correctly asserted in your question, it'll likely be the file permissions.
If you do have CLI access, you can update the permissions safely as so (first command gets the group)
id -n -g <username>
chmod 770 <directory>
chown <username>:<group> <directory>
(You may have to pre-pend "sudo" to the "chown" command above, or find other means to run it as "root"..., reply back if you get stuck.)
If you've not got access to run command-line, you'll presumably be doing this via a (S)FTP client or the alike. I'm afraid the options get a little to broad at that point, you'll have to figure it out (or reply back with the client you're using!)
As always, YMMV.
Finally, bear in mind if this is your own code, people will at some point try uploading PHP scripts (or worse). If that directory is accessible via a public URL ... you're opening the hugest of security holes! (.htaccess, or non-document root locations are your friend.)
If you are not sure how is your server configured (and this would influence who's the final file owner) then add write permission to anyone (chmod a+w folder), upload one file and ls -l to see the owner. Then you can adjust permissions to allow write access to certain users only
The PHP script that saves the files is running with the privileges of some user account on the server; the specific account depends on your OS and the web server configuration. On Linux and when PHP is running as an Apache module this user is the same user that Apache runs as.
Solving your problem reduces to determining which user account we are talking about and then ensuring that this user has permission to write to the save directory (either as owner or as a member of the group; giving write access to everyone is not the best idea).
You'll need to set the permissions of the directory to that of the webserver (probably Apache, nginx or similiar), as that's what is executing the PHP.
You can quickly find out the apache user with ps aux | grep apache, then you want to set the permssions of the upload directory to that user, something like this:
chown -R www-data:www-data images/uploads

Am I wrong to make directory executable?

I am writing a file upload using Zend_Form_Element_File(). I created a directory called users in the public directory. When I load the file, I got an error saying page is not found. I check the directory and saw that the permission is drwxr-xr-x. So I change the permission to drwxrw-rw- and load the page again. The page loads properly. But when I upload a file, it produces an error again. So I finally change the permission to drwxrwxrwx and everything runs properly.
My question is that am I doing the usual way that others are doing? I found it strange to make a directory executable.
Can someone explain whether I'm doing it correct? I am just learning Zend framework.
Directories must be executable if a program should be able to "enter" it. Entering a directory basically means accessing any file/directory below that directory.
Having "read" access to a folder allows you to list its contents - what "write" access does is pretty obvious.
However, for security reasons you should check if drwxrwx--- (770) is not sufficient; often your user and the webserver share a common group. If that's the case, there's no need to give any access to "world".
It would be even better to run your scripts as the same user as you - by using fastcgi that wouldn't be too hard, but if you are on shared hosting you usually do not have the necessary access to do this.
Typically when you set permissions on the directory it is so they cascade down to the files within via extended ACLS in the majority of cases. The issue that I see immediately is that you have granted world access which is a bad idea. The only user that needs permissions to the directory (700 at max) is going to be your web server. So I would revert security to be 700 asap.

Files written though PHP/Apache don't honor directory setgid bit

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.

Why are my file permissions on Apache being reset?

We recently switched from using PCs at work to Macs, so I'm new to the *nix way of doing things. I have the default Apache running that shipped with 10.5, but I've noticed that when I drag files from a Windows server to my machine, the permissions are changed. Specifically, I'm writing data to an XML file, and occasionally after swapping some files back and forth, it stops working.
Can someone help me understand why this is happening and how I can either force Windows to respect the original file permissions (they were set on my machine when I created the file) or apply a less secure set of default permissions when the files are moved from Windows to Mac?
A couple facts to be aware of:
I'm using the Cornerstone Subversion client.
I can use Terminal if you spell it out for me.
Ultimately I'm uploading these files via Transmit to a Linux server in another location.
I'm already familiar with using Get Info to change the file permissions, but maybe I'm doing something wrong.
I'm logged in as root. (I know, bad bad bad.)
I should also mention I know this is a simple question that should have a simple answer, but I've googled up and down without finding it. I need your help.
Thanks.
It would be incredibly helpful if you could drop to the Terminal, use cd to navigate to the folder with the files that don't work because of permissions and then type: ls -l (those are both lowercase Ls back there).
If you start from your home folder, it'll look something like this:
macbookpro:~ artlogic$ cd Sites
macbookpro:Sites artlogic$ ls -l
total 8
drwxr-xr-x 6 artlogic staff 204 Mar 11 2008 images
-rw-r--r-- 1 artlogic staff 2628 Mar 11 2008 index.html
macbookpro:Sites artlogic$
Please paste the output into this thread. Knowing what Apache is changing the permissions to would help.
On a side note, Apache generally runs under a different user and permission level than the logged in user and so if it's somehow creating or overwriting files it may be changing the permissions that way.

Categories