Thanks for your interest in the issue, Frank.

I've looked into the run-mailcap(1) script (the reference parser, included in 
this package), and I found it also vulnerable to shell command injection.

(Test with --norun, at your own risk.)
-- rule
text/*; /usr/bin/w3m -T %t %s
-- exploit
$ type='text/$(rm -fr *)' # e.g. from a malicious mail header
$ run-mailcap --action=view "$type":filename

-- rule
text/html; /usr/bin/w3m -I %{charset} %s
-- exploit
$ charset="'\$(rm -fr *)'" # e.g. from a malicious mail header
$ charset=$charset run-mailcap --action=view filename.html

If run-mailcap is used by some mail program or script for mailcap support, then 
it's a vector for arbitrary command execution. Perhaps this deserves its own 
bug report.

Quotes on the rule obviously don't help:
-- rule
text/*; /usr/bin/w3m -T '%t' '%s'
-- exploit
$ type="text/'\$(rm -fr *)' "
-- rule
text/html; /usr/bin/w3m -I '%{charset}' '%s'
-- exploit
$ charset=" '\$(rm -rf *)' "

Other run-mailcap quirks include the replacement of '' with ', breaking 
commands like join -t ''. Not that you want to do that often, but such 
manipulation is nonstandard nonetheless.

Fortunately run-mailcap handling of %s seems safe because, if the name contains 
any shell-special punctuation or whitespace, a temporary symlink with a safe 
name is created, and the link name is used instead.

Please don't try to fix the command injection issue by adding special cases. It 
just makes it more complex to reason about, and there's always a way around it!
The only fix that would work with both quoted and unquoted rules is to just 
reject *any* shell-special punctuation or whitespaces in %-expansions.
But even if that was acceptable, it would just encourage rule writers to do 
whatever they want, and bury the security problem deeper.
Vulnerable mailcap parsers are common, in fact I haven't seen a secure one yet, 
do they actually exist?
Well, it's not entirely their fault, the right thing to do is not written 
anywhere; the standard is underspecified and security was not even considered.

I also tried to look into Thunderbird source code, which is huge and unfamiliar 
to me, so correct me if I got something wrong.

https://hg.mozilla.org/mozilla-central/file/661f0d8ae4c44db58e668c831b555dbc038b77d0/uriloader/exthandler/unix/nsOSHelperAppService.cpp

I made a couple of disturbing discoveries:
1) Thunderbird doesn't really use the %-expansion in the rules at all!
The parsing function extracts what it thinks is the "executable name" and 
returns just that.
Comments are hilarious:
"UnescapeCommand really needs some work -- it should actually do some 
unescaping"
// XXX ugly hack.  Just grab the executable name
...
// XXX End ugly hack
:D

2) Thunderbird gives a higher priority to non-wildcard rules, even if they 
appear later.
E.g. given this two rules and a text/rtf, Thunderbird picks the second rule:
text/*; emacs %s
text/rtf; soffice %s

As a consequence, it's impossible to force the use of, say emacs, for all text 
subtypes without explicitly enumerating them (generated rules can change 
anytime).
This is a violation of the rfc, which states that "The configuration 
information will be obtained from the FIRST matching entry".


In summary, mailcap is harmful.
And I won't feel safe until I can get rid of it.

I already have MAILCAP/MAILCAPS environment variables set to /dev/null, and NOP 
rules on my /etc/mailcap:
# ----- User Section Begins ----- #
application/*; true; compose=true; composetyped=true; edit=true; print=true
audio/*;       true; compose=true; composetyped=true; edit=true; print=true
font/*;        true; compose=true; composetyped=true; edit=true; print=true
image/*;       true; compose=true; composetyped=true; edit=true; print=true
message/*;     true; compose=true; composetyped=true; edit=true; print=true
model/*;       true; compose=true; composetyped=true; edit=true; print=true
multipart/*;   true; compose=true; composetyped=true; edit=true; print=true
text/*;        true; compose=true; composetyped=true; edit=true; print=true
video/*;       true; compose=true; composetyped=true; edit=true; print=true
# -----  User Section Ends  ----- #

But I've seen programs bypass both tricks and still pick a generated rule!
Now I'm considering doing this to prevent automatic update of /etc/mailcap:
# echo 'exit;' >/etc/update-mime.conf

Is this solution supported? If not, is there another way? update-mime.conf is 
sourced from update-mime(8), but undocumented.

Personally, I don't like the idea of having automatic associations between 
types and programs anyway, so I'm not going to miss mailcap. I'm just very 
concerned about the overall quality of the system, because something is so 
obviously broken and no one seems to care.

Reply via email to