Repository navigation
CVE-2008-5983 python: untrusted python modules search path #50003
Description
Activity
Common Vulnerabilities and Exposures assigned an identifier
CVE-2008-5983 (and related CVE ids) to the following vulnerability:Untrusted search path vulnerability in the PySys_SetArgv API function in
Python 2.6 and earlier, and possibly later versions, prepends an empty
string to sys.path when the argv[0] argument does not contain a path
separator, which might allow local users to execute arbitrary code via a
Trojan horse Python file in the current working directory.References:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5983
https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2008-5983
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5984
https://bugzilla.redhat.com/show_bug.cgi?id=481551
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5985
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5986
https://bugzilla.redhat.com/show_bug.cgi?id=481550
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5987
https://bugzilla.redhat.com/show_bug.cgi?id=481553
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0314
http://bugzilla.gnome.org/show_bug.cgi?id=569214
https://bugzilla.redhat.com/show_bug.cgi?id=481556
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0315
https://bugzilla.redhat.com/show_bug.cgi?id=481560
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0316
https://bugzilla.redhat.com/show_bug.cgi?id=481565
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0317
https://bugzilla.redhat.com/show_bug.cgi?id=481570
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0318
https://bugzilla.redhat.com/show_bug.cgi?id=481572- addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-securityA security issueA security issue
on Apr 14, 2009 To sum up the behavior, the following table displays whether
modules are read from the current working directory for various
ways how the python scripts can be launched (unfixed/fixed version):unfixed fixed run as ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ yes no python test.py yes no python ./test.py yes no python /tmp/396/test.py yes no /bin/env python test.py yes yes test.py yes yes ./test.py yes yes /tmp/396/test.py yes yes /usr/bin/python test.py yes yes /usr/bin/python ./test.py yes yes /usr/bin/python /tmp/396/test.py no no test-in-different-dir.py no no ./bin/test-in-different-dir.py no no python ./bin/test-in-different-dir.pyAs no longer work of "python ./foo.py" after patch utilization may
cause, the update won't be acceptable, could you guys review the
above patch and potentially provide an another one?Just drop into /tmp and run (you will need the zenity package installed):
python3.1 ./test.py
or
gedit # unfixed gedit
in that directory.
What is the problem exactly?
An user can run arbitrary Python code from a file in his own account --
well, sure, that's a feature. Unless I'm misunderstanding something.I wanted to read the patch at
https://bugzilla.redhat.com/attachment.cgi?id=334888 but apparently its
access is restricted...Antoine,
The problem is that apparently every program that embeds Python calls
PySys_SetArgv and does not understand the consequences of doing so. For
example, a user running 'gedit' to edit some files in a potentially
insecure directory may not expect that starting the program there will
cause it to load python files from that directory.The 'python' executable itself is not really "vulnerable" in quite the
same way, because if you (i.e. a developer) start 'python' in some
directory, you *do* typically expect that it will load code from that
directory. For applications written *in* python, that have scripts in,
let's say, /usr/bin, the directory added to the path is /usr/bin, not
the application's working directory.I'm not sure we can change the behaviour of PySys_SetArgv() like that.
At least not in a bugfix release.
In 2.7/3.1, we could either change PySys_SetArgv(), or introduce a new
PySys_SetArgvEx() with an additional argument indicating whether
sys.path should be modified or not. I suggest asking on python-dev first.both the behavior change and PySys_SetArgvEx() with an additional
boolean parameter sounds good to me.Some people may disagree about changing the default behavior. So long
as its documented in the whatsnew I personally think it is fine. But
would doing that require incrementing the API version number?+1 on adding a PySys_SetArgvEx() in time for 3.1 (the clock is ticking
fast).+0 on the existing API default change.
By the way, the advantage of a new function over a behaviour change is
that the new function could safely be backported to 2.6.3, since it is
also a "security fix".Here is a patch for trunk.
Jan, would the new API be ok to you?
25 remaining items
Can anyone move this to Stage: patch review (for the fix approach proposed in msg90336)? Or does anyone have better idea on how to move this closer to final fix or wontfix / reject? Thank you!
Can anyone move this to Stage: patch review (for the fix approach
proposed in msg90336)? Or does anyone have better idea on how to move
this closer to final fix or wontfix / reject? Thank you!I stand by my opinion that adding another hack in the initialization
path will not do us a lot of good, while a separate API would solve the
problem neatly. Perhaps Dave Malcolm can chime in?FWIW I agree with Antoine.
Attempting to summarize IRC discussion about this.
PySys_SetArgv is used to set up sys.argv There is plenty of code which assumes that this is a list containing at least a zeroth string element; for example warnings.warn (see msg89688).
It seems reasonable for an program that embeds Python to have no arguments, and for this case, it makes sense for sys.argv to be [""] (i.e. a list containing a single empty string).
However, in this case, it doesn't necessarily make sense to prepend the empty string to the front of sys.path
Looking through Python/sysmodule.c: if argc is 0 in the call to PySys_SetArgv, it looks like makeargvobject makes sys.argv be [""] (which is good), but it looks like it uses argc[0] (as "argv") to prepend sys.path.
My reading of PySys_SetArgv is that if argv is NULL, then "char *argv0 = argv[0];" will read through NULL and thus will segfault on a typical platform.
So one possible way to handle this might be to support PySys_SetArgv(0, NULL) as signifying that sys.argv should be set to [""] with no modification of sys.path
This Google code search for "pysys_setargv(0" shows 25 hits:
http://www.google.com/codesearch?hl=en&lr=&q=pysys_setargv\\(0&sbtn=SearchHoever, the function is complicated, and adding more special-cases seems error-prone.
I favor Antoine's approach in http://bugs.python.org/file13860/setargvex.patch of adding a new API entry point, whilst maximizing compatibilty for all of the code our there using the existing entry point.
I think that both the old and the new entry point need to have better documentation, in particular, spelling out the meaning of the args, what the effect of argc==0 is, and that argv must be non-NULL in the old entry point, but may be NULL for argc==0 in the new entry point (assuming that I'm reading that correctly).
Ok, I will try to write better documentation.
My reading of PySys_SetArgv is that if argv is NULL, then
"char *argv0 = argv[0];" will read through NULL and thus will
segfault on a typical platform.Right.
I favor Antoine's approach in
http://bugs.python.org/file13860/setargvex.patch of adding a new API
entry point, whilst maximizing compatibilty for all of the code our
there using the existing entry point.Sadly, this won't help existing applications affected by this problem, without all of them needing to be changed.
My change proposed in msg90336 won't help either, at least not in all cases. Apps that call PySys_SetArgv with 1, { "myappname", NULL } can still be tricked to add full CWD path at the beginning of sys.path on platforms with realpath().
Here is a new patch giving more details in the doc, and explicitly mentioning the CVE entry.
+ - If the name of an existing script is passed in ``argv[0]``, its absolute
+ path is prepended to :data:`sys.path`Absolute path to the directory where script is located. And I believe there's no absolute path guarantee for platforms without realpath / GetFullPathName.
Should the documentation also give some guidance to those that embed python and don't want to start using SetArgvEx right away and break compatibility with older python versions? Something like:
If you're embedding python in your application, using SetArgv and don't want modified sys.path, call PyRun_SimpleString("sys.path.pop(0)\n"); after SysArgv to unconditionally drop the first sys.path argument added by SetArgv.
Absolute path to the directory where script is located. And I believe
there's no absolute path guarantee for platforms without realpath /
GetFullPathName.Yes, this is more precise indeed. As for realpath(), I would expect it
to be present on modern Unices (man page says "4.4BSD, POSIX.1-2001").If you're embedding python in your application, using SetArgv and
don't want modified sys.path, call
PyRun_SimpleString("sys.path.pop(0)\n"); after SysArgv to
unconditionally drop the first sys.path argument added by SetArgv.I suppose
PyRun_SimpleString("import sys; sys.path.pop(0)\n");
would be better.
Thanks for the comments, I'll update the patch.Committed in r81398 (trunk), r81399 (2.6), r81400 (py3k), r81401 (3.1). Thank you!
Demo/embed/demo.c calls PySys_SetArgv(), which may be where
some people are copying their code from. I've updated it to
use PySys_SetArgvEx() and added an explanatory comment in rev. 81881.Since the function was also added to 2.6, the 2.6 What's New should mention it; added in rev81887.
This issue is equivalent to MS Windows DLL hijacking (the MS situation is worse, because the DDL can be in network shares or, even , in remote webdav servers):
http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
http://news.cnet.com/8301-27080_3-20014625-245.htmlWhen I learned about this attack, my first thought was "what if sys.path.index('')>=0?". Arg!.
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: