From a4bfed8415c7ff33de56aebbc14856eab8f5d6ec Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 26 Mar 2015 11:13:17 -0700 Subject: [PATCH] Censor response bodies from Mercurial error messages Summary: Ref T6755. In Git and Subversion, running `git clone http://google.com/` or `svn checkout http://google.com/` does not echo the response body. In Mercurial, it does. Censor it from the output of `hg pull` and `hg clone`. This prevents an attacker from: - Creating a Mercurial remote repository with URI `http://10.0.0.1/secrets/`; and - reading the secrets out of the error message after the clone fails. Test Plan: Set a Mercurial remote URI to a non-Mercurial repository, ran `repository update`, saw censored error message. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6755 Differential Revision: https://secure.phabricator.com/D12170 --- .../PhabricatorRepositoryPullEngine.php | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php index 81878fb1dd..72c3b1f4d0 100644 --- a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php +++ b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php @@ -395,10 +395,16 @@ final class PhabricatorRepositoryPullEngine } } - $repository->execxRemoteCommand( - 'clone --noupdate -- %P %s', - $remote, - $path); + try { + $repository->execxRemoteCommand( + 'clone --noupdate -- %P %s', + $remote, + $path); + } catch (Exception $ex) { + $message = $ex->getMessage(); + $message = $this->censorMercurialErrorMessage($message); + throw new Exception($message); + } } } @@ -438,12 +444,38 @@ final class PhabricatorRepositoryPullEngine if ($err == 1 && preg_match('/no changes found/', $stdout)) { return; } else { - throw $ex; + $message = $ex->getMessage(); + $message = $this->censorMercurialErrorMessage($message); + throw new Exception($message); } } } + /** + * Censor response bodies from Mercurial error messages. + * + * When Mercurial attempts to clone an HTTP repository but does not + * receive a response it expects, it emits the response body in the + * command output. + * + * This represents a potential SSRF issue, because an attacker with + * permission to create repositories can create one which points at the + * remote URI for some local service, then read the response from the + * error message. To prevent this, censor response bodies out of error + * messages. + * + * @param string Uncensored Mercurial command output. + * @return string Censored Mercurial command output. + */ + private function censorMercurialErrorMessage($message) { + return preg_replace( + '/^---%<---.*/sm', + pht('')."\n", + $message); + } + + /** * @task hg */