Bugtraq mailing list archives

Re: Apache - all versions vulnerability in OLD procesors.


From: Chris Adams <cmadams () hiwaay net>
Date: Sat, 24 Apr 2004 20:15:14 -0500

Once upon a time, Adam Zabrocki <pi3ki31ny () wp pl> said:
      There are few scenarios, few calls leading to that bug. 
The first call is in mod_auth, mod_auth3 and mod_auth4. As follows:

"src/modules/standard/mod_auth.c"
and
"src/modules/standard/mod_aut3.c"
and
"src/modules/standard/mod_aut4.c"

Apache HTTPD 1.3.29 doesn't include a mod_aut3.c or mod_aut4.c, so this
is not a "default install".

static int authenticate_basic_user(request_rec *r)
{
...
...
    const char *sent_pw;
    char *real_pw;
...
...
    if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
        return res;
...
...
    if (!(real_pw = get_pw(r, c->user, sec->auth_pwfile))) {
       ...
       ...
    }
...
...
    invalid_pw = ap_validate_password(sent_pw, real_pw);
...
...
}

request_rec structure is declared in "src/include/httpd.h".

Now look at ap_validate_password() function in "src/ap/ap_check.c":

You mean src/ap/ap_checkpass.c?

<snip>

    while (count >= SHA_BLOCKSIZE) {
        ebcdic2ascii((AP_BYTE *)sha_info->data, buffer, SHA_BLOCKSIZE);
        buffer += SHA_BLOCKSIZE;
        count -= SHA_BLOCKSIZE;
        maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
        sha_transform(sha_info);
    }
    ebcdic2ascii((AP_BYTE *)sha_info->data, buffer, count);
...
...
}

This whole section only gets called when CHARSET_EBCDIC is defined,
which is only on a few mainframe platforms, so this is not even active
on the vast majority of platforms.

Aha... good, while count is bigger or equal following constant:

"src/ap/ap_sha1.c"
...
...
#define SHA_BLOCKSIZE           64
...
...

Hm... ok, this get's evaluated further more in ebcdic2ascii() ?

"src/ap/ap_ebcdi.c"
API_EXPORT(void *)
ebcdic2ascii(void *dest, const void *srce, size_t count)
{
    unsigned char *udest = dest;
    const unsigned char *usrce = srce;

    while (count-- != 0) {
        *udest++ = os_toascii[*usrce++];
    }

    return dest;
}

Above function copies 64 bytes, structre AP_SHA1_CTX is an array of 16
elements.  Take a look at structure element declaration :

"src/include/ap_sha1.h"
typedef unsigned long AP_LONG;     /* a 32-bit quantity */

This is fine, assuming that we have 32 bits CPU, and sizeof(unsigned
long) equals 4. So 4*16=64.  There is no guarantee that on some archs
unsigned long is going to stay 32 bit width. When it's either longer
or shorter (I am not sure if long can be 16 bits long, but possibly
ANSI C standart doesn't say anythin about it's length in bits). Ie. on
64bit platforms, depending on compiler options, and compiler it self
long can be either 64 (default) or 32 bits. 

See my other message; an unsigned long will always be at least 32 bits
(or a storage size large enough to hold a 32 bit unsigned number, which
I believe on all Apache 1.3 supported platforms will be a binary 32 bit
or 64 bit allocation).

When sizeof( unsigned long )!=4 it can lead to memory corruption in
function ebcdic2ascii(), which will either copy too much, copyied in
this example 32 bytes more than he should and that situaction do this
bug! To bypass this not popular vulnerability we should only
resolution is quite simple, SHA_BLOCKSIZE should be declared as
sizeof(unsigned long)*16.  Possibly SHA_BLOCKSIZE must stay 64 bytes
long, than obviously author should take care more about single
elements size.

I don't see a potential for a problem, because the ->data field is
always at least 64 bytes long, but only the first 64 bytes are used (and
since they are byte-addressed always, there is no uninitialized data
read).

Also, IIRC, the C compilers on the EBCDIC platforms uses a 32 bit
unsigned long, so there would be no problem anyway.
-- 
Chris Adams <cmadams () hiwaay net>
Systems and Network Administrator - HiWAAY Internet Services
I don't speak for anybody but myself - that's enough trouble.


Current thread: