classification
Title: Win32: Security problem with default installation directory
Type: security Stage: test needed
Components: Installation, Windows Versions: Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: steve.dower Nosy List: BreamoreBoy, Friedrich.Spee.von.Langenfeld, Gynvael.Coldwind, carlfk, dsmiller, eryksun, ezio.melotti, flox, fran.rogers, georg.brandl, giampaolo.rodola, jason.coombs, loewis, mel, mhammond, michael.foord, nnorwitz, norvellspearman, pitrou, r.david.murray, steve.dower, tim.golden, tim.peters
Priority: normal Keywords:

Created on 2005-09-07 21:34 by mel, last changed 2015-04-15 20:35 by steve.dower. This issue is now closed.

Messages (33)
msg26234 - (view) Author: Mika Eloranta (mel) Date: 2005-09-07 21:34
(Sorry, this is a bit long since the issue is not
entirely trivial.)

This problem only exists on Windows operating systems
installed on an NTFS file system. Confirmed on several
Windows 2000, XP and Windows 2003 Server systems. All
Python versions (at least 2.x) are affected.

The default installation target directory where Python
is installation on Windows is directly under the system
drive's root directory (e.g. "C:\python24"). The file
and directory permissions inherited by the
python24-directory from the root directory are not
secure enough for keeping application binaries.

Microsoft has, in their infinite wisdom, decided that
the root directory of the system drive should allow
regular (non-admin) users to create directories and
files there. This set of permissions is inherited by
the python directory when it is created in the default
location (i.e. "C:\python24" or whatever).

This "feature" allows a regular (non-admin) user to
perform a priviledge escalation attack for example in
the following manner:

1. Figure out the name of some DLL python (or some
extension .PYD) loads using LoadLibrary() without an
absolute path.

2. Copy a DLL with the same name into the
python-directory (this should not be allowed, but it
is!) containing some code the attacker wants to run
with escalated priviledges.

3. Wait until python is run by an admin in the same
machine or by the LocalSystem account.

How to view the problematic part of the ACL:
1. Right-click the "C:\python24" directory in Windows
Explorer
2. select Properties... -> Security -> Advanced
3. In the "Permissions" tab you will see an entry for
the "Users" group, it says "Special" in the
"Permissions" column
4. Select the above entry and click "Edit..."
5. Well hidden? I think so, too.

The fix:
The proper (default) location where application
binaries should be installed is under the "c:\program
files\" directory. This directory has properly set
permissions by default.

PS. The same problem exists in ActivePerl, Ruby and
many other tools.
msg26235 - (view) Author: Neal Norwitz (nnorwitz) * (Python committer) Date: 2005-09-30 06:26
Logged In: YES 
user_id=33168

Martin, do you know anything about this?  (Sorry, don't know
who else might know.)
msg26236 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2005-10-08 09:48
Logged In: YES 
user_id=21627

I disagree that the default location of Python should be
c:\Program Files. The Python interpreter's path name is
often typed into a terminal, batch file, etc., so it needs
to be convenient to type.

I agree that the permissions are problematic; the proper
solution would be to give c:\python24 more restrictive
permissions. You can do this yourself: in the security tab,
edit the permission. In "Advanced", unselect the "Inherit
permission" checkbox, and choose "copy" when asked. Then
edit the permissions to your liking.

I can consider supporting such permission setting during
installation in the future - an invocation of cacls.exe
should do. 

Notice that this is an incompatible change: as currently all
users can create files in the tree, the .pyc files are often
not created during installation, but on first use. If write
permissions are denied, normal users could not cause .pyc
creation anymore, causing increased startup costs unless the
.pyc files are created during installation.
msg26237 - (view) Author: Mika Eloranta (mel) Date: 2005-11-15 11:39
Logged In: YES 
user_id=109057

Please consider these points as well:

* The "program files" directory has "sensible" ACLs set by
default (the defaults are different in different OS
versions). If you install your application under "program
files", you do not need to worry about the permissions.

