civetweb: patch CVE-2020-27304

Details: https://nvd.nist.gov/vuln/detail/CVE-2020-27304

Take the patches referenced in
https://jfrog.com/blog/cve-2020-27304-rce-via-directory-traversal-in-civetweb-http-server/
(which URL is also referenced by NIST)

Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
This commit is contained in:
Gyorgy Sarvari
2025-10-04 22:24:33 +02:00
parent 49c4e29bc9
commit b157fa0412
3 changed files with 119 additions and 0 deletions
@@ -0,0 +1,27 @@
From e7c4fca110a0823262cf444371d01309c85c760f Mon Sep 17 00:00:00 2001
From: bel2125 <bel2125@gmail.com>
Date: Sat, 3 Jul 2021 21:54:28 +0200
Subject: [PATCH] Sanitize upload filename like URL
CVE: CVE-2020-27304
Upstream-Status: Backport [https://github.com/civetweb/civetweb/commit/b2ed60c589172b37f3d705c69d84313eeb8348b1]
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
---
src/handle_form.inl | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/handle_form.inl b/src/handle_form.inl
index 9853faf1..21536158 100644
--- a/src/handle_form.inl
+++ b/src/handle_form.inl
@@ -55,6 +55,8 @@ url_encoded_field_found(const struct mg_connection *conn,
mg_cry_internal(conn, "%s: Cannot decode filename", __func__);
return MG_FORM_FIELD_STORAGE_SKIP;
}
+ remove_dot_segments(filename_dec);
+
} else {
filename_dec[0] = 0;
}
@@ -0,0 +1,90 @@
From 69b2b98f009603e669aac9d1a1e57d00769881b2 Mon Sep 17 00:00:00 2001
From: bel2125 <bel2125@gmail.com>
Date: Sat, 3 Jul 2021 22:35:50 +0200
Subject: [PATCH] handle_form example: Upload to temporary directory and do
some filename checks
For Windows, determine the temporary directory from the GetTempPath API.
According to RFC7578, path information should be ignored and you should not
overwrite existing files.
CVE: CVE-2020-27304
Upstream-Status: Backport [https://github.com/civetweb/civetweb/commit/b2ed60c589172b37f3d705c69d84313eeb8348b1]
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
---
examples/embedded_c/embedded_c.c | 51 ++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/examples/embedded_c/embedded_c.c b/examples/embedded_c/embedded_c.c
index 8956bbce..29ab6b36 100644
--- a/examples/embedded_c/embedded_c.c
+++ b/examples/embedded_c/embedded_c.c
@@ -258,17 +258,64 @@ field_found(const char *key,
size_t pathlen,
void *user_data)
{
+#ifdef _WIN32
+ char temppath[MAX_PATH + 2];
+ DWORD temppathlen;
+#endif
+
struct mg_connection *conn = (struct mg_connection *)user_data;
mg_printf(conn, "\r\n\r\n%s:\r\n", key);
if (filename && *filename) {
+
+ /* According to
+ * https://datatracker.ietf.org/doc/html/rfc7578#section-4.2: Do not use
+ * path information present in the filename. Drop all "/" (and "\" for
+ * Windows).
+ */
+ char *sep = strrchr(filename, '/');
+ if (sep) {
+ memmove(filename, sep + 1, strlen(sep));
+ }
+
#ifdef _WIN32
- _snprintf(path, pathlen, "D:\\tmp\\%s", filename);
+ sep = strrchr(filename, '\\');
+ if (sep) {
+ memmove(filename, sep + 1, strlen(sep));
+ }
+
+ /* For Windows: Find the directory for temporary files */
+ temppathlen = GetTempPathA(sizeof(temppath), temppath);
+ if (temppathlen > 0) {
+ _snprintf(path, pathlen, "%s\\%s", temppath, filename);
+ } else {
+ _snprintf(path, pathlen, "C:\\tmp\\%s", filename);
+ }
#else
snprintf(path, pathlen, "/tmp/%s", filename);
#endif
- return MG_FORM_FIELD_STORAGE_STORE;
+
+ /* According to https://datatracker.ietf.org/doc/html/rfc7578#section-7:
+ * Do not overwrite existing files.
+ */
+ {
+ FILE *ftest = fopen(path, "r");
+ if (!ftest) {
+ return MG_FORM_FIELD_STORAGE_STORE;
+ }
+ fclose(ftest);
+ /* This is just simple demo code. More sophisticated code could add
+ * numbers to the file name to make filenames unique. However, most
+ * likely file upload will not end up in the temporary path, but in
+ * a user directory - multiple directories for multiple users that
+ * are logged into the web service. In this case, users might want
+ * to overwrite their own code. You need to adapt this example to
+ * your needs.
+ */
+ }
+
+ return MG_FORM_FIELD_STORAGE_SKIP;
}
return MG_FORM_FIELD_STORAGE_GET;
}
@@ -8,6 +8,8 @@ SRCREV = "4b440a339979852d5a51fb11a822952712231c23"
PV = "1.12+git${SRCPV}"
SRC_URI = "git://github.com/civetweb/civetweb.git;branch=master;protocol=https \
file://0001-Unittest-Link-librt-and-libm-using-l-option.patch \
file://0001-Sanitize-upload-filename-like-URL.patch \
file://0002-handle_form-example-Upload-to-temporary-directory-an.patch \
"
S = "${WORKDIR}/git"