NOTE: This task is currently incomplete, more details will be available shortly.
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.
- 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 parses the special `--config` and `--debugger` flags in an unusual, nonstandard 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:
(WARNING) The argument `--debugger`, and any argument beginning with `--config`, are unsafe to pass to Mercurial as part of //any// command, in //any// position, even after a `--` "end of flags" marker. Callers must filter arguments and reject any such argument before passing it to `hg`. Generally, the `hg` binary can not interact normally with files named `--debugger`, branches named `--debugger`, bookmarks named `--debugger`, search for the pattern `--debugger` using `grep`, etc., even though this is a valid file name, a valid branch name, a valid bookmark name, a valid pattern, and so on. Likewise for `--config`.
See also CVE-2017-1000116, although this is not as closely related as the `--debugger` vulnerability.
Phabricator incorrectly assumed that Mercurial used standard behavior for all flags, and executed some commands like these: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
Via HackerOne.parse the second argument as a parameter for the `--branch` argument, not a separate flag, See also <https://hackerone.com/reports/288704>.
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.