Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-13 Thread Adam Jon Richardson
2012/3/7 Ángel González keis...@gmail.com

 On 07/03/12 00:04, Adam Jon Richardson wrote:
  It would be the responsibility of the framework or CMS or application
  to protect against this type of attack (which they do quite well.)
  When you can force a plugin to work through your API, you can take
  appropriate measures. When the plugin can avoid working through, say,
  a file API that protects against misuse by using the internal file
  functions, this is a much more difficult issue to mitigate.
 The key point is precisely, how do you ensure they can only call your API?


The idea would be to have a default whitelist of internal functions that
can be easily expanded per include as needed. That way, the script
including another script can determine how much power/trust they're willing
to hand off.

For example:

// EXAMPLE 1: included script would only be able to call functions found in
default whitelist
include_restricted('file/path1');

// EXAMPLE 2: included script would only be able to call functions found in
default whitelist and PDO
include_restricted('file/path2', $whitelist = array(SANDBOX_PDO));

The types of restrictions that involve restricting calls to internal
functions (e.g., file()) are, at least conceptually, is straight forward.
However, PDO has an object interface. For objects, I'm researching the idea
of limiting the creation of new objects within the included script. That is
to say that in example 1, the included script would raise an error if it
tried to create a PDO object directly.

However, in some situations, the framework or CMS may hand off a PDO object
to the included script or expose a factory API (maybe the intent is to
share a DB connection), and in this case, the sandbox would allow the PDO
object to be utilized within the script. The idea is for the framework/CMS
to be the gatekeeper for all of the applications resources, and if the
framework designers want to hand off an object for use, then that fits with
the general model I'm proposing.

Right now, it's very difficult to enforce any restrictions on included
scripts because they have access to all of the internal functions available
to the framework/CMS (using something like the disable_functions directive
limits the framework/CMS too much and works from a blacklist approach.)

I'm not saying this would be easy to implement, or that it would be
perfectly secure. I am saying that it's worth careful examination and that
there are many potential solutions that could make things better in terms
of application security.

Thanks for the feedback,

Adam


Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-12 Thread Richard Lynch
On Tue, March 6, 2012 3:30 am, Florian Anderiasch wrote:

Security by blacklist almost always isn't security...

You're bound to miss one of the functions you should have blacklisted,
 but didn't.

Something like Drupal would be crippled by this because major
extensions used by all rely on access that would probably want to be
blocked.

So then they'd have to come up with a blessed list of extension to
not block, and then...

Nice idea, in the abstract, but I don't think it will work out to be
very useful in the Real World (tm).

-- 
brain cancer update:
http://richardlynch.blogspot.com/search/label/brain%20tumor
Donate:
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclickhosted_button_id=FS9NLTNEEKWBE



-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-12 Thread Adam Jon Richardson
On Mon, Mar 12, 2012 at 5:08 PM, Richard Lynch c...@l-i-e.com wrote:

 On Tue, March 6, 2012 3:30 am, Florian Anderiasch wrote:

 Security by blacklist almost always isn't security...

 You're bound to miss one of the functions you should have blacklisted,
  but didn't.


Agreed. The approach I'm developing would be a whitelisting approach.


 Something like Drupal would be crippled by this because major
 extensions used by all rely on access that would probably want to be
 blocked.

 So then they'd have to come up with a blessed list of extension to
 not block, and then...


The idea would be to make it easy to add to the default whitelist per
include.

Nice idea, in the abstract, but I don't think it will work out to be
 very useful in the Real World (tm).


I'm working on documenting the ideas and refining the approach. I think it
will hold significant value, but a few years ago I also thought that WebOS
would become a major player in the mobile market :)

Adam

P.S. - Thankful to see that your recent update on your medical prognosis,
Richard.


Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-07 Thread Ángel González
On 07/03/12 00:04, Adam Jon Richardson wrote:
 It would be the responsibility of the framework or CMS or application
 to protect against this type of attack (which they do quite well.)
 When you can force a plugin to work through your API, you can take
 appropriate measures. When the plugin can avoid working through, say,
 a file API that protects against misuse by using the internal file
 functions, this is a much more difficult issue to mitigate.
