Avoid HashDoS attacks via random per-session hash initial state (#1433)

This commit is contained in:
Martin Chang 2022-11-10 13:41:21 +08:00 committed by GitHub
parent 9dff8b296b
commit c0d48da99f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 25 deletions

View File

@ -148,21 +148,27 @@ class DROGON_EXPORT HttpRequest
virtual const std::string &getCookie(const std::string &field) const = 0;
/// Get all headers of the request
virtual const std::unordered_map<std::string, std::string> &headers()
const = 0;
virtual const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&headers() const = 0;
/// Get all headers of the request
const std::unordered_map<std::string, std::string> &getHeaders() const
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&getHeaders() const
{
return headers();
}
/// Get all cookies of the request
virtual const std::unordered_map<std::string, std::string> &cookies()
const = 0;
virtual const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&cookies() const = 0;
/// Get all cookies of the request
const std::unordered_map<std::string, std::string> &getCookies() const
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&getCookies() const
{
return cookies();
}
@ -267,11 +273,14 @@ class DROGON_EXPORT HttpRequest
}
/// Get parameters of the request.
virtual const std::unordered_map<std::string, std::string> &parameters()
const = 0;
virtual const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&parameters() const = 0;
/// Get parameters of the request.
const std::unordered_map<std::string, std::string> &getParameters() const
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&getParameters() const
{
return parameters();
}

View File

@ -19,6 +19,7 @@
#include <drogon/Cookie.h>
#include <drogon/HttpTypes.h>
#include <drogon/HttpViewData.h>
#include <drogon/utils/Utilities.h>
#include <json/json.h>
#include <memory>
#include <string>
@ -190,11 +191,14 @@ class DROGON_EXPORT HttpResponse
virtual void removeHeader(std::string key) = 0;
/// Get all headers of the response
virtual const std::unordered_map<std::string, std::string> &headers()
const = 0;
virtual const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&headers() const = 0;
/// Get all headers of the response
const std::unordered_map<std::string, std::string> &getHeaders() const
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&getHeaders() const
{
return headers();
}
@ -222,10 +226,14 @@ class DROGON_EXPORT HttpResponse
virtual const Cookie &getCookie(const std::string &key) const = 0;
/// Get all cookies.
virtual const std::unordered_map<std::string, Cookie> &cookies() const = 0;
virtual const std::
unordered_map<std::string, Cookie, utils::internal::SafeStringHash>
&cookies() const = 0;
/// Get all cookies.
const std::unordered_map<std::string, Cookie> &getCookies() const
const std::
unordered_map<std::string, Cookie, utils::internal::SafeStringHash>
&getCookies() const
{
return cookies();
}

View File

@ -408,5 +408,22 @@ inline bool fromString<bool>(const std::string &p) noexcept(false)
}
throw std::runtime_error("Can't convert from string '" + p + "' to bool");
}
namespace internal
{
DROGON_EXPORT extern const size_t fixedRandomNumber;
struct SafeStringHash
{
size_t operator()(const std::string &str) const
{
const size_t A = 6665339;
const size_t B = 2534641;
size_t h = fixedRandomNumber;
for (char ch : str)
h = (h * A) ^ (ch * B);
return h;
}
};
} // namespace internal
} // namespace utils
} // namespace drogon

View File

@ -137,8 +137,9 @@ class HttpRequestImpl : public HttpRequest
pathEncode_ = pathEncode;
}
const std::unordered_map<std::string, std::string> &parameters()
const override
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&parameters() const override
{
parseParametersOnce();
return parameters_;
@ -291,12 +292,16 @@ class HttpRequestImpl : public HttpRequest
return defaultVal;
}
const std::unordered_map<std::string, std::string> &headers() const override
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&headers() const override
{
return headers_;
}
const std::unordered_map<std::string, std::string> &cookies() const override
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&cookies() const override
{
return cookies_;
}
@ -541,9 +546,15 @@ class HttpRequestImpl : public HttpRequest
bool pathEncode_{true};
string_view matchedPathPattern_{""};
std::string query_;
std::unordered_map<std::string, std::string> headers_;
std::unordered_map<std::string, std::string> cookies_;
mutable std::unordered_map<std::string, std::string> parameters_;
std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
headers_;
std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
cookies_;
mutable std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
parameters_;
mutable std::shared_ptr<Json::Value> jsonPtr_;
SessionPtr sessionPtr_;
mutable AttributesPtr attributesPtr_;

View File

@ -130,7 +130,9 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
removeHeaderBy(key);
}
const std::unordered_map<std::string, std::string> &headers() const override
const std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
&headers() const override
{
return headers_;
}
@ -200,7 +202,9 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
return defaultCookie;
}
const std::unordered_map<std::string, Cookie> &cookies() const override
const std::
unordered_map<std::string, Cookie, utils::internal::SafeStringHash>
&cookies() const override
{
return cookies_;
}
@ -446,8 +450,11 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
statusMessage_ = string_view{message, messageLength};
}
std::unordered_map<std::string, std::string> headers_;
std::unordered_map<std::string, Cookie> cookies_;
std::
unordered_map<std::string, std::string, utils::internal::SafeStringHash>
headers_;
std::unordered_map<std::string, Cookie, utils::internal::SafeStringHash>
cookies_;
int customStatusCode_{-1};
HttpStatusCode statusCode_{kUnknown};

View File

@ -1221,5 +1221,14 @@ bool secureRandomBytes(void *ptr, size_t size)
return false;
}
namespace internal
{
DROGON_EXPORT const size_t fixedRandomNumber = []() {
size_t res;
utils::secureRandomBytes(&res, sizeof(res));
return res;
}();
}
} // namespace utils
} // namespace drogon