CVE-2012-3501 (published 2012-08-25T10:29Z)

The squidclamav_check_preview_handler function in squidclamav.c in SquidClamav 5.x before 5.8 and 6.x before 6.7 passes an unescaped URL to a system command call, which allows remote attackers to cause a denial of service (daemon crash) via a URL with certain characters, as demonstrated using %0D or %0A.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)

Weakness information:
cwe_id: CWE-119
cwe_name: Improper Restriction of Operations within the Bounds of a Memory Buffer
description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
extended_description: 
            Certain languages allow direct addressing of memory locations and do not automatically ensure that these locations are valid for the memory buffer that is being referenced. This can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
         
         

Fix information:
repo_url: https://github.com/darold/squidclamav
commit_details: repo_url: https://github.com/darold/squidclamav
author: Darold Gilles
author_date: 2012-07-24 15:44:54+02:00
msg: Add a workaround for a squidGuard bug that unescape the URL and send it back unescaped. This could conduct in wrong result and ssquidclamav crash especially with URL containing the %0D or %0A character. John Xue
repository: repo_url: https://github.com/darold/squidclamav
repo_name: darold/squidclamav
description: SquidClamAv is a dedicated ClamAV antivirus redirector for Squid. It can run antivirus checks based on filename regex, content-type regex, and more. It is easy to install and works even with heavy Squid access.
repo_language: Shell
owner: darold
file_changes: filename: squidclamav.c
change_type: ModificationType.MODIFY
diff: @@ -133,7 +133,7 @@ void cfgreload_command(char *, int, char **);
 int create_pipe(char *command);
 int dconnect (void);
 int connectINET(char *serverHost, uint16_t serverPort);
-
+char * replace(const char *s, const char *old, const char *new);
 
 /* ----------------------------------------------------- */
 
@@ -365,10 +365,14 @@ int squidclamav_check_preview_handler(char *preview_data, int preview_data_len,
      
      /* Check URL header against squidGuard */
      if (usepipe == 1) {
+	char *rbuff = NULL;
 	ci_debug_printf(2, "DEBUG squidclamav_check_preview_handler: Sending request to chained program: %s\n", squidguard);
 	ci_debug_printf(2, "DEBUG squidclamav_check_preview_handler: Request: %s %s %s %s\n", httpinf.url,clientip,username,httpinf.method);
-	fprintf(sgfpw,"%s %s %s %s\n",httpinf.url,clientip,username,httpinf.method);
+	/* escaping escaped character to prevent unescaping by squidguard */
+	rbuff = replace(httpinf.url, "%", "%25");
+	fprintf(sgfpw,"%s %s %s %s\n",rbuff,clientip,username,httpinf.method);
 	fflush(sgfpw);
+	xfree(rbuff);
 	/* the chained redirector must return empty line if ok or the redirection url */
 	chain_ret = (char *)malloc(sizeof(char)*MAX_URL_SIZE);
 	if (chain_ret != NULL) {
@@ -1628,3 +1632,40 @@ connectINET(char *serverHost, uint16_t serverPort)
         return asockd;
 }
 
+
+/**
+ * Searches all occurrences of old into s
+ * and replaces with new
+ */
+char *
+replace(const char *s, const char *old, const char *new)
+{
+	char *ret;
+	int i, count = 0;
+	size_t newlen = strlen(new);
+	size_t oldlen = strlen(old);
+
+	for (i = 0; s[i] != '\0'; i++) {
+		if (strstr(&s[i], old) == &s[i]) {
+			count++;
+			i += oldlen - 1;
+		}
+	}
+	ret = malloc(i + 1 + count * (newlen - oldlen));
+	if (ret != NULL) {
+		i = 0;
+		while (*s) {
+			if (strstr(s, old) == s) {
+				strcpy(&ret[i], new);
+				i += newlen;
+				s += oldlen;
+			} else {
+				ret[i++] = *s++;
+			}
+		}
+		ret[i] = '\0';
+	}
+
+	return ret;
+}
+

programming_language: C