The key point is precisely, how do you ensure they can only call your API?


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread Florian Anderiasch
Hi,
On 03/06/2012 08:34 AM, Adam Jon Richardson wrote:
[...]
 1) Internal functions seen as universally safe would by default be allowed
 (e.g, str_replace(), array_pop(), etc.)
 2) Unsafe internal functions would have to be explicitly declared (e.g.,
 file(), stream_*, etc.)
 3) Any includes or requires within the sandboxed code would be forced to
 meet the same restrictions. (tricky)
 4) Code containing unsafe functions not included in the whitelist would
 raise an error.
[...]
 Thoughts?

Isn't that basically what all template engines tried to solve before
with giving you a defined subset of tokens that are more or less
directly converted to php code? The benefit I see is that plugin
developers wouldn't need to learn a new DSL (domain-specific language),
but use PHP code. Just that it's not PHP if you disable 90% of the
functions available.

While the idea is certainly not bad, I'm not sure you could write
sensible plugins for applications with only a few string functions at
hand. My gut instinct tells me you'll run into something like I wish I
had this dir() to get the files in this directory more sooner than
later. Last plugin (for Drupal) I wrote for example hooked into the File
API and saves/retrieves uploads to/from MogileFS. So that's file access
AND network access, and those would quite probably the first on the list
to be blacklisted. And if you only blacklist a few, disable_functions
might be enough.

To sum it up, to solve this problem I'd be more thinking about creating
a specific DSL (like puppet) to fill my needs and not try to make people
write some sort of 50%-PHP with constant lookup which functions are
allowed and which are not.

Greetings,
Florian

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread Stas Malyshev

Hi!


Thoughts?


This is a fine idea, however actually doing it is not that easy. Note 
that knowing which function is safe is pretty hard, but that's only a 
start. Plugin code, for example, can call functions outside plugin 
context, while passing all kinds of arguments - is it safe or not? It 
depends on the context - e.g. plugin may need access to the database - 
directly or through some API - but that opens the door to various SQL 
injections and other mischief, etc. etc.
So while the idea is fine, designing a working sandbox is a very 
complicated task. That said, if you have any ideas - you're welcome to 
propose.

--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread Adam Jon Richardson
On Tue, Mar 6, 2012 at 3:30 AM, Florian Anderiasch flor...@anderiasch.dewrote:

 Isn't that basically what all template engines tried to solve before
 with giving you a defined subset of tokens that are more or less
 directly converted to php code? The benefit I see is that plugin
 developers wouldn't need to learn a new DSL (domain-specific language),
 but use PHP code. Just that it's not PHP if you disable 90% of the
 functions available.


I agree, many template engines do offer a controlled set of language
constructs that limit the attack surface. However, DSL's tend to be focused
on one specific problem area (such as templating, as you noted) as opposed
to providing general programming capabilities, so building plugins in a DSL
can be quite limiting in terms of potential power:

http://martinfowler.com/bliki/DomainSpecificLanguage.html

As another option, one could always develop a full-fledge programming
language that compiles down to PHP (similar to CoffeeScript's compiling to
JavaScript.) One can then use the language to abstract away calls to
functions deemed unsafe without explicit permission. However, this requires
learning a new programming language and would require the consumer of the
script to perform compilation to ensure the security.

I'm not sure how many functions would be disabled, but I estimate it's a
much lower number than 90%. For instance, if a function is pure (i.e., has
no side effects), that function would be considered safe. That said, I'll
start sifting this list of functions and see what list I come up with:

http://php.net/quickref.php


 While the idea is certainly not bad, I'm not sure you could write
 sensible plugins for applications with only a few string functions at
 hand. My gut instinct tells me you'll run into something like I wish I
 had this dir() to get the files in this directory more sooner than
 later. Last plugin (for Drupal) I wrote for example hooked into the File
 API and saves/retrieves uploads to/from MogileFS. So that's file access
 AND network access, and those would quite probably the first on the list
 to be blacklisted. And if you only blacklist a few, disable_functions
 might be enough.


Valid points. Your Drupal plugin example could use several of the functions
initially blacklisted. However, the developer would then be able to, upon
reading the documentation and requirements for your plugin OR seeing the
error raised when attempting to sandbox your script, make an informed
decision as to how much they trust you, the provider of the script, and,
whether the perceived risk is worth the value. If the value is enough, the
developer would then be able to add the needed functions to the whitelist
and run your plugin.

