CVE-2019-10907: Inadequate Encryption Strength (CWE-326)
value: Airsonic 10.2.1 uses Spring's default remember-me mechanism based on MD5, with a fixed key of airsonic in GlobalSecurityConfig.java. An attacker able to capture cookies might be able to trivially bruteforce offline the passwords of associated users.
CWE description: The product stores or transmits sensitive data using an encryption scheme that is theoretically sound, but is not strong enough for the level of protection required.
CVSS v3 base score: 9.8
Published: 2019-04-07T14:29Z
Repository: https://github.com/airsonic/airsonic
Language: Java
Files changed: airsonic-main/src/main/java/org/airsonic/player/security/GlobalSecurityConfig.java
Commit date: 2019-04-01 11:33:35 +0200
Commit message: Use a random key to "encrypt" the remember-me cookie's value

Since Spring's default remember-me technique is
terrible security-wise (`user:timstamp:md5(use:timestamp:password:key)`),
we should at least use a random key, instead of a fixed one,
otherwise, and attacker able to capture the cookies
might be able to trivially bruteforce offline
the password of the associated user.

Diff: diff --git a/airsonic-main/src/main/java/org/airsonic/player/security/GlobalSecurityConfig.java b/airsonic-main/src/main/java/org/airsonic/player/security/GlobalSecurityConfig.java
index 7ea7757..0fc5376 100644
--- a/airsonic-main/src/main/java/org/airsonic/player/security/GlobalSecurityConfig.java
+++ b/airsonic-main/src/main/java/org/airsonic/player/security/GlobalSecurityConfig.java
@@ -20,19 +20,29 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
 import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 
+import java.security.SecureRandom;
+
 @Configuration
 @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
 @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
 public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter {
 
     private static Logger logger = LoggerFactory.getLogger(GlobalSecurityConfig.class);
 
     static final String FAILURE_URL = "/login?error=1";
 
+    private static final String key;
+
+    static {
+      byte[] array = new byte[32];
+      new SecureRandom().nextBytes(array);
+      key = new String(array);
+    }
+
     @Autowired
     private SecurityService securityService;
 
     @Autowired
     private CsrfSecurityRequestMatcher csrfSecurityRequestMatcher;
@@ -160,10 +170,10 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
                     .usernameParameter("j_username")
                     .passwordParameter("j_password")
                     // see http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#csrf-logout
                     .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")).logoutSuccessUrl(
                     "/login?logout")
-                    .and().rememberMe().key("airsonic");
+                    .and().rememberMe().key(key);
         }
 
     }
-}
\ No newline at end of file
+}

Vulnerable code:                     .and().rememberMe().key("airsonic");
}
Fixed code: import java.security.SecureRandom;

    private static final String key;

    static {
      byte[] array = new byte[32];
      new SecureRandom().nextBytes(array);
      key = new String(array);
    }

                    .and().rememberMe().key(key);
}