From ac1743d42c8c7ef1997d023d90ab590ccc16a8f0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 4 Sep 2014 19:29:45 +0100 Subject: [PATCH] More defensive measures for form-encoded data --- .../config/server/EncryptionController.java | 23 +++++++++++++++---- .../server/EncryptionControllerTests.java | 9 ++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EncryptionController.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EncryptionController.java index 6a0745d0..fe8fb338 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EncryptionController.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EncryptionController.java @@ -16,6 +16,8 @@ package org.springframework.cloud.config.server; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.security.KeyPair; import java.util.Collections; import java.util.HashMap; @@ -33,6 +35,7 @@ import org.springframework.core.io.ByteArrayResource; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.codec.Base64; import org.springframework.security.crypto.encrypt.TextEncryptor; import org.springframework.security.rsa.crypto.KeyStoreKeyFactory; import org.springframework.security.rsa.crypto.RsaKeyHolder; @@ -101,7 +104,7 @@ public class EncryptionController { Map body = new HashMap(); body.put("status", "OK"); - encryptor = new EncryptorFactory().create(stripFormData(data, type)); + encryptor = new EncryptorFactory().create(stripFormData(data, type, false)); if (encryptor instanceof RsaKeyHolder) { body.put("publicKey", ((RsaKeyHolder) encryptor).getPublicKey()); @@ -142,7 +145,7 @@ public class EncryptionController { if (encryptor == null) { throw new KeyNotInstalledException(); } - data = stripFormData(data, type); + data = stripFormData(data, type, false); return encryptor.encrypt(data); } @@ -153,7 +156,7 @@ public class EncryptionController { throw new KeyNotInstalledException(); } try { - data = stripFormData(data, type); + data = stripFormData(data, type, true); return encryptor.decrypt(data); } catch (IllegalArgumentException e) { @@ -161,9 +164,21 @@ public class EncryptionController { } } - private String stripFormData(String data, MediaType type) { + private String stripFormData(String data, MediaType type, boolean cipher) { if (data.endsWith("=") && !type.equals(MediaType.TEXT_PLAIN)) { + try { + data = URLDecoder.decode(data, "UTF-8"); + if (cipher) { + data = data.replace(" ", "+"); + } + } + catch (UnsupportedEncodingException e) { + // Really? + } + if (cipher && Base64.isBase64(data.getBytes())) { + return data; + } // User posted data with content type form but meant it to be text/plain data = data.substring(0, data.length() - 1); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EncryptionControllerTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EncryptionControllerTests.java index 1d120f0a..383a5f89 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EncryptionControllerTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EncryptionControllerTests.java @@ -78,6 +78,15 @@ public class EncryptionControllerTests { assertTrue("Wrong key format: " + key, key.startsWith("ssh-rsa")); } + @Test + public void formDataIn() { + controller.setEncryptor(new RsaSecretEncryptor()); + // Add space to input + String cipher = controller.encrypt("foo bar=", MediaType.APPLICATION_FORM_URLENCODED); + String decrypt = controller.decrypt(cipher + "=", MediaType.APPLICATION_FORM_URLENCODED); + assertEquals("Wrong decrypted plaintext: " + decrypt, "foo bar", decrypt); + } + @Test public void decryptEnvironment() { controller.uploadKey("foo", MediaType.TEXT_PLAIN);