首页 -> 安全研究

安全研究

安全漏洞
Apache mod_digest客户提供Nonce确认漏洞

发布日期:2004-02-04
更新日期:2004-02-11

受影响系统:
Apache Software Foundation Apache 1.3.29
Apache Software Foundation Apache 1.3.28
Apache Software Foundation Apache 1.3.27
Apache Software Foundation Apache 1.3.26
Apache Software Foundation Apache 1.3.25
Apache Software Foundation Apache 1.3.24
Apache Software Foundation Apache 1.3.23
Apache Software Foundation Apache 1.3.22
Apache Software Foundation Apache 1.3.20
Apache Software Foundation Apache 1.3.19
Apache Software Foundation Apache 1.3.18
Apache Software Foundation Apache 1.3.17
Apache Software Foundation Apache 1.3.14
Apache Software Foundation Apache 1.3.12
Apache Software Foundation Apache 1.3.11
Apache Software Foundation Apache 1.3
描述:
BUGTRAQ  ID: 9571
CVE(CAN) ID: CVE-2003-0987

Apache是一款流行的WEB服务程序。

Apache mod_digest模块没有充分验证针对用户提供的nonces信息,远程攻击者可以利用这个漏洞可以从其他站点伪造应答信息。

这个漏洞只有在伪造站和服务器上的用户的用户名密码相同,及实际名也相同的情况下产生,不过这种情况比较少。

<*来源:Dirk-Willem van Gulik
        OpenPKG (openpkg@openpkg.org
  
  链接:dev@httpd.apache.org/msg19005.html" target="_blank">http://www.mail-archive.com/dev@httpd.apache.org/msg19005.html
        http://marc.theaimsgroup.com/?l=bugtraq&m=108437852004207&w=2
        http://www.linux-mandrake.com/en/security/2004/2004-046.php
        http://www.linux-mandrake.com/en/security/2004/2004-046.php
        http://www.auscert.org.au/render.html?it=4608
        http://security.gentoo.org/glsa/glsa-200405-22.xml
*>

建议:
临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* 如果不需要mod_digest模块,就关闭此模块,或者使用mod_auth_digest代替。

厂商补丁:

Apache Software Foundation
--------------------------
Apache 1.3.30的参考补丁:

Index: include/http_core.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/http_core.h,v
retrieving revision 1.71
diff -u -r1.71 http_core.h
--- include/http_core.h 7 Jul 2003 00:34:09 -0000       1.71
+++ include/http_core.h 18 Dec 2003 17:30:29 -0000
@@ -162,6 +162,7 @@

API_EXPORT(const char *) ap_auth_type (request_rec *);
API_EXPORT(const char *) ap_auth_name (request_rec *);
+API_EXPORT(const char *) ap_auth_nonce (request_rec *);
API_EXPORT(int) ap_satisfies (request_rec *r);
API_EXPORT(const array_header *) ap_requires (request_rec *);

@@ -244,6 +245,7 @@
     int satisfy;
     char *ap_auth_type;
     char *ap_auth_name;
+    char *ap_auth_nonce;       /* digest auth */
     array_header *ap_requires;

     /* Custom response config. These can contain text or a URL to redirect to.
Index: main/http_core.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v
retrieving revision 1.327
diff -u -r1.327 http_core.c
--- main/http_core.c    17 Nov 2003 17:14:53 -0000      1.327
+++ main/http_core.c    18 Dec 2003 17:30:30 -0000
@@ -236,6 +236,9 @@
     if (new->ap_auth_name) {
         conf->ap_auth_name = new->ap_auth_name;
     }
+    if (new->ap_auth_nonce) {
+        conf->ap_auth_nonce= new->ap_auth_nonce;
+    }
     if (new->ap_requires) {
         conf->ap_requires = new->ap_requires;
     }
@@ -577,6 +580,29 @@
     return conf->ap_auth_name;
}

+API_EXPORT(const char *) ap_auth_nonce(request_rec *r)
+{
+    core_dir_config *conf;
+    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+                                                  &core_module);
+    if (conf->ap_auth_nonce)
+       return conf->ap_auth_nonce;
+
+    /* Ideally we'd want to mix in some per-directory style
+     * information; as we are likely to want to detect replay
+     * across those boundaries and some randomness. But that
+     * is harder due to the adhoc nature of .htaccess memory
+     * structures, restarts and forks.
+     *
+     * But then again - you should use AuthNonce in your config
+     * file if you care. So the adhoc value should do.
+     */
+    return ap_psprintf(r->pool,"%lu%lu%lu%lu%lu%s",
+       *(unsigned long *)&((r->connection->local_addr).sin_addr ),
+       ap_user_name, ap_listeners, ap_server_argv0, ap_pid_fname
+    );
+}
+
API_EXPORT(const char *) ap_default_type(request_rec *r)
{
     core_dir_config *conf;
@@ -2797,6 +2823,28 @@
     return NULL;
}

