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.