Selaa lähdekoodia

Reject control characters in the request-target

RFC 9112 §3.2 does not allow control characters in the request-target,
and §2.2 requires a bare CR to be treated as invalid. parse_request_line
accepted them, so e.g. "GET /a\rb HTTP/1.1" was routed normally. Reject
any byte that is not VCHAR or obs-text with 400 Bad Request. obs-text is
still allowed since some clients send raw UTF-8 in the target.
yhirose 1 viikko sitten
vanhempi
commit
e11dbec7b3
2 muutettua tiedostoa jossa 23 lisäystä ja 0 poistoa
  1. 7 0
      httplib.h
  2. 16 0
      test/test.cc

+ 7 - 0
httplib.h

@@ -13296,6 +13296,13 @@ inline bool Server::parse_request_line(const char *s, Request &req) const {
     return false;
   }
 
+  // RFC 9112 §2.2/§3.2: reject control characters (incl. bare CR) in the
+  // request-target. obs-text is allowed since some clients send raw UTF-8.
+  if (!std::all_of(req.target.begin(), req.target.end(),
+                   detail::fields::is_field_vchar)) {
+    return false;
+  }
+
   {
     // Skip URL fragment
     for (size_t i = 0; i < req.target.size(); i++) {

+ 16 - 0
test/test.cc

@@ -10390,6 +10390,22 @@ TEST(ServerRequestParsingTest, InvalidSpaceInURL) {
   EXPECT_EQ("HTTP/1.1 400 Bad Request", out.substr(0, 24));
 }
 
+TEST(ServerRequestParsingTest, InvalidControlCharInURL) {
+  for (auto target : {"/h\ri", "/h\x7fi"}) {
+    std::string out;
+    test_raw_request(std::string("GET ") + target + " HTTP/1.1\r\n\r\n", &out);
+    EXPECT_EQ("HTTP/1.1 400 Bad Request", out.substr(0, 24)) << target;
+  }
+}
+
+TEST(ServerRequestParsingTest, NonAsciiInURLAccepted) {
+  std::string out;
+  test_raw_request("GET /hi?q=\xE3\x81\x82 HTTP/1.1\r\n"
+                   "Connection: close\r\n\r\n",
+                   &out);
+  EXPECT_EQ("HTTP/1.1 200 OK", out.substr(0, 15));
+}
+
 TEST(ServerRequestParsingTest, RemoteAddrSetOnBadRequest) {
   Server svr;