Re: Apache - all versions vulnerability in OLD procesors.
Once upon a time, Adam Zabrocki <pi3ki31ny@xxxxx> 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@xxxxxxxxxx>
Systems and Network Administrator - HiWAAY Internet Services
I don't speak for anybody but myself - that's enough trouble.