Browse Source

Allow non-quoted strings in multipart requests (#433)

bel2125 8 năm trước cách đây
mục cha
commit
1ce371ac0e
1 tập tin đã thay đổi với 58 bổ sung10 xóa
  1. 58 10
      src/handle_form.inl

+ 58 - 10
src/handle_form.inl

@@ -635,23 +635,50 @@ mg_handle_form_request(struct mg_connection *conn,
 			/* Get the mandatory name="..." part of the Content-Disposition
 			 * header. */
 			nbeg = strstr(content_disp, "name=\"");
-			if (!nbeg) {
-				/* Malformed request */
-				return -1;
+			while ((nbeg != NULL) && (strcspn(nbeg - 1, ":,; \t") != 0)) {
+				/* It could be somethingname= instead of name= */
+				nbeg = strstr(nbeg + 1, "name=\"");
 			}
-			nbeg += 6;
-			nend = strchr(nbeg, '\"');
-			if (!nend) {
-				/* Malformed request */
-				return -1;
+
+			if (nbeg) {
+				nbeg += 6;
+				nend = strchr(nbeg, '\"');
+				if (!nend) {
+					/* Malformed request */
+					return -1;
+				}
+			} else {
+				/* name= without quotes is also allowed */
+				nbeg = strstr(content_disp, "name=");
+				while ((nbeg != NULL) && (strcspn(nbeg - 1, ":,; \t") != 0)) {
+					/* It could be somethingname= instead of name= */
+					nbeg = strstr(nbeg + 1, "name=");
+				}
+				if (!nbeg) {
+					/* Malformed request */
+					return -1;
+				}
+				/* RFC 2616 Sec. 2.2 defines a list of allowed
+				 * separators, but many of them make no sense
+				 * here, e.g. various brackets or slashes.
+				 * If they are used, probably someone is
+				 * trying to attack with curious hand made
+				 * requests. Only ; , space and tab seem to be
+				 * reasonable here. Ignore everything else. */
+				nend = nbeg + strcspn(nbeg, ",; \t");
 			}
 
 			/* Get the optional filename="..." part of the Content-Disposition
 			 * header. */
 			fbeg = strstr(content_disp, "filename=\"");
+			while ((fbeg != NULL) && (strcspn(fbeg - 1, ":,; \t") != 0)) {
+				/* It could be somethingfilename= instead of filename= */
+				fbeg = strstr(fbeg + 1, "filename=\"");
+			}
 			if (fbeg) {
 				fbeg += 10;
 				fend = strchr(fbeg, '\"');
+
 				if (!fend) {
 					/* Malformed request (the filename field is optional, but if
 					 * it exists, it needs to be terminated correctly). */
@@ -660,11 +687,32 @@ mg_handle_form_request(struct mg_connection *conn,
 
 				/* TODO: check Content-Type */
 				/* Content-Type: application/octet-stream */
+			}
+			if (!fbeg) {
+				/* Try the same without quotes */
+				fbeg = strstr(content_disp, "filename=");
+				while ((fbeg != NULL) && (strcspn(fbeg - 1, ":,; \t") != 0)) {
+					/* It could be somethingfilename= instead of filename= */
+					fbeg = strstr(fbeg + 1, "filename=");
+				}
 
-			} else {
-				fend = fbeg;
+				fend = fbeg + strcspn(nbeg, ",; \t");
+			}
+			if (!fbeg) {
+				fend = NULL;
+			}
+
+			/* In theory, it could be possible that someone crafts
+			 * a request like name=filename=xyz. Check if name and
+			 * filename do not overlap. */
+			if (!(((ptrdiff_t)fbeg > (ptrdiff_t)nend)
+			      || ((ptrdiff_t)nbeg > (ptrdiff_t)fend)
+
+			          )) {
+				return -1;
 			}
 
+			/* Call callback for new field */
 			memset(path, 0, sizeof(path));
 			field_count++;
 			field_storage = url_encoded_field_found(conn,