CVE-2020-7063

Information Exposure
Affects
PHP
in
PHP
No items found.
Versions
<7.2.28, >=7.3.0 <7.3.15, >=7.4.0 <7.4.3

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

PHP is a general-purpose scripting language used mostly for web development. It runs behind web servers through server APIs such as Apache mod_php and PHP-FPM, and powers content management systems and frameworks such as WordPress, Drupal, Moodle and Laravel. Its Phar extension creates and reads PHP archives as well as tar and zip archives, through the Phar and PharData classes.

An Information Exposure vulnerability (CVE-2020-7063) has been identified in the buildFromIterator() and buildFromDirectory() methods of PHP's Phar extension, which store every file they add to an archive with all-access permissions (mode 0666) regardless of the permissions of the original file, so that anyone who extracts the archive may get files that every local user can read and write. PHP tracks this issue as bug #79082.

Per MITRE CWE-281: The product does not preserve permissions or incorrectly preserves permissions when copying, restoring, or sharing objects, which can cause them to have less restrictive permissions than intended.

This issue affects all versions of PHP before 7.2.28, PHP 7.3 before 7.3.15 and PHP 7.4 before 7.4.3, which includes the End-of-Life PHP 5.6, 7.0 and 7.1 release lines through their final releases (5.6.40, 7.0.33 and 7.1.33).

Details

Module Info

Vulnerability Info

This Medium-severity vulnerability is found in the Phar extension of all PHP versions before 7.2.28, 7.3 before 7.3.15 and 7.4 before 7.4.3, including the End-of-Life PHP 5.6, 7.0 and 7.1 release lines, which never received the upstream fix. The PHP project scores it 5.5 under CVSS 3.1 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N).

Archive formats such as tar and zip record a permission mode for each file, and tools that extract the archive apply that mode to the files they write. Phar::buildFromIterator(), and buildFromDirectory(), which uses the same code, add the files that an iterator or a directory listing returns. Each new archive entry starts with the extension's default file mode, PHAR_ENT_PERM_DEF_FILE (0666). In PHP 5.6.40, the code that copies a file into the archive sets its contents and size but never replaces that default:

data->internal_file->fp = NULL;
data->internal_file->fp_type = PHAR_UFP;
data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp);
data->fp = NULL;
php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len);
data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
    php_stream_tell(p_obj->fp) - data->internal_file->offset;

As a result every file is stored as readable and writable by everyone, even when the source file was private, for example a configuration file with mode 0600. The reporter showed that files added with these methods came out of the archive with mode 0666 while the same file added with addFile() kept its restrictive mode. When such an archive is extracted, the files can be readable by every local user, which may expose secrets such as credentials, and writable by them as well.

The issue affects applications that build archives with buildFromIterator() or buildFromDirectory() from files that should stay private, when those archives are later extracted on a system with other local users, under any SAPI. It does not let a remote attacker read anything by itself: the exposure happens on the system where the archive is extracted, and the CVSS score accordingly rates it as a local issue that needs user interaction.

The fix copies the permission bits of each source file into its archive entry. When the source cannot be stat'ed, for example a stream, it applies the process umask to the default mode instead:

if (php_stream_stat(fp, &ssb) != -1) {
    data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ;
} else {
#ifndef _WIN32
    mode_t mask;
    mask = umask(0);
    umask(mask);
    data->internal_file->flags &= ~mask;
#endif
}

Mitigation

The PHP project publishes security fixes only for its supported release lines. PHP 5.6, 7.0 and 7.1 are End-of-Life and will not receive any public updates to address this issue.

Until an upgrade is possible, set the intended mode on each entry with PharFileInfo::chmod() after building the archive, or do not include private files in archives built with buildFromIterator() or buildFromDirectory().

Users of the affected components should apply one of the following mitigations:

  • Upgrade to PHP 7.2.28, 7.3.15, 7.4.3, or later.
  • Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.

Credits

Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
Medium
ID
CVE-2020-7063
PROJECT Affected
PHP
Versions Affected
<7.2.28, >=7.3.0 <7.3.15, >=7.4.0 <7.4.3
NES Versions Affected
Published date
February 27, 2020
≈ Fix date
February 20, 2020
Fixed in
Category
Information Exposure
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
PHP
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.