2

Someone knows a trick to have a PHP script self-restrict access to the file system (fopen, file_get_contents etc.)?

Such calls should be blocked except for a handful of selected file names (log file, access to /tmp and similar).

This is not a security thing, but rather a means of forcing the development team not to access the file system directly (and detect spots in existing code, where this is already the case). We want to see an exception in that case (which gets caught and reported), as the content of such files must be accessed by other means.

I was thinking about implementing my own streamWrapper for the file:// protocol, but apparently there is no way to extend the built-in filewrapper class.

Udo G
  • 12,572
  • 13
  • 56
  • 89
  • Does it have to be runtime? You can regularly check the source code, or even each commit, if it contains these restricted functions (except the one wrapper class). – Marek Nov 19 '14 at 16:05
  • 1
    I would do it on the file system level. – Gumbo Nov 19 '14 at 16:16
  • @Marek: the code base is too large to check it manually and static code analysis would probably be overkill to implement in this case. I need to restrict only certain scripts of a large project. Other scripts running as the same user still need to access the files directly. – Udo G Nov 19 '14 at 17:12
  • @UdoG As you say, you need to restrict only certain scripts, so you need to check only those. I didn't mean manually, but simple `grep` will do. – Marek Nov 19 '14 at 17:28
  • @Marek: I understand, but the project is too big/complicated for a simple `grep`. – Udo G Nov 20 '14 at 08:30

2 Answers2

2

Option #1

You can use open_basedir which is a php.ini directive to limit the directories the app has access too. The directories can be semicolon separated so you can just list the directories you want the app to access including the /tmp folder.

The caveat is that this also affects things like include, require.

Option #2

You could rename them using rename_function or runkit_function_rename and then wrap the renamed versions with your own logic.

Quote from the documentation:

Renames a orig_name to new_name in the global function table. Useful for temporarily overriding built-in functions.

Example:

rename_function('file_get_contents', 'nouse_file_get_contents');

function file_get_contents($filename, $use_include_path = false, $context, $offset = -1, $maxlen) {
    //
    // Do some validation here
    //
    return nouse_file_get_contents($filename, $use_include_path, $context, $offset, $maxlen);
}

Option #3

You could setup some coding standards for your devs and write some unit tests that run as part of the deployment before things are pushed to production. Not sure what your release procedures are but these types of things should be caught before production.

Marc Seiler
  • 494
  • 4
  • 15
  • Sounds good, if it wouldn't require to add a debugger to a production system.. :-/ – Udo G Nov 20 '14 at 08:31
  • What? There is no need for a debugger? I have added an example to my suggestion. – Marc Seiler Nov 20 '14 at 13:58
  • I understand your suggestion, however I'm uncomfortable using APD as it is in fact not installed/used at the moment. Further, the manual states `Caution -- APD is a Zend Extension, modifying the way the internals of PHP handle function calls, and thus may or may not be compatible with other Zend Extensions (for example Zend Optimizer).` – Udo G Nov 26 '14 at 16:41
  • 1
    I think you may have restricted your self down to very little options. If you can't modify the functions to work as you please then you can maybe make your own and enforce the usage through deployment testing to see if those methods (like file_get_contents) are used instead of whatever wrappers you make. This will catch any abuse before production. – Marc Seiler Nov 26 '14 at 16:46
  • I found a similar, IMHO better solution. The [runkit_function_rename](http://php.net/manual/en/function.runkit-function-rename.php) function allows to do the same, but comes from Runkit, a currently maintained extension without any debugger stuff. APD won't even build for PHP 5.4+ without patches. Accepting your soution as in the end it's the best approach. – Udo G Nov 26 '14 at 20:27
  • I added runkit_function_rename with a link to option 2. Thanks for pointing it out. – Marc Seiler Nov 26 '14 at 21:06
1

you could of course have everybody develop run php as a user which has only access to the files you want. but this is an OS level solution.

timwaagh
  • 303
  • 3
  • 14