CVE-2021-25958 (Java, published 2021-08-30T14:15Z)
Description: value: In Apache Ofbiz, versions v17.12.01 to v17.12.07 implement a try catch exception to handle errors at multiple locations but leaks out sensitive table info which may aid the attacker for further recon. A user can register with a very long password, but when he tries to login with it an exception occurs.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-209 \u2014 Generation of Error Message Containing Sensitive Information
The product generates an error message that includes sensitive information about its environment, users, or associated data.
Repository: https://github.com/apache/ofbiz-framework
Files changed:
framework/common/src/main/java/org/apache/ofbiz/common/login/LoginServices.java
Commit message: Fixed: UserLoginHistory failed the store operation with large password (OFBIZ-12287)

Backport 2aa68dc4de8892e8a7cbb38c10a3a3dd65d233e5 from trunk

When you have a user with long password (greater than 256 characters) present in OFBiz and you try to log with, OFBiz return a long error message with sensitive information due to exceeding value size to store on the field UserLoginHistory.passwordUsed.

To solve this we don't return any information on the genericValue that failed and analyze the field passwordUsed to escape the case where the password set to login is create than the database field capacity.

Thanks to Daniel Elkabes <daniel.elkabes@whitesourcesoftware.com> and Hagai Wechsler <hagai.wechsler@whitesourcesoftware.com> from white source software to raise the problem.


Vulnerable code:
                                        if ("N".equals(successfulLogin) && !"false".equals(EntityUtilProperties.getPropertyValue("security", "store.login.history.incorrect.password", delegator))) {
                                            ulhCreateMap.put("passwordUsed", password);
                                geeErrMsg += ": " + e.toString();

Fixed code:
import org.apache.ofbiz.entity.model.ModelField;
                                        // we will check in the hash size isn't too huge for the store other wise store a fix string
                                        if ("N".equals(successfulLogin) && !"false".equals(EntityUtilProperties.getPropertyValue("security",
                                                "store.login.history.incorrect.password", delegator))) {
                                            ulhCreateMap.put("passwordUsed", isGivenPasswordCanBeStored(delegator, password)
                                                    ? " TOO LONG FOR STORAGE "
                                                    : password);
    /**
     * To escape an exception when the password store due to limitation size for passwordUsed field, we analyse if it's possible.
     * @param delegator
     * @param password
     * @return
     * @throws GenericEntityException
     */
    private static boolean isGivenPasswordCanBeStored(Delegator delegator, String password)
            throws GenericEntityException {
        ModelEntity modelEntityUserLoginHistory = delegator.getModelEntity("UserLoginHistory");
        ModelField passwordUsedField = modelEntityUserLoginHistory.getField("passwordUsed");
        int maxPasswordSize = delegator.getEntityFieldType(
                modelEntityUserLoginHistory,
                passwordUsedField.getType()).stringLength();
        int passwordUsedCurrentSize = password.length();

        // if the field is encrypted, we check the size of the hashed result
        ModelField.EncryptMethod encryptMethod = passwordUsedField.getEncryptMethod();
        if (encryptMethod.isEncrypted()) {
            passwordUsedCurrentSize = delegator.encryptFieldValue("UserLoginHistory", encryptMethod, password).toString().length();
        }
        return passwordUsedCurrentSize > maxPasswordSize;
    }