+/*
+ * Load an authorisation nonce into our location configuration, and
+ * force it to be in the 0-9/A-Z realm.
+ */
+static const char *set_authnonce (cmd_parms *cmd, void *mconfig, char *word1)
+{
+    core_dir_config *aconfig = (core_dir_config *)mconfig;
+    int i;
+
+    aconfig->ap_auth_nonce = ap_escape_quotes(cmd->pool, word1);
+
+    if (strlen(aconfig->ap_auth_nonce) > 510)
+               return "AuthNonce lenght limited to 510 chars for browser
compatibility";
+
+    for(i=0;i<strlen(aconfig->ap_auth_nonce );i++)
+       if (!ap_isalnum(aconfig->ap_auth_nonce [i]))
+               return "AuthNonce limited to 0-9 and A-Z range for browser
compatibilty";
+
+    return NULL;
+}
+
+
#ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
static const char *set_bs2000_account(cmd_parms *cmd, void *dummy, char *name)
{
@@ -3411,6 +3459,9 @@
   "An HTTP authorization type (e.g., \"Basic\")" },
{ "AuthName", set_authname, NULL, OR_AUTHCFG, TAKE1,
   "The authentication realm (e.g. \"Members Only\")" },
+{ "AuthNonce", set_authnonce, NULL, OR_AUTHCFG, TAKE1,
+  "An authentication token which should be different for each logical realm. "\
+  "A random value or the servers IP may be a good choise.\n" },
{ "Require", require, NULL, OR_AUTHCFG, RAW_ARGS,
   "Selects which authenticated users or groups may access a protected space" },
{ "Satisfy", satisfy, NULL, OR_AUTHCFG, TAKE1,
Index: main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.330
diff -u -r1.330 http_protocol.c
--- main/http_protocol.c        3 Feb 2003 17:13:22 -0000       1.330
+++ main/http_protocol.c        18 Dec 2003 17:30:32 -0000
@@ -76,6 +76,7 @@
#include "util_date.h"          /* For parseHTTPdate and BAD_DATE */
#include <stdarg.h>
#include "http_conf_globals.h"
+#include "util_md5.h"          /* For digestAuth */

#define SET_BYTES_SENT(r) \
   do { if (r->sent_bodyct) \
@@ -1391,11 +1392,24 @@

API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r)
{
+    /* We need to create a nonce which:
+     * a) changes all the time (see r->request_time)
+     *    below and
+     * b) of which we can verify that it is our own
+     *    fairly easily when it comes to veryfing
+     *    the digest coming back in the response.
+     * c) and which as a whole should not
+     *    be unlikely to be in use anywhere else.
+     */
+    char * nonce_prefix = ap_md5(r->pool,
+       ap_psprintf(r->pool, "%s%lu",
+               ap_auth_nonce(r), r->request_time));
+
     ap_table_setn(r->err_headers_out,
            r->proxyreq == STD_PROXY ? "Proxy-Authenticate"
                  : "WWW-Authenticate",
-           ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%lu\"",
-               ap_auth_name(r), r->request_time));
+           ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%s%lu\"",
+               ap_auth_name(r), nonce_prefix, r->request_time));
}

API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
Index: modules/standard/mod_digest.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_digest.c,v
retrieving revision 1.52
diff -u -r1.52 mod_digest.c
--- modules/standard/mod_digest.c       3 Feb 2003 17:13:27 -0000       1.52
+++ modules/standard/mod_digest.c       18 Dec 2003 17:30:32 -0000
@@ -316,6 +316,23 @@

/* The actual MD5 code... whee */

+/* Check that a given nonce is actually one which was
+ * issued by this server in the right context.
+ */
+static int check_nonce(pool *p, char * prefix, const char * nonce) {
+    char * timestamp = (char *)nonce + 2 * MD5_DIGESTSIZE;
+    char * md5;
+
+    if (strlen(nonce) < MD5_DIGESTSIZE)
+       return AUTH_REQUIRED;
+
+    md5 = ap_md5(p, ap_pstrcat(p, prefix, timestamp, NULL));
+
+    return strncmp(md5, nonce, 2 * MD5_DIGESTSIZE);
+}
+
+/* Check the digest itself.
+ */
static char *find_digest(request_rec *r, digest_header_rec * h, char *a1)
{
     return ap_md5(r->pool,
@@ -339,7 +356,6 @@
/* Determine user ID, and check if it really is that user, for HTTP
  * basic authentication...
  */
-
static int authenticate_digest_user(request_rec *r)
{
     digest_config_rec *sec =
@@ -355,7 +371,15 @@

     if (!sec->pwfile)
        return DECLINED;
-
+
+    /* Check that the nonce was one we actually issued. */
+    if (check_nonce(r->pool, ap_auth_nonce(r), response->nonce)) {
+       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+                   "Client us using a nonce not issued by us for this context: %s",
r->uri);
+       ap_note_digest_auth_failure(r);
+       return AUTH_REQUIRED;
+    }
+
     if (!(a1 = get_hash(r, c->user, sec->pwfile))) {
        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
                    "user %s not found: %s", c->user, r->uri);

浏览次数:4527
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障