How Can eval() in This Code Be Not Secure? - php

I'm using the code below to automatically load and declare classes so that I only need to put class files in a folder named classes. The part in spl_autoload_regsister() may seem to be unnecessary for you but it is needed to work as a WordPress plugin without errors.
It uses eval() and I've seen so many web pages talking about using eval() is bad and can create a security hole. So how could this be dangerous?
$strDirPath = dirname(__FILE__) . '\\classes\\';
$arrClassFiles = array_map(create_function( '$a', 'return basename($a, ".php");' ), glob($strDirPath . '*.php'));
spl_autoload_register(
create_function('$class_name', '
global $arrClassFiles, $strDirPath;
if (in_array($class_name, $arrClassFiles))
include($strDirPath . $class_name . ".php");' )
);
foreach ($arrClassFiles as $strClassName) {
$strClassName_alpha = $strClassName . "_Alpha";
eval("class $strClassName_alpha extends $strClassName {};");
}
print_r(get_declared_classes());
Maybe, somebody can put a file name of php code in the folder? But I don't see it can compromise the system.

If they can name a class file something like randomclass {}; echo $db_password;//.php, then you could have a code execution attack.
I'm pretty sure that's not a valid file name, but there are people far wilier than me at crafting valid malicious inputs.
It's just usually not an attack surface you need to open yourself up to, given that it's practically always possible to avoid with better code structure.

If an error condition is handled, I don't see a problem here.
Just be sure that if someone tries to call a different class that does exist (i.e. code that would be valid here, but that you wouldn't want your hacker to run directly because it would bypass a restriction on your system), that it won't be a security problem - or that it wouldn't be possible to run that class at all from this context.
Just in case, deny any attempts to run code with the words "class," or other keywords, or any built in class names, or built in function names, other builtins, etc. and you should be fine, but even that probably isn't necessary in your particular case here because would probably result in an error.

Related

unrequire a file once it's been required in PHP

Suppose I do
require('lol.php');
whereby lol.php contains the following function declaration
function lolfunc(){
}
is it possible to "unrequire" lol.php such that I can then require another file
require('lol2.php');
whereby lol2.php contains a function with the same name previously declared in lol.php:
function lolfunc(){
echo "this is lol2 biyotch";
}
and have lolfunc() be the one declared in lol2.php? eg if I call lolfunc() it'll echo "this is lol2 biyotch"??
My answer: don't do that.
Try to work with the original author to include the functions you need into a patched version of the old code and then use that patched version everywhere.
If you can't do that, find out how big a job it would actually be to update all the code to new version. Start with white-box analysis: see what's changed in terms of interfaces, data structures et al. Then examine the calling code to see whether the caller cares about any of the things that have changed.
If you can't even do that, use namespacing or some other form of wrapping so that you can include both libs. However, make sure any initialisaton or setup is done on both libs!
What you should do, is to include the required (sets) of files based on conditional clauses, instead of trying to "unrequire".
So:
if($flag_use_oldver)
{
include("oldver.php");
}
else
{
include("newver.php");
}
If you want a more sophisticated solution, of course you could try to have a wrapper class hierarchy that will extend/override as required, but I think that is a bit over-engineering for a pretty straightforward problem statement.

Reloading a Class

I have a PHP daemon script running on the command line that can be connected to via telnet etc and be fed commands.
What it does with the command is based on what modules are loaded, which is currently done at the start. (psuedocode below for brevity)
$modules = LoadModules();
StartConnection();
while(true){
ListenForCommands();
}
function LoadModules(){
$modules = Array();
$dir = scandir("modules");
foreach($dir as $folder){
include("modules/".$folder."/".$folder.".php");
$modules[$folder] = new $folder;
}
}
function ListenForCommands(){
if(($command = GetData())!==false){
if(isset($modules[$command])){
$modules[$command]->run();
}
}
}
So, an example module called "bustimes" would be a class called bustimes, living in /modules/bustimes/bustimes.php
This works fine. However, I'd like to make it so modules can be updated on the fly, so as part of ListenForCommands it looks at the filemtime of the module, works out if it's changed, and if so, effectively reloads the class.
This is where the problem comes in, obviously if I include the class file again, it'll error as the class already exists.
All of the ideas I have of how to get around this problem so far are pretty sick and I'd like to avoid doing.
I have a few potential solutions so far, but I'm happy with none of them.
when a module updates, make it in a new namespace and point the reference there
I don't like this option, nor am I sure it can be done (as if I'm right, namespaces have to be defined at the top of the file? That's definitely workaroundable with a file_get_contents(), but I'd prefer to avoid it)
Parsing the PHP file then using runkit-method-redefine to redefine all of the methods.
Anything that involves that kind of parsing is a bad plan.
Instead of including the file, make a copy of the file with everything the same but str_replacing the class name to something with a rand() on the end or similar to make it unique.
Does anyone have any better ideas about how to either a) get around this problem or b) restructure the module system so this problem doesn't occur?
Any advice/ideas/constructive criticism would be extremely welcome!
You should probably load the files on demand in a forked process.
You receive a request
=> fork the main process, include the module and run it.
This will also allow you to run several commands at once, instead of having to wait for each one to run before launching the next.
Fork in php :
http://php.net/manual/en/function.pcntl-fork.php
Tricks with namespaces will fail if module uses external classes (with relative paths in namespace).
Trick with parsing is very dangerous - what if module should keep state? What if not only methods changed, but, for example, name of implemented interface? How it will affect other objects if they have link to instance of reloaded class?
I think #Kethryweryn is something you can try.

