diff options
author | Tatu Lund <tatu@vaadin.com> | 2021-01-29 13:32:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-29 13:32:09 +0200 |
commit | 885c2298fd709f4b05ee9fd4b38286c82c37cd1e (patch) | |
tree | d1ff791f691c30f7e2b602e16f25665bd8384cf3 | |
parent | b4f011230fd5c9d56a0dd7ad7c00c584e25ee990 (diff) | |
download | vaadin-framework-885c2298fd709f4b05ee9fd4b38286c82c37cd1e.tar.gz vaadin-framework-885c2298fd709f4b05ee9fd4b38286c82c37cd1e.zip |
fix: use time-constant comparison for security tokens (#12189)
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
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; |