CVE-2013-6372: Credentials Management Errors (CWE-255)
value: The Subversion plugin before 1.54 for Jenkins stores credentials using base64 encoding, which allows local users to obtain passwords and SSH private keys by reading a subversion.credentials file.
CWE description: Weaknesses in this category are related to the management of credentials.
Published: 2014-05-08T14:29Z
Repository: https://github.com/jenkinsci/subversion-plugin
Language: Java
Files changed: src/main/java/hudson/scm/SubversionSCM.java
Commit date: 2013-11-18 18:07:09 -0800
Commit message: [FIXED SECURITY-58]

encryption of passphrases wasn't sufficiently secure.

Diff: diff --git a/src/main/java/hudson/scm/SubversionSCM.java b/src/main/java/hudson/scm/SubversionSCM.java
index 18fb5a6..b591a8d 100755
--- a/src/main/java/hudson/scm/SubversionSCM.java
+++ b/src/main/java/hudson/scm/SubversionSCM.java
@@ -1506,23 +1506,27 @@ public class SubversionSCM extends SCM implements Serializable {
             /**
              * 
              */
             private static final long serialVersionUID = -1676145651108866745L;
             private final String userName;
-            private final String password; // scrambled by base64
+            private final Secret password; // for historical reasons, scrambled by base64 in addition to using 'Secret'
 
             public PasswordCredential(String userName, String password) {
                 this.userName = userName;
-                this.password = Scrambler.scramble(password);
+                this.password = Secret.fromString(Scrambler.scramble(password));
             }
 
             @Override
             public SVNAuthentication createSVNAuthentication(String kind) {
                 if(kind.equals(ISVNAuthenticationManager.SSH))
-                    return new SVNSSHAuthentication(userName,Scrambler.descramble(password),-1,false);
+                    return new SVNSSHAuthentication(userName, getPassword(),-1,false);
                 else
-                    return new SVNPasswordAuthentication(userName,Scrambler.descramble(password),false);
+                    return new SVNPasswordAuthentication(userName, getPassword(),false);
+            }
+
+            private String getPassword() {
+                return Scrambler.descramble(Secret.toString(password));
             }
         }
 
         /**
          * Public key authentication for Subversion over SSH.
@@ -1531,20 +1535,20 @@ public class SubversionSCM extends SCM implements Serializable {
             /**
              * 
              */
             private static final long serialVersionUID = -4649332611621900514L;
             private final String userName;
-            private final String passphrase; // scrambled by base64
+            private final Secret passphrase; // for historical reasons, scrambled by base64 in addition to using 'Secret'
             private final String id;
 
             /**
              * @param keyFile
              *      stores SSH private key. The file will be copied.
              */
             public SshPublicKeyCredential(String userName, String passphrase, File keyFile) throws SVNException {
                 this.userName = userName;
-                this.passphrase = Scrambler.scramble(passphrase);
+                this.passphrase = Secret.fromString(Scrambler.scramble(passphrase));
 
                 Random r = new Random();
                 StringBuilder buf = new StringBuilder();
                 for(int i=0;i<16;i++)
                     buf.append(Integer.toHexString(r.nextInt(16)));
@@ -1611,11 +1615,11 @@ public class SubversionSCM extends SCM implements Serializable {
                                 }
                             });
                         } else {
                             privateKey = FileUtils.readFileToString(getKeyFile(),"iso-8859-1");
                         }
-                        return new SVNSSHAuthentication(userName, privateKey.toCharArray(), Scrambler.descramble(passphrase),-1,false);
+                        return new SVNSSHAuthentication(userName, privateKey.toCharArray(), Scrambler.descramble(Secret.toString(passphrase)),-1,false);
                     } catch (IOException e) {
                         throw new SVNException(
                                 SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE,"Unable to load private key").initCause(e));
                     } catch (InterruptedException e) {
                         throw new SVNException(
@@ -1633,24 +1637,24 @@ public class SubversionSCM extends SCM implements Serializable {
             /**
              * 
              */
             private static final long serialVersionUID = 5455755079546887446L;
             private final Secret certificate;
-            private final String password; // scrambled by base64
+            private final Secret password; // for historical reasons, scrambled by base64 in addition to using 'Secret'
 
             public SslClientCertificateCredential(File certificate, String password) throws IOException {
-                this.password = Scrambler.scramble(password);
+                this.password = Secret.fromString(Scrambler.scramble(password));
                 this.certificate = Secret.fromString(new String(Base64.encode(FileUtils.readFileToByteArray(certificate))));
             }
 
             @Override
             public SVNAuthentication createSVNAuthentication(String kind) {
                 if(kind.equals(ISVNAuthenticationManager.SSL))
                     try {
                         SVNSSLAuthentication authentication = new SVNSSLAuthentication(
                                 Base64.decode(certificate.getPlainText().toCharArray()),
-                                Scrambler.descramble(password), false);
+                                Scrambler.descramble(Secret.toString(password)), false);
                         authentication.setCertificatePath("dummy"); // TODO: remove this JENKINS-19175 workaround
                         return authentication;
                     } catch (IOException e) {
                         throw new Error(e); // can't happen
                     }

Vulnerable code:             private final String password; // scrambled by base64
                this.password = Scrambler.scramble(password);
                    return new SVNSSHAuthentication(userName,Scrambler.descramble(password),-1,false);
                    return new SVNPasswordAuthentication(userName,Scrambler.descramble(password),false);
            private final String passphrase; // scrambled by base64
                this.passphrase = Scrambler.scramble(passphrase);
                        return new SVNSSHAuthentication(userName, privateKey.toCharArray(), Scrambler.descramble(passphrase),-1,false);
            private final String password; // scrambled by base64
                this.password = Scrambler.scramble(password);
                                Scrambler.descramble(password), false);
Fixed code:             private final Secret password; // for historical reasons, scrambled by base64 in addition to using 'Secret'
                this.password = Secret.fromString(Scrambler.scramble(password));
                    return new SVNSSHAuthentication(userName, getPassword(),-1,false);
                    return new SVNPasswordAuthentication(userName, getPassword(),false);
            }

            private String getPassword() {
                return Scrambler.descramble(Secret.toString(password));
            private final Secret passphrase; // for historical reasons, scrambled by base64 in addition to using 'Secret'
                this.passphrase = Secret.fromString(Scrambler.scramble(passphrase));
                        return new SVNSSHAuthentication(userName, privateKey.toCharArray(), Scrambler.descramble(Secret.toString(passphrase)),-1,false);
            private final Secret password; // for historical reasons, scrambled by base64 in addition to using 'Secret'
                this.password = Secret.fromString(Scrambler.scramble(password));
                                Scrambler.descramble(Secret.toString(password)), false);