From cf3cbd43081a0f850f335eea1516d158394f6463 Mon Sep 17 00:00:00 2001 From: dutor <440396+dutor@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:57:47 +0800 Subject: [PATCH] Fixed vulnerability issues --- community-release-3.8-2024-08-22.diff | 104 ++++++++++++++++++ src/common/network/NetworkUtils.cpp | 12 ++ src/common/network/NetworkUtils.h | 2 + .../processors/job/DownloadJobExecutor.cpp | 23 +++- src/webservice/SetFlagsHandler.cpp | 8 ++ 5 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 community-release-3.8-2024-08-22.diff diff --git a/community-release-3.8-2024-08-22.diff b/community-release-3.8-2024-08-22.diff new file mode 100644 index 00000000000..f5c0f6d7270 --- /dev/null +++ b/community-release-3.8-2024-08-22.diff @@ -0,0 +1,104 @@ +diff --git a/src/common/network/NetworkUtils.cpp b/src/common/network/NetworkUtils.cpp +index 43d67d892..1e302a9dc 100644 +--- a/src/common/network/NetworkUtils.cpp ++++ b/src/common/network/NetworkUtils.cpp +@@ -307,6 +307,18 @@ std::string NetworkUtils::toHostsStr(const std::vector& hosts) { + return hostsString; + } + ++Status NetworkUtils::validateIP(const std::string& ip) { ++ if (ip.empty()) { ++ return Status::Error("ip is empty."); ++ } ++ static const std::regex ipv4( ++ R"(^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$)"); ++ if (!std::regex_match(ip, ipv4)) { ++ return Status::Error("%s is not a valid IP", ip.c_str()); ++ } ++ return Status::OK(); ++} ++ + Status NetworkUtils::validateHostOrIp(const std::string& hostOrIp) { + if (hostOrIp.empty()) { + return Status::Error("local_ip is empty, need to config it through config file."); +diff --git a/src/common/network/NetworkUtils.h b/src/common/network/NetworkUtils.h +index f5cd79211..30528e0ed 100644 +--- a/src/common/network/NetworkUtils.h ++++ b/src/common/network/NetworkUtils.h +@@ -50,6 +50,8 @@ class NetworkUtils final { + static StatusOr> toHosts(const std::string& peersStr); + static std::string toHostsStr(const std::vector& hosts); + ++ static Status validateIP(const std::string& ip); ++ + static Status validateHostOrIp(const std::string& HostOrIp); + + private: +diff --git a/src/meta/processors/job/DownloadJobExecutor.cpp b/src/meta/processors/job/DownloadJobExecutor.cpp +index 996c75c5f..65ee49e73 100644 +--- a/src/meta/processors/job/DownloadJobExecutor.cpp ++++ b/src/meta/processors/job/DownloadJobExecutor.cpp +@@ -8,6 +8,7 @@ + #include "common/hdfs/HdfsHelper.h" + #include "common/utils/MetaKeyUtils.h" + #include "meta/MetaServiceUtils.h" ++#include "meta/processors/BaseProcessor.h" + + namespace nebula { + namespace meta { +@@ -34,20 +35,30 @@ nebula::cpp2::ErrorCode DownloadJobExecutor::check() { + } + + auto u = url.substr(hdfsPrefix.size(), url.size()); +- std::vector tokens; ++ std::vector tokens; + folly::split(":", u, tokens); + if (tokens.size() == 2) { ++ if (!NetworkUtils::validateIP(tokens[0]).ok()) { ++ LOG(ERROR) << "Illegal hdfs host: " << url; ++ return nebula::cpp2::ErrorCode::E_INVALID_JOB; ++ } + host_ = std::make_unique(tokens[0]); +- int32_t position = tokens[1].find_first_of("/"); +- if (position != -1) { ++ auto position = tokens[1].find_first_of("/"); ++ if (position != std::string::npos) { + try { +- port_ = folly::to(tokens[1].toString().substr(0, position).c_str()); ++ port_ = folly::to(tokens[1].substr(0, position).c_str()); + } catch (const std::exception& ex) { + LOG(ERROR) << "URL's port parse failed: " << url; + return nebula::cpp2::ErrorCode::E_INVALID_JOB; + } +- path_ = +- std::make_unique(tokens[1].toString().substr(position, tokens[1].size())); ++ auto path = tokens[1].substr(position, tokens[1].size()); ++ // A valid hdfs path must start with /, and only regular characters allow for now ++ const std::regex pattern("^/[-_/0-9a-zA-Z]*$"); ++ if (!std::regex_match(path, pattern)) { ++ LOG(ERROR) << "Illegal hdfs path: " << url; ++ return nebula::cpp2::ErrorCode::E_INVALID_JOB; ++ } ++ path_ = std::make_unique(path); + } else { + LOG(ERROR) << "URL Parse Failed: " << url; + return nebula::cpp2::ErrorCode::E_INVALID_JOB; +diff --git a/src/webservice/SetFlagsHandler.cpp b/src/webservice/SetFlagsHandler.cpp +index 6a8de1772..660a5c04d 100644 +--- a/src/webservice/SetFlagsHandler.cpp ++++ b/src/webservice/SetFlagsHandler.cpp +@@ -79,6 +79,14 @@ void SetFlagsHandler::onEOM() noexcept { + for (auto &item : flags.items()) { + try { + const std::string &name = item.first.asString(); ++ if (name == "enable_authorize") { ++ LOG(ERROR) << "Modifying enable_authorize is not allowed"; ++ ResponseBuilder(downstream_) ++ .status(WebServiceUtils::to(HttpStatusCode::BAD_REQUEST), ++ WebServiceUtils::toString(HttpStatusCode::BAD_REQUEST)) ++ .sendWithEOM(); ++ return; ++ } + const std::string &value = item.second.asString(); + const std::string &newValue = gflags::SetCommandLineOption(name.c_str(), value.c_str()); + if (newValue.empty()) { diff --git a/src/common/network/NetworkUtils.cpp b/src/common/network/NetworkUtils.cpp index 43d67d892be..1e302a9dc90 100644 --- a/src/common/network/NetworkUtils.cpp +++ b/src/common/network/NetworkUtils.cpp @@ -307,6 +307,18 @@ std::string NetworkUtils::toHostsStr(const std::vector& hosts) { return hostsString; } +Status NetworkUtils::validateIP(const std::string& ip) { + if (ip.empty()) { + return Status::Error("ip is empty."); + } + static const std::regex ipv4( + R"(^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$)"); + if (!std::regex_match(ip, ipv4)) { + return Status::Error("%s is not a valid IP", ip.c_str()); + } + return Status::OK(); +} + Status NetworkUtils::validateHostOrIp(const std::string& hostOrIp) { if (hostOrIp.empty()) { return Status::Error("local_ip is empty, need to config it through config file."); diff --git a/src/common/network/NetworkUtils.h b/src/common/network/NetworkUtils.h index f5cd7921113..30528e0edfd 100644 --- a/src/common/network/NetworkUtils.h +++ b/src/common/network/NetworkUtils.h @@ -50,6 +50,8 @@ class NetworkUtils final { static StatusOr> toHosts(const std::string& peersStr); static std::string toHostsStr(const std::vector& hosts); + static Status validateIP(const std::string& ip); + static Status validateHostOrIp(const std::string& HostOrIp); private: diff --git a/src/meta/processors/job/DownloadJobExecutor.cpp b/src/meta/processors/job/DownloadJobExecutor.cpp index 996c75c5f23..65ee49e734d 100644 --- a/src/meta/processors/job/DownloadJobExecutor.cpp +++ b/src/meta/processors/job/DownloadJobExecutor.cpp @@ -8,6 +8,7 @@ #include "common/hdfs/HdfsHelper.h" #include "common/utils/MetaKeyUtils.h" #include "meta/MetaServiceUtils.h" +#include "meta/processors/BaseProcessor.h" namespace nebula { namespace meta { @@ -34,20 +35,30 @@ nebula::cpp2::ErrorCode DownloadJobExecutor::check() { } auto u = url.substr(hdfsPrefix.size(), url.size()); - std::vector tokens; + std::vector tokens; folly::split(":", u, tokens); if (tokens.size() == 2) { + if (!NetworkUtils::validateIP(tokens[0]).ok()) { + LOG(ERROR) << "Illegal hdfs host: " << url; + return nebula::cpp2::ErrorCode::E_INVALID_JOB; + } host_ = std::make_unique(tokens[0]); - int32_t position = tokens[1].find_first_of("/"); - if (position != -1) { + auto position = tokens[1].find_first_of("/"); + if (position != std::string::npos) { try { - port_ = folly::to(tokens[1].toString().substr(0, position).c_str()); + port_ = folly::to(tokens[1].substr(0, position).c_str()); } catch (const std::exception& ex) { LOG(ERROR) << "URL's port parse failed: " << url; return nebula::cpp2::ErrorCode::E_INVALID_JOB; } - path_ = - std::make_unique(tokens[1].toString().substr(position, tokens[1].size())); + auto path = tokens[1].substr(position, tokens[1].size()); + // A valid hdfs path must start with /, and only regular characters allow for now + const std::regex pattern("^/[-_/0-9a-zA-Z]*$"); + if (!std::regex_match(path, pattern)) { + LOG(ERROR) << "Illegal hdfs path: " << url; + return nebula::cpp2::ErrorCode::E_INVALID_JOB; + } + path_ = std::make_unique(path); } else { LOG(ERROR) << "URL Parse Failed: " << url; return nebula::cpp2::ErrorCode::E_INVALID_JOB; diff --git a/src/webservice/SetFlagsHandler.cpp b/src/webservice/SetFlagsHandler.cpp index 6a8de177279..660a5c04d1c 100644 --- a/src/webservice/SetFlagsHandler.cpp +++ b/src/webservice/SetFlagsHandler.cpp @@ -79,6 +79,14 @@ void SetFlagsHandler::onEOM() noexcept { for (auto &item : flags.items()) { try { const std::string &name = item.first.asString(); + if (name == "enable_authorize") { + LOG(ERROR) << "Modifying enable_authorize is not allowed"; + ResponseBuilder(downstream_) + .status(WebServiceUtils::to(HttpStatusCode::BAD_REQUEST), + WebServiceUtils::toString(HttpStatusCode::BAD_REQUEST)) + .sendWithEOM(); + return; + } const std::string &value = item.second.asString(); const std::string &newValue = gflags::SetCommandLineOption(name.c_str(), value.c_str()); if (newValue.empty()) {