sektioneins / suhosin

SUHOSIN [수호신] for PHP 5.x - The PHP security extension.
https://www.suhosin.org
Other
471 stars 71 forks source link

Eval blacklist malfunction #53

Closed rafaelabdo-zz closed 10 years ago

rafaelabdo-zz commented 10 years ago

Hi,

There is an issue when we try to use the function suhosin.executor.eval.blacklist, please see the samples below:

eval(system("echo 'Test 1\n';")); // not working
eval('system("date");'); // working
eval(base64_decode("ZWNobyAiVGVzdCAxIFxuIjs=")); // not working
eval(eval('base64_decode("ZWNobyAiVGVzdCAxIFxuIjs=");')); // working

Apparently this function just works when arguments are between quotes.

All tests were made using suhosin as extension and the version of PHP was 5.4.24.

Is this behavior expected?

bef commented 10 years ago

Hi!

Assuming suhosin.executor.eval.blacklist=system, system() must not be executed within eval(...). E.g.

You may take a look at suhosin.executor.func.blacklist=system instead, which blocks system() calls altogether.

Thank you for playing.

rafaelabdo-zz commented 10 years ago

Yes, I understood your point. I was assuming that if I blacklist the function base64_decode (e.g), the expression eval(base64_decode(...)) wouldn't work anymore. Maybe suhosin wasn't designed to prevent it.

Actually we cannot use suhosin.executor.func.blacklist because we are a shared hosting. We are trying to prevent the use of eval and base64_decode together. This kind of use is commonly used by backdoor scripts.

bef commented 10 years ago

As intended, the eval.blacklist will prevent functions from evaluating within eval() - e.g. eval('... your code here');. When calling something like eval(a(b(c())), PHP will call c(), then b(), then a(), then eval(). As you see, eval() will not actually evaluate any of the other functions, but rather evaluates the return value of a() in this case. On the other hand, eval('a(b(c()));') will let eval() call c, b and a in turn, which can all be blacklisted.

Trying to prevent a certain attack pattern in a shared hosting environment is another matter entirely and somewhat out of scope here.

rafaelabdo-zz commented 10 years ago

Ok, thanks!

bellwood commented 10 years ago

If that is the case, then it would be IMMENSELY helpful to have an actual SuHosin feature to actually blacklist functions within eval versus, what appears to be function returns.

Based on the interpretation of everyone I've spoken to, the presumption was that any function you placed in eval.blacklist was "blacklisted" and would not run.

No where was the indication really clearly given that you are blacklisting "function returns"

From the standpoint of a shared hosting environment, this is a much much more needed feature than say the SQL user restriction that was recently added.

I've seen infinitely more PHP injections using eval(base64_decode()) [and their respective flavors, rot13, etc] than I have ever seen a user randomly get into another users database; which is a really a security issue allowing one user to break their home dir and read another users config files and can be solved external to SuHosin.

Kinda disappointed to read this @bef :/

croensch commented 10 years ago

@bellwood What you are looking for is near impossible because it works on a very different level than the whole programming language would do. Also i do not see the use case you want to improve. Maybe add an example?

@bef's Description of the feature is correct. The way it works is correct too and totally safe.

UPDATE (example): Something like this: http://raamdev.com/2013/cleaning-evalbase64_decode-from-a-hacked-wordpress-website-via-ssh/ can be mitigated by blocking header() and exit(), which is should be fine

bellwood commented 10 years ago

@croensch: if you have say this injected at the top of every php file in a Wordpress site:

<?php eval(base64_decode('really long bs that is a drop shell or botnet, etc'));
//rest of file
?>

I basically want to say that within eval() do not EVER allow base64_decode() to run in any fashion no matter what the returned code from base64_decode() is

This method is the #1 abuse method for malware right now.

A team finds a exploitable plugin or facet within Wordpress, drops in a, or many shells, then uses those to inject every PHP file within the scope of access for that user.

On load, those files then either try to infect the user loading them or perpetuate the bot.

Now, in our case, we simply have eval() completely blocked in PHP's disable.functions but ideally I'd rather just block the functions that are used in conjunction with eval().

Unfortunately with the popularity of Wordpress and the under-educated crowd it draws (in regards to security of the product) exploitable installs will plague administrators forever, however, locking down PHP so that what they inject cannot run would be greatly beneficial.

bef commented 10 years ago

Suhosin provides a number of useful features suitable for mitigating attacks - even in a shared hosting environment. Recommendations:

Also keep in mind to set up your environment as restrictive/secure as possible in addition to PHP hardening. Examples: Kernel hardening (SELinux...), virtualization, chroot environment, ulimits, app hardening (apparmor), restrict file permissions, incoming and outgoing firewall / packet filter, user separation, logging + monitoring, backup/restore plan, regular software updates, extra-htaccess (password/ip-filter) for admin interfaces, secure passwords, HTTPS / transport encryption, ...

bellwood commented 10 years ago

@bef: thanks for the reply.

We already have eval completely disabled, along with all the other typical system level functions.

Coupled with hardware & software firewalls, cloudlinux, suPHP, suEXEC, mod_sec, etc, we've done just about all a provider can do for a SHARED environment.

I cannot force customers to use .htaccess on the Wordpress logins, nor force them to upgrade them without making the hosting featureless and restrictive to the point its non-usable.

stefanesser commented 10 years ago

Hi,

i was without access to GitHub for a week or so and therefore I was not able to comment.

The wish to block something like eval(base64_decode(...)) is understandable, but you have to understand that the base64_decode() function when you call it like this is not running in the context of eval(). What happens in reality is that the base64_decode(...) runs as a normal PHP function in the normal context and then its return value is used as parameter into eval(). Therefore the suhosin.executor.eval.* config options cannot work.

Stopping a script if you see base64_decode() inside an eval() parameter would be an entirely different feature. And to implement it fully it would require taint tracking. Implementing this might not even be possible from an extension and require a patch of the PHP code instead. Of course it might be possible to add a little hack that will detect eval(base64_decode()) but then malicious people will just make the call look different like eval(base64_decode()." ") and detecting it will fail.

And as a side note: You should not use PHP 5.4/5.3 if you want to use the blacklist/whitelist functions, because of a bug in PHP < 5.5 that makes these configurations bypassable.

stefanesser commented 10 years ago

Closed because original post was a misunderstanding how eval blacklist works.