The OpenNET Project
 
Search (keywords):  SOFT ARTICLES TIPS & TRICKS SECURITY
LINKS NEWS MAN DOCUMENTATION


[UNIX] Apache Memory Corruption in Various Architectures


<< Previous INDEX Search src Set bookmark Go to bookmark Next >>
Date: 26 Apr 2004 12:54:22 +0200
From: SecuriTeam <[email protected]>
To: [email protected]
Subject: [UNIX] Apache Memory Corruption in Various Architectures

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html 

- - - - - - - - -



  Apache Memory Corruption in Various Architectures
------------------------------------------------------------------------


SUMMARY

The  <http://www.apache.org/>; Apache Software Foundation's HTTP Server is 
"an effort to develop and maintain an open-source HTTP server for modern 
operating systems including UNIX and Windows NT. The goal of this project 
is to provide a secure, efficient and extensible server that provides HTTP 
services in sync with the current HTTP standards".

The Apache HTTP server contains a bug in the way it handles SHA (Secure 
Hash) contexts. In various processor architectures the possibility exists 
that memory corruption can occur.

DETAILS

Vulnerable Systems:
 * Apache HTTP server, all versions as of 1.3.29

The problem lies in the fact that while copying a SHA context, the program 
calculates the number of bytes to copy based on the size of the unsigned 
long integer type. In effect, on architectures where the size of an 
unsigned long is not 32-bit, possible memory corruption can occur. There 
are several places in the code that lead to the same vulnerable section of 
code:
"src/modules/standard/mod_auth.c"
and
"src/modules/standard/mod_aut3.c"
and
"src/modules/standard/mod_aut4.c"
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);
..
..
}

While the request_rec structure is declared in "src/include/httpd.h". 
Taking a closer look at the ap_validate_password() in the 
"src/ap/ap_check.c" file:
API_EXPORT(char *) ap_validate_password(const char *passwd, const char 
*hash)
{
    char sample[120];
..
..
    /* Netscape / SHA1 ldap style strng
     */
    else if (strncmp(hash, AP_SHA1PW_ID, AP_SHA1PW_IDLEN) == 0) {

        ap_sha1_base64(passwd, strlen(passwd), sample);
    }
..
..
}

While AP_SHA1PW_ID in "src/include/ap_sha1.h" is defined as:
..
..
#define AP_SHA1PW_ID "{SHA}"
..
..

In order for the strncmp hash to be zero, the above should be the password 
for the ap_get_basic_auth_pw() function:
"src/main/http_pro.c"
API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
{
..
..
}

The second argument, pw is evaluated inside ap_validate_password that is 
called from inside get_pw():
"src/modules/standard/mod_auth.c"
static char *get_pw(request_rec *r, char *user, char *auth_pwfile)
{
..
..
}

Now, the function ap_validate_password calls ap_sha1_base64(). Taking a 
closer look shows:
"src/ap/ap_sha1.c"
API_EXPORT(void) ap_sha1_base64(const char *clear, int len, char *out)
{
..
..
    AP_SHA1_CTX context;
..
..
    ap_SHA1Init(&context);
    ap_SHA1Update(&context, clear, len);
..
..
}

AP_SHA1_CTX:

"src/ap/ap_sha1.c"
typedef struct {
    AP_LONG digest[5];             /* message digest */
    AP_LONG count_lo, count_hi;    /* 64-bit bit count */
    AP_LONG data[16];              /* SHA data buffer */
    int local;                     /* unprocessed amount in data */
} AP_SHA1_CTX;

Taking note of the type of AP_LONG and looking at ap_SHA1Init():
"src/ap/ap_sha1.c"
API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *sha_info)
{
    sha_info->digest[0] = 0x67452301L;
    sha_info->digest[1] = 0xefcdab89L;
    sha_info->digest[2] = 0x98badcfeL;
    sha_info->digest[3] = 0x10325476L;
    sha_info->digest[4] = 0xc3d2e1f0L;
    sha_info->count_lo = 0L;
    sha_info->count_hi = 0L;
    sha_info->local = 0;
}

"src/ap/ap_sha1.c"
API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *sha_info, const char *buf,
                               unsigned int count)
{
..
..
    const AP_BYTE *buffer = (const AP_BYTE *) buf;
..
..
    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);
..
..
}

Notice the loop with the condition that count has to be greater or equal 
to the following contant:
"src/ap/ap_sha1.c"
..
..
#define SHA_BLOCKSIZE           64
..
..

And what happens 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;
}

The above function copies 64 bytes, but the AP_SHA1_CTX structure is an 
array of 16 elements. Take a look at the structure's element declaration:
"src/include/ap_sha1.h"
typedef unsigned long AP_LONG;     /* a 32-bit quantity */

Assuming that an unsigned long is indeed 32-bit (4 bytes), the function 
will indeed copy only 64 bytes of data into the context structure. However 
on architectures other than, 80x86, there is no guarantee that the size of 
unsigned long would be 32-bit. On 64-bit platforms it could very well be 
possible with some compiler options. When the sizeof(unsigned long) is not 
4 bytes, memory corruption can occur in the ebcdic2ascii() function.


ADDITIONAL INFORMATION

The information has been provided by  <mailto:[email protected]> Adam 
Zabrocki.




This bulletin is sent to members of the SecuriTeam mailing list. To unsubscribe from the list, send mail with an empty subject line and body to: [email protected] In order to subscribe to the mailing list, simply forward this email to: [email protected]

DISCLAIMER: The information in this bulletin is provided "AS IS" without warranty of any kind. In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.

<< Previous INDEX Search src Set bookmark Go to bookmark Next >>



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру