Managing Security Risks in the PHP Engine & Web Applications
This blog explains:
- How the PHP community manages security risks in the PHP engine.
- How PHP security issues are classified and handled.
- How to secure web applications against risks — and minimize the chance you are affected by existing or future security issues.
Managing Security Risks: What Are Security Risks?
To better understand what security risks are and how they are handled, let's start with a definition of software security, by Gary McGraw:
“Software security is the idea of engineering software so that it continues to function correctly under malicious attack.”
In our context:
- Function correctly means that the software is doing what is was intended to do by its author. In our case, the PHP Engine should be executing PHP scripts exactly as they are written, following the instructions and the intent of the programmer. Any security issues that are contained within PHP code files are outside of the scope of the PHP engine and community security fixes.
- Under attack — When we talk about security issues, we consider scenarios where there is a purposeful action to cause some kind of “incorrect functionality.” The attacker triggering the action may or may not be human. For example, it could be a script.
- Malicious attack — This takes place when incorrect functionality gives an attacker an advantage or the ability to perform some action that could be harmful.
Managing Security Risks in the PHP Engine
In engine development, we have a set of rules to determine what incorrect functionality could be defined as a security issue. Usually, it's a bug that can be triggered by a remote attacker to:
- Gain data access.
- Trigger actions.
- Consume resources that the web application author did not intend.
It is important to note that the purpose of this classification is to determine whether we want to handle the issue according to a special set of procedures defined below, but it does not reflect any opinion on the issue's importance.
The Lifecycle of PHP Security Issues
The lifecycle of PHP security issues starts with the bug report, submitted either at bugs.php.net or at [email protected] (Use Security classification if you submit a PHP security issue.) Once the problem is reported, we evaluate it according to the rules above. If it indeed reproduces and is classified as a PHP security issue, we start looking for the fix.
Most issues are fixed within weeks. However, some take days or longer, depending on the issue’s complexity. Once the fix is available, we contact the original reporter and ask them to verify the fix. This cooperation is very important. As open-source developers, our resources are limited, and we sometimes need help to cover all testing scenarios.
Once the fix is validated, the bug information and the fix are kept private under the release time. Releases happen every four weeks, and are announced at https://www.php.net/. Release notes include CVE identifiers assigned to security issues. Note that since CVE descriptions are kept secret until the release, it takes some time (usually several days up to a week) between the release and CVE descriptions being updated. You can always use full bug description and details in the PHP Bugs database.
Security Risks: Vulnerable Areas in the PHP Engine
There are several areas in the engine where security issues appear more frequently. They have to do with:
- Direct user inputs (HTTP request handling, file uploads).
- Complex binary formats including images (exif, gd) and archives (phar, zip).
- Parsing third-party data (XML, HTML, YAML).
- Talking to outside services — SQL, HTTP, DNS, LDAP, XMLRPC — if the counterpart is malicious.
PHP also relies on a number of third-party libraries — such as oniguruma, pcre, libgd — which can have security vulnerabilities. If the vulnerable library version is bundled with PHP on build, then the resulting engine build may be vulnerable too.
Dangerous Areas Outside the PHP Engine: Here There Be Dragons
In some cases, the engine alone cannot ensure ample security under hostile attack. That’s why PHP developers need to take proactive steps to mitigate any security vulnerabilities. This includes risks from components — such as authorization, validation, whitelisting, OS permissions, and containerization — as well as attacks from the following vectors:
- Serialize/unserialize: due to the complexity and wide range of supported functionality, PHP serialization format should not be used when data can be maliciously manipulated. Use simpler data exchange formats like JSON, or ensure the data is intact (by signing, whitelisting, etc…).
- Binary access modules like FFI, runkit or COM: you should ensure no malicious manipulation is possible when using such functionality, since the engine puts virtually no limitation on what can be done with these functions.
- Debug functionality: error messages, backtraces, xdebug and other similar debugging modules should not be available to third parties that can manipulate them to disclose or modify information.
- Hostile code: the engine does not always guarantee correct functionality when running hostile code. While we are making the best effort to fix all known bugs, we know bugs exist in both the engine and extensions, and thus cannot guarantee 100% correctness with code written specifically to trigger them. If you need to run potentially hostile PHP code, measures should be taken by configuring your OS, infrastructure (such as containers), and other environments so they do not allow hostile code to perform any harmful action.
Evaluating PHP Security Issues
If you encounter a PHP security issue, first you need to know how bad it is by evaluating the following three dimensions:
- The severity of the bug itself.
- The relevance of the bug to your platform, especially, your OS and the PHP versions and modules you are running. You can usually find this information about the bug in the PHP bug database and CVE report.
- The relevance of the bug to your usage. For example, when you read a bug's description, pay attention to the conditions when it is triggered, and which functions are affected. You should also check whether these conditions and functions are relevant for your specific usage.
When It Comes to PHP Security Issues, Overreaction Is Better
If you are unsure whether a PHP security issue applies to you, it’s better to err on the side of caution and assume it does. This can save valuable time in patching the vulnerability instead of tracking down whether you use the specific module, function, or scenario impacted by the threat.
Managing Security Risks: Bug Severity
The criteria used to evaluate bug severity includes its prerequisites, complexity, and impact.
A Bug's Prerequisites
Which conditions should be true for the attack scenario to succeed? The more specific and uncommon prerequisites are, the lower the bug severity, and vice versa. For example, does the bug occur only when a specific:
- OS or engine version is used?
- Configuration is enabled or disabled or set in certain ways?
- Function(s) is called?
- User action(s) is performed, such as clicking a link or opening an email?
A Bug's Complexity
How hard is it to perform an attack via this bug? The easier the attack, the more severe is the bug. For example, does the bug need:
- Some actions to be performed by a user?
- Some preparations or omissions on the side of the system designer?
- The attacker to take many steps or perform laborious research — or can the attacker trigger the problem with one request to the target system?
A Bug's Impact
What will the attacker gain with a successful attack?
The Impact of Security Risks
Any PHP security issues can lead to one of the following consequences if not patched in time:
- Information disclosure: the attacker sees information that they could never access if the correct function were preserved. The revealed information could be random or useless, or could be very valuable, such as passwords or encryption keys. One example of a very severe information disclosure bug is the infamous Heartbleed bug.
- Availability impact: the attacker could slow down the system or consume resources beyond what is reasonably allocated to similar requests. This could be CPU resources, memory, disk space, network bandwidth, or any limited resource of the system. The effects could range from small slowdown to a complete denial of service (DoS).
- Integrity violation: the attacker can modify or destroy certain data on the affected system. This can lead to the attacker gaining more access to the system and using it as a platform to attack others, completely destroy system data, or manipulate it for their purposes.
- Remote code execution: the attacker can execute any code on the system, completely taking over system functionality. This effect usually encompasses all the above consequences, since code execution access would likely allow one to access or modify all the information that the system itself was intended to access and manipulate.
Evaluating Issues With CVSS
CVSS is the example of a formal system for evaluating issues according to the criteria in this blog. A best practice is to use it to evaluate all issues for the applications in your environment. It’s also important to note that evaluations are subjective on some levels. When it comes to severity, people must hypothesize about the possible actions of an attacker and their impact on a system.
How to Secure Web Applications Against Security Risks
The most basic thing to do to secure web applications against any engine vulnerabilities is to stay informed about all engine updates. You can start by:
- Looking at the release notes for the PHP versions you run.
- Keeping up to date with the latest releases.
- Upgrading when new fixes are released.
The next step to secure web applications is to practice defense in layers, so that every aspect of your system plays its part in overall security. This includes your PHP code, PHP engine, operating system, and infrastructure.
How to Secure Web Applications: Review Your PHP Code
Make sure that the data that can be maliciously manipulated is filtered, sanitized, and in the proper form. For example, URLs need to look like URLs. Emails need to look like emails. Numbers should look like numbers — and should be within sane ranges. PHP has a number of functions, such as filter extension. You should also follow industry best practices for secure PHP coding.
How to Secure Web Applications: Keep Your Engine Up to Date
Use up-to-date versions and secure configurations. For example, do not output error messages to the user. Disable functionality you don't use such as unnecessary modules — or unnecessary functionality like file uploading if you don't allow uploading files. Configure reasonable limits for your applications including how much memory they can consume and how long requests should take. Monitor your system for violations of these limits because these metrics can suggest an attack is in progress.
How to Secure Web Applications: Set Your Environment Privileges
Give your applications the minimal privileges needed for all tasks. For example, if your application only needs to read from the database, give it read permissions — but not write permissions. If it only needs to read certain files, ensure the application cannot write to them. Limiting access privileges will limit the impact of any vulnerability.
How to Secure Web Applications: Ensure Appropriate Operation System Settings
Assign restrictive permissions to processes executing your application, so they only can access what they need.
How to Secure Web Applications: Use Strategic Infrastructure
Use containers, firewalls, and other technologies to ensure minimal impact of any potential vulnerability.
For more information about PHP security issues and how to secure web applications, watch my video on PHP engine security.