The Open Web Application Security Project (OWASP) considered Injection attacks to be the most critical security risk in 2013. There are many different forms of injection attacks such as SQL injection, Path injection, Command injection, and many more. Injection attacks especially hurtful because they are easy to exploit, and can cause severe damage.
At Scrutinizer, we already notified you of SQL injection issues f.e. if you did
not use parameter binding offered by PHP’s PDO abstraction, or libraries like
Doctrine. However, there is a whole range of other PHP functions that are safe
per-se, but can lead to severe security issues if passed arbitrary user input.
file_get_contents
for example is one of these functions. Malicious users can
use it to gain access to sensitive credentials from your application.
Flagging each call to file_get_contents
would be a very naive approach and not
really helpful. However, at Scrutinizer we have invested into a solid foundation.
Our PHP analyzer is almost like a compiler for PHP and uses advanced techniques
such as data flow analysis,
and abstract interpretation
which distinguishes us from other competitors, or also existing open-source tools
that only use AST-based
approaches. It are these very analysis techniques that help us understand how data
flows through your application.
In the most recent version of PHP analyzer, we have added a security analysis framework that specifically focuses on making sure your request data is not ending up in one of PHP’s sensitive functions, and that consequentially could make you vulnerable to injection attacks. Let’s take a look at an example:
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\HttpFoundation\Request;
class Instance
{
private $config;
public function __construct($config)
{
$this->config = $config;
}
public function getParsedConfig()
{
return Yaml::parse($this->config);
}
}
class MyController
{
public function createAction(Request $request)
{
$instance = new Instance($request->request->get('config'));
// ... save new instance, etc.
}
}
In this example, we are assigning a YAML configuration from request data to a class property, and then save the new instance. Let’s see what Scrutinizer finds when analyzing this code:
This might come a bit unexpected. There is no problem with database persistence
here, Doctrine takes care of escaping the content for us, but we still introduced
a security issue by passing raw request data to the Yaml::parse()
function which
in turn calls file_get_contents()
. Let’s take a look at it to see what is
happening there:
class Yaml
{
public static function parse($input, $exceptionOnInvalidType = false, $objectSupport = false)
{
// if input is a file, process it
$file = '';
if (strpos($input, "\n") === false && is_file($input)) {
if (false === is_readable($input)) {
throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $input));
}
$file = $input;
$input = file_get_contents($file);
}
// ...
}
}
This function has a feature that expands the input in case it is a valid file path,
and replaces it with the contents of that path before parsing its actual contents.
If someone were to pass a path such as ../app/config/parameters.yml
, he
might gain access to the parameters file of a Symfony2 application.
I would like to point out that we have not hard-coded the Yaml::parse
function
in PHP analyzer, but since we not only analyze your application, but also all
your dependencies. We also assess the security relevance of the specific dependency
version that your application uses. Analyzing your dependencies is even more important
as you might not be as familiar with your dependencies’ code and consequentially
also not aware of some of their features such as the file expansion shown above.
This also allows us to compile a stack trace for you that aids in assessing the
security issue more easily.
We are proud to now add this additional level of security to your PHP applications on
Scrutinizer. Currently, we support tracking request data from Symfony2’s, and Zend’s
request abstraction, as well as usage of PHP’s super globals like $_GET
. If you are
using another request data abstraction, just let us know by
opening an issue.
Happy & secure coding!