[ python-Bugs-1003471 ] Python 1.5.2 security vulnerability still present in 2.3.4

SourceForge.net noreply at sourceforge.net
Mon Aug 9 20:43:21 CEST 2004


Bugs item #1003471, was opened at 2004-08-04 14:42
Message generated for change (Comment added) made by tim_one
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1003471&group_id=5470

Category: Python Interpreter Core
Group: Python 2.3
Status: Open
Resolution: None
Priority: 5
Submitted By: Kirby Kuehl (vacuum)
Assigned to: Nobody/Anonymous (nobody)
Summary: Python 1.5.2 security vulnerability still present in 2.3.4 

Initial Comment:
First off, I realize that Python 1.5.2 is old, I am just 
reporting it to be thorough.

I was doing a security audit of an application that used 
this old version of python and found the following bug in 
the joinpath function.

#0  0xff133bf0 in strncpy () from /usr/lib/libc.so.1
(gdb) bt

#0  0xff133bf0 in strncpy () from /usr/lib/libc.so.1
(gdb) bt
#0  0xff133bf0 in strncpy () from /usr/lib/libc.so.1
#1  0x000304e0 in joinpath (buffer=0x83528 'A' 
<repeats 200 times>..., 
    stuff=0x84140 'A' <repeats 200 times>...) 
at ./getpath.c:255
#2  0x00030604 in search_for_prefix 
(argv0_path=0xffbff530 "/opt/OPSW/bin", 
    home=0xff3a0840 'A' <repeats 200 times>...) 
at ./getpath.c:300
#3  0x00030a48 in calculate_path () at ./getpath.c:481
#4  0x00030e6c in Py_GetProgramFullPath () 
at ./getpath.c:634
#5  0x0002dcac in _PySys_Init () at sysmodule.c:413
#6  0x0002b414 in Py_Initialize () at pythonrun.c:142
#7  0x0001755c in Py_Main (argc=1, argv=0xffbffcdc) 
at main.c:245
#8  0x000171f0 in main (argc=1, argv=0xffbffcdc) at 
python.c:12
#8  0x000171f0 in main (argc=1, argv=0xffbffcdc) at 
python.c:12
(gdb) frame 1
#1  0x000304e0 in joinpath (buffer=0x83528 'A' 
<repeats 200 times>..., 
    stuff=0x84140 'A' <repeats 200 times>...) 
at ./getpath.c:255
255     ./getpath.c: No such file or directory.
        in ./getpath.c


snippet from Python-1.5.2/Modules/getpath.c :

static void
joinpath(buffer, stuff)
    char *buffer;
    char *stuff;
{
    int n, k;
    if (stuff[0] == SEP)
        n = 0;
    else {
        n = strlen(buffer);
        if (n > 0 && buffer[n-1] != SEP && n < 
MAXPATHLEN)
            buffer[n++] = SEP;
    }
    k = strlen(stuff);
    if (n + k > MAXPATHLEN)
        k = MAXPATHLEN - n;
    strncpy(buffer+n, stuff, k);
    buffer[n+k] = '\0';
}

further examining the backtrace:
(gdb) print n
$1 = 4999
(gdb) print k
$2 = -3975

(gdb) print buffer
$4 = 0x83528 'A' <repeats 200 times>...
(gdb) print stuff
$5 = 0x84140 'A' <repeats 200 times>...

if (n + k > MAXPATHLEN) /* NOTE: MAXPATHLEN is 1024 
*/
        k = MAXPATHLEN - n; /* NOTE: here k is 1024 - 
4999  which is the -3975 */

Which of course crashes in strncpy(buffer+n, stuff, k);


Thanks,
Kirby Kuehl





----------------------------------------------------------------------

>Comment By: Tim Peters (tim_one)
Date: 2004-08-09 14:43

Message:
Logged In: YES 
user_id=31435

vacuum, are you saying that sharefuzz provokes an actual 
bug in Python 2.4a2?  In Python 2.3.4?

