Generate new passwords in a secure way

Previously, lost passwords were generated via
org.apache.commons.lang.RandomStringUtils,
which is using java.util.Random internally.

This PRNG is has a 48-bit seed, that can easily be bruteforced
if an attacker is able to get the PRNG's output, for example
but resetting their own account multiple times,
leading to trivial privileges escalation attacks.

This commit makes use of java.security.SecureRandom
instead.
master
jvoisin 5 years ago
parent e330eeb864
commit 61c842923a
  1. 14
      airsonic-main/src/main/java/org/airsonic/player/controller/RecoverController.java

@ -4,7 +4,6 @@ import de.triology.recaptchav2java.ReCaptcha;
import org.airsonic.player.domain.User;
import org.airsonic.player.service.SecurityService;
import org.airsonic.player.service.SettingsService;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -22,6 +21,7 @@ import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.SecureRandom;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -37,6 +37,10 @@ public class RecoverController {
private static final Logger LOG = LoggerFactory.getLogger(RecoverController.class);
private static final String SYMBOLS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private final SecureRandom random = new SecureRandom();
private static final int PASSWORD_LENGTH = 32;
@Autowired
private SettingsService settingsService;
@Autowired
@ -69,7 +73,13 @@ public class RecoverController {
} else if (user.getEmail() == null) {
map.put("error", "recover.error.noemail");
} else {
String password = RandomStringUtils.randomAlphanumeric(8);
StringBuilder sb = new StringBuilder(PASSWORD_LENGTH);
for(int i=0; i<PASSWORD_LENGTH; i++) {
int index = random.nextInt(SYMBOLS.length());
sb.append(SYMBOLS.charAt(index));
}
String password = sb.toString();
if (emailPassword(password, user.getUsername(), user.getEmail())) {
map.put("sentTo", user.getEmail());
user.setLdapAuthenticated(false);

Loading…
Cancel
Save