Sandboxing Mongo->execute(MongoCode) in PHP to prevent any DB interaction - php

As a feature in the software I'm writing, I'm allowing myself to create calculators written in JS to compute the fees to be applied to a specific set of data, using said data as a reference. Since I'm using Mongo, I can run this safely server-side, and the browser can just call a php page and get the response. The function will be written from an administration control panel and saved to the database. I of course won't be doing any db interactions from inside that function, but executing mongocode is done within the database, so mongocode by nature can do db.foo
Just to protect myself and anyone else who might end up writing calculators, I've set db = null; in $context being passed to new MongoCode()
It looks a bit like this:
$sample = [
'estimatedvalue' => 200,
'estimatedcost' => 400,
'contractor' => false,
'db' => null,
];
$fees = [
'_id' => new MongoId(),
'name' => 'Friendly name!',
'code' => new MongoCode('function(){return (contractor ? estimatedCost : estimatedValue)*0.01; /* If a contractor is doing the work, base fee on cost. */}', $sample),
];
$a = $this->siteDB->execute($fees['code']);
if(isset($a['errno'])){
echo $a['errmsg'];
}else{
var_dump($a['retval']);
}
Fortunately, that works, and if I was to inject that into all context, there would be no db. commands runnable. I don't want to create a point where NoSQL injection can happen!
An example of something that this prevents is:
'code' => new MongoCode('function(){db.foo.remove();}', $sample),
// Since db is now null, the above won't work
My concern: Are there any other variables that exist in this MongoCode Execute environment that could be potentially harmful to leave in a user-editable function? I couldn't find any documentation on what else is accessible through mongocode functions. If db is it, then I'm all set!

This is not safe, and I don't think you can have a user-editable JS function that is. For example, this requires no variables and shuts down your server:
> db.eval("(new Mongo('localhost:27017')).getDB('admin').shutdownServer()")
They can insert data, drop databases, connect to other servers in your system, and generally wreck havoc.
If you are trying to allow a user-editable compute function in JavaScript, use a separate JS engine, pull the values from MongoDB, and pass the values + user-defined function to the totally separate JS engine.

Related

Putting more coding logic in array/json vs. class method calls

When working with PHP, I notice it's popular nowadays for class libraries to use lots of "prep" method calls that build up to an action. E.g.:
$db = new database();
$result = $db->select("*")
->from("table1")
->where(["field3" => "apple"])
->orderBy("field4")
->run();
I can see the benefits this gives you when using an IDE with autocomplete. But I also see advantages to putting this information into one array that gets passed at once. E.g.:
$queryParams = [
"fields" => "*",
"table" => "table1",
"constraint" => ["field3" => "apple"],
"sort" => "field4",
];
$db = new database();
$result = $db->select($queryParams);
The advantage I see is that the information is treated as one unit and is easy to pass around. It could be stored as JSON in a file or table, unserialized, and with one statement the information gets processed. Also, it's less intermingled with PHP code; if I want to convert my project from one language/framework to another, if a good part of the information that makes up my project is already in compatible JSON, then it will be easier for me to do so.
I understand that I could easily write up my own code that iterates over $queryParams and passes the values to the proper method calls, but I am curious why passing all the information a class needs to run an action at once is not good practice.

In Laravel, how can I add items to array in controller and then process after response via App::finish()

I am creating an analytics storage process (using elastic search) where I need to add the items to be stored in elastic from my controller. But then I want to wait until after the response has been sent to the user to actually do the processing. I don't want the user to have to wait for this process to complete before getting the server response.
I am planning on running the processing part using:
App::finish(function(){
// DO THE PROCESSING
})
I know that this will run after the response has been sent. However, I am not sure how to get the data which has been compiled in a controller (or any class) to be referenced in the App::finish() closure method.
I have tried using App::singleton() but there are many instances where I need to be able to continually 'set' the data, I can't just set it once. I guess I am essentially looking for a global variable that I can manipulate but I know that doesn't exist in Laravel.
Another option is to use Session::push() and Session::get() but right now I have my Session storage using memcached for this app and I would rather not do additional I/O on memcached when I could just be storing the data needed to be saved in temporary memory.
Seems like I just need a simple container to write to and read from which is saved only in memory but I cannot find that in the Laravel docs.
You might be able to use the __destruct() magic method on whichever controllers you need to do the processing on.
You could also potentially implement it in BaseController as well if it should run for all controllers.
Another option would be to use sqlite in memory. Simply create a new connection
'sqlite_memory' => array(
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
),
Then you can use DB::connection('sqlite_memory') to use that connection and store/save whatever you need using the query builder.
You can pass data to the closure using "use".
In PHP 5.3.0, what is the function "use" identifier?
I ended up using something like this for storing data in the cache after returning the data to the user.
App::finish(function($request, $response) use ($id, $json){
Cache::put('key_'.$id, $json, 1440);
});

How to test the interaction with the database PHPUnit?

To test the PHP code I am using PHPUnit.
Presently engaged in writing of the application architecture, while using the template Data Mapper. Accordingly, most of the tests should be reduced to the verification code interaction with the database. CRUD operations with an entity, etc. I think there should be checked directly on the database, and not replaced by a stub objects. Is testing the interaction with the database module? And how to conduct this test. Whether to use DBUnit. how? I ask not that you can read in the documentation, and specifically about the best solutions that come with experience. Thank you!
protected function update($obj) {
$values = array(":id" => $obj->getId(),
":title" => $obj->getTitle(),
":path" => $obj->getPath(),
":type" => $obj->getType(),
":size" => $obj->getSize());
$this->updateStmt->execute($values);
}

PHP/JS Form Class - Array vs OO

