27

Let's say that a partner wants to upload a PHP script to my Apache server. What kind of mayhem could be caused by this?

Which PHP parameters pose threats? If those PHP parameters are fully disabled, would allowing PHP to be inserted on my servers then be safe?

These are some PHP parameters that I know of that pose a security flaw. What others are there that are unsafe?

Writing to server:

  1. fwrite

  2. file_get_contents

  3. FILE_APPEND

Opening files on server:

  1. fopen

  2. file_get_contents

  3. include

  4. fread

  5. url_get_contents

  6. curl_init

  7. curl_setopt

Deleting files:

  1. unlink
  2. unset

Are there any other security flaws that I should be thinking about before allowing partners to add .php files onto my server? I imagine that there might be a lot that I'm unaware of.

I'm also worried about loop scripts that could use up all of my RAM and CPU, backdoor access attacks, malware and the like. Are there any measures that I can take to prevent any of that and more from happening?

If there is Javascript, JQuery or other languages embedded in the PHP script, are those dangerous as well? And what kind of parameters in other languages would I need to disable in order to protect my server?

How do websites like jsfiddle and codepen keep their sites secure while allowing people to post their own code?

Machavity
  • 3,766
  • 1
  • 14
  • 29
Michael d
  • 487
  • 5
  • 8
  • 5
    A sandbox might help. See [Is there a PHP Sandbox, something like JSFiddle is to JS?](https://stackoverflow.com/q/4616159) and Google `PHP sandbox`. – Neil Smithline Mar 21 '18 at 14:00
  • 5
    What is your use case? Do you want their PHP to become part of your site? – Neil Smithline Mar 21 '18 at 14:02
  • 31
    Just to be clear, you intend to execute the PHP? Not just let people download it as code? – Anders Mar 21 '18 at 14:21
  • 1
    I have someone who would like to put some PHP on my site, kind of like outsourcing. They have some good code. I'd just like to know if there is a way that I can prevent catastrophe in the event of malicious behavior. If I had a list of commands that I could check for then I could review the code to make sure that there's nothing hidden in it that is dangerous. The PHP is intended to run on the site. And it could contain other languages such as javascript, jquery, ajax, etc. – Michael d Mar 21 '18 at 15:27
  • Hi @NeilSmithline, if I ran a PHP sandbox with something like Runkit_Sandbox would the submitted PHP then be 100% safe? Or is there still a way for people to corrupt the server through sandbox? – Michael d Mar 21 '18 at 15:31
  • 4
    I'm not a PHP sandbox expert, but I don't think that any sandbox provides 100% security. But they try. So this is a low-risk, but not no-risk strategy. – Neil Smithline Mar 21 '18 at 17:01
  • 2
    It sounds like you want the code to actually run, and provide some part of the functionality of your site, in which case sandboxing (even if you could guarantee it) isn't going to help since it's trying to avoid just that. If this is that kind of collaborative development you'd deal with that as part of your deployment process - that's a different scenario to providing a means for people to upload code to your site and execute it – Mohirl Mar 21 '18 at 17:46
  • Even with a perfect sandbox, you still have potential abuse: What happens if his script uses a bunch of CPU/Memory? If you've enabled file or network access, it can also use up all of those resources as well. – Nathan Merrill Mar 22 '18 at 06:06
  • Are the other languages going to be limited to client-side stuff like JavaScript, HTML, etc.? Or is there also going to be stuff like bash code in there? Additionally, are you worried about your *user's* safety, or just your own sites? – Soron Mar 22 '18 at 06:35
  • On further thought, I think this is a great thing to ask, but should probably be several related questions due to the sheer scope vs. the level of starting knowledge (unless the answer you're looking for is just "there are a ton of dangerous things, don't do this without research"). I'm voting to close as "too broad", but please interpret that as a suggestion to split off several narrower questions! e.g., "is JavaScript in PHP dangerous", "what sorts of dangerous things can PHP do on a server", "how do I disable (these specific) dangerous things in PHP", and so on. – Soron Mar 22 '18 at 06:57
  • If the amount of uploaded scripts you expect is low, consider manually vetoing them before making them available for execution. – Aaron Mar 22 '18 at 13:30
  • 2
    In a comment you say "_kind of like outsourcing_". If this person is _working_ for you (even if only on an ad-hoc basis) then perhaps a sound contract (with "_shall not maliciously..._" clauses) is an alternative / additional approach. And if you wouldn't trust her/him to _be_ an employee (or equivalent) you probably shouldn't take their code. – TripeHound Mar 22 '18 at 16:59
  • Short answer: 3rd world war! – Billal Begueradj Mar 23 '18 at 12:42
  • I don't get why you are making this person *upload* php files to your site. I mean: if he wants to contribute, then he should do pull requests on the repository of your source code, so you can review them and accept/deny them... – Bakuriu Mar 24 '18 at 11:58

8 Answers8

33

It's very dangerous, because you are allowing to someone to upload PHP file with unknown code and unknown intentions, so if you need this functionality as part of your web site, you should harden your server, for example:

  • Set a only one directory to upload PHP files from users, you should apply right user permissions (read, write or execution) for this directory, remember create a specific user for this directory, not use root user.
  • You can create a .htaccess file for directory, then you could set specific settings for that directory (Configuring .htaccess file).
  • Validate input user, even you should set a specific name format and size maximum for PHP files, if a PHP file doesn't match with that format or its size is bigger than what is allowed then application shouldn´t allow to user to upload that file.
  • Use canonicalization before use file functions, for example: realpath, basename. This helps you to avoid path traversal attack.
  • You should disable PHP functions with high risk, for example: exec, shell_exec. You can do this through php.ini file, for example, you could add the following line helps to disable functions for OS command execution and settings management:

    disable_functions =exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
    

    The following line helps to disable functions for include or open files from external sources:

    allow_url_fopen=Off
    allow_url_include=Off
    

Official documentation php.ini file

Those are some basic recommendations. You should analyze your web application and your needs to set the right settings for your server and web application.

I hope this information helps you.

hmrojas.p
  • 1,049
  • 1
  • 8
  • 16
  • 4
    Set a only one directory to upload PHP files from users - Shouldn't this be one directory per user. (So each external user has one specific directory and one specific local user that runs code from this directory) – Taemyr Mar 21 '18 at 16:57
  • @Taemyr you are right, it could be another security level. – hmrojas.p Mar 21 '18 at 17:47
  • 31
    That you spend over 95% of this answer explaining how to try to secure the server disturbs me immensely. It should be the other way around: spend 95% of the answer discouraging it and 5% talking about what you can do. – jpmc26 Mar 21 '18 at 21:19
  • 7
    @jpmc26 Ok, I understand your point because it's a dangerous topic, for this reason I said "If you need this funcionality ..." before to explain my recommendations, now those are only recommendations, he can decide to follow them or not, also this site is about security and how to solve this kind of problems, not avoid them, so users of this site are professionals and they sometimes have to try to solve problems before to decide not continue with a solution, for those reasons I considered to give some recommendations, but I respect your point. – hmrojas.p Mar 21 '18 at 22:26
  • Don't forget the potential to steal cookies and bypass domain related security policies, this will need isolating on a separate domain. I'd also disable eval and create_function – Tom J Nowell Mar 23 '18 at 01:13
  • 11
    @hmrojas.p "This site is about security and how to solve this kind of problems, not avoid them." I patently disagree. Very often the only sane answer in security is, "Don't do that." And also very often, if you have to ask whether something widely known to be dangerous is a risk, you simply do not have the knowledge to try to defend from it, nor is the time and money spent trying to defend from it a good investment. – jpmc26 Mar 23 '18 at 01:57
29

If you allow somebody to upload and execute a PHP script on your server, you effectively give this person the right to do whatever he or she could do, if she had ssh access with username/password for process the PHP script runs as.

So, if the person in question would run the script through Apache, the person could do anything the Apache user on your server could do.

As an additional risk, this person could use the given access to try privilege escalation, something that would probably break the legal agreement you have with them (you do have a legal agreement, don't you?).

Jacco
  • 7,402
  • 4
  • 32
  • 53
  • 1
    If I had a list of commands that are a security risk I could search for those commands and review the code to make sure that everything looks safe. Or are there just too many things that could go wrong that a list of commands just isn't enough? – Michael d Mar 21 '18 at 15:28
  • 40
    PHP is a programming language that enables programming. So if I create mycmd='c'+'a'+'t'+' ''+'>'+'/'+'e'+'t'+'c'+'/'+... what are you going to grep for? If I get more complex... The simple answer is there is no simple way to run untrusted code safely. – Adam Shostack Mar 21 '18 at 15:39
  • @AdamShostack Grep for any command that interprets a string as code (Eg. eval), and any command that passes a string to the OS (eg. exec). The string mycmd on its own is not a danger. (Not that I recommend allowing strangers to upload PHP, - or execting a black list to be sufficient protection if you do) – Taemyr Mar 21 '18 at 16:51
  • 11
    @Taemyr: PHP has several ways of executing functions dynamically, e.g. http://php.net/manual/en/functions.variable-functions.php – poizan42 Mar 21 '18 at 16:57
  • 31
    @Taemyr I look forward to watching you make a fortune with your awesome new static analysis tool which makes this safe. – Adam Shostack Mar 21 '18 at 17:02
  • 12
    @Taemyr, that might work in a sensible language, but this is PHP we're talking about. – Mark Mar 21 '18 at 23:45
  • 13
    @Michaeld, blacklisting is not a solution that works, there are *way* too many options to bypass blacklists; this is a fact that has been shown way too many times. Whitelisting in this case only works if you can guarantee that you are smarter that the combined knowledge of all people that may use your system. – Jacco Mar 22 '18 at 07:48
  • 4
    @Taemyr https://ideone.com/lBVfRW and no, you can't just blacklist `rkrp`, because I can come up with infinitely many ways to obfuscate it. – gronostaj Mar 22 '18 at 13:22
  • @gronostaj you are missing the point of my comment. I really don't care how you obfuscate the contents of a variable. If I can't prevent you from executing the contents of a variable I have already lost. – Taemyr Mar 22 '18 at 13:31
  • 1
    @poizan42 Charming. Who though that was a good idea? – Taemyr Mar 22 '18 at 13:31
  • 9
    @Taemyr *"Charming. Who though that was a good idea?"* Pretty sure this could be said of most of PHP in general. – anaximander Mar 22 '18 at 14:52
  • 7
    @Taemyr "If I can't prevent you from executing the contents of a variable I have already lost" - I believe this is the point being made. You can't, there's many ways of achieving that in PHP and it's a core part of the metaprogramming structure. – Phoshi Mar 22 '18 at 17:28
  • 3
    @anaximander [Indeed](https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/). (A bit dated now, but *still*.) – jpmc26 Mar 23 '18 at 02:07
  • 1
    And for the [fun](http://phpsadness.com/)! They are all real case, free range error, tested, encoutered by a programmer. – Drag and Drop Mar 23 '18 at 14:33
  • Just to reinforce @gronostaj's point, this is another php script that uses exec to shell out to another program: – bdsl Mar 25 '18 at 11:31
25

To me it sounds like you are about to shoot yourself in the foot. Letting people you don't trust upload and run PHP on your server is extremely dangerous. Here are some things an attacker could try:

  • Run batch commands taking over your webserver. It can then be used as a staging ground to attack other servers from within your network.
  • Read files containing secrets, e.g. passwords, encryption keys, TLS keys, etc.
  • Do XSS attacks (using JavaScript) to steal session cookies or other credentials from your users. This is assuming the uploaded files run on the same domain or a subdomain as other applications.

The list goes on and on and on. There are ways you could try to block these attacks (hmrojas.p has some suggestions), but that is no simple thing to do. Blacklisting functions is a start, but blacklisting is never more than a partial defense. Even for the best of experts, containing someone who can run PHP is a challenge.

In the end, if you don't trust the person who wrote the code you will have to carefully and manually audit the code to make sure it is benign. That takes time and effort, and it isn't compatible with direct file upload.

Sometimes, the only winning move is not to play. I'd say this is one of these cases.

Anders
  • 64,406
  • 24
  • 178
  • 215
  • 1
    I think I know what you mean here but trusting code doesn't make it safe. Sorry to be pedantic but I've seen people get confused by things like this and do the opposite of what they should do. – JimmyJames Mar 22 '18 at 15:54
  • @JimmyJames Obviously trust can be misplaced, and obviously there can still be mistakes. But by definition, if your trust is well placed, there are no deliberate issues with the code. I'll try to edit to make it clearer. – Anders Mar 22 '18 at 16:18
  • 1
    I guess what I am trying to say is a trust relationship should be considered a significant risk. You are not only assuming that the trusted party will be non-nefarious but also that they have adequate security and protect their credentials. It also creates opportunities for third parties to subvert that trust relationship via flaws. Your edit seems to address this. – JimmyJames Mar 23 '18 at 16:50
17

While there are sites that allow you to run PHP code on demand (i.e. 3v4l), they severely limit what you can do and jump through some major hoops to do it safely

I use a setup where scripts are executed in a small virtual machine. For security reasons this machine has no network and only a minimal filesystem. Scripts are executed by a daemon (written in Golang) and results (with statistics) are reported to a PostgreSQL database. All results are stored and used to provide averages for the performance overview.

I would not allow users to upload PHP scripts in a live environment. We once had an intern who was writing an image upload script. Except he forgot to validate anything about the file he was accepting. Someone uploaded a PHP malware script from Turkey and attempted to take it over (he would have gotten away with it too had it not been for other security efforts on the server).

Machavity
  • 3,766
  • 1
  • 14
  • 29
5

PHP has a lot of functions to disable features and restrict certain actions so it can be used in shared hosting scenarios. So it is much safer to allow people to upload php scripts than i.e. perl scripts, when your webserver and php instance are configured correctly.

So I want to address another thing than the security of urlopen and similar: You are allowing people to run interactive sites.

The consequences are dangerous independend from how much network or disk IO they can make, because they can for example setup a phishing site, which can reflect badly on your domain and IP reputation.

So you do not end up on a blacklist because of spam mails as they are blocked by disallowing php to send mail, but possibly because you're running a script which phishes for user's facebook logins.

allo
  • 3,173
  • 11
  • 24
2

You mention an Apache server, but not whether or not it has PHP installed.

Either piece of software can be used/installed without the other.

Both pieces of software are available for multiple operating systems.. you haven't mentioned which is in play here.

In the case that PHP is installed on the server:

The risk is that, should the user account PHP ends up running under, have administrative rights to the machine, they can do anything in the PHP library.

Should that account not have administrative rights, this restricts what they can do.

Some operating systems have discoverable/known exploits allowing non-administrative accounts to 'get' administrative rights. These are known as privilege escalation exploits. If one is used, then again.. they can do anything in the PHP library.

In the case that PHP is not installed on the server:

There's little to no risk at all. A PHP file is just a text file of instructions that PHP interprets and acts on. It's no more harmful than a text file with a recipe for stew.

1

There is no way you can “secure” this. Any amount of allowing someone/anyone to execute code at will on a system can lead to complete system takeover, either inherently due to executing all instructions of due to defects in the system that is trying to prevent certain functions from being used.

Even a scripting language in a jail/chroot/container as a dedicated user can ultimately exploit vulnerabilities (existing/new ones) that allows for full root access and more (i.e. firmware access). This is what shared hosting providers have to deal with all day long. Most of the prevention and fixing comes from two things:

  1. Legal; list what they can and cannot do in a contract ahead of time

  2. Process; have redundancies and recovery schemes in place do deal with breaches/loss

John Keates
  • 820
  • 4
  • 7
-2

Yeah, you're going to want to sandbox this. Probably the simplest way to do that is with execution in a VM or docker container. Of course, then you'll need to audit the security around that.

Marcin
  • 385
  • 2
  • 7
  • 4
    No that's wrong. It is possible to escape a Docker container, there are documented exploits for this (some harder than others, but here we are). Considering that the [Docker daemon runs as root](https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface), trusting Docker to keep the malicious code contained seems ill-advised. In the end, jailing the untrusted code (even by virtualisation) doesn't matter much when you must also protect the services inside that same jail. – korrigan Mar 22 '18 at 17:04
  • @korrigan When you say "services [in the] same jail" do you mean services within the very same sandbox, or other services on the same host machine? My assumption is that there is no protection of things that are together in the same sandbox. – Marcin Mar 23 '18 at 19:22
  • From OP's comment: `The PHP is intended to run on the site.`. Yes I meant in the same sandbox (or jail). Your assumption is right in this regard. – korrigan Mar 23 '18 at 19:31
  • @korrigan Obviously. You'd want to separate serving from running here. E.g. have the php server running in the vm, and the rest of the site running outside of that jail. – Marcin Mar 23 '18 at 19:32