Of note, the sandbox I'm suggesting would only impact internal functions
within files included with the sandboxing function. If Drupal, for example,
offered a file API and made it available to your plugin through the scoping
rules inherent in the application, you would be able to call those
functions without issue. The sandboxing would only limit direct calls to
unsafe, internal functions. The idea is to limit the access to the
environment that the framework or CMS can't properly limit. They can
already limit access to their environment through the API, and this
proposal would trust them to do that.

The disable_functions directive is indeed very handy, but it forces you to
give up the functions throughout the entire environment, whereas the
sandboxing would be limited to the scope of specific includes.
Additionally, shared host environments don't allow you to adjust this
setting.

To sum it up, to solve this problem I'd be more thinking about creating
 a specific DSL (like puppet) to fill my needs and not try to make people
 write some sort of 50%-PHP with constant lookup which functions are
 allowed and which are not.


The hope would be that you wouldn't have to constantly look up the
functions that are allowed. Rather, you'd use the functions you need and
the consumer of your plugin would decide if your plugin merited trusting
you with the unsafe internal functions you used. While the consumer might
not be able to audit every plugin they use, the sandboxing would bring to
light the plugins that needed extra attention and caution.

Excellent feedback, Florain. Thanks!

Adam


Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread Adam Jon Richardson
On Tue, Mar 6, 2012 at 4:38 AM, Stas Malyshev smalys...@sugarcrm.comwrote:

 Hi!

  Thoughts?


 This is a fine idea, however actually doing it is not that easy. Note that
 knowing which function is safe is pretty hard, but that's only a start.
 Plugin code, for example, can call functions outside plugin context, while
 passing all kinds of arguments - is it safe or not? It depends on the
 context - e.g. plugin may need access to the database - directly or through
 some API - but that opens the door to various SQL injections and other
 mischief, etc. etc.
 So while the idea is fine, designing a working sandbox is a very
 complicated task. That said, if you have any ideas - you're welcome to
 propose.


