1

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

  1. Within docroot
  2. Owned by user1
  3. 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

Community
  • 1
  • 1
puk
  • 16,318
  • 29
  • 119
  • 199

3 Answers3

1

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.

puk
  • 16,318
  • 29
  • 119
  • 199
  • If you follow the suphp developers DL as I do, then you will see that if you don't then you will open yourself to exploitable vulnerabilities. If I find a writeable directory in some else's tree, I edit the file, symlink to it and execute it as a URI -- I am then running in the other guy's credentials. Nahhhh - you don't want to allow this to happen, do you? – TerryE Mar 06 '12 at 00:23
  • @TerryE are you sure you are running "in the other guy's credentials"? You still run the script as yourself, therefore, you can't, for example, delete his files – puk Mar 06 '12 at 00:42
  • Look at the [mod_suphp.c code](https://ssl.marsching.biz/subversion/suphp/trunk/src/apache2/mod_suphp.c). There is no `suPHP_GlobalDocRoot`. What do you mean "yourself". Apache runs as www-data, say. `/usr/lib/suphp` is a root-owned SUID-bit file. "You" is only established by the UID of the script, not the person who issued the request. – TerryE Mar 06 '12 at 09:47
  • "I am pretty confident there is **absolutely no** solution to my problem."?? I've just told you how to implement what you want to do, but not the way you want to do it. If you have root access write this as a [RewriteMap](http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritemap) **External Rewriting Program**. If you don't have root access, then how are you different from an attacker? – TerryE Mar 06 '12 at 09:53
  • @TerryE What I meant is that the if user John has a script in user Jacob's home folder, how is that any more of a security threat than allowing symbolic links to other people's folders? I am assuming Jacob is smart enough to not change all his file permissions to `0777` – puk Mar 06 '12 at 10:31
  • @TerryE forgive me, but I still don't see how RewriteMap could help me. It is just a collection of name value pairs. – puk Mar 06 '12 at 10:35
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/8584/discussion-between-terrye-and-puk) – TerryE Mar 06 '12 at 12:26
0

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.

Anthony
  • 36,459
  • 25
  • 97
  • 163
  • I was under the impression suPHP runs as root and then switches to the user of the file before executing. In any case, doing `chmod 0777 validate/` did not fix the problem. Changing the owner back to `user1`, then taking away write permissions for others (`0755`) does fix the problem (though not *my* problem) – puk Mar 05 '12 at 03:14
0

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.

TerryE
  • 10,724
  • 5
  • 26
  • 48
  • You lost me at the last paragraph. what are "user and user privileged functions"? What is a "RewriteMap" or "systemy function"? Why would I use CGI over suPHP? Or php-cli? Also what are "Map prg functions"? – puk Mar 06 '12 at 00:48
  • My motivation is described in these sites: http://stackoverflow.com/questions/9542263/need-help-implementing-php-sessions-in-suphp and http://stackoverflow.com/questions/9533150/is-there-any-security-with-suphp and http://stackoverflow.com/questions/8032140/implementing-log-in-alongside-suphp – puk Mar 06 '12 at 00:54
  • @puk, As the you comment below show you haven't got that the server is not a person. "you" don't exist. There is the UID of Apache, root, and the UID of the script. Every other UID is an attacker. The path from the script dir to / must be owned by the script UID or root. I've given the link to the Apache docs on RewriteMap etc. in my answer below. I'll look at the other Qs – TerryE Mar 06 '12 at 10:03