]> source.dussan.org Git - vaadin-framework.git/commitdiff
fix: use time-constant comparison for security tokens (#12192)
authorTatu Lund <tatu@vaadin.com>
Wed, 3 Feb 2021 14:52:08 +0000 (16:52 +0200)
committerGitHub <noreply@github.com>
Wed, 3 Feb 2021 14:52:08 +0000 (16:52 +0200)
This is the same as #12190, 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.

Backporting of #12189

server/src/main/java/com/vaadin/server/VaadinSession.java
server/src/main/java/com/vaadin/server/communication/FileUploadHandler.java
server/src/main/java/com/vaadin/server/communication/PushHandler.java
uitest/src/test/java/com/vaadin/tests/VerifyBrowserVersionTest.java

index 8bdf51683b01ccaadfb1b979c333d065497bfad1..6537d84c73ff83a124788f38aee39e6c36d89edf 100644 (file)
@@ -747,6 +747,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();
 
     /**
index 1209c562accb0edcf871a79d5a427dc84949b5dd..d5dc16c6e719a3a5c1777471bca114f372cc43e0 100644 (file)
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.security.MessageDigest;
 
 import com.vaadin.server.ClientConnector;
 import com.vaadin.server.NoInputStreamException;
@@ -273,8 +274,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])) {
-                // TODO Should rethink error handling
+            String securityKey = parts[3];
+            if (secKey == null || !MessageDigest.isEqual(
+                    secKey.getBytes(UTF8),
+                    securityKey.getBytes(UTF8))) {
                 return true;
             }
 
index 8c359b3d3625d43ef9e93c38d6c75165c2456e62..5bd7fd3232ebb9b50e691ac9cb41fc2ba42315b1 100644 (file)
@@ -18,6 +18,7 @@ package com.vaadin.server.communication;
 
 import java.io.IOException;
 import java.io.Reader;
+import java.security.MessageDigest;
 import java.util.Collection;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -57,6 +58,8 @@ public class PushHandler {
 
     private int longPollingSuspendTimeout = -1;
 
+    private static final String UTF8 = "UTF-8";
+
     /**
      * Callback interface used internally to process an event with the
      * corresponding UI properly locked.
@@ -471,7 +474,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
@@ -480,10 +485,12 @@ public class PushHandler {
      * @return {@code true} if the id is valid, {@code false} otherwise
      */
     private static boolean isPushIdValid(VaadinSession session,
-            String requestPushId) {
+            String requestPushId) throws IOException {
 
         String sessionPushId = session.getPushId();
-        if (requestPushId == null || !requestPushId.equals(sessionPushId)) {
+        if (requestPushId == null || !MessageDigest.isEqual(
+                requestPushId.getBytes(UTF8),
+                sessionPushId.getBytes(UTF8))) {
             return false;
         }
         return true;
index b044571ca39911e19cdd726ae446c1e7c4fe385d..ec3fb525a38c6566510b6082db8e5e984283a8a7 100644 (file)
@@ -25,7 +25,7 @@ public class VerifyBrowserVersionTest extends MultiBrowserTest {
             // Chrome version does not necessarily match the desired version
             // because of auto updates...
             browserIdentifier = getExpectedUserAgentString(
-                    getDesiredCapabilities()) + "87";
+                    getDesiredCapabilities()) + "88";
         } else {
             browserIdentifier = getExpectedUserAgentString(desiredCapabilities)
                     + desiredCapabilities.getVersion();