java.lang.security.audit.md5-used-as-password.md5-used-as-password

Author
unknown
Download Count*
License
It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. You can use javax.crypto.SecretKeyFactory
with SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
or, if using Spring, org.springframework.security.crypto.bcrypt
.
Run Locally
Run in CI
Defintion
rules:
- id: md5-used-as-password
languages:
- java
severity: WARNING
message: It looks like MD5 is used as a password hash. MD5 is not considered a
secure password hash because it can be cracked by an attacker in a short
amount of time. Use a suitable password hashing function such as PBKDF2 or
bcrypt. You can use `javax.crypto.SecretKeyFactory` with
`SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")` or, if using Spring,
`org.springframework.security.crypto.bcrypt`.
metadata:
category: security
technology:
- java
- md5
references:
- https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html
- https://github.com/returntocorp/semgrep-rules/issues/1609
- https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory
- https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.html
owasp:
- A03:2017 - Sensitive Data Exposure
- A02:2021 - Cryptographic Failures
cwe:
- "CWE-327: Use of a Broken or Risky Cryptographic Algorithm"
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
mode: taint
pattern-sources:
- patterns:
- pattern-inside: |
$TYPE $MD = MessageDigest.getInstance("MD5");
...
- pattern: $MD.digest(...);
pattern-sinks:
- patterns:
- pattern: $MODEL.$METHOD(...);
- metavariable-regex:
metavariable: $METHOD
regex: (?i)(.*password.*)
Examples
md5-used-as-password.java
package website.controller;
import website.RandomUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.hibernate.service.spi.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.security.MessageDigest;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {
private final UserService service;
@Autowired
public UserController(UserService service) {
this.service = service;
}
@RequestMapping(value = "addUser", method = RequestMethod.POST)
public Result addUser(@RequestBody UserModel user) {
UserModel userModel = service.findUserByEmail(user.getEmail());
if (userModel != null) {
return new Result<>(CodeConst.USER_REPEAT.getResultCode(), CodeConst.USER_REPEAT.getMessage());
}
String salt = RandomUtil.createSalt();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(user.getPassword());
// ruleid: md5-used-as-password
user.setPassword(md.digest(), salt);
user.setValidateCode(Md5Util.encode(user.getEmail(), ""));
user.setSalt(salt);
service.addUser(user);
return new Result<>(user);
}
@RequestMapping(value = "addUserOk", method = RequestMethod.POST)
public Result addUserOk(@RequestBody UserModel user) {
UserModel userModel = service.findUserByEmail(user.getEmail());
if (userModel != null) {
return new Result<>(CodeConst.USER_REPEAT.getResultCode(), CodeConst.USER_REPEAT.getMessage());
}
String salt = RandomUtil.createSalt();
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(user.getPassword());
// ok: md5-used-as-password
user.setPassword(md.digest(), salt);
user.setValidateCode(Md5Util.encode(user.getEmail(), ""));
user.setSalt(salt);
service.addUser(user);
return new Result<>(user);
}
}
Short Link: https://sg.run/JxEQ