Getting CakeS3 to work in the CakeShell

I want to be able to call the CakeS3 plugin from the Cake Shell. However, as I understand it components cannot be loaded from the shell. I have read this post outlining strategies for overcoming it: using components in Cakephp 2+ Shell - however, I have had no success. The CakeS3 code here is similar to perfectly functioning cake S3 code in the rest of my app.
<?php
App::uses('Folder','Utility');
App::uses('File','Utility');
App::uses('CakeS3.CakeS3','Controller/Component');
class S3Shell extends AppShell {
public $uses = array('Upload', 'User', 'Comment');
public function main() {
$this->CakeS3 = new CakeS3.CakeS3(
array(
's3Key' => 'key',
's3Secret' => 'key',
'bucket' => 'bucket')
);
$this->out('Hello world.');
$this->CakeS3->permission('private');
$response = $this->CakeS3->putObject(WWW_ROOT . '/file.type' , 'file.type', $this->CakeS3->permission('private'));
if ($response == false){
echo "it failed";
} else {
echo "it worked";
}
}
This returns an error of "Fatal error: Class 'CakeS3' not found in /home/app/Console/Command/S3Shell.php. The main reason I am trying to get this to work is so I can automate some uploads with a cron. Of course, if there is a better way, I am all ears.
Forgive me this "advertising"... ;) but my plugin is probably better written and has a better architecture than this CakeS3 plugin if it is using a component which should be a model or behaviour task. Also it was made for exactly the use case you have. Plus it supports a few more storage systems than only S3.
You could do that for example in your shell:
StorageManager::adapter('S3')->write($key, StorageManager::adapter('Local')->read($key));
A file should be handled as an entity on its own that is associated to whatever it needs to be associated to. Every uploaded file (if you use or extend the models that come with the plugin, if not you have to take care of that) is stored as a single database entry that contains the name of the config that was used and some meta data for that file. If you do the line of code above in your shell you will have to keep record in the table if you want to access it this way later. Just check the examples in the readme.md out. You don't have to use the database table as a reference to your files but I really recommend the system the plugin implements.
Also, you might not be aware that WWW_ROOT is public accessible, so in the case you store sensitive data there it can be accessed publicly.
And finally in a shell you should not use echo but $this->out() for proper shell output.
I think the App:uses should look like:
App::uses('CakeS3', 'CakeS3.Controller/Component');
I'm the author of CakeS3, and no I'm afraid there is no "supported" way to do this as when we built this plugin, we didn't need to run uploads from shell and just needed a simple interface to S3 from our controllers. We then open sourced the plugin as a simple S3 connector.
If you'd like to have a go at modifying it to support shell access, I'd welcome a PR.
I don't have a particular road map for the plugin, so I've tagged your issue on github as an enhancement and will certainly consider it in future development, but I can't guarantee that it would fit your time requirements so that's why I mention you doing a PR.

JS Lexer to detect function calls

In order to localize strings used within my javascript, I want scan all my js files for such strings.
I am using a t() function to request string translations as follows:
t("Hello world");
or with dynamic portions:
t("Hello #user", {"#user": "d_inevitable"});
I want to detect all calls to the t() function and thus gather the strings contained in the first argument in a php "build" script, but skipping the following:
function foo(t) {
t("This is not the real t, do not localize this!");
}
function bar() {
var t = function(){}; //not the real t either...
}
function zoo() {
function t() {
//This also isn't the real t() function.
}
}
t("Translate this string, because this is the real t() in its global scope");
So the simple rule here is that the t function being invokes must be in global scope in order for the first argument to qualify as a translation string.
As a rule, dynamic runtime data as first argument is not allowed. The first argument to t() must always be a "constant" literal string.
I think php codesniffer will help me do it, however all the documentation I could find on it is about enforcing code standard (or detecting violations of it). I need lower level access to its js lexer.
My question is:
Would the php codesniffer's js lexer be able to help me solve my problem?
If so how do I access that lexer?
Are there any other php libs that could help me find the calls to t()?
Please do not suggest stand-alone regular expressions as they cannot possibly solve my problem in full.
Thank you in advance.
What you are describing is basically a coding standard. Certainly, ensuring strings are localised correctly is part of many project standards. So I think PHPCS is the right tool for you, but you will need to write a custom sniff for it because nothing exists to do exactly what you are after.
The best thing to do is probably clone the PHPCS Git repo from Github and then create a new directory under CodeSniffer/Standards to contain your custom sniff. Let's say you call it MyStandard. Make sure you create a Sniffs directory under it and then a subdirectory to house your new sniff. Take a look at the other standards in there to see how they work. You'll also find it easier to copy an existing ruleset.xml file from another standard and just change the cotent to suit you. if you don't want to include any other sniffs from anywhere (you just want to run this one check over your code) then you can just specify a name and description and leave the rest blank.
There is a basic tutorial that covers that.
Inside your sniff, you'll obviously want it to check JS files only, so make sure you specify that in the supportedTokenizers member var (also in the docs). This will ensure PHP and CSS files are always ignored.
When you get down to the actual checking, you'll have full low-level access to the parsed and tokenised content of your file. There are a lot of helper functions to check things like if the code inside other scopes, or to help you move backwards and forwards through the stack looking for bits of code you need.
TIP: run PHPCS using the -v option to see the token output on your file. It should help you see the structure more easily.
If you want to really do things properly, you can even create a nice unit test for your sniff to make sure it keeps running over time.
After all this, you'd check your code like this:
phpcs --standard=MyStandard /path/to/code
And you can use a lot of integrations that exist for PHPCS inside code editors.
You might decide to add a new more sniffs to the standard to check other things, which you can then do easily using your ruleset.xml file or by writing more custom sniff classes.
I hope that helps a bit. If you do decide to write your own sniff and need help, just let me know.

