This is an automated email from the ASF dual-hosted git repository.

papegaaij pushed a commit to branch crypt-unification
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit e1c2f265082461f629daee38ec8806c9139ceeca
Author: Emond Papegaaij <[email protected]>
AuthorDate: Tue Aug 4 13:14:36 2026 +0200

    WICKET-7190 Verify the upload token by decrypting it
    
    The signed upload settings introduced in 483b83ca62 were validated by
    re-encrypting the expected settings and comparing the resulting ciphertext
    to the token supplied by the client. That only worked because the default
    crypt at the time was deterministic PBE: the same plaintext always produced
    the same ciphertext.
    
    SchemeCrypt encrypts with a fresh random nonce per message, as an AEAD mode
    must, so no two encryptions of the same settings agree and the comparison
    never succeeds - every upload through FileUploadToResourceField was 
rejected.
    
    Validate the token by decrypting it and comparing the settings it carries
    instead. The authentication tag is what makes the token unforgeable, and
    decryption returns null for anything tampered with, so the check keeps
    rejecting a client that alters the limits.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 .../upload/resource/AbstractFileUploadResource.java    | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/resource/AbstractFileUploadResource.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/resource/AbstractFileUploadResource.java
index dea29a3494..c20e7a5ce8 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/resource/AbstractFileUploadResource.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/resource/AbstractFileUploadResource.java
@@ -227,9 +227,21 @@ public abstract class AbstractFileUploadResource extends 
AbstractResource
                        return false;
                }
 
-               String expectedToken = createUploadToken(uploadId, maxSize, 
fileMaxSize, fileCountMax);
-               return 
MessageDigest.isEqual(expectedToken.getBytes(StandardCharsets.UTF_8),
-                       actualToken.getBytes(StandardCharsets.UTF_8));
+               // the token is authenticated but not deterministic - 
encryption uses a fresh nonce per
+               // message - so it cannot be validated by re-encrypting and 
comparing ciphertext. Decrypt
+               // it instead and compare the settings it carries; the 
authentication tag is what makes it
+               // unforgeable, and decryption fails on anything that was 
tampered with.
+               String decryptedToken = 
Application.get().getSecuritySettings().getCryptFactory().newCrypt()
+                       .decryptUrlSafe(actualToken);
+               if (decryptedToken == null)
+               {
+                       return false;
+               }
+
+               String expectedSettings = serializeUploadSettings(uploadId, 
maxSize, fileMaxSize,
+                       fileCountMax);
+               return 
MessageDigest.isEqual(expectedSettings.getBytes(StandardCharsets.UTF_8),
+                       decryptedToken.getBytes(StandardCharsets.UTF_8));
        }
 
        private ResourceResponse createErrorResponse(ResourceResponse 
resourceResponse, String errorMessage)

Reply via email to