安全研究
安全漏洞
Apache Web Server MIME Boundary远程信息泄露漏洞
发布日期:2003-02-25
更新日期:2003-03-04
受影响系统:
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
- Caldera OpenLinux Server 3.1.1
- Caldera OpenLinux Server 3.1
- Caldera OpenLinux Workstation 3.1.1
- Caldera OpenLinux Workstation 3.1
- Conectiva Linux 8.0
- Conectiva Linux 7.0
- Conectiva Linux 6.0
- Mandrake Linux Corporate Server 1.0.1
- Mandrake Linux 8.1
- Mandrake Linux 8.0
- Mandrake Linux 7.2
- RedHat Linux 7.2
- RedHat Linux 7.1
- RedHat Linux 7.0
- RedHat Linux 6.2
- Sun Solaris 9.0
- Sun Solaris 8.0
BUGTRAQ ID: 6943
Apache是一款流行的开放源代码httpd服务程序。
Apache Web服务程序在生成MIME消息边界(message boundaries)时存在问题,远程攻击者可以利用这个漏洞获得服务器敏感信息。
Apache的把系统敏感信息用在生成的MIME消息边界中,因此攻击者可以在返回信息中获得这些敏感信息,可以进一步对系统进行攻击。OpenBSD提供了补丁使用BASE64编码的随机号来生成MIME边界。
<*链接:http://www.openbsd.org/errata.html
*>
建议:
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* 使用OpenBSD发布的安全补丁:
ftp://ftp.openbsd.org/pub/OpenBSD/patches/3.2/common/008_httpd.patch
Apply by doing:
cd /usr/src
patch -p0 < 008_httpd.patch
And then rebuild and install httpd and it's modules:
cd usr.sbin/httpd
make -f Makefile.bsd-wrapper obj
make -f Makefile.bsd-wrapper depend
make -f Makefile.bsd-wrapper
make -f Makefile.bsd-wrapper install
If httpd had been started, you might want to run
apachectl stop
apachectl start
afterwards.
Index: usr.sbin/httpd/src/main/http_main.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/main/http_main.c,v
retrieving revision 1.25.2.1
retrieving revision 1.25.2.2
diff -u -p -r1.25.2.1 -r1.25.2.2
--- usr.sbin/httpd/src/main/http_main.c 8 Nov 2002 00:04:04 -0000 1.25.2.1
+++ usr.sbin/httpd/src/main/http_main.c 24 Feb 2003 02:09:38 -0000 1.25.2.2
@@ -1,4 +1,4 @@
-/* $OpenBSD: http_main.c,v 1.25.2.1 2002/11/08 00:04:04 jason Exp $ */
+/* $OpenBSD: http_main.c,v 1.25.2.2 2003/02/24 02:09:38 margarida Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -5176,6 +5176,7 @@ static void standalone_main(int argc, ch
}
ap_set_version(); /* create our server_version string */
ap_init_modules(pconf, server_conf);
+ ap_init_etag(pconf);
version_locked++; /* no more changes to server_version */
if(!is_graceful && !is_chrooted)
Index: usr.sbin/httpd/src/main/http_protocol.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/main/http_protocol.c,v
retrieving revision 1.13
retrieving revision 1.13.2.1
diff -u -p -r1.13 -r1.13.2.1
--- usr.sbin/httpd/src/main/http_protocol.c 19 Jul 2002 21:31:16 -0000 1.13
+++ usr.sbin/httpd/src/main/http_protocol.c 24 Feb 2003 02:09:39 -0000 1.13.2.1
@@ -1,3 +1,4 @@
+/* $OpenBSD: http_protocol.c,v 1.13.2.1 2003/02/24 02:09:39 margarida Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
*
@@ -76,6 +77,7 @@
#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
#include <stdarg.h>
#include "http_conf_globals.h"
+#include "ap_sha1.h"
#define SET_BYTES_SENT(r) \
do { if (r->sent_bodyct) \
@@ -276,7 +278,10 @@ static int byterange_boundary(request_re
API_EXPORT(int) ap_set_byterange(request_rec *r)
{
const char *range, *if_range, *match;
+ char *bbuf, *b;
+ u_int32_t rbuf[12]; /* 48 bytes yields 64 base64 chars */
long length, start, end, one_start = 0, one_end = 0;
+ size_t u;
int ranges, empty;
if (!r->clength || r->assbackwards)
@@ -322,8 +327,20 @@ API_EXPORT(int) ap_set_byterange(request
* caller will perform if we return 1.
*/
r->range = range;
- r->boundary = ap_psprintf(r->pool, "%lx%lx",
- r->request_time, (long) getpid());
+ for (u = 0; u < sizeof(rbuf)/sizeof(rbuf[0]); u++)
+ rbuf[u] = htonl(arc4random());
+
+ bbuf = ap_palloc(r->pool, ap_base64encode_len(sizeof(rbuf)));
+ ap_base64encode(bbuf, (const unsigned char *)rbuf, sizeof(rbuf));
+ for (b = bbuf; *b != '\0'; b++) {
+ if (((b - bbuf) + 1) % 7 == 0)
+ *b = '-';
+ else if (!isalnum(*b))
+ *b = 'a';
+ }
+
+ r->boundary = bbuf;
+
length = 0;
ranges = 0;
empty = 1;
@@ -646,7 +663,7 @@ API_EXPORT(int) ap_meets_conditions(requ
* could be modified again in as short an interval. We rationalize the
* modification time we're given to keep it from being in the future.
*/
-API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak)
+API_EXPORT(char *) ap_make_etag_orig(request_rec *r, int force_weak)
{
char *etag;
char *weak;
@@ -3106,4 +3123,164 @@ API_EXPORT(void) ap_send_error_response(
ap_kill_timeout(r);
ap_finalize_request_protocol(r);
ap_rflush(r);
+}
+
+/*
+ * The shared hash context, copies of which are used by all children for
+ * etag generation. ap_init_etag() must be called once before all the
+ * children are created. We use a secret hash initialization value
+ * so that people can't brute-force inode numbers.
+ */
+static AP_SHA1_CTX baseCtx;
+
+int ap_create_etag_state(pool *pconf)
+{
+ u_int32_t rnd;
+ unsigned int u;
+ int fd;
+ const char* filename;
+
+ filename = ap_server_root_relative(pconf, "logs/etag-state");
+ ap_server_strip_chroot(filename, 0);
+
+ if ((fd = open(filename, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, 0640)) ==
+ -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "could not create %s", filename);
+ exit(-1);
+ }
+
+ if (fchown(fd, -1, ap_group_id) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "could not chown %s", filename);
+ exit(-1);
+ }
+
+ /* generate random bytes and write them */
+ for (u = 0; u < 4; u++) {
+ rnd = arc4random();
+ if (write(fd, &rnd, sizeof(rnd)) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "could not write to %s", filename);
+ exit(-1);
+ }
+ }
+
+ close (fd);
+}
+
+API_EXPORT(void) ap_init_etag(pool *pconf)
+{
+ if (ap_read_etag_state(pconf) == -1) {
+ ap_create_etag_state(pconf);
+ if (ap_read_etag_state(pconf) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "could not initialize etag state");
+ exit(-1);
+ }
+ }
+}
+
+int ap_read_etag_state(pool *pconf)
+{
+ struct stat st;
+ u_int32_t rnd;
+ unsigned int u;
+ int fd;
+ const char* filename;
+
+ ap_SHA1Init(&baseCtx);
+
+ filename = ap_server_root_relative(pconf, "logs/etag-state");
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, NULL,
+ "Initializing etag from %s", filename);
+
+ ap_server_strip_chroot(filename, 0);
+
+ if ((fd = open(filename, O_RDONLY|O_NOFOLLOW, 0640)) == -1)
+ return (-1);
+
+ fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP);
+ fchown(fd, -1, ap_group_id);
+
+ if (fstat(fd, &st) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "could not fstat %s", filename);
+ exit(-1);
+ }
+
+ if (st.st_size != sizeof(rnd)*4) {
+ return (-1);
+ }
+
+ /* read 4 random 32-bit uints from file and update the hash context */
+ for (u = 0; u < 4; u++) {
+ if (read(fd, &rnd, sizeof(rnd)) < sizeof(rnd))
+ return (-1);
+
+ ap_SHA1Update_binary(&baseCtx, (const unsigned char *)&rnd,
+ sizeof(rnd));
+ }
+
+ if (close(fd) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "could not properly close %s", filename);
+ exit(-1);
+ }
+}
+
+API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak)
+{
+ AP_SHA1_CTX hashCtx;
+ core_dir_config *cfg;
+ etag_components_t etag_bits;
+ int weak;
+ unsigned char md[SHA_DIGESTSIZE];
+ unsigned int i;
+
+ memcpy(&hashCtx, &baseCtx, sizeof(hashCtx));
+
+ cfg = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ etag_bits = (cfg->etag_bits & (~ cfg->etag_remove)) | cfg->etag_add;
+ if (etag_bits == ETAG_UNSET)
+ etag_bits = ETAG_BACKWARD;
+
+ weak = ((r->request_time - r->mtime <= 1) || force_weak);
+
+ if (r->finfo.st_mode != 0) {
+ if (etag_bits & ETAG_NONE) {
+ ap_table_setn(r->notes, "no-etag", "omit");
+ return "";
+ }
+ if (etag_bits & ETAG_INODE) {
+ ap_SHA1Update_binary(&hashCtx,
+ (const unsigned char *)&r->finfo.st_dev,
+ sizeof(r->finfo.st_dev));
+ ap_SHA1Update_binary(&hashCtx,
+ (const unsigned char *)&r->finfo.st_ino,
+ sizeof(r->finfo.st_ino));
+ }
+ if (etag_bits & ETAG_SIZE)
+ ap_SHA1Update_binary(&hashCtx,
+ (const unsigned char *)&r->finfo.st_size,
+ sizeof(r->finfo.st_size));
+ if (etag_bits & ETAG_MTIME)
+ ap_SHA1Update_binary(&hashCtx,
+ (const unsigned char *)&r->mtime,
+ sizeof(r->mtime));
+ }
+ else {
+ weak = 1;
+ ap_SHA1Update_binary(&hashCtx, (const unsigned char *)&r->mtime,
+ sizeof(r->mtime));
+ }
+ ap_SHA1Final(md, &hashCtx);
+ return ap_psprintf(r->pool, "%s\""
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "\"", weak ? "W/" : "",
+ md[0], md[1], md[2], md[3], md[4], md[5], md[6], md[7],
+ md[8], md[9], md[10], md[11], md[12], md[13], md[14], md[15],
+ md[16], md[17], md[18], md[19]);
}
厂商补丁:
Apache Software Foundation
--------------------------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.apache.org/
浏览次数:4954
严重程度:0(网友投票)
绿盟科技给您安全的保障