Repository: mesos Updated Branches: refs/heads/1.4.x 509443ecc -> f6b2a0433
Added constant time comparison of JWT signatures. A vulnerability in our JWT implementation allows an unauthenticated remote attacker to execute to execute timing attacks [1]. This patch removes the vulnerability by adding a constant time comparison of hashes, where the whole message is visited during the comparison instead of returning at the first failure. [1] https://codahale.com/a-lesson-in-timing-attacks/ Review: https://reviews.apache.org/r/67357 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/f6b2a043 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/f6b2a043 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/f6b2a043 Branch: refs/heads/1.4.x Commit: f6b2a0433b1030c3f6bd55b674e4e36a7882ea4b Parents: 509443e Author: Alexander Rojas <alexan...@mesosphere.io> Authored: Tue May 29 16:07:51 2018 +0200 Committer: Alexander Rojas <alexan...@mesosphere.io> Committed: Wed Jun 6 16:35:12 2018 +0200 ---------------------------------------------------------------------- 3rdparty/libprocess/src/jwt.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/f6b2a043/3rdparty/libprocess/src/jwt.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/src/jwt.cpp b/3rdparty/libprocess/src/jwt.cpp index 921031e..6fd2a09 100644 --- a/3rdparty/libprocess/src/jwt.cpp +++ b/3rdparty/libprocess/src/jwt.cpp @@ -154,6 +154,24 @@ Try<JSON::Object> parse_payload(const string& component) return payload; } + +// Implements equality between strings which run in constant time by either +// comparing the sizes, and thus ignoring their content, or checking the whole +// content of them, thus avoiding timing attacks when comparing hashes. +bool constantTimeEquals(const string& left, const string& right) +{ + if (left.size() != right.size()) { + return false; + } + + unsigned valid = 0; + for (size_t i = 0; i < left.size(); ++i) { + valid |= left[i] ^ right[i]; + } + + return valid == 0; +} + } // namespace { @@ -245,9 +263,7 @@ Try<JWT, JWTError> JWT::parse(const string& token, const string& secret) JWTError::Type::UNKNOWN); } - const bool valid = hmac.get() == signature.get(); - - if (!valid) { + if (!constantTimeEquals(hmac.get(), signature.get())) { return JWTError( "Token signature does not match", JWTError::Type::INVALID_TOKEN);