]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Enforce token characters for field-name (#700)
authorAmos Jeffries <yadij@users.noreply.github.com>
Tue, 4 Aug 2020 04:34:32 +0000 (04:34 +0000)
committerAmos Jeffries <yadij@users.noreply.github.com>
Sun, 9 Aug 2020 18:06:11 +0000 (06:06 +1200)
RFC 7230 defines field-name as a token. Request splitting and cache
poisoning attacks have used non-token characters to fool broken HTTP
agents behind or in front of Squid for years. This change should
significantly reduce that abuse.

If we discover exceptional situations that need special treatment, the
relaxed parser can allow them on a case-by-case basis (while being extra
careful about framing-related header fields), just like we already
tolerate some header whitespace (e.g., between the response header
field-name and colon).

src/HttpHeader.cc

index b19644a558e0f878cbd53ea0ba4c98b68fb8b89b..8fc28a0efa78e5d47d9f307f3a82185886d52116 100644 (file)
@@ -497,22 +497,6 @@ HttpHeader::parse(const char *header_start, size_t hdrLen, Http::ContentLengthIn
             return 0;
         }
 
-        /* AYJ 2017-05-23: I suspect we need to change this whitespace check to conform to the
-           updated WSP character set in RFC 7230/7231. For now I left it as the
-           characters in w_space which the previous code was using. */
-        static CharacterSet wsp = (CharacterSet::WSP + CharacterSet::CR + CharacterSet::LF);
-        if (e->id == Http::HdrType::OTHER && e->name.findFirstOf(wsp) != SBuf::npos) {
-            debugs(55, warnOnError, "WARNING: found whitespace in HTTP header name {" <<
-                   getStringPrefix(field_start, field_end-field_start) << "}");
-
-            if (!Config.onoff.relaxed_header_parser) {
-                delete e;
-                PROF_stop(HttpHeaderParse);
-                clean();
-                return 0;
-            }
-        }
-
         addEntry(e);
     }
 
@@ -1464,6 +1448,20 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end, const htt
         }
     }
 
+    /* RFC 7230 section 3.2:
+     *
+     *  header-field   = field-name ":" OWS field-value OWS
+     *  field-name     = token
+     *  token          = 1*TCHAR
+     */
+    for (const char *pos = field_start; pos < (field_start+name_len); ++pos) {
+        if (!CharacterSet::TCHAR[*pos]) {
+            debugs(55, 2, "found header with invalid characters in " <<
+                   Raw("field-name", field_start, min(name_len,100)) << "...");
+            return nullptr;
+        }
+    }
+
     /* now we know we can parse it */
 
     debugs(55, 9, "parsing HttpHeaderEntry: near '" <<  getStringPrefix(field_start, field_end-field_start) << "'");