I have recently begun working on a PHP/JS Form Class that will also include a SQL Form builder (eg. building simple forms from sql and auto inserts/updates).
I have tried several classes (zend_form, clonefish, PHP Form Builder Class, phorms etc) but as yet haven't come across a complete solution that is simple, customizable and complete (both server side and client side validation, covers all simple html elements and lots of dhtml elements: sorting, wysiwyg, mutli file upload, date picker, ajax validation etc)
My question is why do some "classes" implement elements via an array and others via proper OO class calls.
eg.
Clonefish (popular commercial php class):
$config = Array(
'username' => Array(
'type' => 'inputText',
'displayname' => 'Username',
validation => Array(
Array(
'type' => 'string',
'minimum' => 5,
'maximum' => 15,
),
),
));
$clonefish = new clonefish( 'loginform', 'test.php', 'POST' );
$clonefish->addElements( $config, $_POST );
Then others eg. Zend_Form
$form = new Zend_Form;
$username = new Zend_Form_Element_Text('username');
$username->addValidator(new Zend_Validate_Alnum());
$form->addElement($username);
I realise Zend_Form can pass elements in via an array similar to clonefish but why do this?
Is there any benefit? It seems to make things more complicated especially when using a proper IDE like Komodo.
Any thoughts would be appreciated as I dont want to get too far down the track and realize there was great benefit in using arrays to add elements (although this wouldn't be much of a task to add on).
Cheers
My question is why do some "classes" implement elements via an array and others via proper OO class calls.
For convenience. It's less verbose and it feels less like coding and more like configuration and you need less intimate knowledge of the API.
Btw, the reason you have not yet come across a complete solution that is simple, customizable and complete is because it is not simple. Forms, their validation and rendering is complex, especially if you want to have it customizable for any purpose. ZF's form components are a good example of how to properly decouple and separate all concerns to get the ultimate extensible form builder (including client side code through Zend_Dojo or ZendX_Jquery). But they are also a great example of the complexity required for this. Even with the convenient array configuration, it is damn difficult to make them bend to your will, especially if you need to depart from the default configuration and rendering.
Why to use objects? Becouase they are a much more complex types. Consider the following example (I never useed Zend_Form so I don't even know its architecture):
class MySuperAlnumValidator extends Zend_Validate_Alnum {
protected $forbiddenWords = array();
public function addForbiddenWord($word) {
$this->forbiddenWords[] = $word;
}
// Override Zend_Value_Alnum::validate() - I don't know whether such a method even exists
// but you know what's the point
public function validate() {
parent::validate();
if (in_array($this->value, $this->forbiddenWords) {
throw new Exception('Invalid value.');
}
return $this->value;
}
}
// -----------------------
$validator = new MySuperAlnumValidator();
$validator->addForbiddenWord('admin');
$validator->addForbiddenWord('administrator');
$username->addValidator($validator);
This is only a simple example but when you start writing more complex validators/form fields/etc. then objects are, in principle, the only meaningful tool.

Efficient way to handle multiple HTMLPurifier configs

I'm using HTMLPurifier in a current project and I'm not sure about the most efficient way to go about handling multiple configs. For the most part the only major thing changing is the allowed tags.
Currently I have a private method, in each class using HTMLPurifier, that gets called when a config is needed and it creates one from the default. I'm not really happy with this as if 2 classes are using the same config, that's duplicating code, and what if a class needs 2 configs? It just feels messy.
The one upside to it, is it's lazy in the sense that it's not creating anything until it's needed. The various classes could be used and never have to purify anything. So I don't want to be creating a bunch of config objects that might not even be used.
I just recently found out that you can create a new instance of HTMLPurifier and directly set config options like so:
$purifier = new HTMLPurifier();
$purifier->config->set('HTML.Allowed', '');
I'm not sure if that's bad form at all or not, and if it isn't I'm not really sure of a good way to put it to use.
My latest idea was to create a config handler class that would just return an HTMLPurifier config for use in subsequent purify calls. At some point it could probably be expanded to allow the setting of configs, but just from the start I figured they'd just be hardcoded and run a method parameter through a switch to grab the requested config. Perhaps I could just send the stored purifier instance as an argument and have the method directly set the config on it like shown above?
This to me seems the best of the few ways I thought of, though I'm not sure if such a task warrants me creating a class to handle it, and if so, if I'm handling it in the best way.
I'm not too familiar with the inner workings of HTMLPurifier so I'm not sure if there are any better mechanisms in place for handling multiple configs.
Thanks for any insight anyone can offer.
Configuration objects have one important invariant: after they've been used to perform a purification, they cannot be edited. You might be interested in some convenience methods that the class has, in particular, inherit, and you can load an array of values using loadArray.
I just wrote up a quick, simple config handler class.
You can view / use it # http://gist.github.com/358187/
It takes an array of configs at initialization.
$configs = array(
'HTML.Doctype' => 'HTML 4.01 Strict',
'posts' => array(
'HTML.Allowed' => 'p,a[href],img[src]'
),
'comments' => array(
'HTML.Allowed' => 'p'
),
'default' => array(
'HTML.Allowed' => ''
)
);
Directives put directly into the array are global and will be applied to all configs. If the same directive is set inside a named config, the value in the named config will be used.
Then you can grab a config like so:
$purifierConfig = new purifierConfig($configs);
$commentsConfig = $purifierConfig->getConfig('comments');
or, shorthand:
$commentsConfig = $purifierConfig['comments'];
If the requested config does not exist or no config is specified in the call, the default config will be returned.
I'll probably flesh it out at some point, but for now this works.
I was looking for how people handled such things in their projects or if there were any built in mechanisms that made something like this more steamlined, but I suppose my question was a bit too narrow in scope.

Categories