Greetings to the habrasoobschestvu.
Imagine? that you are developing a product in which there is a system of modules. Modules can be written by third-party developers. Next, you load the modules into the system and run the code.
In this situation, the question often arises - how can you limit the possibilities of the code being run?
We all remember the stories with hidden miners that were added to the open source dependencies library.
')
How to protect your product from a module that simply makes a request to the database and uploads the archive to any ftp server.
If you are not Apple, Google, etc. and you do not have a staff of moderators who will moderate the loadable modules. Perhaps a solution under the cat will make your life easier.
At once I will make a reservation that at the moment this post is only an attempt to test the ground and gather the opinions of the community in order to understand whether it is worth digging further. The project is so far only a concept.
There is a global security problem in IT, due to the fact that PLs do not provide opportunities at the language level to control privilege levels as various operating systems do. To some extent, we can use these features, for example, to change file permissions, to allow the prohibition of opening ports, to configure the firewall. But this is not always convenient. There is no possibility to divide the code of your product into system and user (by analogy with kernel and userspace).
The idea is to make some kind of ACL for the poor until the respected language developers introduce such features into the language itself.
It is based on a beautiful
uopz extension. Thank you guys for the great work. PHP 7 is currently supported. (7.1 and something like 7.2)
It allows us to override the built-in PHP functions and very important class methods.
Using this, we can redefine all dangerous functions (access to filesystems, sockets, exec calls, proc_open, etc.), replace them with our own, so that on the basis of this we can make a set of rules by which we allow / reject this action.
I must say that functions such as require, include, etc. There is no possibility to override it. These are not functions at all. But about it a little lower.
This works in the following way. Calls of dangerous functions are redirected to a wrapper function, which creates an object containing information about the call, then this object is passed to the rules ACL array. If at least one rule returns true, the action is allowed (passed to the native function). Otherwise, an error occurs.
Initialization code is pretty simple. At the entry point we write.
$acl = \PhpAcl\ACLComponent::getInstance(); $acl->init(require_once __DIR__ . '/../app/config/acl.php');
The config file for a project on a symphony can have the following form:
<?php use PhpAcl\IOOperation; define('ROOT_DIR', realpath(__DIR__ . '/../../../code')); return [ 'io' => [ 'enabled' => true, 'rules' => [
In this configuration, an attempt to write / read / open a file from a third-party code, even yours, will result in an error.
Currently not many features are supported. If the comments do not reveal a clear lack of such an approach, it will not be difficult to outline the remaining functions.
About
require and their ilk. Unfortunately, it is impossible to win in this way. An evil hacker can still connect your configs file and display it directly in the browser.
But since this is
a language construct , we cannot call it indirectly, by hiding the name in variables, etc.
We cannot write something like:
$_req = 'require'; $_req('/app/config/config.yml');
So we can go over the source and just find these dangerous challenges and take action.
Perhaps this functionality should be added to this project.
The issue with the database can be solved in a similar way. It is possible for plugins to provide the ability to work only on behalf of a specific database user, by prohibiting from an ACL to receive a link to the full connection to the database. For example, in the doctrine, we can create several EntityManager and, through the ACL, prohibit third-party code methods that will allow it to get the default EntityManager with extended rights.
The source code can be viewed
on github .
I think I managed to bring the main idea. Hopefully in the comments get your feedback.