21 Jan, 2019

Avoid Website Corruption when Migrating to PHP 7.2

If your website is presenting you with problems, it may not be malware. Recent cases have shown that when switching over to the latest PHP 7.2, there have been compatibility issues causing the site to crash.
We have received reports from several customers that their site was hacked and stopped working. As always, we checked the malware monitoring reports and the web application firewall, but in these cases, we didn't see any signs of intrusion. The next step, to check for any possible zero-day exploits, was a full audit of the sites.

These audits showed that the problem wasn't due to malware or intrusion. The owners had recently migrated their sites from PHP 5.x to the latest version, 7.2. Compatibility issues between the versions broke the sites, resulting in their seeing an HTTP 500 (internal server error) page. If you run into this problem, your site is safe, but you'll have to make some changes to get all the pages working again.
Understanding HTTP Error 500 and PHP Deprecation
The HTTP error code 500 is a very generic one. It says that something went wrong which prevented the server from displaying the page. PHP-based sites often display it when the PHP code reports an error.

Each version of PHP introduces changes that can break old code. It has backward-incompatible changes and deprecated features. Understanding the difference between the two is important. Backward-incompatible changes generally require fixes to the affected code. Deprecation doesn't stop code from working, but it's a warning that the features will disappear in a subsequent version. Changing the code before it stops working is a good idea.

Deprecation sometimes breaks code immediately, depending on the value of error_reporting(). The function takes a bitmask which tells PHP which kinds of errors to report. If the bitmask includes E_DEPRECATED, PHP will report deprecated features as errors, causing HTTP 500 messages and other problems.

A temporary fix is to change the error_reporting mask. You can set it in php.ini:

error_reporting = E_ALL & ~E_DEPRECATED

If you're running on a PHP platform or CMS, it might change the value of error_reporting in some unexpected place, so fixing it might be difficult. At best, that's a temporary fix; you'll have to change the code when a future version of PHP removes the features.
PHP Compatibility Issues
Lists of changes are available for PHP 7.0, 7.1, and 7.2. Some of these changes are for security reasons, and getting rid of those deprecated functions will eliminate ways malware can infect your site.

The function create_function() is deprecated in version 7.2. It was a clumsy attempt to support functional programming, and you can do the same thing better with eval or native anonymous functions. It's one of many ways in PHP to turn a string into executable code. Reducing the number of ways makes it easier for anti-malware software to catch attempts to install backdoors.

The function assert() is used for debugging. Previously, it took either a string or a boolean expression as an argument. Like create_function, it would treat a string as PHP code. PHP 7.2 still supports Boolean expressions as arguments, but not strings.

A number of compatibility checkers are available to find issues in your code. They will list all the compatibility issues, possibly with recommendations on how to fix them.

In many cases, the code with issues isn't your own, and you will need to upgrade third-party components.

  • The content management system (CMS) may be an old one, designed for an older version of PHP. Installing the latest version should fix any compatibility issues. Besides, old versions are likely to have security and performance problems. Keeping them up to date is the safest course.
  • You may be using outdated third-party add-ons (plugins, themes, etc.) with your CMS. You'll need to bring them up to date. If any of them are no longer supported, look into ways of replacing them. Unsupported add-ons are favorite targets.
  • If you use a framework to develop your code, such as Laravel or Symfony, an old version may generate incompatible code. You'll need to update the framework, rebuild everything, and test it.
  • You may be calling third-party libraries from your code. If they're out of date, that could be the cause of the trouble. As in the other cases, you should update them. If there's no update, look for a way to stop using them.
Any software update carries the risk of introducing bugs, so be sure to test your changes thoroughly before going to production. You don't want your site to stay broken for long, but haste can make things worse.
Other Issues
In particular, upgrading sometimes causes problems with file permissions. If new or changed files don't have the right permission in the file system, they may not be able to run, causing a 500 error. These are the recommended permissions:

  • PHP files: 644 (owner can read and write, group and others can read)
  • Directories: 755 (the same, and the directory is searchable by all)
If you have command line (SSH) access, several commands can help you. For example, PHP files shouldn't have execute permission. To search for files which do, use this command:

find -L . -type f ( -perm -u=x -o -perm -g=x -o -perm -o=x )

This tells the shell to:

  • Look for normal files (-type f), as opposed to directories.
  • Follow symbolic links (-L). This is optional.
  • List files which have the specified user, group, and other permissions (-perm). The -o option lets you combine multiple tests using an "or" operator.
You can vary this command to check for other permissions.

To fix permissions, you can combine find with chmod. For example:

find -L . -type f -exec chmod -x {} \;

This will go recursively through all subdirectories and symbolic links. Be sure not to run it on a directory with legitimate executable files!

Directories shouldn't be writable by anyone but the owner. To check, use this command:

find -L . -type d ( -perm -g=w -o -perm -o=w )

You can fix them with this command, which will go through all subdirectories and symbolic links:

find -L . -type d -exec chmod 755 {} \;

Still Having Problems?
If you continue to have problems, there could be subtle issues in the migration which the compatibility checker missed. Sometimes it's necessary to do serious debugging after going to a new version of PHP. Updating frameworks and libraries sometimes break existing code.

If nothing fixes the problem, it's possible that you really do have a security issue. As part of our best-in-class support for our ThreatSign Website Security customers, we are here to assist with website management issues like this one. Our experts, with their vast experience in cybersecurity, IT, and website management, are at your service 24 x 7 to make sure your website is malware-free and running smoothly.