Getting Ahead In Security By Watching The Neighbours
As some of you are likely aware by now, Ruby On Rails posted a security advisory concerning critical remote code execution (RCE) vulnerabilities in its Action Pack for all versions of Rails since 2.0.
This vulnerability can likely be used in a wide variety of potential attacks so you should immediately update any Rails applications you are currently running. There’s a good analysis of the issue over on http://www.insinuator.net/2013/01/rails-yaml/ and it raises the very real risk that the global nature of this vulnerability may make automated attacks or worms feasible. A concrete POC has not been released to give folk more time to update their applications before attackers figure out how to take advantage of this.
Yes, but HOOEY! How does this relate to PHP, Paddy?!
Code execution vulnerabilities are, by definition, hideous monsters. The ability for external inputs to enter an execution context (i.e. injecting or manipulating code that is executed on the server) can be difficult to spot through the haze of convenience that such machinations are often designed to deliver. In Rail’s case, that convenience was to automatically cast data entries in XML or YAML inputs into Ruby types including, unfortunately, Symbols and Objects.
These types of “buried” code execution vulnerabilities are still easy to locate in PHP, at least, because you are still restricted to normal code execution pathways in the absence of Ruby’s dark magic, e.g. eval(), include(), require_once(), system() and, let’s not forget, unserialize(). Anyone can perform a mini-audit using grep searches just by checking for instances of these and similar functions and then identifying whether they are in unusual places or accepting variable inputs that could be exploited. For example, a few years back many applications were found to be unserializing user inputs which allowed for code execution attacks by manipulating parameters to __wakeup() and __destruct() method calls.
Rails is a battle hardened framework but all frameworks will suffer from unanticipated security vulnerabilities. You just won’t see them become as well publicised as Rails! It’s the nature of programming for programmers to err or fail to foresee unintended uses for their code. PHP applications and libraries are already suffering from any number of obviously pervasive ills including three security problems I called the Three Ugly Sisters in my recent article for December’s Web Advent series (SSL Peerjacking, XMl Injection and Cross-Site Scripting). We all have the capacity to do better on the security front.
No PHP project is immune to security vulnerabilities simply because of its size, user base, or funding. Even a good security audit is not immune to the blind spots of the reviewer, emerging security issues still flying under the radar and the continuing assault by researchers on practices and techniques we take for granted.
One part of being prepared for unexpected vulnerabilities is to find common ground with your competitors. Ruby on Rails is a web application framework. If you are a PHP framework developer and not monitoring Rails’ or Django’s security woes then it’s time to start. We can learn a lot because, despite the barrier of a different programming language, many security problems are universal. Frameworks in Ruby, PHP, Java and Python can all run afoul of very similar vulnerabilities. Using that knowledge can lead into avenues of investigation you did not previously consider. Within PHP itself, monitoring frameworks like Zend Framework and Symfony can reveal security advisories that, in all probability, are not unique to those frameworks.
As a case in point, the Rails vulnerability I opened this article with led me to wonder if something similar might be possible in a PHP framework. So, I took a look at Symfony 2’s YAML component. Johannes Schmitt apparently had the same thought! As it happens, there are two possible points in the YAML classes where code execution could potentially be manipulated by untrusted input. The component is generally used to parse local configuration files (so typical Symfony applications will not be vulnerable) but there is nothing to stop it from being used as a generic YAML parser for other use cases such as user submitted files or YAML output from a remote API. As always, Fabien promptly set the Elves in his North Pole hideout on red alert and has already released fresh versions of Symfony 2.0 and 2.1 to rectify these issues. You can read the official advisory at http://symfony.com/blog/security-release-symfony-2-0-22-and-2-1-7-released.
The code execution vulnerabilities in Symfony’s YAML component relied on calls to include() and unserialize(). One included a file as PHP and parsed its output as YAML (disabled by default since Symfony 2.1 but still enabled by default on Symfony 2.0 versions) and the other unserialised objects stored to a YAML scalar value (enabled by default in all versions). As I mentioned earlier, grep can be really helpful in locating these types of problems – so get cracking on the command line!
Pay attention to competing applications or frameworks – their problems may also be your problems. If you’re worried about arbitrary code execution vulnerabilities then audit your code. You can even, as a sanity check, use grep to find uses of functions like eval(), unserialize(), etc and analyse where their parameters’ might originate from. The answer “somewhere out there” or “how the heck am I supposed to know what crazy users will do” usually means it’s untrusted by definition. Keep in mind that code execution vulnerabilities can also appear in the form of arbitrary object instantiation, i.e. the constructor and destructors being executed for any object targeted even if there are no other method calls made. Manipulating code execution can be just as bad as arbitrary code execution.
- Analysis of Rails XML Parameter Parsing Vulnerability (insinuator.net)
- Extremely crtical Ruby on Rails bug threatens more than 200,000 sites (arstechnica.com)