Shell Command Injection in "Mailcap" file handling

Bug #1510317 reported by Bernd Dietzel
258
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Python
New
Unknown
python3.5 (Ubuntu)
Confirmed
Undecided
Unassigned

Bug Description

https://docs.python.org/2/library/mailcap.html
mailcap.findmatch(caps, MIMEtype[, key[, filename[, plist]]])
Return a 2-tuple; the first element is a string containing the command line to be executed (which can be passed to os.system()), ...

Security Bug in mailcap.findmatch() function :
====================================

1) If the "filename" or path contains a shell command , it will be injected when you use os.system() to execute the resulting command line. As you can read in the docs above, the function is designed to run os.system(<string containing the command line>).
(Have a look at the Exploit Example 1 below )

2) If you try to 'quote' the filename before using mailcap.findmatch() , the shell command can be injected too, because there may be another quoting inside the mailcaps strings witch allows the shell commands to escape.
(Have a look at the Exploit Example 2 below)

3) There is no way to split the resulting command line in a correct way afterwards into a list object with a "command" and its "parameters" because after running the function you will never now if the characters for splitting the line where a part of the the filename or a part of the mailcap command in the first place. So even if you use subprocess for executing the commandline instead of os.system , you can get in trouble with unwanted parameters witch may make the viewer doing bad things.

Python Exploit Example 1 :

import mailcap , os
d=mailcap.getcaps()
FILE="';ls;#';ls;#.mp4"
cmd,m=mailcap.findmatch(d, "audio/mpeg4", filename=FILE)
os.system(cmd)
## this will lead to this in cmd :
## vlc '';ls;#';ls;#.mp4'
## Or it will lead us to this in cmd :
## vlc ';ls;#';ls;#.mp4
## No matter what, it will inject the ls command after you quit vlc

--

Python Exploit Example 2 :

import mailcap , os
try:
  from shlex import quote
except ImportError:
  from pipes import quote
d=mailcap.getcaps()
FILE=quote(";ls;#.txt")
cmd,m=mailcap.findmatch(d, "text/plain", filename=FILE)
os.system(cmd)
## this will lead to this in cmd :
## less '';ls;#.txt''
## And it will inject the ls command after you quit less '' with the Q key

--

TODO :
a) The Return 2-tuple Command line should be quoted in this way to make shell commands stay inside the 'quotes' :
    1.] Remove the quotes from the caps string, for example make it
          less %s and NOT less '%s'
    2.] Now quote the filename with quote(filename) , so we get for example
          ';xmessage hello world;#.txt' in the filename variable.
    3.] Now we replace %s with the filename , so now we get
         less ';xmessage hello world;#.txt' and NOT less '';xmessage hello world;#.txt''

b) The mailcap.py script itself is using "os.system()" witch is vulnerable for shell injections.
     They should be all replaced with "subprocess.Popen()" or "subprocess.call()".

c) The "MIMEtype" parameter is missing for test.
    if there is %s in the 'test' entries key we get a "TypeError: cannot concatenate 'str' and 'list' objects" error.
   Should be like this :
   test = subst( e['test'], MIMEtype, filename, plist)

d) Think about replacing this script completely with the "run-mailcap" program of the debian project.

--
You can find mailcap.py in this locations :
libpython2.7-stdlib: /usr/lib/python2.7/mailcap.py
libpython3.4-stdlib: /usr/lib/python3.4/mailcap.py
libpython3.4-testsuite: /usr/lib/python3.4/test/test_mailcap.py
libpython3.5-stdlib: /usr/lib/python3.5/mailcap.py
libpython3.5-testsuite: /usr/lib/python3.5/test/test_mailcap.py
pypy-lib: /usr/lib/pypy/lib-python/2.7/mailcap.py
python-mailutils: /usr/lib/python2.7/dist-packages/mailutils/mailcap.py

--

Weblinks :
http://www.freiesmagazin.de/mobil/freiesMagazin-2015-10-bilder.html#fm_15_10_shell_command_injection
http://bugs.python.org/issue24778

ProblemType: Bug
DistroRelease: Ubuntu 15.10
Package: libpython3.5-stdlib 3.5.0-3
ProcVersionSignature: Ubuntu 4.2.0-16.19-generic 4.2.3
Uname: Linux 4.2.0-16-generic x86_64
ApportVersion: 2.19.1-0ubuntu3
Architecture: amd64
CurrentDesktop: XFCE
Date: Mon Oct 26 22:48:55 2015
InstallationDate: Installed on 2015-10-09 (16 days ago)
InstallationMedia: Ubuntu 15.10 "Wily Werewolf" - Alpha amd64 (20151009)
SourcePackage: python3.5
UpgradeStatus: No upgrade log present (probably fresh install)

Revision history for this message
Bernd Dietzel (l-ubuntuone1104) wrote :
information type: Private Security → Public Security
description: updated
Revision history for this message
Bernd Dietzel (l-ubuntuone1104) wrote :

My "Idea" for a quick bugfix :

Inside the mailcap.py script,
we copy the file to temp and give the file an random name like this ...
/temp/<RandomName>.tmp
... and then resulting with the random name instead of the original name.

Revision history for this message
Bernd Dietzel (l-ubuntuone1104) wrote :

My patch.

1) I removed the os.system() calls and append a new function "run" witch uses subprocess.

2) "Subst" function now uses quote() and is returning a list, not a string. So it can be passed to subprocess.

3) If you do not want to get back a command "string" but a command [list] , you can now call "findmatch_list"

 .. please test it.

Revision history for this message
Ubuntu Foundations Team Bug Bot (crichton) wrote :

The attachment "mailcap.py without shell injections" seems to be a patch. If it isn't, please remove the "patch" flag from the attachment, remove the "patch" tag, and if you are a member of the ~ubuntu-reviewers, unsubscribe the team.

[This is an automated message performed by a Launchpad user owned by ~brian-murray, for any issues please contact him.]

tags: added: patch
Revision history for this message
Bernd Dietzel (l-ubuntuone1104) wrote :

I fixed a typo and make code shorter.

New patch attached.

Revision history for this message
Bernd Dietzel (l-ubuntuone1104) wrote :
Revision history for this message
Marc Deslauriers (mdeslaur) wrote :

Thanks for reporting this issue.

Have you reported it to the upstream Python project? If not, please file a bug with them and link the bug here.

Thanks!

Revision history for this message
Bernd Dietzel (l-ubuntuone1104) wrote :

I have reported it to upstream :
http://bugs.python.org/issue24778

I have uploaded my patches to upstream:
http://bugs.python.org/file40897/mailcap%20patch.zip

Changed in python:
status: Unknown → New
Alex Murray (alexmurray)
Changed in python3.5 (Ubuntu):
status: New → Confirmed
To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.