diff --git a/src/actions/transformations/base64_decode.cc b/src/actions/transformations/base64_decode.cc index fe910e5012..29dec57abb 100644 --- a/src/actions/transformations/base64_decode.cc +++ b/src/actions/transformations/base64_decode.cc @@ -23,9 +23,14 @@ namespace modsecurity::actions::transformations { bool Base64Decode::transform(std::string &value, const Transaction *trans) const { if (value.empty()) return false; - value = Utils::Base64::decode(value); + + std::string decoded; + if (!Utils::Base64::decode(value, decoded)) { + return false; + } + + value = std::move(decoded); return true; } - } // namespace modsecurity::actions::transformations diff --git a/src/utils/base64.cc b/src/utils/base64.cc index e27cace943..9afc19f1e3 100644 --- a/src/utils/base64.cc +++ b/src/utils/base64.cc @@ -55,14 +55,33 @@ std::string Base64::decode(const std::string& data, bool forgiven) { return decode_forgiven(data); } - return decode(data); + std::string out; + decode(data, out); + return out; } -std::string Base64::decode(const std::string& data) { - return base64Helper(data.c_str(), strlen(data.c_str()), mbedtls_base64_decode); -} +bool Base64::decode(const std::string& data, std::string &out) { + size_t out_len = 0; + const auto *src = reinterpret_cast(data.c_str()); + const size_t slen = strlen(data.c_str()); + + const int ret = mbedtls_base64_decode(nullptr, 0, &out_len, src, slen); + + if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) { + return false; + } + + out.resize(out_len); + if (mbedtls_base64_decode( + reinterpret_cast(out.data()), + out.size(), &out_len, src, slen) != 0) { + return false; + } + out.resize(out_len); + return true; +} std::string Base64::decode_forgiven(const std::string& data) { return base64Helper(data.c_str(), data.size(), decode_forgiven_engine); diff --git a/src/utils/base64.h b/src/utils/base64.h index 97639a5413..9470bf1706 100644 --- a/src/utils/base64.h +++ b/src/utils/base64.h @@ -29,7 +29,7 @@ class Base64 { static std::string encode(const std::string& data); static std::string decode(const std::string& data, bool forgiven); - static std::string decode(const std::string& data); + static bool decode(const std::string& data, std::string &out); static std::string decode_forgiven(const std::string& data); static void decode_forgiven_engine(unsigned char *plain_text, diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index 550294c70e..73c8e6363a 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -54,7 +54,11 @@ void RemoteUser::evaluate(Transaction *transaction, base64 = std::string(header, 6, header.length()); } - base64 = Utils::Base64::decode(base64); + std::string decoded; + + if (Utils::Base64::decode(base64, decoded)) { + base64 = std::move(decoded); + } if (const auto pos{base64.find(":")}; pos != std::string::npos) { transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));