Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: more tweaks

...

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); // prints ABC-DEF-PQR-XYZ
            }
        }
    }
}

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 made possible by facilitating at least one hash collision with respect to the key of the map.

...

Code Block
public class DemoClient {
    public static void main(String[] args) {
        LicenseManager licenseManager = new LicenseManager();
        LicenseType type = new LicenseType();
        type.setType("custom-license-key");
        licenseManager.setLicenseKey(type, "CUS-TOM-LIC-KEY");
        Object licenseKeyValue = licenseManager.getLicenseKey(type);
        System.out.println(licenseKeyValue); // prints CUS-TOM-LIC-KEY
    }
}

 

Compliant Solution (final class)

...

This noncompliant code example consists of a Widget class that attempts to mandate that comparison of a widget having negative number of components with another yields a false result class and a LayoutManager class containing a set of widgets.

Code Block
bgColor#ffcccc
public class Widget {
    private int noOfComponents;
    public Widget(int noOfComponents) {
        this.noOfComponents = noOfComponents;
    }
    public int getNoOfComponents() {
        return noOfComponents;
    }
    public final void setNoOfComponents(int noOfComponents) {
        this.noOfComponents = noOfComponents;
    }
    public boolean equals(Object o) {
        if (o == null || !(o instanceof Widget)) {
            return false;
        }
        Widget widget = (Widget) o;
        return this.noOfComponents == widget.getNoOfComponents();
    }
    @Override
    public int hashCode() {
        int res = 31;
        res = res * 17 + noOfComponents;
        return res;
    }
}
public class LayoutManager {
    private Set<Widget> layouts = new HashSet<Widget>();
    public void addWidget(Widget widget) {
        if (!layouts.contains(widget)) {
            layouts.add(widget);
        }
    }
    public int getLayoutSize() {
        return layouts.size();
    }
}

LayoutManager class containing a set of widgets is used by the example. An attacker can extend the Widget class as a Navigator widget and override the equals() method.

Code Block
public class Navigator extends Widget {
    public Navigator(int noOfComponents) {
        super(noOfComponents);
    }
    @Override
    public int hashCode() {
        int res = 31;
        res = res * 17;
        return res;
    }
}

Client code follows.

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

...

The reason for this discrepancy is that the hashCode() method of Widget is used only once when the widget is added to the set. When the navigator is added, the hashCode() method provided by the Navigator class is used. 

...

In this noncompliant code example, class Worker starts a thread in startThread()method and so does its subclass SubWorker.

Code Block
bgColor#ffcccc
public class Worker implements Runnable {
    Worker() { }
    public void startThread(String name) {
        new Thread(this, name).start();
    }
    @Override
    public void run() {
        System.out.println("Parent");
    }
}

public class SubWorker extends Worker {
    @Override
    public void startThread(String name) {
        super.startThread(name);
		new Thread(this, name).start();        
    }
    @Override
    public void run() {
        System.out.println("Child");
    }
}

...