I am trying to set up PHP sessions for suPHP (see here). I need to have my php validation file owned by the user so that when suPHP kicks in, it will do so for the correct user. However, I also don't want the user to have access to that file, o.w. they can edit it to just return true rather then actually check the database.
My first attempt was something like this (where Apache runs as user www-data
)
/etc/validate
├── [drwx------ www-data ] user1
│ └── [-rwx------ user1 ] validate.php
/var/www/
└── [drwx------ user1 ] user1
└── [-rwx------ user1 ] index.html
Then have the web pages redirect to the validate page, which would validate, then return /var/www/user1/index.html
RewriteCond %{REQUEST_URI} !^/xyz
RewriteRule ^(.*) /etc/validate/user1/validate.php?uri=$1
However suPHP complains that I am accessing something outside of my docroot (/var/www/user1
). I don't want to set the docroot to /
and updating suphp.conf
file so that check_vhost_docroot=false
, doesn't fix (and I don't it is meant to fix this). Therefore, instead I just moved /etc/validate
into /var/www
like so (it's a little messy, I know)
/var/www/
└── [drwx------ user1 ] user1
├── [-rwx------ user1 ] index.html
└── [dr-x------ www-data ] validate
└── [-rwx------ user1 ] validate.php
So now the validate file is
- Within docroot
- Owned by user1
- Not editable by user1
But now if I try to load the page I get the following error
Directory /var/www/user1/validate is not owned by user1
At this point I am losing my patience, so I just stick another dummy folder in there so the file structure looks like so
/var/www/
└── [drwx------ user1 ] user1
├── [-rwx------ user1 ] index.html
└── [dr-x------ www-data ] validate
└── [drwx------ user1 ] dummy
└── [-rwx------ user1 ] validate.php
Now, when I try to load the page, Apache tells me "You don't have permission to access xyz on this server." where xyz
is whatever comes after my domain name. I don't know why Apache is telling me that because I am not trying to access the trailing values as a file/folder. I think, the redirect is failing and Apache just assumes it is the hard link that is failing.
Can anyone tell me what I am doing wrong or provide an alternative way to prevent users from being able to edit their files. It could not get into directory dummy
because its permissions were rwx------
and only user1
could cd
into it. When I changed the permissions from 0700
to 0755
, it went back to suPHP errors. So the question now becomes: how do I get suPHP to execute scripts when one of its upstage directories is owned by someone else?
EDIT: I realize now why Apache was complaining. It could not get into
I can't find any official link for this, but according to this site:
All Files & Directories MUST be owned by your username, and not "nobody" or some other name/number. If it is not owned by you, suPHP will refuse to run the script and produce an "Internal Server Error 500".
I can understand files, but I don't see the need for directories to belong to you. I have found one patch online (see here), however, I don't know if it works or not as I have not tested it yet.
EDIT: There is a way to allow users to access scripts outside of their docroot (via suPHP_GlobalDocRoot
). I can't get it to work for me, Apache claims it is a syntax error. In any case, even if it did work, It would still require at least execute access 0111
(and possibly also read 0555
) on all the directories all the way up to /
.
Therefore, I am pretty confident there is absolutely no solution to my problem. I am therefor accepting this as the answer. I will select another answer if someone manages to provide one.
I could be wrong, but if suPHP works the way I remember, then PHP is running under the user (in this case user1) not as Apache (www-data), in which case www-data)is the only one with read and write access to the validate file and user1 is not www-data.
The solution, I think, would be to grant read permission to all for validate and write permission only to www-data. So:
/var/www/
└── [drwx------ user1 ] user1
├── [-rwx------ user1 ] index.html
└── [dr-x---r-- www-data ] validate
└── [-rwx------ user1 ] validate.php
With the above, user1 can not edit their validate file, only read it.
You might also want to try:
/var/www/
└── [drwx------ user1 ] user1
├── [-rwx------ user1 ] index.html
└── [dr-x-----x www-data ] validate
└── [-rwx------ user1 ] validate.php
I always confused on how exactly "execute" works, but I believe the idea is that the file can be run (executed) by the user, but not read or written to. But this would require validate
to be executable, so if it's a script, that may not work. Someone else here might be able to confirm.
There are quite a few configuration options for suPHP, and without them I can't give an exact answer, so I'll assume that you are running a pretty std configuration, because if you don't have it set up pretty strictly then you introduce so many exploitable holes that there isn't much point in using it.
- PHP scripts must be owned by non-privileged UID
- The path backward to / must be own by the same UID or root.
- If the script or any parent directory cannot be writeable by other the user UID.
- The script is executed in the users UID.
This is part of the formal assurance model of suPHP and if you want to change it, then don't use suPHP.
The user can define his/her own path for loading PHP.ini. By default the user can specify a custom php.ini and IIRC you can't disable the suPHP_ConfigPath
option. After all at the end of the day, you are running php-cgi in the users UID. So this mean that even if you establish an auto_prepend_file
(which could be owned by root and not writeable by the UID) then the knowledgeable user could still bypass this.
My simple Q is why are you using PHP, or at least the suPHP established PHP handler to do what you are trying to achieve here? Keep PHP for the user and user privileged functions. Use a CGI script or even a RewriteMap and a prg: option for these "systemy" functions. You could even trivially implement this in PHP if this is your preferred language as this would be executed using php-cli. There are lots of tutorials on how to write Map prg functions. They're pretty easy to implement.