[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#168350: Security patch for Apache-SSL



Package: apache-ssl
Version: 1.3.26.1+1.48-0woody2
Severity: critical
Tags: security patch sid fixed

We had to issue an advisory against a couple of bugs in the Apache
package.  Most of them are fixed in the 1.3.27 version, some others
aren't, though.  These patches aren't included in the new upstream
release and should be applied to the package in unstable as well:

security_htdigest_bufferoverflow
security_htdigest_tempfiles
security_htpasswd_tempfiles

Below please find the patch we used in the security update for stable.

Regards,

	Joey


diff -u -Nur --exclude CVS orig/apache-ssl-1.3.26.1+1.48/debian/changelog apache-ssl-1.3.26.1+1.48/debian/changelog
--- orig/apache-ssl-1.3.26.1+1.48/debian/changelog	2002-10-26 11:33:50.000000000 +0200
+++ apache-ssl-1.3.26.1+1.48/debian/changelog	2002-10-26 11:23:58.000000000 +0200
@@ -1,3 +1,16 @@
+apache-ssl (1.3.26.1+1.48-0woody3) stable-security; urgency=high
+
+  * Non-maintainer upload by the Security Team
+  * Backport security fixes from 1.3.27 for the following issues:
+    - CAN-2002-0839 (shared memory scoreboard uid/gid)
+    - CAN-2002-0840 (cross-site scripting in error page)
+    - CAN-2002-0843 (buffer overflows in ApacheBench ab.c)
+  * Fix insecure temporary file creation in htpasswd and htdigest
+  * Added another fix against two overflowed buffer in the htdigest
+    program
+
+ -- Martin Schulze <joey@infodrom.org>  Sat, 26 Oct 2002 11:23:54 +0200
+
 apache-ssl (1.3.26.1+1.48-0woody2) testing-security; urgency=high
 
   * Recompile on woody.
diff -u -Nur --exclude CVS orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_1.3.27_backports apache-ssl-1.3.26.1+1.48/debian/patches/security_1.3.27_backports
--- orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_1.3.27_backports	1970-01-01 01:00:00.000000000 +0100
+++ apache-ssl-1.3.26.1+1.48/debian/patches/security_1.3.27_backports	2002-10-26 11:22:05.000000000 +0200
@@ -0,0 +1,184 @@
+diff -ru build-tree.orig/apache_1.3.26/src/include/http_conf_globals.h build-tree/apache_1.3.26/src/include/http_conf_globals.h
+--- build-tree.orig/apache_1.3.26/src/include/http_conf_globals.h	2002-03-13 16:05:29.000000000 -0500
++++ build-tree/apache_1.3.26/src/include/http_conf_globals.h	2002-10-19 14:33:18.000000000 -0400
+@@ -103,6 +103,8 @@
+ 
+ extern enum server_token_type ap_server_tokens;
+ 
++extern API_VAR_EXPORT int ap_change_shmem_uid;
++
+ /* Trying to allocate these in the config pool gets us into some *nasty*
+  * chicken-and-egg problems in http_main.c --- where do you stick them
+  * when pconf gets cleared?  Better to just allocate a little space
+diff -ru build-tree.orig/apache_1.3.26/src/main/http_core.c build-tree/apache_1.3.26/src/main/http_core.c
+--- build-tree.orig/apache_1.3.26/src/main/http_core.c	2002-10-19 14:28:02..000000000 -0400
++++ build-tree/apache_1.3.26/src/main/http_core.c	2002-10-19 14:33:18.000000000 -0400
+@@ -2761,11 +2761,14 @@
+ 	return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
+ 			  " Server at <A HREF=\"mailto:";,
+ 			  r->server->server_admin, "\">",
+-			  ap_get_server_name(r), "</A> Port ", sport,
++			  ap_escape_html(r->pool, ap_get_server_name(r)), 
++			  "</A> Port ", sport,
+ 			  "</ADDRESS>\n", NULL);
+     }
+     return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
+-		      " Server at ", ap_get_server_name(r), " Port ", sport,
++		      " Server at ", 
++		      ap_escape_html(r->pool, ap_get_server_name(r)), 
++		      " Port ", sport,
+ 		      "</ADDRESS>\n", NULL);
+ }
+ 
+@@ -2793,6 +2796,18 @@
+ }
+ #endif /*_OSD_POSIX*/
+ 
++static const char *set_change_shmem_uid(cmd_parms *cmd,
++                                              core_dir_config *d, int arg) 
++{
++    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
++    if (err != NULL) {
++        return err;
++    }
++
++    ap_change_shmem_uid = arg != 0;
++    return NULL;
++}
++
+ /*
+  * Handle a request to include the server's OS platform in the Server
+  * response header field (the ServerTokens directive).  Unfortunately
+@@ -3426,6 +3441,8 @@
+   (void*)XtOffsetOf(core_dir_config, limit_req_body),
+   OR_ALL, TAKE1,
+   "Limit (in bytes) on maximum size of request message body" },
++{ "ShmemUIDisUser", set_change_shmem_uid, NULL, RSRC_CONF, FLAG,
++  "Enable the setting of SysV shared memory scoreboard uid/gid to User/Group" },
+ { "AcceptMutex", set_accept_mutex, NULL, RSRC_CONF, TAKE1,
+   "Serialized Accept Mutex; the methods " 
+ #ifdef HAVE_USLOCK_SERIALIZED_ACCEPT
+@@ -3828,7 +3845,8 @@
+ 
+     if (r->method_number == M_INVALID) {
+ 	ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+-		    "Invalid method in request %s", r->the_request);
++		    "Invalid method in request %s",
++		    ap_escape_logitem(r->pool, r->the_request));
+ 	return NOT_IMPLEMENTED;
+     }
+     if (r->method_number == M_OPTIONS) {
+diff -ru build-tree.orig/apache_1.3.26/src/main/http_main.c build-tree/apache_1.3.26/src/main/http_main.c
+--- build-tree.orig/apache_1.3.26/src/main/http_main.c	2002-10-19 14:28:01..000000000 -0400
++++ build-tree/apache_1.3.26/src/main/http_main.c	2002-10-19 14:33:18.000000000 -0400
+@@ -398,6 +398,9 @@
+ /* Global, alas, so http_core can talk to us */
+ enum server_token_type ap_server_tokens = SrvTk_FULL;
+ 
++/* Also global, for http_core and http_protocol */
++API_VAR_EXPORT int ap_change_shmem_uid = 0;
++
+ /*
+  * This routine is called when the pconf pool is vacuumed.  It resets the
+  * server version string to a known value and [re]enables modifications
+@@ -2327,7 +2330,9 @@
+ 	 * We exit below, after we try to remove the segment
+ 	 */
+     }
+-    else {			/* only worry about permissions if we attached the segment */
++    /* only worry about permissions if we attached the segment
++       and we want/need to change the uid/gid */
++    else if (ap_change_shmem_uid) {
+ 	if (shmctl(shmid, IPC_STAT, &shmbuf) != 0) {
+ 	    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ 		"shmctl() could not stat segment #%d", shmid);
+diff -ru build-tree.orig/apache_1.3.26/src/main/util_script.c build-tree/apache_1.3.26/src/main/util_script.c
+--- build-tree.orig/apache_1.3.26/src/main/util_script.c	2002-03-21 11:07:02.000000000 -0500
++++ build-tree/apache_1.3.26/src/main/util_script.c	2002-10-19 14:33:18.000000000 -0400
+@@ -280,7 +280,8 @@
+     ap_table_addn(e, "PATH", env_path);
+     ap_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
+     ap_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version());
+-    ap_table_addn(e, "SERVER_NAME", ap_get_server_name(r));
++    ap_table_addn(e, "SERVER_NAME", 
++		  ap_escape_html(r->pool,ap_get_server_name(r)));
+     ap_table_addn(e, "SERVER_ADDR", r->connection->local_ip);	/* Apache */
+     ap_table_addn(e, "SERVER_PORT",
+ 		  ap_psprintf(r->pool, "%u", ap_get_server_port(r)));
+diff -ru build-tree.orig/apache_1.3.26/src/support/ab.c build-tree/apache_1.3.26/src/support/ab.c
+--- build-tree.orig/apache_1.3.26/src/support/ab.c	2002-10-19 14:28:01.000000000 -0400
++++ build-tree/apache_1.3.26/src/support/ab.c	2002-10-19 14:33:18.000000000 -0400
+@@ -1080,11 +1080,12 @@
+ 		 * this is first time, extract some interesting info
+ 		 */
+ 		char *p, *q;
++		int qlen;
+ 		p = strstr(c->cbuff, "Server:");
+-		q = servername;
++		q = servername; qlen = sizeof(servername);
+ 		if (p) {
+ 		    p += 8;
+-		    while (*p > 32)
++		    while (*p > 32 && qlen-- > 1) 
+ 			*q++ = *p++;
+ 		}
+ 		*q = 0;
+@@ -1307,7 +1308,7 @@
+ 
+ 	/* check for time limit expiry */
+ 	gettimeofday(&now, 0);
+-	if (tlimit && timedif(now, start) > (tlimit * 1000)) {
++	if (tlimit && timedif(now, start) >= (tlimit * 1000)) {
+ 	    requests = done;	/* so stats are correct */
+ 	}
+ 	/* Timeout of 30 seconds. */
+@@ -1576,9 +1577,9 @@
+ 	    strcpy(content_type, optarg);
+ 	    break;
+ 	case 'C':
+-	    strncat(cookie, "Cookie: ", sizeof(cookie));
+-	    strncat(cookie, optarg, sizeof(cookie));
+-	    strncat(cookie, "\r\n", sizeof(cookie));
++	    strncat(cookie, "Cookie: ", sizeof(cookie)-strlen(cookie)-1);
++	    strncat(cookie, optarg, sizeof(cookie)-strlen(cookie)-1);
++	    strncat(cookie, "\r\n", sizeof(cookie)-strlen(cookie)-1);
+ 	    break;
+ 	case 'A':
+ 	    /*
+@@ -1590,9 +1591,9 @@
+ 	    l = ap_base64encode(tmp, optarg, strlen(optarg));
+ 	    tmp[l] = '\0';
+ 
+-	    strncat(auth, "Authorization: Basic ", sizeof(auth));
+-	    strncat(auth, tmp, sizeof(auth));
+-	    strncat(auth, "\r\n", sizeof(auth));
++	    strncat(auth, "Authorization: Basic ", sizeof(auth)-strlen(auth)-1);
++	    strncat(auth, tmp, sizeof(auth)-strlen(auth)-1);
++	    strncat(auth, "\r\n", sizeof(auth)-strlen(auth)-1);
+ 	    break;
+ 	case 'P':
+ 	    /*
+@@ -1603,9 +1604,9 @@
+ 	    l = ap_base64encode(tmp, optarg, strlen(optarg));
+ 	    tmp[l] = '\0';
+ 
+-	    strncat(auth, "Proxy-Authorization: Basic ", sizeof(auth));
+-	    strncat(auth, tmp, sizeof(auth));
+-	    strncat(auth, "\r\n", sizeof(auth));
++	    strncat(auth, "Proxy-Authorization: Basic ", sizeof(auth)-strlen(auth)-1);
++	    strncat(auth, tmp, sizeof(auth)-strlen(auth)-1);
++	    strncat(auth, "\r\n", sizeof(auth)-strlen(auth)-1);
+ 	    break;
+ 	case 'X':
+ 	    {
+@@ -1623,8 +1624,8 @@
+ 	    }
+ 	    break;
+ 	case 'H':
+-	    strncat(hdrs, optarg, sizeof(hdrs));
+-	    strncat(hdrs, "\r\n", sizeof(hdrs));
++	    strncat(hdrs, optarg, sizeof(hdrs)-strlen(hdrs)-1);
++	    strncat(hdrs, "\r\n", sizeof(hdrs)-strlen(hdrs)-1);
+ 	    break;
+ 	case 'V':
+ 	    copyright();
diff -u -Nur --exclude CVS orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_bufferoverflow apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_bufferoverflow
--- orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_bufferoverflow	1970-01-01 01:00:00.000000000 +0100
+++ apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_bufferoverflow	2002-10-26 11:22:05.000000000 +0200
@@ -0,0 +1,14 @@
+diff -u -Nur --exclude CVS build-tree.orig/apache_1.3.26/src/support/htdigest.c build-tree/apache_1.3.26/src/support/htdigest.c
+--- build-tree.orig/apache_1.3.26/src/support/htdigest.c	2002-10-23 09:22:02.000000000 +0200
++++ build-tree/apache_1.3.26/src/support/htdigest.c	2002-10-26 09:33:54.000000000 +0200
+@@ -255,8 +255,8 @@
+ 	fprintf(stderr, "Use -c option to create new one.\n");
+ 	exit(1);
+     }
+-    strcpy(user, argv[3]);
+-    strcpy(realm, argv[2]);
++    strncpy(user, argv[3], sizeof (user));
++    strncpy(realm, argv[2], sizeof (realm));
+ 
+     found = 0;
+     while (!(getline(line, MAX_STRING_LEN, f))) {
diff -u -Nur --exclude CVS orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_tempfiles apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_tempfiles
--- orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_tempfiles	1970-01-01 01:00:00.000000000 +0100
+++ apache-ssl-1.3.26.1+1.48/debian/patches/security_htdigest_tempfiles	2002-10-26 11:22:05.000000000 +0200
@@ -0,0 +1,38 @@
+diff -u -Nur --exclude CVS build-tree.orig/apache_1.3.26/src/support/htdigest.c build-tree/apache_1.3.26/src/support/htdigest.c
+--- build-tree.orig/apache_1.3.26/src/support/htdigest.c	2002-03-13 22:05:37.000000000 +0100
++++ build-tree/apache_1.3.26/src/support/htdigest.c	2002-10-22 20:57:59.000000000 +0200
+@@ -94,7 +94,7 @@
+ 
+ #define MAX_STRING_LEN 256
+ 
+-char *tn;
++static char tn[MAX_STRING_LEN];
+ 
+ 
+ static void getword(char *word, char *line, char stop)
+@@ -216,8 +216,8 @@
+     char x[MAX_STRING_LEN];
+     char command[MAX_STRING_LEN];
+     int found;
++    int tfd;
+ 
+-    tn = NULL;
+     signal(SIGINT, (void (*)(int)) interrupted);
+     if (argc == 5) {
+ 	if (strcmp(argv[1], "-c"))
+@@ -241,11 +241,13 @@
+     else if (argc != 4)
+ 	usage();
+ 
+-    tn = tmpnam(NULL);
+-    if (!(tfp = fopen(tn, "w"))) {
++    strcpy(tn, "/tmp/htdigest-XXXXXX");
++    tfd = mkstemp(tn);
++    if (tfd == -1) {
+ 	fprintf(stderr, "Could not open temp file.\n");
+ 	exit(1);
+     }
++    tfp = fdopen(tfd, "w");
+ 
+     if (!(f = fopen(argv[1], "r"))) {
+ 	fprintf(stderr,
diff -u -Nur --exclude CVS orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_htpasswd_tempfiles apache-ssl-1.3.26.1+1.48/debian/patches/security_htpasswd_tempfiles
--- orig/apache-ssl-1.3.26.1+1.48/debian/patches/security_htpasswd_tempfiles	1970-01-01 01:00:00.000000000 +0100
+++ apache-ssl-1.3.26.1+1.48/debian/patches/security_htpasswd_tempfiles	2002-10-26 11:22:05.000000000 +0200
@@ -0,0 +1,49 @@
+diff -ru build-tree.orig/apache_1.3.26/src/support/htpasswd.c build-tree/apache_1.3.26/src/support/htpasswd.c
+--- build-tree.orig/apache_1.3.26/src/support/htpasswd.c	2002-03-13 16:05:37.000000000 -0500
++++ build-tree/apache_1.3.26/src/support/htpasswd.c	2002-10-19 14:41:30.000000000 -0400
+@@ -125,7 +125,7 @@
+  * This needs to be declared statically so the signal handler can
+  * access it.
+  */
+-static char *tempfilename;
++static char tempfilename[MAX_STRING_LEN];
+ /*
+  * If our platform knows about the tmpnam() external buffer size, create
+  * a buffer to pass in.  This is needed in a threaded environment, or
+@@ -377,8 +377,8 @@
+     int noninteractive = 0;
+     int i;
+     int args_left = 2;
++    int tfd;
+ 
+-    tempfilename = NULL;
+     signal(SIGINT, (void (*)(int)) interrupted);
+ 
+     /*
+@@ -565,7 +565,8 @@
+      * to add or update.  Let's do it..
+      */
+     errno = 0;
+-    tempfilename = tmpnam(tname_buf);
++    strcpy(tempfilename, "/tmp/htpasswd-XXXXXX");
++    tfd = mkstemp(tempfilename);
+     if ((tempfilename == NULL) || (*tempfilename == '\0')) {
+ 	fprintf(stderr, "%s: unable to generate temporary filename\n",
+ 		argv[0]);
+@@ -575,13 +576,13 @@
+ 	perror("tmpnam");
+ 	exit(ERR_FILEPERM);
+     }
+-    ftemp = fopen(tempfilename, "w+");
+-    if (ftemp == NULL) {
++    if (tfd == -1) {
+ 	fprintf(stderr, "%s: unable to create temporary file '%s'\n", argv[0],
+ 		tempfilename);
+-	perror("fopen");
++	perror("open");
+ 	exit(ERR_FILEPERM);
+     }
++    ftemp = fdopen(tfd, "w+");
+     /*
+      * If we're not creating a new file, copy records from the existing
+      * one to the temporary file until we find the specified user.

-- 
This is Linux Country.  On a quiet night, you can hear Windows reboot.

Please always Cc to me when replying to me on the lists.



Reply to: