While I do know that system calls and security don't go hand in hand, there is a project for which I do need it. I'm writing a small code checker and I need to compile and execute the user submitted code to test against my test cases.
Basically I want to run the code in a sandbox, so that it can't touch any files outside of the temporary directory and any files that it creates can't be accessed by the outside world.
Recently I came across an exploit with with which the user could create a file say shell.php with the following contents.
<?php
echo system($_GET['x']);
?>
This gives the attacker a remote shell and since the owner of the file is apache, the attacker could basically move around my entire /var/www where mysql passwords were stored along with other configuration information.
While I am aware of threats like SQL Injections and have sanitized the user input before any operations that involve the DB, I have no idea as to how I can set up the sandbox. What are the techniques that I can use to disable system calls (right now I'm searching for the word 'system' in the user submitted code and not executing those snippets where it is found) and restrict the access to the files that the user submitted code creates.
As of now my code checker only works for C and I plan to add support for other languages like C++, Java, Ruby and Python after I can secure it. Also I'd like to learn more about this problem that I've encountered so pointers to a place where I could learn more about web security would also be appreciated.
My development machine is running Mac OS Lion and the deployment machine is a linux server so if a solution, that was cross platform would be most appreciated but one that dealt with just the linux machine would do too.
What you will probably want to do is set up a chroot to some random temp directory on your filesystem for the user running your scripts. Here is some reading on setting up a chroot, and some security to-know's.
I would suggest you also install a security module such as suExec or MPM-iTK for Apache. Then, within your Apache's VirtualHost (if you are not running a virtual host, do so!), assign a specific UserID to handle requests for this specific VirtualHost. This separates the request from the Apache default user, and adds a little security.
AssignUserID nonprivilegeduser nonprivilegeduser
Then, harden PHP a little by setting the following PHP options so the user cannot access files outside of the specific directories, and move your tmp_dir and session_save_path within this directory. This will prevent the users access outside of their base directory.
php_admin_value open_basedir /var/www/
php_admin_value upload_tmp_dir /var/www/tmp
php_admin_value session.save_path /var/www/tmp
Along with the lines of PHP, prevent access to specific functions and classes, and read up on PHP's security write-up.
Also, I would have you look into for that user, disabling access to sudo and su, to prevent a script from attempting to access root privileges. Learn more, here.
All in all, you said it nice and clear. There is no way to fully prevent a user from accessing your system if they have the will. The trick is to just make it as difficult as possible, and confusing as possible for them.
There is no way to make this work on a cross-platform basis, period. Sandboxing is inherently highly system-specific.
On Mac OS X, there is the Sandbox facility. It is poorly documented, but quite effective (Google Chrome relies heavily on it). Some enterprising souls have documented parts of it. However, it's only available on Mac OS X, so that probably rules it out.
On Linux, your options are considerably less developed. Some kernels support the seccomp mechanism to prevent processes from using any except a small "safe" set of system calls; however, not all do. Moreover, that "safe" subset doesn't include some calls that you are likely to need in code that hasn't been specifically written to run under seccomp -- for instance, mmap and sbrk are not permitted, so you can't allocate memory. Helper tools like seccomp-nurse may get you somewhere, though.
Here are the things I suggest doing.
1.
Disable system classes and functions in php.ini with
disable_functions="system,curl_init,fopen..."
disable_classes="DirectoryIterator,SplFileObject..."
2.
Run in a read only environment with no important data stored on it. In case anyone ever got into your server you don't want them to access anything. A good way to do this is buy an Amazon AWS EC2 and use a jailed user to run your server and PHP.
3.
Ask people to break it. The only way you can find flaws and loop holes that you are unaware of is to find them. If necessary, get a temporary server with a "test" application that replicates the same type of application your "production" environment will be.
Here are some helpful resources.
List of functions to disable. It can definitely be expanded upon but it's a good start.
Information on to avoid security issues.
The source and README in Viper-7's Codepad
I think what you are looking for is Mandatory Access Control. In Linux, it is available via SeLinux. Using it you can limit who can execute what command. In your case, you can limit the php user (Apache) to execute only limited commands like gcc etc. Also look into AppArmor
Also, look into runkit php virtual environment
You can try to run user submitted code in a container (docker) which are very light weight VMs. They start in less than a second.
Related
We are working on making a wordpress type system from scratch with a templating system and am wondering about security. We hope to have a SaaS model where the user will be on the same server as a few other users, but we hope to also give them the tools to modify their own Views files, which means PHP access. We are using Laravel as the framework. As a long time Dreamhost user, I know you can section the same machine off into multiple environments, but not really sure what they were using to do so.
How can I prevent the execution of commands like eval(), system commands, and limit the users access to fopen (I assume that is mostly through the linux user permissions). I would like to give them direct file access to the Views folder and to develop their own solutions instead of forcing them to go through me, but without jeopardizing too much. If there are mysql considerations beyond separate users, feel free to chime in there as well.
There are several layers that you need to protect.
Some of the hosters incorrectly rely on PHP "protections" like open_basedir, safe_mode (older PHPs), disable_functions etc.
Even PHP does NOT consider them being security features - http://php.net/security-note.php
These can be disabled with any exploit for PHP and then the whole system is doomed, do not do that.
How it should be done
the bottom
Separate OS-level/system user for each hosted site
correct permissions (one can't be able to view/edit page of the other one) - also make sure sub-directories have correct permission as they're going to be similar
separate session files (LOT of webhostings put session files of each PHP-hosted site into the same directory, that's bad bad bad!
Apache finally got it's own module for this - Apache MPM-ITK.
Long story short: picture this as you'd give the user a shell on the machine (under his own uid) - he can't be able to do anything to the other hosted sites.
different uid/gid
system permissions
framworks like SELinux, AppArmor and similar
grsecurity if you want to be hardcore.. but the system will be harder to maintain.
going up?
You can get more hard-core. The best I've seen is a shared-library for apache (or whatever you use) - that is used when apache is started using LD_PRELOAD and it implements all the potentially malicious system calls like system(), execve() and basically any other call that you find bad.
I haven't seen a good implementation of this out there yet (other than custom ones somewhere) - correct me if I'm wrong.
Make sure to implement a white-list for this as eg. mail() in PHP executes sendmail by default and that won't work anymore.
conslusion
Add classic disable_functions, open_basedir, etc. into global php.ini, add session.save_path to every vhost - put sessions into user directories. Make sure users don't share anything.
Implement underlaying OS-level separation correctly.
Get hardcore with grsec and LD_PRELOAD lib hooking system calls.
Separation, separation, separation .. soon enough systems like Docker will provide LXC-based containers to separate users on kernel level but it's not quite production ready yet (imho).
I have users upload PHP files to my server (I know this is a security risk, but it must be done).
I might have to execute the PHP scripts on the server.
So I was wondering, is there a way I can deny those PHP scripts access to any files and any directories outside of their current folder? This would make it secure enough for me to use.
Thanks.
Sigh... "but it must be done" - says whom?
Some options might exist: Looking at the comments on the documentation for the (now-removed) PHP Safe Mode, I found a link to suPHP which "is a tool for executing PHP scripts with the permissions of their owners". This would require local UNIX accounts for each user though - which I'm not sure is possible in your situation.
A real solution would need to go much deeper. I was once on a website that allowed you to compile and run applications in just about any language, as part of an exam. By compiling some "interesting" programs, I was able to determine that I was actually running in a QEMU VM "jail", and they were somehow funneling IO to/from the VM via my HTTP connection.
But the right answer is probably, of course, don't do it. With more information as to what exactly you're designing, we might be able to offer more sane alternatives.
You could set up a chrooted environment for these scripts to run in. Not absolutely waterproof, but a lot better than potentially giving access to your entire filesystem.
This article contains lots of info on how to get certain services running correctly inside your chrooted environment, it also contains a link to a best practices document concerning the correct usage of chroot.
Now, php also has a chroot command, it might be possible to tinker some kind of "sandbox" that's "good enough" for your purposes by using that function.
Anyways, although chroot can help tremendously to protect your system during the execution of foreign code you should remain very careful, and the basic rule is to provide as little services and facilities inside the chrooted environment as possible. In that context, the SO article pointed to by Emilio Gort contains a (very long) list of exploitable functions, probably most or all of these should be blocked by using the disable_functions setting in php.ini
I'm developing a platform that allows users to create apps using PHP. Is there any safe way of allowing users to do this? Can you restrict use of functions that could damage existing source code or the server in anyway? I only want them able to use basic functions, and give them access to 1 database. This must be possible, because of the existence of shared servers, ran by many users.
...
Any advice?
You can list all disabled functions in your php.ini. You can set it differently for every vhost
disable_functions = "exec,passthru"
Shared hostings are just doing the same as I stated above.
Other functions that can be considered to diable:
readfile,fopen,fsockopen,popen,file_get_contents, include,stream_context_create,chmod,chown
Complete list can be found here
But if you are using these functions inside your code also, It's better to made all code files readonly to apache user or for all, in this case chown and chmod disabling play great role.
Never did this before, but i think this approach can help you with a sane and secure environment.
If you are on ubuntu (debian based) i recommend you create a jailed chroot. From the link
A chroot is basically a special directory on your computer which
prevents applications, if run from inside that directory, from
accessing files outside the directory. In many ways, a chroot is like
installing another operating system inside your existing operating
system.
You must also install a dedicated instance of PHP that must be used by applications runned from inside of chroot'd directories.
You can configure your php.ini with "max_execution_time", "disable_functions", ... etc
this is exactly what you need actually.
I used to run a shared server using PHP safe mode, but apparently it's deprecated now.
A better solution is to run each user's PHP processes under a different user account, in a chroot jail, and let the OS worry about security. Users will be able to upload and run arbitrary code, but as long as it's properly sandboxed, they won't be able to do much harm.
You can also use disk quota. Use ulimits for per-user memory usage, and consider disallowing network connections (incoming and outgoing).
For the database, just set them up with a single database, with access to only their own, and don't give them privileges to create more.
CODE_DESC: "This web-accessible script will list security recommendations after scanning available PHP configuration variables and functions for common exploit vectors."
SOURCE_CODE:
http://php-security-audit.com/scripts/view/php_security.php
Will this PHP harm/modifiy/etc my system if run?
I looked at the code
Basically it's running through a bunch of php commands / functions / classes and seeing what they return
I've ran scripts like this in the past; its basically checking the integrity of php.ini and different versions of php
Shouldn't be harm in it, but always exercise caution running someone else's code.
If your interested in security testing, http://www.owasp.org/index.php/Main_Page is a great resource. I've used their resources many times in testing for PCI and ISO. They have many tools geared towards PHP / mysql, etc...
You should set up a test server to run this against. Basically, you should never run unknown, untrusted third-party code against your production set up.
I would like to host a few 3rd party PHP scripts on a Windows server (running in VMware), so I am looking for a way to limit all the users to accessing their own directories (and subdirectories) and prevent them from executing anything on the machine.
Port 25 is completely blocked and there is a very low limit on the number of external connections they are allowed to make.
There must be others that have come across this issue and any ideas, advice and tips are welcome.Thanks!
For PHP, there's the open_basedir restriction that is supposed to limit PHP script access to certain directories, and it usually does. However, it seems to be flawed. Article here - It's from 2008 though, so the shortcomings described there may have been already addressed in a recent release.
There's also the much hated safe mode that may have its place until PHP 6 comes along (it will be removed there.) be very careful with allowing scripts to execute outside binaries.
Suhosin adds additional security and restriction possibilities to PHP and is certainly a good idea to install. Its defaults may interfere with more complex apps, so be sure to look deeply into its config file. However, it looks like you have to recompile PHP to get it running on Windows. This is something I would really recommend looking into.
If you need something stronger and can use Linux, putting Apache in a chroot jail is something I came across a few days ago. It looks totally advanced, though.