----------------------------------------------------------------------

Comment By: Kirby Kuehl (vacuum)
Date: 2004-08-09 14:26

Message:
Logged In: YES 
user_id=116409

Use the sharefuzz utility that I referenced in another 
comment. Then call any function that will invoke the joinpath 
function call.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-08-09 13:56

Message:
Logged In: YES 
user_id=31435

The patch didn't intend to fix a bug that's known to exist.  
Python 2.0 presumably fixed the bugs here, but in a shaky 
way, relying on dozens of distinct call sites to establish an 
undocumented precondition.  joinpath() suffers a buffer 
overrun if the precondition isn't met.  The patch verifies that 
the precondition *is* met, killing the Python process if it's 
not.  That should never happen, but joinpath() is called on so 
many distinct code paths that "eyeball analysis" is inadequate.

To test the patch, change any of joinpath's call sites to 
violate the precondition, and see that Python dies then.  The 
OP suggested a driver to provoke an envar attack, in the 
2004-08-07 14:15 comment.

----------------------------------------------------------------------

Comment By: A.M. Kuchling (akuchling)
Date: 2004-08-09 13:39

Message:
Logged In: YES 
user_id=11375

How would I go about testing the patch?  Where can I find
code that tickles the bug?


----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-08-07 21:01

Message:
Logged In: YES 
user_id=31435

I checked in the attached patch too.  If there's ever another 
release in the 2.3 line, these patches would make decent 
backport candidates.

----------------------------------------------------------------------

Comment By: Kirby Kuehl (vacuum)
Date: 2004-08-07 18:19

Message:
Logged In: YES 
user_id=116409

As tim_one poin

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-08-07 15:15

Message:
Logged In: YES 
user_id=31435

Unassigned myself, since I did all I can here.  Someone on 
Linux should test the patch I attached.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-08-07 15:13

Message:
Logged In: YES 
user_id=31435

I checked in the change to PC/getpathp.c, which is used on 
Windows.  I'm attaching a patch to Modules/getpath.c, which 
isn't used on Windows (so I can't test it).

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-08-07 14:44

Message:
Logged In: YES 
user_id=31435

I'm going to add the panic-check I suggested -- this code is 
too complicated to have any confidence in "eyeball analysis" 
over time.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-08-07 14:39

Message:
Logged In: YES 
user_id=31435

Yup, and rev 1.32 intended to plug the envar attack.

----------------------------------------------------------------------

Comment By: Kirby Kuehl (vacuum)
Date: 2004-08-07 14:15

Message:
Logged In: YES 
user_id=116409

by exporting environment variables. Check sharefuzz which
can be found here:
http://www.atstake.com/research/tools/index.html#vulnerability_scanning


----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2004-08-07 12:43

Message:
Logged In: YES 
user_id=31435

Pretty compilcated internally.  A very similar joinpath still 
exists.  While it's not documented or checked, joinpath's code 
clearly *assumes* strlen(buffer) <= MAXPATHLEN on entry.  
But it's called from 25 places, and it's not immediately obvious 
that all call sites guarantee this on all paths.

Rev 1.32 of getpath (for Python 2.0) *intended* to fix buffer 
overflow problems, mostly by changing unsafe strcpy() calls 
to strncpy() calls.

This is delicate, though.  I'd be a lot happier if joinpath 
verified that n <= MAXPATHLEN on entry, and called 
Py_FatalError() if not so (converting a buffer overrun into a 
bug report).

----------------------------------------------------------------------

Comment By: Michael Hudson (mwh)
Date: 2004-08-07 11:55

Message:
Logged In: YES 
user_id=6656

I'm not sure I understand.  How do you get n to be so huge?

At any rate, I don't think the bug is present in modern Python, but 
until I understand how this one was triggered, I'm not prepared to 
be sure...

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1003471&group_id=5470


More information about the Python-bugs-list mailing list