* The installation directory can be added to the PATH
environment variable instead of typing it every time from
console...

* The current default installation directory is teaching
python library developers bad habits of not handling Python
installed into a directory that contains spaces properly. It
is actually a miracle to find a third party library that
installs a working script (batch file) to "python/scripts"
if the python directory contains spaces.

* The "program files" directory is the standard location
where applications should be installed in Windows. This is
what Microsoft requires in their guidelines and most
applications obey them. You would not install python to
"/python24" by default in Unix would you?

msg26238 - (view) Author: Mika Eloranta (mel) Date: 2005-11-19 08:46
Logged In: YES 
user_id=109057

Wow, even easy_install.exe from setuptools fails if python
is installed under "c:\program files":

C:\temp>easy_install
C:\program: can't open file 'files\Python24\python.exe':
[Errno 2] No such file or directory

IMHO the root cause to all these problems is the wrong
default installation directory. If the installation
directory would conform to Windows guidelines, these kind of
problems would have been easily spotted by python library
developers.

    - Mika
msg26239 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2006-03-22 19:09
Logged In: YES 
user_id=21627

I completely disagree. It was wrong to give the system
default binary directory a name with a space in it, on a
system that doesn't provide command line argument vectors in
its standard API.
msg26240 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2006-03-22 20:27
Logged In: YES 
user_id=31435

A long time ago, Python did install (by default) under
"Program Files".  I changed that, because of the endless
problems created by the frickin' embedded space, and rarer
but subtler problems due to "Program Files" not being a
DOSish 8.3 name.  Overall I still think it was a good change.

Note that, unlike most Windows applications (which are
GUI-based), programming languages are _intended_ to be used
heavily from the command line, invoked by scripts, and so
on.  That's what makes a space in the path endlessly
error-prone.  In WinXP Pro, I noticed that MS was still
careful to put its own command-line/script tools (sort.exe,
ipconfig.exe, cscript.exe, ..., even notepad.exe) under pure
DOSish 8.3 space-free paths ;-)
msg26241 - (view) Author: D. Scott Miller (dsmiller) Date: 2006-05-06 01:04
Logged In: YES 
user_id=1517734

Here's a few possible solutions to the permissions problem
that retain the idea of defaulting to an install path with
no spaces without making too many assumptions about what
permissions the installing admin actually wants:
-----------------
Idea #1

Install by default to %systemroot%\PythonXX. Hey, Java
sticks some stuff in there, right? If the idea is "this is
kind of a part-of-the-OS thing, and MS does it this way for
cscript.exe" then this seems to make sense. (We hope any
admins who're using a %systemroot% with spaces in it know
what they're doing.)

Is the default name for %systemroot% different on any
particular localized versions of Windows? I know it's
"WINDOWS" in Japanese versions, anyway.
-----------------
Idea #2

Have two folder select boxes in the installer, one for where
to install Python and one for a folder from which to copy
ACLs. These would default to %systemdrive%\PythonXX and
%programfiles%, respectively. Have a check box to disable
the ACL copying, but have it checked by default.

This is still bad, as it doesn't solve the problem of being
a special separate directory with its own individual ACL to
maintain, but it's somewhat less bad than it is now for
people who click through the installer trusting it to not
open up their system to new flavors of privilege escalation.
-----------------
Idea #3

Do something goofy with NTFS junctions.
-----------------

Regardless of what's done, given that people expect not to
have to worry about spaces these days, it may be a good idea
to include an explanation/warning about the situation in the
installer text.
-----------------

In regards to Martin Löwis' concern about non-admin users
not being able to cause the generation of .pyc files in the
main Python directory tree: It's already like that on most
OS's, correct? So it would just apply in cases where someone
a) writes an add-on specifically targeting the Python
directory tree, specifically for Windows and b) expects .pyc
generation to be done later rather than scripted as part of
the installation. I have no idea if that's common or not,
but it seems relatively safe to break.
msg26242 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2006-06-12 12:26
Logged In: YES 
user_id=21627

Lowering the priority; this is now a documented bug.
msg26243 - (view) Author: Norvell Spearman (norvellspearman) Date: 2006-12-20 15:53
Would installing Python to \PROGRA~1\PythonXX prevent the space-in-filename problems?  This trick has (sometimes) worked for me when installing other programs that don't like spaces.

Another -- albeit inelegant -- solution would be to create a PythonXX directory under "\Program Files", cut and paste it to the root directory, then install Python to it.  I tested this and it seems to preserve the inherited permissions from "\Program Files" -- that is, normal users can't create files or directories in it.
msg58052 - (view) Author: Carl Karsten (carlfk) Date: 2007-12-01 16:02
Another reason to fix: perception.  installing to the root looks like a
hack.  Installing to the proper place* looks professional.  

As for it being hard to type, either add it to PATH or put a .bat file
in the path.  I think vista even supports some sort of symlink, so that
might be best.

As for easy_install.exe and others breaking when they hit a space, They
should be fixed too.  avoiding fixing them means people who try to force
the installer to do the right thing end up with a headache, which is evil.

* proper place isn't always "C:\Program Files" - the installer builder
should have an option to determine what it should be.  The environment
var %ProgramFiles% holds the correct path.  There is an API call too.
msg68683 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2008-06-24 12:52
+1 on using "Program Files" by default.

In addition to the points mentioned above, there are other considerations.

In 64-bit platforms (Windows XP x64 and Vista 64-bit), programs are
segmented by their binary compatibility (C:\Program Files and C:\Program
Files (x86)).  Installing Python to the proper program directory helps
keep it organized as to it's binary compatibility.

Additionally, I often run several version of Python side-by-side, and
having these clutter my root directory is simply unacceptable.

I've been running Python from C:\Program Files for years, and I have
encountered problems, even including the recent setuptools bug, but for
the most part, these issues have been worked out.  I add C:\Program
Files\Python and c:\Program Files\Python\Scripts to my path, and things
work well.  I would think that since only a few issues remain, if Python
is moved to the standard location, any remaining issues can be ironed out.
msg100289 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-03-02 12:31
Note that Ezio and Flox have been improving the test suite and code to handle paths-with-spaces better.  Perhaps we will eventually get to the point where it is possible to fix this, although Tim's point about python being a CLI/scripting tool remains.

Or perhaps the permissions of the actual install directory could be changed at install time if the install is done by an administrator.
msg100290 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-03-02 12:39
This is similar to an issue I reported to the security team (same underlying issue). My concern was that with an admin installed version of Python an arbitrary user can modify site.py, or create sitecustomize.py, and cause arbitrary code execution when the admin runs Python.

