From f75b1cf562c0c3646324864851d693ef1069a068 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Apr 2016 05:38:09 -0700 Subject: [PATCH] (stable) Warn users about remote code execution in older Git Summary: Ref T10832. Raise a setup warning for out-of-date versions of `git`. Test Plan: {F1224632} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10832 Differential Revision: https://secure.phabricator.com/D15745 --- .../check/PhabricatorBinariesSetupCheck.php | 126 +++++++++--------- 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/src/applications/config/check/PhabricatorBinariesSetupCheck.php b/src/applications/config/check/PhabricatorBinariesSetupCheck.php index c33dcae36f..c3c0740cfa 100644 --- a/src/applications/config/check/PhabricatorBinariesSetupCheck.php +++ b/src/applications/config/check/PhabricatorBinariesSetupCheck.php @@ -102,15 +102,24 @@ final class PhabricatorBinariesSetupCheck extends PhabricatorSetupCheck { $version = null; switch ($vcs['versionControlSystem']) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: - $minimum_version = null; - $bad_versions = array(); + $bad_versions = array( + '< 2.7.4' => pht( + 'Prior to 2.7.4, Git contains two remote code execution '. + 'vulnerabilities which allow an attacker to take control of a '. + 'system by crafting a commit which affects very long paths, '. + 'then pushing it or tricking a victim into fetching it. This '. + 'is a severe security vulnerability.'), + ); list($err, $stdout, $stderr) = exec_manual('git --version'); $version = trim(substr($stdout, strlen('git version '))); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - $minimum_version = '1.5'; $bad_versions = array( - '1.7.1' => pht( + // We need 1.5 for "--depth", see T7228. + '< 1.5' => pht( + 'The minimum supported version of Subversion is 1.5, which '. + 'was released in 2008.'), + '= 1.7.1' => pht( 'This version of Subversion has a bug where `%s` does not work '. 'for files added in rN (Subversion issue #2873), fixed in 1.7.2.', 'svn diff -c N'), @@ -119,12 +128,15 @@ final class PhabricatorBinariesSetupCheck extends PhabricatorSetupCheck { $version = trim($stdout); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: - $minimum_version = '1.9'; $bad_versions = array( - '2.1' => pht( + // We need 1.9 for HTTP cloning, see T3046. + '< 1.9' => pht( + 'The minimum supported version of Mercurial is 1.9, which was '. + 'released in 2011.'), + '= 2.1' => pht( 'This version of Mercurial returns a bad exit code '. 'after a successful pull.'), - '2.2' => pht( + '= 2.2' => pht( 'This version of Mercurial has a significant memory leak, fixed '. 'in 2.2.1. Pushing fails with this version as well; see %s.', 'T3046#54922'), @@ -136,20 +148,25 @@ final class PhabricatorBinariesSetupCheck extends PhabricatorSetupCheck { if ($version === null) { $this->raiseUnknownVersionWarning($binary); } else { - if ($minimum_version && - version_compare($version, $minimum_version, '<')) { - $this->raiseMinimumVersionWarning( - $binary, - $minimum_version, - $version); + $version_details = array(); + + foreach ($bad_versions as $spec => $details) { + list($operator, $bad_version) = explode(' ', $spec, 2); + $is_bad = version_compare($version, $bad_version, $operator); + if ($is_bad) { + $version_details[] = pht( + '(%s%s) %s', + $operator, + $bad_version, + $details); + } } - foreach ($bad_versions as $bad_version => $details) { - if ($bad_version === $version) { - $this->raiseBadVersionWarning( - $binary, - $bad_version); - } + if ($version_details) { + $this->raiseBadVersionWarning( + $binary, + $version, + $version_details); } } } @@ -223,57 +240,34 @@ final class PhabricatorBinariesSetupCheck extends PhabricatorSetupCheck { pht('Report this Issue to the Upstream')); } - private function raiseMinimumVersionWarning( - $binary, - $minimum_version, - $version) { + private function raiseBadVersionWarning($binary, $version, array $problems) { + $summary = pht( + 'This server has a known bad version of "%s".', + $binary); - switch ($binary) { - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: - break; - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: - $summary = pht( - "The '%s' binary is version %s and Phabricator requires version ". - "%s or higher.", - $binary, - $version, - $minimum_version); - $message = pht( - "Please upgrade the '%s' binary to a more modern version.", - $binary); - $this->newIssue('bin.'.$binary) - ->setShortName(pht("Unsupported '%s' Version", $binary)) - ->setName(pht("Unsupported '%s' Version", $binary)) - ->setSummary($summary) - ->setMessage($summary.' '.$message); - break; - } - } + $message = array(); - private function raiseBadVersionWarning($binary, $bad_version) { - switch ($binary) { - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: - break; - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: - $summary = pht( - "The '%s' binary is version %s which has bugs that break ". - "Phabricator.", - $binary, - $bad_version); - $message = pht( - "Please upgrade the '%s' binary to a more modern version.", - $binary); - $this->newIssue('bin.'.$binary) - ->setShortName(pht("Unsupported '%s' Version", $binary)) - ->setName(pht("Unsupported '%s' Version", $binary)) - ->setSummary($summary) - ->setMessage($summary.' '.$message); - break; - } + $message[] = pht( + 'This server has a known bad version of "%s" installed ("%s"). This '. + 'version is not supported, or contains important bugs or security '. + 'vulnerabilities which are fixed in a newer version.', + $binary, + $version); + $message[] = pht('You should upgrade this software.'); + $message[] = pht('The known issues with this old version are:'); + + foreach ($problems as $problem) { + $message[] = $problem; + } + + $message = implode("\n\n", $message); + + $this->newIssue("bin.{$binary}.bad-version") + ->setName(pht('Unsupported/Insecure "%s" Version', $binary)) + ->setSummary($summary) + ->setMessage($message); } }