diff options
author | Anna Koskinen <Ansku@users.noreply.github.com> | 2021-02-03 16:35:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-03 16:35:06 +0200 |
commit | 560cccc916ed8e9614712aff8720d3fdfe9a0ccc (patch) | |
tree | cab9bc4aad28b6d50ddc11594015ded06a17db9e | |
parent | 3e9873b1182f6b56403202ebe1556e685ded0ff8 (diff) | |
download | vaadin-framework-560cccc916ed8e9614712aff8720d3fdfe9a0ccc.tar.gz vaadin-framework-560cccc916ed8e9614712aff8720d3fdfe9a0ccc.zip |
fix: use time-constant comparison for security tokens (#12189) (#12195)
This is the same as https://github.com/vaadin/framework/pull/12188,
but also applied for the upload security key
and the push id since both of those are also used to protect against
cross-site attacks. In addition, documentation for the push id is
clarified to point out its role.
Cherry-picked from: https://github.com/vaadin/flow/pull/9896
Authored-by: Tatu Lund <tatu@vaadin.com>
3 files changed, 18 insertions, 3 deletions
diff --git a/server/src/main/java/com/vaadin/server/VaadinSession.java b/server/src/main/java/com/vaadin/server/VaadinSession.java index dd64de4fa5..6f25fdc56f 100644 --- a/server/src/main/java/com/vaadin/server/VaadinSession.java +++ b/server/src/main/java/com/vaadin/server/VaadinSession.java @@ -743,6 +743,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { */ private final String csrfToken = UUID.randomUUID().toString(); + /* + * This token should be handled with care since it's used to protect against + * cross-site attacks in addition to general identifier duty. + */ private final String pushId = UUID.randomUUID().toString(); /** diff --git a/server/src/main/java/com/vaadin/server/communication/FileUploadHandler.java b/server/src/main/java/com/vaadin/server/communication/FileUploadHandler.java index bd20bea9ed..81cd21c813 100644 --- a/server/src/main/java/com/vaadin/server/communication/FileUploadHandler.java +++ b/server/src/main/java/com/vaadin/server/communication/FileUploadHandler.java @@ -23,6 +23,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import com.vaadin.server.ClientConnector; import com.vaadin.server.NoInputStreamException; @@ -279,7 +281,10 @@ public class FileUploadHandler implements RequestHandler { streamVariable = uI.getConnectorTracker() .getStreamVariable(connectorId, variableName); String secKey = uI.getConnectorTracker().getSeckey(streamVariable); - if (secKey == null || !secKey.equals(parts[3])) { + String securityKey = parts[3]; + if (secKey == null || !MessageDigest.isEqual( + secKey.getBytes(StandardCharsets.UTF_8), + securityKey.getBytes(StandardCharsets.UTF_8))) { return true; } diff --git a/server/src/main/java/com/vaadin/server/communication/PushHandler.java b/server/src/main/java/com/vaadin/server/communication/PushHandler.java index 77dd1b9b57..f1997ff7cf 100644 --- a/server/src/main/java/com/vaadin/server/communication/PushHandler.java +++ b/server/src/main/java/com/vaadin/server/communication/PushHandler.java @@ -18,6 +18,8 @@ package com.vaadin.server.communication; import java.io.IOException; import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; @@ -510,7 +512,9 @@ public class PushHandler { } /** - * Checks whether a given push id matches the session's push id. + * Checks whether a given push id matches the session's push id. The + * comparison is done using a time-constant method since the push id is used + * to protect against cross-site attacks. * * @param session * the vaadin session for which the check should be done @@ -522,7 +526,9 @@ public class PushHandler { String requestPushId) { String sessionPushId = session.getPushId(); - if (requestPushId == null || !requestPushId.equals(sessionPushId)) { + if (requestPushId == null || !MessageDigest.isEqual( + requestPushId.getBytes(StandardCharsets.UTF_8), + sessionPushId.getBytes(StandardCharsets.UTF_8))) { return false; } return true; |