From d78a166fedd9d02c23e4b71d5f53bd9b2c4b9a51 Mon Sep 17 00:00:00 2001
From: covener <covener@apache.org>
Date: Mon, 6 Mar 2023 4:27:31 AM GMT+0800
Subject: [PATCH] don't forward invalid query strings

Conflict:NA
Reference:https://github.com/apache/httpd/commit/d78a166fedd9d02c23e4b71d5f53bd9b2c4b9a51

---
 modules/http2/mod_proxy_http2.c    | 14 ++++++++++++++
 modules/mappers/mod_rewrite.c      | 22 ++++++++++++++++++++++
 modules/proxy/mod_proxy_ajp.c      | 14 ++++++++++++++
 modules/proxy/mod_proxy_balancer.c | 14 ++++++++++++++
 modules/proxy/mod_proxy_http.c     | 14 ++++++++++++++
 modules/proxy/mod_proxy_wstunnel.c | 14 ++++++++++++++
 6 files changed, 92 insertions(+)

diff --git a/modules/http2/mod_proxy_http2.c b/modules/http2/mod_proxy_http2.c
index 03c77ed..b9be869 100644
--- a/modules/http2/mod_proxy_http2.c
+++ b/modules/http2/mod_proxy_http2.c
@@ -154,10 +154,24 @@ static int proxy_http2_canon(request_rec *r, char *url)
         if (apr_table_get(r->notes, "proxy-nocanon")) {
             path = url;   /* this is the raw path */
         }
+        else if (apr_table_get(r->notes, "proxy-noencode")) {
+            path = url;   /* this is the encoded path already */
+            search = r->args;
+        }
         else {
             path = ap_proxy_canonenc(r->pool, url, (int)strlen(url),
                                      enc_path, 0, r->proxyreq);
             search = r->args;
+            if (search && *(ap_scan_vchar_obstext(search))) {
+                /*
+                 * We have a raw control character or a ' ' in r->args.
+                 * Correct encoding was missed.
+                 */
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
+                              "To be forwarded query string contains control "
+                              "characters or spaces");
+                return HTTP_FORBIDDEN;
+            }
         }
         break;
     case PROXYREQ_PROXY:
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index 65abfa2..80fdbde 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -4702,6 +4702,17 @@ static int hook_uri2file(request_rec *r)
         unsigned skip;
         apr_size_t flen;
 
+        if (r->args && *(ap_scan_vchar_obstext(r->args))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10410)
+                          "Rewritten query string contains control "
+                          "characters or spaces");
+            return HTTP_FORBIDDEN;
+        }
+
         if (ACTION_STATUS == rulestatus) {
             int n = r->status;
 
@@ -4986,6 +4997,17 @@ static int hook_fixup(request_rec *r)
     if (rulestatus) {
         unsigned skip;
 
+        if (r->args && *(ap_scan_vchar_obstext(r->args))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10411)
+                          "Rewritten query string contains control "
+                          "characters or spaces");
+            return HTTP_FORBIDDEN;
+        }
+
         if (ACTION_STATUS == rulestatus) {
             int n = r->status;
 
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index 8c2259e..317ee63 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -65,10 +65,24 @@ static int proxy_ajp_canon(request_rec *r, char *url)
     if (apr_table_get(r->notes, "proxy-nocanon")) {
         path = url;   /* this is the raw path */
     }
+    else if (apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the encoded path already */
+        search = r->args;
+    }
     else {
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         search = r->args;
+        if (search && *(ap_scan_vchar_obstext(search))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10406)
+                           "To be forwarded query string contains control "
+                           "characters or spaces");
+             return HTTP_FORBIDDEN;
+        }
     }
     if (path == NULL)
         return HTTP_BAD_REQUEST;
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index e26e95d..f235f4a 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -102,10 +102,24 @@ static int proxy_balancer_canon(request_rec *r, char *url)
     if (apr_table_get(r->notes, "proxy-nocanon")) {
         path = url;   /* this is the raw path */
     }
+    else if (apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the encoded path already */
+        search = r->args;
+    }
     else {
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         search = r->args;
+        if (search && *(ap_scan_vchar_obstext(search))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10407)
+                           "To be forwarded query string contains control "
+                           "characters or spaces");
+             return HTTP_FORBIDDEN;
+        }
     }
     if (path == NULL)
         return HTTP_BAD_REQUEST;
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index 679ecdd..ae5e3d5 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -86,10 +86,24 @@ static int proxy_http_canon(request_rec *r, char *url)
         if (apr_table_get(r->notes, "proxy-nocanon")) {
             path = url;   /* this is the raw path */
         }
+        else if (apr_table_get(r->notes, "proxy-noencode")) {
+            path = url;   /* this is the encoded path already */
+            search = r->args;
+        }
         else {
             path = ap_proxy_canonenc(r->pool, url, strlen(url),
                                      enc_path, 0, r->proxyreq);
             search = r->args;
+            if (search && *(ap_scan_vchar_obstext(search))) {
+                /*
+                 * We have a raw control character or a ' ' in r->args.
+                 * Correct encoding was missed.
+                 */
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10408)
+                              "To be forwarded query string contains control "
+                              "characters or spaces");
+                return HTTP_FORBIDDEN;
+            }
         }
         break;
     case PROXYREQ_PROXY:
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index fb53fe6..28d6363 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -69,10 +69,24 @@ static int proxy_wstunnel_canon(request_rec *r, char *url)
     if (apr_table_get(r->notes, "proxy-nocanon")) {
         path = url;   /* this is the raw path */
     }
+    else if (apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the encoded path already */
+        search = r->args;
+    }
     else {
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         search = r->args;
+        if (search && *(ap_scan_vchar_obstext(search))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10409)
+                          "To be forwarded query string contains control "
+                          "characters or spaces");
+            return HTTP_FORBIDDEN;
+        }
     }
     if (path == NULL)
         return HTTP_BAD_REQUEST;
-- 
2.27.0

