1
0
Эх сурвалжийг харах

fix #473: CVE-2023-26146,26147,26148

ithewei 2 жил өмнө
parent
commit
8e380f032d

+ 1 - 0
http/HttpMessage.cpp

@@ -489,6 +489,7 @@ void HttpMessage::DumpHeaders(std::string& str) {
             // %s: %s\r\n
             str += header.first;
             str += ": ";
+            // fix CVE-2023-26148
             // if the value has \r\n, translate to \\r\\n
             if (header.second.find("\r") != std::string::npos ||
                 header.second.find("\n") != std::string::npos) {

+ 17 - 2
http/server/HttpHandler.cpp

@@ -250,7 +250,11 @@ int HttpHandler::invokeHttpHandler(const http_handler* handler) {
 
 void HttpHandler::onHeadersComplete() {
     // printf("onHeadersComplete\n");
-    handleRequestHeaders();
+    int status_code = handleRequestHeaders();
+    if (status_code != HTTP_STATUS_OK) {
+        error = ERR_REQUEST;
+        return;
+    }
 
     HttpRequest* pReq = req.get();
     if (service && service->pathHandlers.size() != 0) {
@@ -334,7 +338,7 @@ void HttpHandler::onMessageComplete() {
     }
 }
 
-void HttpHandler::handleRequestHeaders() {
+int HttpHandler::handleRequestHeaders() {
     HttpRequest* pReq = req.get();
     pReq->scheme = ssl ? "https" : "http";
     pReq->client_addr.ip = ip;
@@ -362,6 +366,16 @@ void HttpHandler::handleRequestHeaders() {
 
     // printf("url=%s\n", pReq->url.c_str());
     pReq->ParseUrl();
+    // printf("path=%s\n",  pReq->path.c_str());
+    // fix CVE-2023-26147
+    if (pReq->path.find("\%") != std::string::npos) {
+        std::string unescaped_path = HUrl::unescape(pReq->path);
+        if (unescaped_path.find("\r\n") != std::string::npos) {
+            hlogw("Illegal path: %s\n",  unescaped_path.c_str());
+            resp->status_code = HTTP_STATUS_BAD_REQUEST;
+            return resp->status_code;
+        }
+    }
 
     if (proxy) {
         // Proxy-Connection
@@ -389,6 +403,7 @@ void HttpHandler::handleRequestHeaders() {
     }
 
     // TODO: rewrite url
+    return HTTP_STATUS_OK;
 }
 
 void HttpHandler::handleExpect100() {

+ 1 - 1
http/server/HttpHandler.h

@@ -143,7 +143,7 @@ public:
 
 private:
     const HttpContextPtr& context();
-    void  handleRequestHeaders();
+    int   handleRequestHeaders();
     // Expect: 100-continue
     void  handleExpect100();
     void  addResponseHeaders();

+ 9 - 4
http/server/http_page.cpp

@@ -1,5 +1,6 @@
 #include "http_page.h"
 #include "hdir.h"
+#include "hurl.h"
 
 #define AUTOINDEX_FILENAME_MAXLEN       50
 
@@ -51,18 +52,22 @@ void make_index_of_page(const char* dir, std::string& page, const char* url) {
 
     std::list<hdir_t> dirs;
     listdir(dir, dirs);
+    std::string escaped_name;
     for (auto& item : dirs) {
         if (item.name[0] == '.' && item.name[1] == '\0') continue;
         page += "    <tr>\n";
-        size_t len = strlen(item.name) + (item.type == 'd');
+        // fix CVE-2023-26146
+        escaped_name = hv::escapeHTML(item.name);
+        const char* filename = escaped_name.c_str();
+        size_t len = escaped_name.size() + (item.type == 'd');
         // name
         snprintf(c_str, sizeof(c_str), "<a href=\"%s%s\">%s%s</a>",
-                item.name,
+                filename,
                 item.type == 'd' ? "/" : "",
-                len < AUTOINDEX_FILENAME_MAXLEN ? item.name : std::string(item.name, item.name+AUTOINDEX_FILENAME_MAXLEN-4).append("...").c_str(),
+                len < AUTOINDEX_FILENAME_MAXLEN ? filename : std::string(filename, filename+AUTOINDEX_FILENAME_MAXLEN-4).append("...").c_str(),
                 item.type == 'd' ? "/" : "");
         _ADD_TD_(page, c_str)
-        if (strcmp(item.name, "..") != 0) {
+        if (strcmp(filename, "..") != 0) {
             // mtime
             struct tm* tm = localtime(&item.mtime);
             snprintf(c_str, sizeof(c_str), "%04d-%02d-%02d %02d:%02d:%02d",