Skip to content

Commit

Permalink
Avoid HashDoS attacks via random per-session hash initial state (#1433)
Browse files Browse the repository at this point in the history
  • Loading branch information
marty1885 committed Nov 10, 2022
1 parent 9dff8b2 commit c0d48da
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 25 deletions.
27 changes: 18 additions & 9 deletions lib/inc/drogon/HttpRequest.h
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
}
Expand Down
18 changes: 13 additions & 5 deletions lib/inc/drogon/HttpResponse.h
Expand Up @@ -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>
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
}
Expand Down
17 changes: 17 additions & 0 deletions lib/inc/drogon/utils/Utilities.h
Expand Up @@ -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
25 changes: 18 additions & 7 deletions lib/src/HttpRequestImpl.h
Expand Up @@ -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_;
Expand Down Expand Up @@ -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_;
}
Expand Down Expand Up @@ -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_;
Expand Down
15 changes: 11 additions & 4 deletions lib/src/HttpResponseImpl.h
Expand Up @@ -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_;
}
Expand Down Expand Up @@ -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_;
}
Expand Down Expand Up @@ -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};
Expand Down
9 changes: 9 additions & 0 deletions lib/src/Utilities.cc
Expand Up @@ -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

0 comments on commit c0d48da

Please sign in to comment.