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).
Related
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 am looking for best practices, modules, etc. to securely do file system manipulation via PHP application. The CMS-like application will not use a database, but instead the markdown files are placed in folders and are processed at display time. Therefore, there will be a lot of moving files around, renaming files, writing to files, etc.
I am looking to either find some libraries (e.g., equivalent to an ORM) that will help to manage such actions, input sanitization, moving files. etc. rather than start from scratch. If nothing like this is available, I would like a listing of best practices, etc.
So far I have only found guidance from PHP.net.
More information: The plan is to build a web based end-user interface which sits ontop of Stacey. I would have a test environment with the end user interface, and when changes are ready they are then synced to the production environment. This is a non-DB based system. Stacey is convenient to manage and work with from a developer standpoint, but user's don't want to work directly with markdown and move files, etc.
Also: Please limit the answer to PHP issues; server things like chrooting or locking down the server would be dependent upon the user's individual environment and needs. From a development standpoint, I want to focus on securing my distributed code.
I don't know of any specific libraries that do this -- the filesystem support in PHP is extensive so I'm not sure why they'd be necessary. You might be better off starting with an existing CMS and modifying it to do what you want -- however I understand that might not be possible. It also sounds like the sort of thing that should be using a database, but I guess you already know that.
I can't claim to know exact best practice, this is more general advice.
First, your web server -- and therefore your PHP scritps -- will be running as a certain user. This depends on your configuration and particular server as well as the underlying OS. Ideally you want to make sure this user only has access to the filesystem area that your using as storage. Deny all access to everywhere else apart from read-access to where it really needs (your scripts, etc) and read-write to the storage area. The exact way to do this depends on your system.
That's your last line of defense, do not rely on it, it's there as a safety net.
It's not clear exactly what will cause files to be renamed, moved, altered but it's a safe bet that it's from user input. Therefore you need to make sure you sanitize all user input, if their page name becomes a file name you want do not want to let some enter ../../index.php as a page name and nuke your main site.
Always assume the worst case: a user who knows the internals of your system intimately and is aiming to do most damage. Do not rely on 'security by obscurity' or 'nobody will ever do that'.
What I would do (and have done before) is two fold. First wrap all the filesystem functions up into a class that provides the same functions as methods. The job of this class is to check that anything happening is allowed, that means it's probably going to have to read the paths and filenames and work out the location of the changes.
Secondly, sanitize all user input that could be malicious when it first arrives. You might want to look at using escapeshellarg or URL encoding, or something else depending on what your input is.
You also mention files are processed at run-time, if users are allowed to write scripts (or worse PHP that gets executed) then you have a lot more issues and may have a fundamental problem. But that's not clear from your question.
Hope that helps.
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.
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.
I just read the Twelve-Factor App, which looks like a pretty comprehensive set of rules to apply in a web-based application. It uses python or rails in its examples, but never php... I was wondering which factors of the manifesto can be applied to PHP projects and how?
Thanks
Short answer:
All points apply to PHP as the twelve factor app manifesto refers specifically for web apps.
PHP has a very hard time complying to twelve factor, in particular in the items 2, 7, 8 9 (as a side effect of 7 and 8) and 12 (partially). Actually that's the first really grounded argument I have heard in the whole "PHP sucks" rant that is common on the Ruby and Python communities (don't get me wrong, I think Ruby and Python are better languages, but I don't hate PHP, and definitively hate the "my language is better" rants.)
Being that said, it may be that your PHP project is not a web app or SaaS, but just a simple website, so you may just deem that twelve factor is not a need.
Long answer: A point-by-point analysis would be:
Codebase: not an issue
Dependencies: the way PEAR works goes quite against this point, as pear dependencies are installed system wide and usually you don't have a consolidated manifesto to declare them. Is also usual for a PHP setup to require you to add packages to your OS installation to get some libraries available. Finally AFAIK there isn't a tool in PHP to provide isolation like "virtualenv", "rbenv" or "rvm" (or if it exists is not popular among the PHP community) Edit: Composer (http://getcomposer.org/) seems to do the right regarding dependencies, it still doesn't isolate the PHP version, but for all the rest it should be fine.
Config: some PHP frameworks are not very well suited to do this, but there are certainly others that do well, so it's not a flaw of the platform itself
Backing Services: shouldn't be much of an issue, despite maybe having to hack some frameworks a little in order to manage the services as resources
Build, release, run: this is totally appliable to PHP as this definitively doesn't concern only "compiling". One may argue that several projects and hosting platforms on the PHP community abuse of direct FTP, etc. but that's not a flaw of PHP itself, and there is no real impediment on doing things right regarding this item.
Processes: This definitively concerns to PHP. PHP is quite capable of running purely stateless processes (the emphasis is on the word stateless), and actually several frameworks make your life easy for it. For example, symfony provides out-of-the-box session management with memcached or database storage instead of regular sessions
Port binding: Over simplyfing it, this point basically demands you to reverse proxy and have the actual webserver embedded on the app instead of being a separated component. This puts PHP in a very hard position to comply. Despite there are ways to do this (see the reply about using PHP as FastCGI) that's definitively not the most common nor the best supported way to serve a PHP app as it is on other communities (e.g. Ruby, Node.js).
Processes: This is not impossible in PHP. However several elements put PHP in a hard position to comply. Namely the lack of good support for items 6 and 7; the fact that the PHP API to spawn new processes isn't really very nice to work with; and specially the way Apache's mod_php handles their workers (which is by far the most common deployment schema for PHP)
Disposability: If you use the right tools there is nothing inherent on PHP to prevent you from creating fast, disposable, tidy web and worker processes. However I believe that since the underlying process model is hard to implement as per points 7 and 8, then 9 becomes a bit cumbersome as a side effect
Dev/prod parity: This is very platform agnostic, and I would say one of the hardest to get done right. PHP is no exception to this rule, but it doesn't have a particular impediment either. Actually most of the tools named on the manifesto can be applied to a PHP project
Logs: Having your app agnostic of the log system on the execution environment is totally doable on PHP
Admin processes: The most important flaw of PHP regarding this point is its lack of a REPL shell. Regarding the rest, several frameworks like Symfony allow you to program admin tasks (e.g Doctine-based database migrations) and run them on the same environment as your "regular" web envionrment.
Since the PHP community is evolving, it may be that it has already righted some of the wrongs mentioned.
Build, release, Run: Applicable to compiled code which is not the case in PHP. So this
point is not something you need to look at.
I don't claim any authority on this 12 factor stuff, but my read of that section is that the author would disagree. It's not just about compiling, it's about managing dependencies both in the small (the snapshot of the code) and in the large (any libraries the code uses).
Imagine you're a new dev and they say, "Okay, this is a custom php app, so...
a) The custom code is really two subprojects, which are in repo A and repo B.
b) You'll need to create a directory layout like so, and then
c) check the code for each subproject out into this subdirectory and this subdirectory.
d) You'll also need these three open source PHP libraries:
version 3.1 of library Foo,
version 2.3 of library Bar, and
version 5.6 of library Bat.
e) download them from their home project sites and unpack them, then copy them into this directory, that directory, and the other directory.
f) then you'll need to set these configurations in the external library,
g) and these configs in our two custom code projects.
h) once that's all done, tar/gzip it all up, upload it up to the QA server and untar it into htdocs.
There's no compiling going in that set of steps, but you can bet there's a lot of building.
Getting all of that set up and working is the build step.
Using tar/gzip to take a snapshot of the working build is the release step.
SCP'ing/unpacking it into the QA server's htdocs directory is the runtime step.
You might say that some of those steps above are unnecessary - the libraries should be deployed at the system level and merely imported. From the 12factors.net site I'd say the author prefers you to import them uniquely and individually for the app. It sidesteps dependency versioning problems at the cost of more disk space (not that anybody cares). There are more hassles in managing all those dependencies as local-to-the-app, but then that's the point of the build/release/runtime scheme.
It might have changed since you read it - there are a few PHP examples now, although a few of them seem like negations of the twelve-factor concept.
One of the ways that normal mod_php sites violate twelve-factor comes with VII. Port binding. From the manifesto:
The twelve-factor app is completely self-contained and does not rely on runtime injection of a webserver into the execution environment to create a web-facing service. The web app exports HTTP as a service by binding to a port, and listening to requests coming in on that port.
However, apache/php can be coaxed into this worldview with something like this:
https://gist.github.com/1398498
Not perfect, but it works for the most part. To test it out, install foreman:
gem install foreman
then run it in the directory you cloned the gist into:
foreman start
then visit
http://localhost:5000/foo
DO NOT TAKE THIS POST AS A REFERENCE, THIS WAS WRITTEN IN 2011, MANY THINGS HAVE CHANGED SINCE THEN... THE WORLD OF PROGRAMMING IS IN CONSTANT EVOLUTION. A POINT OF VIEW OF 2011 IS NOT NECESSARILY STILL VALID IN 2018.
I just read a few lines of each points and here goes my analysis of the document:
Codebase: Everyone, php or not should have a codebase even for the little projects
Dependecies: PHP uses includes and code libraries that you should always be able to port easily by simply copying the code to a server. Sometimes you use PEAR and then if the server doesn't support it, you have to copy and install pear manually. I use Zend Framework most of the time, so it's just copying the code of the framework with the ftp upload.
Config: It is common for php apps to have a writable config file that you store configurations into. Where you store it is your choice as a developer, but it is usually either at the root of your app or in a settings/config folder.
Backing Services: PHP does use backing service most of the time such as MySQL. Other common services depending on your app are twitter and facebook. You use their API to communicate with them and store/retrieve data to work with.
Build, release, Run: Applicable to compiled code which is not the case in PHP. So this point is not something you need to look at.
Processes: HTTP is stateless and is SERVED,thus, you usually have no process apart from the web server. This is not entirely true as a webservice may be bundled with applications you package with or create for it. But, for the sake of standards, you usually don't have to use processes in the web world.
Port binding: PHP doesn't apply to port binding at all because it is not a process that hooks to an address, Apache, NGinx or Lighttpd does that for you. Reading #6/7 makes me understand that a website could never be a Twelve-Factor app.
Concurrency: Again this point treats about processes which do not apply to PHP web pages. This point applies to the server serving the content.
Disposability: This point discusses about how fast a process should be. Obviously, PHP web sites not being a process shouldnt apply but always note that your website should execute pages as fast as possible... Always think about this block or that block of code and see if it is optimized.
Dev/Prod Parity: This point is crucial in any app development. You never want to have a large gap between two app versions or upgrading can become a hassle. Furthermore, never create client specific versions of an app. Always find ways to allow your app to be configured/customized at the template level so you can keep your app as close as possible to all installed versions everywhere.
Logs: Logs are always a good thing to have, they allow you to follow the process of your code without having to output it to screen. My favorite tactic is to "tail -f logfile" inside of a linux console and look at what is happening as i execute my code.
Admin processes: Not applicable, in php, you don't have processes, but you do have pages that you can secure with usernames and passwords.