PHP Checksum before include()
I've been working on an application that will allow for third-party extensions to be built to expand the application's functionality. All this in PHP, of course. I wanted to add a bit of security padding by running files in a certain directory through a checksum function. If the file doesn't pass the checksum, the file isn't "included", the administrator for that installation is notified, and the module is disabled until the administrator acts (re-enables and records the exception, or reinstalls the module).
The problem I'm having right now is being able to run that checksum whenever a user runs the include()
function. I'd rather not have them run two functions back to back just to include a file, but if I have开发者_JAVA百科 to I will. Not all third-party extensions will be very willing to run two functions (something like if(checksum_function($bleh)) include($bleh);
), and even if they were, it'd be so much easier (and more secure) to run the checksum whenever include()
is executed, instead of doubling the line count for include()
statements.
I've done some searching around and haven't found much. Ideas? Thanks in advance!
If your includes are classes named after a certain system (e.g. MyPlugin_Text
) you could make use of PHP's autoloading. Autoloading can be used to automatically include a file when an object of a class is first created.
Extremely simplified example:
function __autoload($class_name) {
require_once $class_name . '.php';
}
$myTextPlugin = new MyPlugin_Text();
Obviously, you will want to extend the autoloader, e.g. to do the preloading only for classes starting with MyPlugin_
and load those from a specific folder.
I know of no other way to achieve what you want to do, except writing a custom wrapper function.
I like your idea in general. However, calculating a checksum - e.g. using crc32()
- is relatively expensive. There shouldn't be too many, and not too big, includes loaded this way. Also, it stands to reason that if an attacker is able to modify PHP files on your system, they are also able to execute them directly without needing your central application. The actual security gain of this exercise is likely to be small.
Consider writing a wrapper for include
:
function include_safe($library) {
if(checksum_function($library))
include($library);
}
You're not going to find many developers that are "happy" to use features like this, but you also can't override PHP language constructs (like include
and require
). Having a function that wraps everything is convenient and fast, so developers are likely to use it.
In many mobile code platforms it is common to see executable code signed with an RSA Digital Signature. This allows an authority to "ok" a piece of code that can then be distributed 3rd parties and customers know that the code is safe. Digital signatures are used to help prevent piracy of modern console video games. They are also used to verify that a software update came from the vendor, and not an attacker.
This php application could have the public key (or even distributed with this public key). The administrator has access to both the public and private key, using this he can sign a .php file. Upon include the signature could be checked. If the php file is modified or damaged the signature will not pass the check.
In practice, PHP applications perform many includes and thus any validation function would be a massive bottle neck. Anything that is secure, is also going to be very expensive. It would be better to check the signature once, and then transfer it to a white-listed directory or database. Another way to improve speed you could use a smaller RSA key for the signature. For instance a 512bit RSA key is good enough for SSLv3, so its probably good enough for this.
MD5 is very bad. If you store a white list of "safe" md5 file hashes, then this opens the door for collision generation. This is an ideal situation to use the md5 prefixing attack because specially crafted binary data a the beginning of the file will not prevent the include()
for executing the code within the php tags <?php ?>
.
CRC is even worse than md5. CRC is not intended to make hash collisions more difficult. CRC is only to detect damage from random noise. Using the similar attack to md5 by appending data a to a message a CRC collision can be generated.
sha1 is a secure and fast hash function that you can use. There is a similar hash collision attack that affects sha1. However unlike md5 no one has generated a sha1 collsion and NIST still considers its use to be safe. Although sha256 would be a more secure choice.
I think checking a checksum on every load is a bad idea because it will slow down your application for sure.
A different approach would be that you put something in your applications admin interface to install or enable the plugin.
Then you could check the plugin one time when it is installed and add it to the list of enabled plugins before it can be used.
You could also check all plugins once a day to check if one was altered... but it's difficult to make that secure because whatever changed the plugin while it was installed could also change your security functions.
精彩评论