3

I have a PHP/MySQL website on 000webhost (http://www.boisvert.me.uk; but it's down for review at the moment) and I'm concerned about its security. What I'm trying to do will make any site vulnerable; it's the PHP equivalent of giving sharp cissors to children. I have various ideas for minimising the site's vulnerability, but more advice would be welcome.

In particular, there are two scripts:

  • An upload script. Its purpose is to allow a registered site user to upload certain XML files (tutorials). Obviously, to do that, a folder on the site gives write access to visitors. I don't like that, but I don't see a way around, I can add checks to the script (type, size) to ensure that files uploaded are limited to XML and some images. Are there other points I could improve this with?

  • Script 2 is an interpreter for PHP - a user can enter PHP in a form and it will execute (without saving). I want users to be allowed to try database access, so a crude string replacement ensures that I don't need to give away MySQL access information. But an attacker could use this interpreter to obtain access to the files area and upload unwelcome material. My solution would be to place the interpreter in a separate domain, where no files can be uploaded.

Any advice to improve on this is welcome, bar "don't do it". I know it's dangerous. So is crossing the street. Thanks for your help.

boisvert
  • 3,679
  • 2
  • 27
  • 53
  • 5
    No offense, but the second point sounds more like "crossing the motorway" :) If it's publicly accessible, you are putting the server this runs on in great danger. A separate *domain* won't do to protect you, as PHP's user may have access to other sites on the server. See e.g. [Exploitable PHP functions](http://stackoverflow.com/q/3115559) – Pekka May 13 '11 at 08:20
  • What kind of a target audience is this for? Is this for a small university course with a few dozen students, or a completely public service? – Pekka May 13 '11 at 08:39
  • I'd have liked it to be public, be based on the answers below it won't be. – boisvert May 13 '11 at 09:01

5 Answers5

3

First point is covered by previous answers (and probably many times elsewhere on this site)

For the second point, I'm going to make some suggestions if you feel you simply must have this. You could compile your own PHP binary, excluding all options that you don't expect your users to need (perhaps omit everything except MySQL). You should then create a php.ini file which disables any functions that are potentially dangerous (use the disable_functions config option for this - see other answers). Limit memory usage and CPU time to sensible numbers (for the simple scripts you want to allow users to run). Now we should be able to run all of that in a chrooted environment using something like system("chroot /path/to/secure/dir ./php tempfile.php");. /path/to/secure/dir should be directory to which you write the users PHP script into a temporary file. It should contain the PHP executable and the secure php.ini file. These files and the secure directory should be owned by a user other than the one running the script (particularly the PHP executable and php.ini file) and not writeable by anyone. The secure directory should be outside of the web root.

Now, I'm not going to pretend that I've thought of everything, but hopefully these ideas could be the basis of a secure environment for you.

qbert220
  • 11,220
  • 4
  • 31
  • 31
1

Well, Script 2 definitely is a no go in my eyes. Unless you are completely sure you can avoid ANY kind of script you don't want to have ran on your server (and believe me, that's simply not done). I would get rid of this idea. In that case you'd more likely will be scripting this and store the code untill it has been reviewed by you and then the user can execute it.

I'm not sure what access you want to give them to the database, but perhaps you could control it a little more by creating some kind of form saying:

(1) give me data from [table]
(2) based on these critera
(3) from startdate to enddate

Not sure if that fit's your needs.. but if it's just databaseaccess you want to give them, doing it using a search function is far more controleable then letting them execute pieces of PHP code.

Your first question is only a risk if you didn't secure it well enough. Opening a folder for uploads isn't the biggest risk, no-one can just put files in there. The risk is a bad security which allows mallicious files to be uploaded (PHP files for example) that can be run afterwards. So besides checking for filetype, fileextension, filesize, fileheaders etc. you might also want to put these files OUTSIDE your website root folder. If they are just images and XML files you can write your PHP script in a way it get the filecontents (file_get_contents) and create an xml/image file based on what it has read.

Joshua - Pendo
  • 4,331
  • 6
  • 37
  • 51
  • Difficulty is, the purpose of database access is to teach PHP/MySQL, so restricting as search facilities do doesn't cut it. – boisvert May 13 '11 at 08:34
1

On the first case if you check to be sure that the file uploaded is XML or image and disallow any other type, it will be ok. I don't see any problem with it.

The second thing you want to do is what concerns me. Even if you place PHP interpreter on separate domain, it's still dangerous, cause anybody can use it to send spam or interpret their own script to delete your files or something else. The only solution I see is to disallow list of php commands and expressions, though you must be sure your list is full. Sorry no any other ideas...

Arman P.
  • 4,314
  • 2
  • 29
  • 47
1

In PHP

Re your second point, you may be able to create a half-way secure solution by

  • Disabling all functions that could execute external commands
  • Disable fopen URL wrappers to prevent http:// requests
  • Disable the mail command, curl and all other potentially problematic commands and wrappers - a useful list is here: Exploitable PHP functions
  • Install the suhosin patch
  • Create databases per user; publish mySQL credentials limited to only that one database. (You're not going to be able to protect individual databases.)

None of this can be done on shared hosting, though, this stuff requires root access to the server. On shared hosting, I'd say what you are trying to do is impossible.

Using a VM

Another idea: I don't know what the background / budget / target audience of your project is - if you can use only a web hosting company, it's out of the question - but if it's for a university project (= limited number of students, longer span of time), have you considered creating a truly sandboxed solution in the form of per-user virtual machines?

Each user could have their own virtual machine with pre-installed PHP and mySQL on it, and do whatever they like on it. You would prevent it from accessing the outside world, and dispose of each VM once the student is done with it.

Creating each virtual machine from a pre-defined image should be possible, but obviously this would need huge hardware resources and sysadmin work, so it may not be the solution for your scenario.

Community
  • 1
  • 1
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • Very helpful, and yes, I accept your suggestion is "half-way secure" but that was always going to be the case. I don't have to use shared hosting. – boisvert May 13 '11 at 08:49
  • 1
    Accepted qbert's because you've got plenty of reputation :) but both your answers have given me a lot of help. – boisvert May 13 '11 at 10:00
0

An alternative has become more established since two years ago: to use one of the pastebin / remote execution tools.

At present I use phpfiddle. Its remote execution API supports MySQL connectivity and more useful techniques worth teaching. Here is a test - my host is slow, but the PHPFiddle part is just fine. So I'm bringing online the dozen PHP tutorials that I've had to control tightly.

Of course, the security remarks in the earlier answers still apply. PHP Fiddle implements something akin to its own compilation of PHP, with only the required modules included.

boisvert
  • 3,679
  • 2
  • 27
  • 53