Summary
Phabricator uses the hg command line binary to serve some requests for information about Mercurial repositories.
The hg binary treats the flags --config=... and --debugger specially, and evaluates them as flags in any position. Attackers could exploit this by accessing certain branches or files with names like --config=... or --debugger to execute code remotely.
You are vulnerable if:
- the Phabricator server has hg installed; and
- an attacker can browse any Mercurial repository in Diffusion.
The mitigation (available in 2017 Week 45) refuses to execute any hg command where any argument begins with --config or --debugger.
Mercurial anticipates providing a "hardened" mode in a future release with stricter argument parsing rules.
This issue was reported to us via HackerOne. See https://hackerone.com/reports/288704 (this may not yet be public, but should become public once the researcher agrees to disclosure).
Mercurial Behavior
Mercurial parses the special --config and --debugger flags in an unusual way: it processes them before processing other flags and arguments, including flags which take arguments and the -- "end of flags" marker. For example, this command:
$ hg log -- --debugger
...invokes the debugger. Likewise, this:
$ hg log --branch --debugger
...means "invoke the debugger", not "log the branch named --debugger".
Note that --debugger is a valid Mercurial branch name, but to create it you must do this:
$ hg branch --debugger --debugger
Then enter c to convince the debugger to continue execution.
The --debugger flag is dangerous (remote code execution) if users control stdin. See CVE-2017-9462 for an earlier attack using this flag. See also D18611 and followup in D18616.
The --config flag is also dangerous and can also enable remote code execution with, e.g., --config=hooks.pre-log=whoami in a log command.
Broadly, the behavior of Mercurial is this:
See also CVE-2017-1000116, although this is not as closely related as the --debugger vulnerability.
Phabricator Behavior
Phabricator incorrectly assumed that Mercurial used standard behavior for all flags, and executed some commands like this:
hg log --branch <branch_name> --rev <revset>
An attacker could browse a branch named something like --config=execute=evil (which is a valid Mercurial branch name) in the web UI, and cause Phabricator to execute an hg command with --branch '--config=...'. Normally, binaries parse the second argument as a parameter for the --branch argument, not a separate flag, but Mercurial treats --config and --debugger specially and parses them as flags in any position.
Since there is no way to escape these flags, we now filter them and refuse to execute commands with any --config or --debugger argument.