Thread: Fwd: Bug#247306: odbc-postgresql: SIGSEGV with long inputs (> 10000 bytes)

Hi PostgreSQL developers!

A week ago we at Debian received the bug report below: due to a buffer
overflow in psqlodbc it is possible to crash (and possibly exploit)
apache. I already sent this mail to the psqlodbc list [1], but
unfortunately got no response so far. So maybe there are some hackers
here who can help with this?

I can reliably reproduce the error (using the small attached php4
script), but I do not know anything about the psqlodbc internals. I
would be glad if someone could assist me with that.

Thanks in advance and have a nice day!

Martin

[1] http://archives.postgresql.org/pgsql-odbc/2004-05/msg00006.php

----- Forwarded message from delman <delman@despammed.com> -----

Subject: Bug#247306: odbc-postgresql: SIGSEGV with long inputs (> 10000 bytes)
Reply-To: delman <delman@despammed.com>, 247306@bugs.debian.org
From: delman <delman@despammed.com>
To: Debian Bug Tracking System <submit@bugs.debian.org>
Date: Tue, 04 May 2004 15:25:24 +0200
X-Spam-Status: No, hits=0.0 required=4.0 tests=SUBJ_BRACKET_BALANCED,
    SUBJ_BRACKET_OFF,SUBJ_BRACKET_ON autolearn=no version=2.61

Package: odbc-postgresql
Version: 1:07.03.0200-2
Severity: grave
Tags: security
Justification: user security hole


I noticed Apache segfaulting when I feed a simple form with long inputs:

    [Tue May  4 11:32:10 2004] [notice] child pid 4084 exit signal Segmentation fault (11)

Such inputs are used by php function odbc_connect as username and password to connect to a DSN using postgresql driver:

    $connection = @odbc_connect(DSN, $_POST['username'], $_POST['password'])

The output of gdb is:

    (gdb) run -X -d apache
    [...]
    [Thread debugging using libthread_db enabled]
    [...]
    Program received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 1076569920 (LWP 832)]
    0x44c3d627 in SOCK_put_next_byte () from /usr/lib/postgresql/lib/psqlodbc.so

Or:
    [same stuff here]
    0x44c4c3d0 in strncpy_null () from /usr/lib/postgresql/lib/psqlodbc.so

I suspect a security issue because playing around with long input strings of "A" I've been able to trigger in Apache
error.logthis message: 

    free(): invalid pointer 0x41414141!

0x41 is obviously one of my "A"...

Other ODBC related messages found are:

    /usr/sbin/apache: relocation error: AAAA[...]AAA: symbol getDSNdefaults, version not defined in file with link time
reference

The SIGSEGV is triggered with input strings > 10000 bytes. I use Apache/1.3.29 (Debian GNU/Linux) PHP/4.3.4
mod_auth_pam/1.1.1mod_ssl/2.8.16 OpenSSL/0.9.7c 

-- System Information:
Debian Release: testing/unstable
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.6.4
Locale: LANG=C, LC_CTYPE=C

Versions of packages odbc-postgresql depends on:
ii  libc6                       2.3.2.ds1-11 GNU C Library: Shared libraries an
ii  odbcinst1                   2.2.4-9      Support library and helper program

-- no debconf information

----- End forwarded message -----

--
Martin Pitt                 Debian GNU/Linux Developer
martin@piware.de                      mpitt@debian.org
http://www.piware.de             http://www.debian.org

Attachment

Re: Fwd: Bug#247306: odbc-postgresql: SIGSEGV with long inputs (> 10000 bytes)

From
Peter Eisentraut
Date:
Martin Pitt wrote:
> A week ago we at Debian received the bug report below: due to a
> buffer overflow in psqlodbc it is possible to crash (and possibly
> exploit) apache. I already sent this mail to the psqlodbc list [1],
> but unfortunately got no response so far. So maybe there are some
> hackers here who can help with this?

The problem is that the ODBC driver just writes the long user name or
password into its internal data structures without paying attention the
fact that it's only got 256 bytes of space.  (function PGAPI_Connect in
file connection.c)  It's the oldest bug in the book really.


Hi!

On 2004-05-12  1:31 +0200, Peter Eisentraut wrote:
> Martin Pitt wrote:
> > A week ago we at Debian received the bug report below: due to a
> > buffer overflow in psqlodbc it is possible to crash (and possibly
> > exploit) apache. I already sent this mail to the psqlodbc list [1],
> > but unfortunately got no response so far. So maybe there are some
> > hackers here who can help with this?
>
> The problem is that the ODBC driver just writes the long user name or
> password into its internal data structures without paying attention the
> fact that it's only got 256 bytes of space.  (function PGAPI_Connect in
> file connection.c)  It's the oldest bug in the book really.

Thanks for this hint and spotting the error, I think I see the problem
now: PGAPI_Connect calls

        make_string(szDSN, cbDSN, ci->dsn);

to copy the string (and similar with uid and password). ci->dsn is
only MEDIUM_REGISTRY_LEN (256) bytes big, so if cbDSN >= 256, it will
crash. So I suppose the function just has to check the cb* values, and
if one of them is >= 256, return an appropriate error?