IMO an admin installed Python should require admin priveleges to write to the Python install directory. I think many users would find installing to "Program Files" a pain and it would break many scripts.
msg100299 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-03-02 16:18
I personally make heavy use of the command line and continue to install python to %ProgramFiles%. I find the space in the pathname to be a non-issue. After %programfiles%\Python26 and %programfiles%\Python26\Scripts are added to the path, and .py is added to PATHEXT, everything behaves very well. I use cmd.exe and powershell, and both of these shells handle the spaces well enough, including supporting tab completion (so if one _does_ need to reference a path with a space in it, it's not even necessary to know what the syntax is).

With Python 3, support for version of Windows prior to XP (including DOS) has been deprecated, so it seems to me rather regressive to insist on DOS 8.3 compatibility.

I concur that early on, I would struggle with the spaces if Python was installed to %programfiles%, but since about Python 2.3 or 2.4, I've had only the one problem with setuptools, and that has been fixed.

IMO, supporting installation to Program Files is not only the right thing to do, but it will make Python more robust.

On the other hand, I may be unaware of any use cases which are still problematic. Perhaps there are still many who always launch python using \python26\python. That command would then become "\program files\python26\python". I find that to be a small price to pay for the gains in security and consistency (and compartmentalization).

Furthermore, a heavy command-line user is probably also a power user, and if typing "C:\Program Files\Python26\Python" is too onerous, I'm sure he can find a workaround, such as setting the path, creating hardlinks or symlinks, setting up aliases, etc.

I agree it's a shame the de-facto location for Programs on Windows isn't a more amenable name.

Personally, I always override the default installation directory, so it matters to me little what choice is made for the default, but on the whole, I believe users would be better off with Python in Program Files.
msg100301 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-03-02 16:35
I've tried installations of Python to Program Files in recent years (Python 2.4 and 2.5) and found many scripts/tools unable to cope with the space in the path. I always ended up reinstalling. (Usually using sys.executable in conjunction with calling out to shell scripts.)
msg100310 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-03-02 21:43
I propose that people in favor of changing the default install location write a PEP proposing that this be done.

Notice that this is independent of the issue at hand, which is about the ACLs on c:\pythonXY. I have tried fixing it, and failed so far.
msg100312 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-03-02 22:39
Martin: Would it be sufficient to copy the ACLs from %programfiles%, or would it be better to hard-code the permissions from %programfiles% from a known standard configuration? Is it known if the ACLs on %programfiles% in WinXP differ from later platforms? What difficulty have you encountered?
msg100313 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-03-02 22:51
> Martin: Would it be sufficient to copy the ACLs from %programfiles%,
> or would it be better to hard-code the permissions from
> %programfiles% from a known standard configuration? Is it known if
> the ACLs on %programfiles% in WinXP differ from later platforms? What
> difficulty have you encountered?

I can only answer the last question: I tried using the ACL features in
MSI (i.e. with the LockPermissions table), and couldn't get that to work.

Personally, I would think that restricting write access to the user
performing the installation should be good enough.
msg104362 - (view) Author: Fran Rogers (fran.rogers) Date: 2010-04-27 21:06
I'd like to concur that Python should install to %ProgramFiles% by default. The root-directory default is particularly anomalous on 64-bit Windows, where you have separate 64- and 32-bit Program Files directories; if I have a Python installation in "C:\Python26", is it amd64 Python or x86 Python? If I want to install both (since many packages don't yet support amd64), which one should I install to \Python26 and which should I rename?

As mel's post above (2005-11-15 11:39) points out, installing to C:\ is comparable to installing to /python2.6 on a Unix box; it's nonstandard, inelegant, and prone to ACL problems like the one this bug was opened for. If convenience on the command line (for non-power-users unfamiliar with %Path%) is the concern, a better solution would be a checkbox in the installer to add the new Python to the system %Path%.
msg104384 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2010-04-27 23:45
Another consideration here will be how distutils will work in a python with restricted permissions - the pattern of "just run 'setup.py install'" will not work unless it is done from an elevated command-prompt.  As I expect this would frustrate people we'd need some story to address this.

