From 8e380f032dad1cb8f60caa1809f94f6bb11054de Mon Sep 17 00:00:00 2001 From: ithewei Date: Wed, 20 Dec 2023 14:32:51 +0800 Subject: [PATCH] fix #473: CVE-2023-26146,26147,26148 --- http/HttpMessage.cpp | 1 + http/server/HttpHandler.cpp | 19 +++++++++++++++++-- http/server/HttpHandler.h | 2 +- http/server/http_page.cpp | 13 +++++++++---- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/http/HttpMessage.cpp b/http/HttpMessage.cpp index 42ea94d44..4d47dff64 100644 --- a/http/HttpMessage.cpp +++ b/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) { diff --git a/http/server/HttpHandler.cpp b/http/server/HttpHandler.cpp index a6a07c273..f63325004 100644 --- a/http/server/HttpHandler.cpp +++ b/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() { diff --git a/http/server/HttpHandler.h b/http/server/HttpHandler.h index b3363ee12..fca6848c4 100644 --- a/http/server/HttpHandler.h +++ b/http/server/HttpHandler.h @@ -143,7 +143,7 @@ class HttpHandler { private: const HttpContextPtr& context(); - void handleRequestHeaders(); + int handleRequestHeaders(); // Expect: 100-continue void handleExpect100(); void addResponseHeaders(); diff --git a/http/server/http_page.cpp b/http/server/http_page.cpp index 47d6fb9ef..f3c1c9d31 100644 --- a/http/server/http_page.cpp +++ b/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 dirs; listdir(dir, dirs); + std::string escaped_name; for (auto& item : dirs) { if (item.name[0] == '.' && item.name[1] == '\0') continue; page += " \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), "%s%s", - 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",