Another possibility would be to add a fourth argument to make_string
that specifies the size of the target buffer (and have it copy
max(stringlen, bufferlen-1) bytes). This would force the correction of
all places where make_string is used (just 13, so it should not get
too hard).

Any comments to that?

Thanks,

Martin

--
Martin Pitt                 Debian GNU/Linux Developer
martin@piware.de                      mpitt@debian.org
http://www.piware.de             http://www.debian.org
Martin Pitt wrote:
> The problem is that make_string() in misc.c does not check whether
> the target buffer is big enough to hold the copied string.
>
> I added a bufsize parameter to make_string() and used it in all calls
> to it. I tried it with my php4 crash test script and now it works
> properly.

Silently truncating various pieces of information is probably not the
right thing.  What are you truncating?  If it's a query string you
might open yourself up to SQL-injection type problems.

Plus, the ODBC driver appears to have buffer overruns all over the
place.  We need to replace every instance of strcpy, strcat, sprintf,
make_string, and the various other feeble attempts with pqexpbuffer
from libpq.  That's the only way to solve this problem once and for
all.


Hi!

On 2004-05-13 19:43 +0200, Peter Eisentraut wrote:
> Silently truncating various pieces of information is probably not the
> right thing.

But IMHO still better than overwriting arbitrary other data and code.
If an user supplies bogus input, he cannot expect to get something
sane out.

> What are you truncating?

By now:

- DSN, username, password, and the whole connection string;

- table names in info.c:
  make_string(szTableName, cbTableName, pktab, sizeof(pktab));

- Two calls in info.c:
  make_string(szPkTableName, cbPkTableName, pk_table_needed, sizeof(pk_table_needed));
  make_string(szFkTableName, cbFkTableName, fk_table_needed, sizeof(fk_table_needed));

If these values should not be truncated, then psqlodbc should not use
fixed buffer sizes. Currently truncating them is way more sane than
letting them mess up the whole memory.

> If it's a query string you might open yourself up to SQL-injection
> type problems.

I don't think that the patch affects whole query strings, but of
course I may be wrong. The point of this patch was to fix the most
apparent overflows with least possible changes, and after a week of
silence on the lists I just had to do something about it. And now at
least the connection and exec methods seem to work safely.

> Plus, the ODBC driver appears to have buffer overruns all over the
> place.  We need to replace every instance of strcpy, strcat, sprintf,
> make_string, and the various other feeble attempts with pqexpbuffer
> from libpq.  That's the only way to solve this problem once and for
> all.

I would be glad if the next psqlodbc version would be written in a
sane way, without fixed string lengths and with a clear and safe
string "class" interface. But doing this is far beyond the scope of a
security patch (especially for Debian stable).

One question: which mailing list is the better place to discuss this?
-odbc or -bugs?

Thanks and have a nice day!

Martin

--
Martin Pitt                 Debian GNU/Linux Developer
martin@piware.de                      mpitt@debian.org
http://www.piware.de             http://www.debian.org

Hi again!

Sorry for crossposting, but I sent the initial post also to -bugs,
because I did not get an answer on -odbc.

On 2004-05-11 12:03 +0200, Martin Pitt wrote:
> I noticed Apache segfaulting when I feed a simple form with long inputs:
>
>     [Tue May  4 11:32:10 2004] [notice] child pid 4084 exit signal Segmentation fault (11)
>
> Such inputs are used by php function odbc_connect as username and password to connect to a DSN using postgresql
driver:
>
>     $connection = @odbc_connect(DSN, $_POST['username'], $_POST['password'])
>
> The output of gdb is:
>
>     (gdb) run -X -d apache
>     [...]
>     [Thread debugging using libthread_db enabled]
>     [...]
>     Program received signal SIGSEGV, Segmentation fault.
>     [Switching to Thread 1076569920 (LWP 832)]
>     0x44c3d627 in SOCK_put_next_byte () from /usr/lib/postgresql/lib/psqlodbc.so
>
> Or:
>     [same stuff here]
>     0x44c4c3d0 in strncpy_null () from /usr/lib/postgresql/lib/psqlodbc.so
>
> I suspect a security issue because playing around with long input strings of "A" I've been able to trigger in Apache
error.logthis message: 
>
>     free(): invalid pointer 0x41414141!
>
> 0x41 is obviously one of my "A"...

The problem is that make_string() in misc.c does not check whether the
target buffer is big enough to hold the copied string.

I added a bufsize parameter to make_string() and used it in all calls
to it. I tried it with my php4 crash test script and now it works
properly.

The attached patch is for the current stable release 07.03.0200.

Thanks a lot to Peter Eisentraut for pointing me at the problem origin.

Unless you have a better idea it would be nice if you could apply the
patch to the official sources and also include it in the next release.

I will upload updated Debian packages for unstable and stable this
afternoon (16:00 CEST) if nobody reports a problem or a better
solution.

Thanks in advance,

Martin

--
Martin Pitt                 Debian GNU/Linux Developer
martin@piware.de                      mpitt@debian.org
http://www.piware.de             http://www.debian.org

Attachment