Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added another NCE

Untrusted code can misuse APIs provided by trusted code by overriding methods such as Object.equals()Object.hashCode() and Thread.run(). These methods are primarily targeted because they are most often used behind the scenes and may interact with components in a way that is not clearly discernible.

By providing overridden implementations, untrusted code may be able to glean sensitive information, cause arbitrary code to run and expose denial of service vulnerabilities.

Noncompliant Code Example

This noncompliant code example shows a LicenseManager class that maintains a licenseMap. The map stores a LicenseType and license value pair.

Code Block
bgColor#ffcccc
public class LicenseManager {
    Map<LicenseType, String> licenseMap = new HashMap<LicenseType, String>();
    
    public LicenseManager() {
        LicenseType type = new LicenseType();
        type.setType("demo-license-key");
        licenseMap.put(type, "ABC-DEF-PQR-XYZ");
    }
    public Object getLicenseKey(LicenseType licenseType) {
        return licenseMap.get(licenseType);
    }
    public void setLicenseKey(LicenseType licenseType, String licenseKey) {
        licenseMap.put(licenseType, licenseKey);
    }
}

class LicenseType {
    private String type;
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    @Override
    public int hashCode() {
        int res = 17;
        res = res * 31 + type == null ? 0 : type.hashCode();
        return res;
    }
    @Override
    public boolean equals(Object arg) {
        if (arg == null || !(arg instanceof LicenseType)) {
            return false;
        }
        if (type.equals(((LicenseType) arg).getType())) {
            return true;
        }
        return false;
    }
}

The constructor for LicenseManager initializes licenseMap with a demo license key which is meant to be kept secret. The license key is hardcoded for illustrative purposes and should ideally be read from an external configuration file that stores its encrypted version. The LicenseType class provides overridden implementations of equals() and hashCode() methods.

This setup can expose the demo license key if an attacker extends the LicenseType class as follows and overrides the equals() and hashCode() methods.

Code Block
public class CraftedLicenseType extends LicenseType {
    private static int guessedHashCode = 0;
    @Override
    public int hashCode() {
        // Returns a new hashCode to test every time get() is called
        guessedHashCode++;
        return guessedHashCode;
    }
    @Override
    public boolean equals(Object arg) {
        // Always returns true
        return true;
    }
}

The client program is shown below.

Code Block
public class DemoClient {
    public static void main(String[] args) {
        LicenseManager licenseManager = new LicenseManager();
        for (int i = 0; i <= Integer.MAX_VALUE; i++) {
            Object guessed = licenseManager
                    .getLicenseKey(new CraftedLicenseType());
            if (guessed != null) {
                System.out.println(guessed);
            }
        }
    }
}

The client program runs through the sequence of all possible hash codes using CraftedLicenseType until it successfully matches the hash code of the demo license key object stored in the LicenseManager class. Consequently, within a few minutes the attacker is able to find the sensitive data present within the licenseMap. That is possible by facilitating at least one hash collision with respect to the key of the map.

Ref - See Guideline 6-5: Do not trust identity equality when overridable on input reference objects

http://jroller.com/tackline/entry/user_supplied_objects_may_not

Noncompliant Code Example

How many items are there in layouts in the end?

...

Code Block
        Widget nav = new Navigator(-1);
        Widget widget = new Widget(10);
        LayoutManager manager = new LayoutManager();
        manager.addWidget(nav);
        manager.addWidget(widget);
        System.out.println(manager.getLayoutSize()); // prints 2

Noncompliant Code Example

What gets printed - main or child / both / either ?

...