PHP, Security, and Lambdas

If you're writing PHP code and you want to use lambda functions, don't use PHP's create_function() method. It's insecure, and will be flagged as such by security software and analysts.

I was directed the other day to a discussion of PHP lambda functions and security:

https://twitter.com/mattonomics/status/459379499088355328

Let me state first that [cci]create_function()[/cci] is insecure. If you can avoid using it, avoid it. If you can’t, take some time to re-evaluate your code to find a way to avoid it.

Lambda Functions

A lambda function is merely an anonymous function in your code.  If you’re using JavaScript, you’ve probably written hundreds of them and not even noticed.  The cool thing about lambda functions is that they can be stored in variables in your code, then passed to other functions.

A great PHP example, straight from Wikipedia, shows:

$foo = create_function( '$x', 'return $x * $x;' );
echo $foo( 10 );

The advantage of this approach is that I can now pass this function as I would any other variable. In a WordPress world, I could pass this function into an [cci]add_action()[/cci] or [cci]add_filter()[/cci] call, then reference the same function later with [cci]remove_action()[/cci] or [cci]remove_filter()[/cci]. It’s an enormously flexible paradigm and allows for robust code that doesn’t litter a namespace with unnecessary clutter since these functions are locally-scoped.

Security

The security issue here is that, internally, [cci]create_function()[/cci] uses [cci]eval()[/cci].[ref]PHP [cci]create_function()[/cci] documentation.[/ref]

Just as [cci]eval()[/cci] is evil and should be avoided at nearly all costs in your PHP code, so should [cci]create_function()[/cci].

The security plugin WordFence will detect uses of [cci]create_function()[/cci] and flag them, appropriately, as security issues. If you’re writing code intended for a WordPress.com VIP environment – arguably the largest WordPress installation in the world – you’ll notice that [cci]create_function()[/cci] is explicitly called out as something looked at during code review.

Alternatives

The easiest alternative to using [cci]create_function()[/cci] is just to define the function somewhere in your code. If you’re using PHP 5.2 (WordPress’ minimum requirement), define your function as a static member of a utility class somewhere in your project. You won’t be able to pass it as a variable, but you can pass its name and then use [cci]call_user_func()[/cci] to achieve similar results.

If you’re using PHP 5.3 or higher, you have even more alternatives.

You can define the function within a namespace (if you need to get around security flags for the [cci]$func( $param );[/cci] pattern).

Or, and my personal preference, you can use an actual anonymous function in PHP:

$func = function( $x ) {
return $x *= 2;
};
echo $func( 10 );

Internally, this creates a [cci]Closure[/cci] object in PHP, and calls its magic [cci]__invoke[/cci] method. It doesn’t interpret arbitrary strings and is far more secure than the oldschool [cci]create_function()[/cci] approach.

An added bonus, it makes your code look more like JavaScript, making swapping between one language and the other far easier on your brain.