The sandbox I'm considering would only impact the ability to directly call
internal functions. The idea rests on the hope that the framework or CMS
provides a security model that protects the integrity of their own
environment. The framework can for example hand off whatever state
variables are deemed appropriate and necessary to a plugin. The framework
can make public whatever methods are appropriate and necessary. However,
the framework can't currently limit the direct calls to internal functions
(without parsing the PHP source and it's dependencies), which could allow
the plugin developer to circumvent the security policies of the framework.

Indeed, the complexity is extreme, even for the limited scope of this idea.
And, avoiding complexity for the developers using the sandboxed version
would be difficult, too.

I'm wondering if it would be easier to allow constants representing entire
classes of functionality. For example:

include_restricted('file/path', $whitelist = array('SANDBOX_FILE',
'SANDBOX_PDO', 'SANDBOX_MYSQL', 'SANDBOX_SOCKET'));

If an error was raised because an included file required additional access,
the error message could detail the exact constant(s) that would have to be
whitelisted for the include to be allowed.

Thank you for the feedback, Stas. The questions and concerns raised in this
discussion help considerably.

Adam


RE: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread John Crenshaw
 Hi!

  Thoughts?


 This is a fine idea, however actually doing it is not that easy. Note 
 that knowing which function is safe is pretty hard, but that's only a 
 start.
 Plugin code, for example, can call functions outside plugin context, 
 while passing all kinds of arguments - is it safe or not? It depends 
 on the context - e.g. plugin may need access to the database - 
 directly or through some API - but that opens the door to various SQL 
 injections and other mischief, etc. etc.
 So while the idea is fine, designing a working sandbox is a very 
 complicated task. That said, if you have any ideas - you're welcome to 
 propose.


 The sandbox I'm considering would only impact the ability to directly call
 internal functions. The idea rests on the hope that the framework or CMS
 provides a security model that protects the integrity of their own
 environment. The framework can for example hand off whatever state
 variables are deemed appropriate and necessary to a plugin. The framework
 can make public whatever methods are appropriate and necessary. However,
 the framework can't currently limit the direct calls to internal functions
 (without parsing the PHP source and it's dependencies), which could allow
 the plugin developer to circumvent the security policies of the framework.

 Indeed, the complexity is extreme, even for the limited scope of this idea.
 And, avoiding complexity for the developers using the sandboxed version
 would be difficult, too.

 I'm wondering if it would be easier to allow constants representing entire
 classes of functionality. For example:

 include_restricted('file/path', $whitelist = array('SANDBOX_FILE',
 'SANDBOX_PDO', 'SANDBOX_MYSQL', 'SANDBOX_SOCKET'));

 If an error was raised because an included file required additional access,
 the error message could detail the exact constant(s) that would have to be
 whitelisted for the include to be allowed.

 Thank you for the feedback, Stas. The questions and concerns raised in this
 discussion help considerably.

 Adam

I've seen a simple safe code evaluator put together using token_get_all. I'm 
certain that you could create an include_restricted() function in userland 
using a similar system: walk through the tokens looking for anything forbidden 
(this will be tricky, because there are a lot of nooks that things could hide, 
like superglobals), then if everything looks good include the file. Use a 
caching system of some sort to improve performance and eliminate redundant 
checks.

I seriously doubt that this would ever get implemented in the core though. PHP 
has been moving away from this sort of thing (and for good reason). Attempting 
a one size fits all sandbox in the core just doesn't make any sense.

John Crenshaw
Priacta, Inc.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread Rasmus Lerdorf
On 03/06/2012 06:03 AM, John Crenshaw wrote:
 I've seen a simple safe code evaluator put together using token_get_all. 
 I'm certain that you could create an include_restricted() function in 
 userland using a similar system: walk through the tokens looking for anything 
 forbidden (this will be tricky, because there are a lot of nooks that things 
 could hide, like superglobals), then if everything looks good include the 
 file. Use a caching system of some sort to improve performance and eliminate 
 redundant checks.

Yeah, a token approach wouldn't work. $a = 'mysql_connect'; $a($args);
trivially circumvents that. It would have to build new function/class
hashtables directly which is rather expensive so from a performance
perspective this would not be pretty. I suppose an opcode cache could
cache these to speed this up quite a bit, but there would still need to
be extra gear in place to manage multiple hash tables and some code to
check if there was an overriding hash to be used for every op_array.

-Rasmus

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread Ángel González
On 06/03/12 14:04, Adam Jon Richardson wrote:
 The sandbox I'm considering would only impact the ability to directly call
 internal functions. The idea rests on the hope that the framework or CMS
 provides a security model that protects the integrity of their own
 environment. The framework can for example hand off whatever state
 variables are deemed appropriate and necessary to a plugin. The framework
 can make public whatever methods are appropriate and necessary. However,
 the framework can't currently limit the direct calls to internal functions
 (without parsing the PHP source and it's dependencies), which could allow
 the plugin developer to circumvent the security policies of the framework.

 Indeed, the complexity is extreme, even for the limited scope of this idea.
 And, avoiding complexity for the developers using the sandboxed version
 would be difficult, too.

 I'm wondering if it would be easier to allow constants representing entire
 classes of functionality. For example:

 include_restricted('file/path', $whitelist = array('SANDBOX_FILE',
 'SANDBOX_PDO', 'SANDBOX_MYSQL', 'SANDBOX_SOCKET'));

 If an error was raised because an included file required additional access,
 the error message could detail the exact constant(s) that would have to be
 whitelisted for the include to be allowed.

 Thank you for the feedback, Stas. The questions and concerns raised in this
 discussion help considerably.

 Adam
It's not that easy. The internal functions could be splitted to
safe/unsafe (according
tosome definition, which would itself be a controversial one) but all
functions defined
outside would be injection candidates, too. Suppose you modified the
function
hash table to store if it's a limited function or it should be run with
high privileges.
Now, you need to audit the whole framework so that no can be tricked
into doing more
things than it should, if called from low-privilege code.
Which is pretty hard when that code could be corrupting your variables.
For instance, a safe framework function to perform database queries,
could become
unsafe by changing the db configuration (usually stored on globals),
allowing connections
to arbitrary servers.
Or a malicious plugin could register a class with the same name as a
framework one, before
the autoloader loads the right one, and have it used by privileged code.

PHP is not designed to use it that way, so unless there is an high level
way to do it, it's probably
impossible to do right. Maybe you can perform a full global replacement
when calling
untrusted code. That might work.


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-06 Thread Adam Jon Richardson
2012/3/6 Ángel González keis...@gmail.com

 On 06/03/12 14:04, Adam Jon Richardson wrote:
  The sandbox I'm considering would only impact the ability to directly
 call...
 It's not that easy. The internal functions could be splitted to
 safe/unsafe (according
 tosome definition, which would itself be a controversial one)


Yes, perhaps controversial, but using an objective criterion like purity
would aid the effort.


 but all
 functions defined
 outside would be injection candidates, too.


The idea I put forth would only deal with internal functions. Frameworks
and CMS's would still be on-the-hook to validate incoming data and escape
data according to context for all of the functions that they expose to the
plugin/library. And this would still be very beneficial. As framework
developer, I can validate the inputs coming into my API hooks and escape
the outputs according to context. However, when plugin developers can call
the internal functions and circumvent my protections, this is a more
difficult issue to solve en masse.


 Suppose you modified the
 function
 hash table to store if it's a limited function or it should be run with
 high privileges.


I'm not promoting a privilege-based system of high and low privileges.
Rather, I'm posing the possibility of limiting the access of included code
to internal functions/objects.


 Now, you need to audit the whole framework so that no can be tricked
 into doing more
 things than it should, if called from low-privilege code.
 Which is pretty hard when that code could be corrupting your variables.
 For instance, a safe framework function to perform database queries,
 could become
 unsafe by changing the db configuration (usually stored on globals),
 allowing connections
 to arbitrary servers.


It would be the responsibility of the framework or CMS or application to
protect against this type of attack (which they do quite well.) When you
can force a plugin to work through your API, you can take appropriate
measures. When the plugin can avoid working through, say, a file API that
protects against misuse by using the internal file functions, this is a
much more difficult issue to mitigate.


 Or a malicious plugin could register a class with the same name as a
 framework one, before
 the autoloader loads the right one, and have it used by privileged code.

 PHP is not designed to use it that way, so unless there is an high level
 way to do it, it's probably
 impossible to do right. Maybe you can perform a full global replacement
 when calling
 untrusted code. That might work.


Javascript wasn't designed this way, either. However, tools like Secure
EcmaScript go a long way towards protecting against the attacks mashups
typically must prevent by protecting/limiting the environment:

http://code.google.com/p/es-lab/wiki/SecureEcmaScript
http://www.infoq.com/presentations/Secure-Mashups-in-ECMAScript-5

Thanks for the feedback, Angel.

Adam


[PHP-DEV] Providing sandboxed versions of include and require language constructs

2012-03-05 Thread Adam Jon Richardson
Plugins are a big deal (see
http://oneofmanyworlds.blogspot.in/2012/03/difficult-decision.html for a
recent example.) In this era of mashups and breakneck innovation,
developers must rely on vast amounts of code they've never seen, let alone
audited. Wordpress, Drupal, and many other tools developed in PHP make
plugin development easy and extremely powerful. While these tools
constantly work to improve security (and, at least relatively, do a solid
job most of the time), there remains significant challenges due to globally
accessible functions that allow manipulation of the environment (files,
DB's, networking, etc.) Any plugin can use these global functions to work
around the security restrictions imposed by the framework, library, or CMS.

While code audits can locate the offending scripts, this is a challenging
task, both in terms of time AND abilities. Languages and/or environments
that can mitigate these issues for the developer, while far from fool
proof, do offer real value on the security front. Lua provides the ability
for developers to limit the functions available in the current environment:
http://lua-users.org/wiki/SandBoxes

PHP does have an extension that offers several forms of sandboxing: runkit.
However, it's often not available in shared host environments.

The include (and require) construct is the front door for any plugin code.
What if PHP offered functions that implemented sandboxed versions of the
include and require language constructs (e.g.,
included_restricted('file/path', $functions = array('file',
'file_get_contents')))? Functional specs could include:

1) Internal functions seen as universally safe would by default be allowed
(e.g, str_replace(), array_pop(), etc.)
2) Unsafe internal functions would have to be explicitly declared (e.g.,
file(), stream_*, etc.)
3) Any includes or requires within the sandboxed code would be forced to
meet the same restrictions. (tricky)
4) Code containing unsafe functions not included in the whitelist would
raise an error.

There would be a performance hit for code that actually used the sandboxed
functions to include scripts, but for many applications, I suspect this
would be worth the hit. Security is becoming more important by the day
(just ask github: http://homakov.blogspot.com/2012/03/how-to.html#), and
empowering the developer with tools to enforce greater restrictions on the
ever-growing heaps of unaudited code seems wise.

Thoughts?

Adam