My take is still that Python is a tool, not an app.  People writing an app they with to distribute using Python should include Python in their package (ie, not rely on an installed version) and these apps should conform with the guidelines.
msg122099 - (view) Author: Gynvael Coldwind (Gynvael.Coldwind) Date: 2010-11-22 08:44
(since Issue 10491 is superseded by this one, I'll reply here)

As I've said in issue 10491, in my opinion this is not a case of frustrating users because they have to elevate the console (I think they have to do that in case of UAC anyway), but a case of privilege escalation vulnerability on mutli-user Windows systems with Python installed globally (i.e. in the default installation directory).

Though I am aware there are not many such systems to begin with, I am pretty certain they do exist (think: servers at an University giving Python access to students, and not using *nix for some reason).
There are also non-multi-user systems with multiple accounts (think: production systems running stuff on different accounts), and this issue can be abused as one of many steps during an attack, after gaining shell access, but before gaining administrative rights.

I acknowledge your right to choose not to fix this issue due to usability issues, but in such case imo there should be an explicit message during the installation making the user aware of this insecurity.
The last months revealed issues like this in many applications and tools, and they have (mostly) been patched, so administrators might assume this was also fixed in Python (especially since this is known from 2005).
msg217507 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2014-04-29 10:21
If on one hand I agree that Python being in C:\PythonXX is not optimal for all the reasons which have been mentioned so far, changing such an old established aspect of the interpreter would be too much disruptive as a change.
To say one, being that on Windows 'python' is not recognized as a command, some folks rely on it simply living in C:\Python** and make that assumption into their scripts (I did exactly this in psutil: https://code.google.com/p/psutil/source/browse/make.bat?name=release-2.1.0#23).

I agree with what Martin says here: http://bugs.python.org/issue1284316#msg26236.
We should let Python live in C\:PythonXX and just fix permissions during installation so that when the installation completes C:\PythonXX will not be writable by limited users. 
If this introduces a performance issue because the pyd files cannot be created afterwards then simply create pyd files as part of the installation process (this should be done if "install for all users" option is checked).
msg217516 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2014-04-29 12:45
I still disagree. If the preferable place for Python to be installed is not in the root (and I fervently feel so), then there could be a transitional approach to move it to the appropriate place, such as creating symbolic links from the legacy destinations (as an opt-out option).

Still, as Martin said, a change to the default install location would require a PEP that would have to address these concerns.
msg228480 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2014-10-04 19:17
I'm concerned that 3.5 is creeping ever closer and I wouldn't like to see work done on the installer backed out at the 11th hour because there has been no agreement here.  Does this need a discussion on python-dev?  For that matter has there been one already that I've forgotten about?
msg228482 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2014-10-04 19:20
Mark Lawrence, please stop acting like you are the project leader. If you want to make concrete contributions to Python, you're welcome. But we don't need your project management guidance.
msg228483 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2014-10-04 19:25
Pardon me for breathing.  As you clearly don't like the way I work would you be so kind as to reopen the issues that I've helped close in the last few months.  It might bugger the stats on the bug tracker but hey ho.
msg228485 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2014-10-04 19:31
Nobody doubts that pinging old issues helps getting some of them closed. But messages like msg228480 sound a bit pretentious, that's what Antoine is referring to.
msg228490 - (view) Author: Friedrich Spee von Langenfeld (Friedrich.Spee.von.Langenfeld) Date: 2014-10-04 20:24
As mentioned before, many packages can not handle paths with spaces. I suppose that it is because of lacking knowledge on how to prevent such bugs. What would you think? Should this piece of information be in our documentation? Or is it already there?
msg228491 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2014-10-04 20:34
> As mentioned before, many packages can not handle paths with spaces.

This is "common knowledge", yet may not be true anymore.  See this recent python-dev thread:

https://mail.python.org/pipermail/python-dev/2014-September/136434.html
msg228494 - (view) Author: Eryk Sun (eryksun) * Date: 2014-10-04 21:00
>> As mentioned before, many packages can not handle paths with 
>> spaces.
>
> This is "common knowledge", yet may not be true anymore.  

Well, see issue 21699. pip 1.5.6 is still using distlib 0.1.8, so the executable wrappers it creates are broken when the path to python.exe contains spaces.
msg233376 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2015-01-03 23:42
I'll reassign this to me, as I'm looking into making Program Files the default location for 3.5.

I'd like to release at least some of the alphas with the change active by default (i.e. it's easy to select the old directory) to get broader feedback. So far I haven't encountered any trouble other than in pip (as is being discussed at https://github.com/pypa/pip/issues/1668).

If things don't work well in the early releases of 3.5 we can easily revert the change, though I suspect the main feedback is going to be about the amount of typing required. In that case, I'll look into hardening the permissions on the root directory as part of installation.

Unless some really bad scenarios arise, getting the legacy permissions will be opt-in. As 3.5 will be the first version with that change there shouldn't be any direct back-compat issues - we can't make a change like that in maintenance releases or even 3.4.
msg241157 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2015-04-15 20:35
Closing this as fixed, as the discussions I've had at PyCon have largely suggested that the fix I've implemented is good.

In short:
* the default (obvious) install will be per-user only into %LocalAppData%\Programs\Python\Python35 - fully modifiable by whoever installed it but inaccessible by other users
* the default location for an all-users install will be %ProgramFiles%\Python 3.5 (with redirection for 32-bit processes) - fully modifiable by administrators and usable by all users

Obviously users can customize the install location to reduce security, but we can't prevent that.
History
Date User Action Args
2015-04-15 20:35:43steve.dowersetstatus: open -> closed
resolution: fixed
messages: + msg241157
2015-01-03 23:42:07steve.dowersetassignee: loewis -> steve.dower
messages: + msg233376
versions: - Python 2.7, Python 3.2, Python 3.3, Python 3.4
2014-10-06 14:12:57brian.curtinsetnosy: - brian.curtin
2014-10-04 21:00:25eryksunsetnosy: + eryksun
messages: + msg228494
2014-10-04 20:34:35georg.brandlsetmessages: + msg228491
2014-10-04 20:24:55Friedrich.Spee.von.Langenfeldsetnosy: + Friedrich.Spee.von.Langenfeld
messages: + msg228490
2014-10-04 19:31:15georg.brandlsetnosy: + georg.brandl
messages: + msg228485
2014-10-04 19:25:14BreamoreBoysetmessages: + msg228483
2014-10-04 19:20:20pitrousetnosy: + pitrou
messages: + msg228482
2014-10-04 19:17:37BreamoreBoysetnosy: + BreamoreBoy
messages: + msg228480
2014-04-29 12:45:37jason.coombssetmessages: + msg217516
2014-04-29 10:21:37giampaolo.rodolasetmessages: + msg217507
2014-04-29 09:41:45giampaolo.rodolasetnosy: + giampaolo.rodola

versions: + Python 3.5
2014-04-28 18:13:19steve.dowersetnosy: + steve.dower
2012-11-19 22:29:42pitrousetnosy: + tim.golden
2012-11-18 21:53:15ezio.melottisetversions: + Python 3.3, Python 3.4
2010-11-22 08:44:44Gynvael.Coldwindsetnosy: + Gynvael.Coldwind
messages: + msg122099
2010-11-21 19:17:17loewislinkissue10491 superseder
2010-04-27 23:45:44mhammondsetmessages: + msg104384
2010-04-27 21:06:47fran.rogerssetnosy: + fran.rogers
messages: + msg104362
2010-03-02 22:51:38loewissetmessages: + msg100313
2010-03-02 22:39:41jason.coombssetmessages: + msg100312
2010-03-02 21:43:03loewissetmessages: + msg100310
2010-03-02 16:35:24michael.foordsetmessages: + msg100301
2010-03-02 16:18:54jason.coombssetmessages: + msg100299
2010-03-02 14:32:14brian.curtinsetnosy: + brian.curtin
2010-03-02 12:39:19michael.foordsetmessages: + msg100290
2010-03-02 12:31:36r.david.murraysetnosy: + flox, ezio.melotti, r.david.murray, michael.foord
messages: + msg100289
components: + Windows
2010-03-02 12:26:16r.david.murraylinkissue5802 superseder
2009-05-15 02:48:05ajaksu2setstage: test needed
type: security
versions: + Python 2.7, Python 3.2
2008-10-08 23:05:19mhammondsetnosy: + mhammond
2008-06-24 12:52:09jason.coombssetnosy: + jason.coombs
messages: + msg68683
2007-12-01 16:02:31carlfksetnosy: + carlfk
messages: + msg58052
2005-09-07 21:34:44melcreate