systematizing error codes for a web app in php?

I'm working on a class-based php web app. I have some places where objects are interacting, and I have certain situations where I'm using error codes to communicate to the end user -- typically when form values are missing or invalid. These are situations where exceptions are unwarranted ( and I'm not sure I could avoid the situations with exceptions anyways).
In one object, I have some 20 code numbers, each of which correspond to a user-facing message, and a admin/developer-facing message, so both parties know what's going on. Now that I've worked over the code several times, I find that it's difficult to quickly figure out what code numbers in the series I've already used, so I accidentally create conflicting code numbers. For instance, I just did that today with 12, 13, 14 and 15.
How can I better organize this so I don't create conflicting error codes? Should I create one singleton class, errorCodes, that has a master list of all error codes for all classes, systematizing them across the whole web app? Or should each object have its own set of error codes, when appropriate, and I just keep a list in the commentary of the object, to use and update that as I go along?
Edit: So I'm liking the suggestions to use constants or named constants within the class. That gives me a single place where I programatically define and keep track of error codes and their messages.
The next question: what kind of interface do I provide to the outside world for this class' error codes and messages? Do I do something like triggerError(20) in the class, and then provide a public method to return the error code, the string constant, and the user- and admin-facing message?
You could create a couple of defines to create named constants for all your error codes :
define('ERROR_CODE_SQL_QUERY', 1);
define('ERROR_CODE_PAGE_NOT_FOUND', 2);
define('ERROR_CODE_NOT_ALLOWED', 3);
// and so on
And, then, use the constants in your code :
if ($errorCode == ERROR_CODE_SQL_QUERY) {
// deal with SQL errors
}
With that, nowhere in your code you'll use the numerical value : everywhere (except in the on and only file where you put the defines), you'll use the codes.
It means :
Less risk of errors, as all numerical values are set in only one file
Less risk of errors, as you'll use the constants, that have a name which indicates what it means
And code that's easier to read.
Another idea could be to create a class to deal with errors :
class Error {
const CODE_SQL_QUERY = 1;
const CODE_PAGE_NOT_FOUND = 2;
const CODE_NOT_ALLOWED = 3;
// Add some methods here, if needed
}
And, then, use something like this :
if ($errorCode == Error::CODE_SQL_QUERY) {
// deal with SQL errors
}
Which one is the best ?
It's probably a matter of personnal preferences... If you need to add some methods to deal with the errors, using a class might be useful. Else, defines are a great solution too.
At the very least, can you bump the code numbers up to be class constants or members?
class MyErrorProneClass {
const TURNED_INTO_A_NEWT = 12;
...
public function dontBurnMe() {
// echo your error here using self::TURNED_INTO_A_NEWT
}
This way you can manage the errors in the same place where you use them, rather than having to maintenance a large central file. I tried something to that effect in the past and it becomes difficult to keep up.
Generating error numbers programmatically may be a better long-term solution. If you could use information about the file or line number (__FILE__ and __LINE__ respectively), that would help.
Hope that moves in the right direction at least.
Thanks, Joe
Edit:
A class member would follow this syntax instead:
class MyErrorProneClass {
protected static $turnedIntoANewt = 12;
...
public function dontBurnMe() {
// echo your error here using self::$turnedIntoANewt
}
Since constants are public by default, you can access them from other classes directly if you want. So, from the outside, the error would be referenced as:
MyErrorProneClass::TURNED_INTO_A_NEWT
For associating to messages, you would use a mapping (either in a database, or in some localization file) from error ID (and frontend/backend) to displayed string. This use of keys for messages isn't optimal, but it would allow you to change error messages without changing code as well.
If you don't know already it might be an idea to use trigger_error (), plus an error handler if you want to present the user with a better error message.
Have you thought about using exceptions? They may be a good choice for your problem here although adding them to your project now would probably require some restructuring.
You can extend the basic exception class so it fits your problem in terms the of user / developer error message separation.

Categories